EMMA Coverage Report (generated Mon Jul 24 20:22:52 CDT 2006)
[all classes][com.mysql.jdbc]

COVERAGE SUMMARY FOR SOURCE FILE [ResultSet.java]

nameclass, %method, %block, %line, %
ResultSet.java100% (1/1)65%  (160/246)66%  (7587/11421)71%  (1588.9/2237)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class ResultSet100% (1/1)65%  (160/246)66%  (7587/11421)71%  (1588.9/2237)
cancelRowUpdates (): void 0%   (0/1)0%   (0/4)0%   (0/1)
deleteRow (): void 0%   (0/1)0%   (0/4)0%   (0/1)
getArray (String): Array 0%   (0/1)0%   (0/6)0%   (0/1)
getAsciiStream (String): InputStream 0%   (0/1)0%   (0/6)0%   (0/1)
getBinaryStream (String): InputStream 0%   (0/1)0%   (0/6)0%   (0/1)
getCharacterStream (String): Reader 0%   (0/1)0%   (0/6)0%   (0/1)
getClob (String): Clob 0%   (0/1)0%   (0/6)0%   (0/1)
getCursorName (): String 0%   (0/1)0%   (0/5)0%   (0/1)
getDate (String): Date 0%   (0/1)0%   (0/6)0%   (0/1)
getDate (String, Calendar): Date 0%   (0/1)0%   (0/7)0%   (0/1)
getDouble (String): double 0%   (0/1)0%   (0/6)0%   (0/1)
getFloat (String): float 0%   (0/1)0%   (0/6)0%   (0/1)
getGmtCalendar (): Calendar 0%   (0/1)0%   (0/11)0%   (0/3)
getLong (String): long 0%   (0/1)0%   (0/6)0%   (0/1)
getNativeArray (int): Array 0%   (0/1)0%   (0/4)0%   (0/1)
getNativeAsciiStream (int): InputStream 0%   (0/1)0%   (0/6)0%   (0/2)
getNativeRef (int): Ref 0%   (0/1)0%   (0/4)0%   (0/1)
getNativeURL (int): URL 0%   (0/1)0%   (0/28)0%   (0/6)
getNativeUnicodeStream (int): InputStream 0%   (0/1)0%   (0/6)0%   (0/2)
getObject (String, Map): Object 0%   (0/1)0%   (0/7)0%   (0/1)
getObject (int, Map): Object 0%   (0/1)0%   (0/4)0%   (0/1)
getObjectStoredProc (String, Map, int): Object 0%   (0/1)0%   (0/8)0%   (0/1)
getObjectStoredProc (String, int): Object 0%   (0/1)0%   (0/7)0%   (0/1)
getObjectStoredProc (int, Map, int): Object 0%   (0/1)0%   (0/5)0%   (0/1)
getRef (String): Ref 0%   (0/1)0%   (0/6)0%   (0/1)
getTime (String, Calendar): Time 0%   (0/1)0%   (0/7)0%   (0/1)
getTimestamp (String, Calendar): Timestamp 0%   (0/1)0%   (0/7)0%   (0/1)
getURL (String): URL 0%   (0/1)0%   (0/28)0%   (0/6)
getUnicodeStream (String): InputStream 0%   (0/1)0%   (0/6)0%   (0/1)
insertRow (): void 0%   (0/1)0%   (0/4)0%   (0/1)
issueDataTruncationWarningIfConfigured (int, int, int): void 0%   (0/1)0%   (0/10)0%   (0/2)
moveToCurrentRow (): void 0%   (0/1)0%   (0/4)0%   (0/1)
moveToInsertRow (): void 0%   (0/1)0%   (0/4)0%   (0/1)
refreshRow (): void 0%   (0/1)0%   (0/4)0%   (0/1)
rowDeleted (): boolean 0%   (0/1)0%   (0/4)0%   (0/1)
rowInserted (): boolean 0%   (0/1)0%   (0/4)0%   (0/1)
rowUpdated (): boolean 0%   (0/1)0%   (0/4)0%   (0/1)
setFetchDirection (int): void 0%   (0/1)0%   (0/18)0%   (0/4)
setStatementUsedForFetchingRows (PreparedStatement): void 0%   (0/1)0%   (0/4)0%   (0/2)
updateArray (String, Array): void 0%   (0/1)0%   (0/4)0%   (0/1)
updateArray (int, Array): void 0%   (0/1)0%   (0/4)0%   (0/1)
updateAsciiStream (String, InputStream, int): void 0%   (0/1)0%   (0/8)0%   (0/2)
updateAsciiStream (int, InputStream, int): void 0%   (0/1)0%   (0/4)0%   (0/1)
updateBigDecimal (String, BigDecimal): void 0%   (0/1)0%   (0/7)0%   (0/2)
updateBigDecimal (int, BigDecimal): void 0%   (0/1)0%   (0/4)0%   (0/1)
updateBinaryStream (String, InputStream, int): void 0%   (0/1)0%   (0/8)0%   (0/2)
updateBinaryStream (int, InputStream, int): void 0%   (0/1)0%   (0/4)0%   (0/1)
updateBlob (String, Blob): void 0%   (0/1)0%   (0/4)0%   (0/1)
updateBlob (int, Blob): void 0%   (0/1)0%   (0/4)0%   (0/1)
updateBoolean (String, boolean): void 0%   (0/1)0%   (0/7)0%   (0/2)
updateBoolean (int, boolean): void 0%   (0/1)0%   (0/4)0%   (0/1)
updateByte (String, byte): void 0%   (0/1)0%   (0/7)0%   (0/2)
updateByte (int, byte): void 0%   (0/1)0%   (0/4)0%   (0/1)
updateBytes (String, byte []): void 0%   (0/1)0%   (0/7)0%   (0/2)
updateBytes (int, byte []): void 0%   (0/1)0%   (0/4)0%   (0/1)
updateCharacterStream (String, Reader, int): void 0%   (0/1)0%   (0/8)0%   (0/2)
updateCharacterStream (int, Reader, int): void 0%   (0/1)0%   (0/4)0%   (0/1)
updateClob (String, Clob): void 0%   (0/1)0%   (0/7)0%   (0/2)
updateClob (int, Clob): void 0%   (0/1)0%   (0/4)0%   (0/1)
updateDate (String, Date): void 0%   (0/1)0%   (0/7)0%   (0/2)
updateDate (int, Date): void 0%   (0/1)0%   (0/4)0%   (0/1)
updateDouble (String, double): void 0%   (0/1)0%   (0/7)0%   (0/2)
updateDouble (int, double): void 0%   (0/1)0%   (0/4)0%   (0/1)
updateFloat (String, float): void 0%   (0/1)0%   (0/7)0%   (0/2)
updateFloat (int, float): void 0%   (0/1)0%   (0/4)0%   (0/1)
updateInt (String, int): void 0%   (0/1)0%   (0/7)0%   (0/2)
updateInt (int, int): void 0%   (0/1)0%   (0/4)0%   (0/1)
updateLong (String, long): void 0%   (0/1)0%   (0/7)0%   (0/2)
updateLong (int, long): void 0%   (0/1)0%   (0/4)0%   (0/1)
updateNull (String): void 0%   (0/1)0%   (0/6)0%   (0/2)
updateNull (int): void 0%   (0/1)0%   (0/4)0%   (0/1)
updateObject (String, Object): void 0%   (0/1)0%   (0/7)0%   (0/2)
updateObject (String, Object, int): void 0%   (0/1)0%   (0/7)0%   (0/2)
updateObject (int, Object): void 0%   (0/1)0%   (0/4)0%   (0/1)
updateObject (int, Object, int): void 0%   (0/1)0%   (0/4)0%   (0/1)
updateRef (String, Ref): void 0%   (0/1)0%   (0/4)0%   (0/1)
updateRef (int, Ref): void 0%   (0/1)0%   (0/4)0%   (0/1)
updateRow (): void 0%   (0/1)0%   (0/4)0%   (0/1)
updateShort (String, short): void 0%   (0/1)0%   (0/7)0%   (0/2)
updateShort (int, short): void 0%   (0/1)0%   (0/4)0%   (0/1)
updateString (String, String): void 0%   (0/1)0%   (0/7)0%   (0/2)
updateString (int, String): void 0%   (0/1)0%   (0/4)0%   (0/1)
updateTime (String, Time): void 0%   (0/1)0%   (0/7)0%   (0/2)
updateTime (int, Time): void 0%   (0/1)0%   (0/4)0%   (0/1)
updateTimestamp (String, Timestamp): void 0%   (0/1)0%   (0/7)0%   (0/2)
updateTimestamp (int, Timestamp): void 0%   (0/1)0%   (0/4)0%   (0/1)
getObjectStoredProc (int, int): Object 100% (1/1)16%  (37/238)21%  (9.4/44)
getBigDecimalFromString (String, int, int): BigDecimal 100% (1/1)16%  (31/190)28%  (7/25)
getDoubleInternal (String, int): double 100% (1/1)17%  (19/109)25%  (7/28)
getBigDecimal (int, int): BigDecimal 100% (1/1)28%  (39/138)46%  (11/24)
getIntFromString (String, int): int 100% (1/1)32%  (41/127)35%  (9/26)
toString (): String 100% (1/1)38%  (6/16)67%  (2/3)
getStringForClob (int): String 100% (1/1)39%  (23/59)44%  (7/16)
getFloatFromString (String, int): float 100% (1/1)43%  (43/100)50%  (10/20)
getLongFromString (String, int): long 100% (1/1)45%  (25/56)45%  (5/11)
checkColumnBounds (int): void 100% (1/1)49%  (22/45)80%  (4/5)
getShortFromString (String, int): short 100% (1/1)49%  (30/61)45%  (5/11)
getObject (int): Object 100% (1/1)50%  (205/408)54%  (44.5/82)
getInt (int): int 100% (1/1)54%  (144/267)62%  (32.2/52)
getShort (int): short 100% (1/1)54%  (148/274)63%  (32.8/52)
getTimestampFromString (int, Calendar, String, TimeZone, boolean): Timestamp 100% (1/1)56%  (407/733)59%  (54.5/93)
extractStringFromNativeColumn (int, int): String 100% (1/1)56%  (63/112)73%  (16/22)
getDateFromString (String, int): Date 100% (1/1)57%  (224/393)58%  (38/66)
getNativeShort (int, boolean): short 100% (1/1)58%  (207/357)74%  (40/54)
getLong (int): long 100% (1/1)58%  (123/212)66%  (29.2/44)
getBytes (int, boolean): byte [] 100% (1/1)59%  (41/70)68%  (10.2/15)
previous (): boolean 100% (1/1)60%  (9/15)60%  (3/5)
parseIntAsDouble (int, String): int 100% (1/1)61%  (17/28)57%  (4/7)
getNativeBoolean (int): boolean 100% (1/1)61%  (77/126)79%  (15/19)
throwRangeException (String, int, int): void 100% (1/1)62%  (37/60)55%  (11/20)
parseIntWithOverflowCheck (int, byte [], String): int 100% (1/1)63%  (39/62)66%  (8.6/13)
parseLongAsDouble (int, String): long 100% (1/1)63%  (17/27)57%  (4/7)
getBigDecimal (int): BigDecimal 100% (1/1)63%  (33/52)83%  (10/12)
getCalendarInstanceForSessionOrNew (): Calendar 100% (1/1)64%  (7/11)67%  (2/3)
getNativeConvertToString (int, Field): String 100% (1/1)67%  (286/427)68%  (73.7/108)
getByteFromString (String, int): byte 100% (1/1)68%  (57/84)76%  (13/17)
getNativeByte (int, boolean): byte 100% (1/1)69%  (230/334)79%  (44/56)
getBlob (int): Blob 100% (1/1)69%  (61/88)82%  (14/17)
parseShortAsDouble (int, String): short 100% (1/1)72%  (21/29)71%  (5/7)
beforeFirst (): void 100% (1/1)73%  (19/26)70%  (7/10)
first (): boolean 100% (1/1)73%  (22/30)70%  (7/10)
absolute (int): boolean 100% (1/1)74%  (66/89)74%  (20/27)
getStringInternal (int, boolean): String 100% (1/1)75%  (204/272)75%  (49/65)
getNativeInt (int, boolean): int 100% (1/1)75%  (239/317)88%  (42/48)
parseShortWithOverflowCheck (int, byte [], String): short 100% (1/1)76%  (47/62)84%  (10.9/13)
afterLast (): void 100% (1/1)76%  (19/25)78%  (7/9)
getNativeDouble (int): double 100% (1/1)76%  (185/243)84%  (27/32)
parseLongWithOverflowCheck (int, byte [], String): long 100% (1/1)77%  (49/64)84%  (10.9/13)
getCharacterStreamFromString (String, int): Reader 100% (1/1)78%  (7/9)67%  (2/3)
getNativeDateTimeValue (int, Calendar, int, int, TimeZone, boolean): Object 100% (1/1)78%  (262/336)85%  (64.1/75)
next (): boolean 100% (1/1)78%  (40/51)81%  (13/16)
realClose (boolean): void 100% (1/1)79%  (232/295)90%  (47.7/53)
getTimeFromString (String, Calendar, int, TimeZone, boolean): Time 100% (1/1)79%  (274/345)79%  (42.1/53)
getNativeLong (int, boolean, boolean): long 100% (1/1)79%  (267/336)88%  (38/43)
getNativeTimestamp (int, Calendar, TimeZone, boolean): Timestamp 100% (1/1)80%  (174/217)93%  (39.9/43)
getURL (int): URL 100% (1/1)82%  (23/28)83%  (5/6)
getNativeString (int): String 100% (1/1)82%  (89/108)81%  (21/26)
getNativeBlob (int): Blob 100% (1/1)83%  (57/69)83%  (15/18)
issueConversionViaParsingWarning (String, int, Object, Field, int []): void 100% (1/1)83%  (141/170)92%  (23.9/26)
getStatement (): Statement 100% (1/1)84%  (16/19)80%  (4/5)
fastDateCreate (Calendar, int, int, int): Date 100% (1/1)86%  (19/22)96%  (3.8/4)
getNativeDate (int, TimeZone): Date 100% (1/1)87%  (117/135)84%  (26.9/32)
getNativeFloat (int): float 100% (1/1)88%  (209/237)86%  (32/37)
fastTimestampCreate (Calendar, int, int, int, int, int, int, int): Timestamp 100% (1/1)88%  (23/26)96%  (3.9/4)
getBytesFromString (String, int): byte [] 100% (1/1)89%  (16/18)67%  (2/3)
getRow (): int 100% (1/1)89%  (32/36)89%  (8/9)
getDate (int, Calendar): Date 100% (1/1)89%  (25/28)95%  (5.7/6)
last (): boolean 100% (1/1)90%  (27/30)90%  (9/10)
getBoolean (int): boolean 100% (1/1)92%  (85/92)84%  (16/19)
relative (int): boolean 100% (1/1)94%  (30/32)83%  (5/6)
findColumn (String): int 100% (1/1)95%  (70/74)92%  (12/13)
getNativeBytes (int, boolean): byte [] 100% (1/1)95%  (73/77)90%  (18/20)
prev (): boolean 100% (1/1)95%  (38/40)92%  (12/13)
getNativeTime (int, Calendar, TimeZone, boolean): Time 100% (1/1)95%  (101/106)96%  (23/24)
<static initializer> 100% (1/1)100% (21/21)100% (3/3)
ResultSet (String, Field [], RowData, Connection, Statement): void 100% (1/1)100% (269/269)100% (73/73)
ResultSet (long, long, Connection, Statement): void 100% (1/1)100% (122/122)100% (40/40)
buildIndexMapping (): void 100% (1/1)100% (89/89)100% (17/17)
checkClosed (): void 100% (1/1)100% (9/9)100% (3/3)
checkRowPos (): void 100% (1/1)100% (34/34)100% (8/8)
clearNextResult (): void 100% (1/1)100% (4/4)100% (2/2)
clearWarnings (): void 100% (1/1)100% (4/4)100% (2/2)
close (): void 100% (1/1)100% (4/4)100% (2/2)
convertLongToUlong (long): BigInteger 100% (1/1)100% (73/73)100% (10/10)
convertToZeroLiteralStringWithEmptyCheck (): String 100% (1/1)100% (10/10)100% (3/3)
convertToZeroWithEmptyCheck (): int 100% (1/1)100% (10/10)100% (3/3)
copy (): ResultSet 100% (1/1)100% (16/16)100% (2/2)
fastTimeCreate (Calendar, int, int, int): Time 100% (1/1)100% (11/11)100% (3/3)
getArray (int): Array 100% (1/1)100% (7/7)100% (2/2)
getAsciiStream (int): InputStream 100% (1/1)100% (13/13)100% (4/4)
getBigDecimal (String): BigDecimal 100% (1/1)100% (6/6)100% (1/1)
getBigDecimal (String, int): BigDecimal 100% (1/1)100% (7/7)100% (1/1)
getBinaryStream (int): InputStream 100% (1/1)100% (22/22)100% (7/7)
getBlob (String): Blob 100% (1/1)100% (6/6)100% (1/1)
getBoolean (String): boolean 100% (1/1)100% (6/6)100% (1/1)
getBooleanFromString (String, int): boolean 100% (1/1)100% (29/29)100% (4/4)
getByte (String): byte 100% (1/1)100% (6/6)100% (1/1)
getByte (int): byte 100% (1/1)100% (23/23)100% (6/6)
getBytes (String): byte [] 100% (1/1)100% (6/6)100% (1/1)
getBytes (int): byte [] 100% (1/1)100% (5/5)100% (1/1)
getCharacterStream (int): Reader 100% (1/1)100% (20/20)100% (6/6)
getClob (int): Clob 100% (1/1)100% (20/20)100% (6/6)
getClobFromString (String, int): Clob 100% (1/1)100% (5/5)100% (1/1)
getConcurrency (): int 100% (1/1)100% (2/2)100% (1/1)
getDate (int): Date 100% (1/1)100% (5/5)100% (1/1)
getDefaultTimeZone (): TimeZone 100% (1/1)100% (9/9)100% (3/3)
getDouble (int): double 100% (1/1)100% (11/11)100% (3/3)
getDoubleFromString (String, int): double 100% (1/1)100% (5/5)100% (1/1)
getDoubleInternal (int): double 100% (1/1)100% (7/7)100% (1/1)
getFetchDirection (): int 100% (1/1)100% (3/3)100% (1/1)
getFetchSize (): int 100% (1/1)100% (3/3)100% (1/1)
getFirstCharOfQuery (): char 100% (1/1)100% (3/3)100% (1/1)
getFloat (int): float 100% (1/1)100% (18/18)100% (5/5)
getInt (String): int 100% (1/1)100% (6/6)100% (1/1)
getMetaData (): ResultSetMetaData 100% (1/1)100% (8/8)100% (2/2)
getNativeBigDecimal (int): BigDecimal 100% (1/1)100% (16/16)100% (3/3)
getNativeBigDecimal (int, int): BigDecimal 100% (1/1)100% (50/50)100% (12/12)
getNativeBinaryStream (int): InputStream 100% (1/1)100% (16/16)100% (5/5)
getNativeByte (int): byte 100% (1/1)100% (5/5)100% (1/1)
getNativeCharacterStream (int): Reader 100% (1/1)100% (15/15)100% (5/5)
getNativeClob (int): Clob 100% (1/1)100% (13/13)100% (4/4)
getNativeDate (int): Date 100% (1/1)100% (5/5)100% (1/1)
getNativeDateViaParseConversion (int): Date 100% (1/1)100% (34/34)100% (4/4)
getNativeInt (int): int 100% (1/1)100% (5/5)100% (1/1)
getNativeLong (int): long 100% (1/1)100% (6/6)100% (1/1)
getNativeShort (int): short 100% (1/1)100% (5/5)100% (1/1)
getNativeTimeViaParseConversion (int, Calendar, TimeZone, boolean): Time 100% (1/1)100% (37/37)100% (4/4)
getNativeTimestampViaParseConversion (int, Calendar, TimeZone, boolean): Time... 100% (1/1)100% (41/41)100% (4/4)
getNextResultSet (): ResultSet 100% (1/1)100% (3/3)100% (1/1)
getNumericRepresentationOfSQLBitType (int): long 100% (1/1)100% (82/82)100% (12/12)
getObject (String): Object 100% (1/1)100% (6/6)100% (1/1)
getRef (int): Ref 100% (1/1)100% (7/7)100% (2/2)
getServerInfo (): String 100% (1/1)100% (3/3)100% (1/1)
getShort (String): short 100% (1/1)100% (6/6)100% (1/1)
getString (String): String 100% (1/1)100% (6/6)100% (1/1)
getString (int): String 100% (1/1)100% (5/5)100% (1/1)
getTime (String): Time 100% (1/1)100% (6/6)100% (1/1)
getTime (int): Time 100% (1/1)100% (8/8)100% (1/1)
getTime (int, Calendar): Time 100% (1/1)100% (8/8)100% (1/1)
getTimeInternal (int, Calendar, TimeZone, boolean): Time 100% (1/1)100% (23/23)100% (4/4)
getTimestamp (String): Timestamp 100% (1/1)100% (6/6)100% (1/1)
getTimestamp (int): Timestamp 100% (1/1)100% (8/8)100% (1/1)
getTimestamp (int, Calendar): Timestamp 100% (1/1)100% (8/8)100% (1/1)
getTimestampInternal (int, Calendar, TimeZone, boolean): Timestamp 100% (1/1)100% (23/23)100% (4/4)
getType (): int 100% (1/1)100% (3/3)100% (1/1)
getUnicodeStream (int): InputStream 100% (1/1)100% (13/13)100% (4/4)
getUpdateCount (): long 100% (1/1)100% (3/3)100% (1/1)
getUpdateID (): long 100% (1/1)100% (3/3)100% (1/1)
getWarnings (): SQLWarning 100% (1/1)100% (3/3)100% (1/1)
isAfterLast (): boolean 100% (1/1)100% (8/8)100% (3/3)
isBeforeFirst (): boolean 100% (1/1)100% (6/6)100% (2/2)
isFirst (): boolean 100% (1/1)100% (6/6)100% (2/2)
isLast (): boolean 100% (1/1)100% (6/6)100% (2/2)
reallyResult (): boolean 100% (1/1)100% (8/8)100% (3/3)
redefineFieldsForDBMD (Field []): void 100% (1/1)100% (19/19)100% (4/4)
setBinaryEncoded (): void 100% (1/1)100% (4/4)100% (2/2)
setDefaultTimeZone (TimeZone): void 100% (1/1)100% (4/4)100% (2/2)
setFetchSize (int): void 100% (1/1)100% (11/11)100% (4/4)
setFirstCharOfQuery (char): void 100% (1/1)100% (4/4)100% (2/2)
setNextResultSet (ResultSet): void 100% (1/1)100% (4/4)100% (2/2)
setOwningStatement (Statement): void 100% (1/1)100% (4/4)100% (2/2)
setResultSetConcurrency (int): void 100% (1/1)100% (4/4)100% (2/2)
setResultSetType (int): void 100% (1/1)100% (4/4)100% (2/2)
setServerInfo (String): void 100% (1/1)100% (4/4)100% (2/2)
setWrapperStatement (Statement): void 100% (1/1)100% (4/4)100% (2/2)
wasNull (): boolean 100% (1/1)100% (3/3)100% (1/1)

1/*
2 Copyright (C) 2002-2004 MySQL AB
3 
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of version 2 of the GNU General Public License as
6 published by the Free Software Foundation.
7 
8 There are special exceptions to the terms and conditions of the GPL
9 as it is applied to this software. View the full text of the
10 exception in file EXCEPTIONS-CONNECTOR-J in the directory of this
11 software distribution.
12 
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 GNU General Public License for more details.
17 
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21 
22 
23 
24 */
25package com.mysql.jdbc;
26 
27import com.mysql.jdbc.profiler.ProfileEventSink;
28import com.mysql.jdbc.profiler.ProfilerEvent;
29 
30import java.io.ByteArrayInputStream;
31import java.io.IOException;
32import java.io.InputStream;
33import java.io.ObjectInputStream;
34import java.io.StringReader;
35import java.io.UnsupportedEncodingException;
36 
37import java.math.BigDecimal;
38import java.math.BigInteger;
39 
40import java.net.MalformedURLException;
41import java.net.URL;
42 
43import java.sql.Array;
44import java.sql.DataTruncation;
45import java.sql.Date;
46import java.sql.Ref;
47import java.sql.SQLException;
48import java.sql.SQLWarning;
49import java.sql.Time;
50import java.sql.Timestamp;
51import java.sql.Types;
52 
53import java.util.Calendar;
54import java.util.GregorianCalendar;
55import java.util.HashMap;
56import java.util.Locale;
57import java.util.Map;
58import java.util.StringTokenizer;
59import java.util.TimeZone;
60 
61/**
62 * A ResultSet provides access to a table of data generated by executing a
63 * Statement. The table rows are retrieved in sequence. Within a row its column
64 * values can be accessed in any order.
65 * 
66 * <P>
67 * A ResultSet maintains a cursor pointing to its current row of data. Initially
68 * the cursor is positioned before the first row. The 'next' method moves the
69 * cursor to the next row.
70 * </p>
71 * 
72 * <P>
73 * The getXXX methods retrieve column values for the current row. You can
74 * retrieve values either using the index number of the column, or by using the
75 * name of the column. In general using the column index will be more efficient.
76 * Columns are numbered from 1.
77 * </p>
78 * 
79 * <P>
80 * For maximum portability, ResultSet columns within each row should be read in
81 * left-to-right order and each column should be read only once.
82 * </p>
83 * 
84 * <P>
85 * For the getXXX methods, the JDBC driver attempts to convert the underlying
86 * data to the specified Java type and returns a suitable Java value. See the
87 * JDBC specification for allowable mappings from SQL types to Java types with
88 * the ResultSet getXXX methods.
89 * </p>
90 * 
91 * <P>
92 * Column names used as input to getXXX methods are case insenstive. When
93 * performing a getXXX using a column name, if several columns have the same
94 * name, then the value of the first matching column will be returned. The
95 * column name option is designed to be used when column names are used in the
96 * SQL Query. For columns that are NOT explicitly named in the query, it is best
97 * to use column numbers. If column names were used there is no way for the
98 * programmer to guarentee that they actually refer to the intended columns.
99 * </p>
100 * 
101 * <P>
102 * A ResultSet is automatically closed by the Statement that generated it when
103 * that Statement is closed, re-executed, or is used to retrieve the next result
104 * from a sequence of multiple results.
105 * </p>
106 * 
107 * <P>
108 * The number, types and properties of a ResultSet's columns are provided by the
109 * ResultSetMetaData object returned by the getMetaData method.
110 * </p>
111 * 
112 * @author Mark Matthews
113 * @version $Id: ResultSet.java 5526 2006-07-18 18:01:22 +0000 (Tue, 18 Jul 2006) mmatthews $
114 * 
115 * @see ResultSetMetaData
116 * @see java.sql.ResultSet
117 */
118public class ResultSet implements java.sql.ResultSet {
119 
120        /**
121         * Epsillon between Float.MIN_VALUE and the double representation of said value.
122         */
123    protected static final double MIN_DIFF_PREC = Float.parseFloat(Float.toString(Float.MIN_VALUE))
124        - Double.parseDouble(Float.toString(Float.MIN_VALUE));
125    
126    /**
127         * Epsillon between Float.MAX_VALUE and the double representation of said value.
128         */
129    protected static final double MAX_DIFF_PREC = Float.parseFloat(Float.toString(Float.MAX_VALUE))
130        - Double.parseDouble(Float.toString(Float.MAX_VALUE));
131    
132        /** Counter used to generate IDs for profiling. */
133        protected static int resultCounter = 1;
134 
135        /**
136         * Converts the given value as a java long, to an 'unsigned' long, using the
137         * java.math.BigInteger class.
138         */
139        protected static BigInteger convertLongToUlong(long longVal) {
140                byte[] asBytes = new byte[8];
141                asBytes[7] = (byte) (longVal & 0xff);
142                asBytes[6] = (byte) (longVal >>> 8);
143                asBytes[5] = (byte) (longVal >>> 16);
144                asBytes[4] = (byte) (longVal >>> 24);
145                asBytes[3] = (byte) (longVal >>> 32);
146                asBytes[2] = (byte) (longVal >>> 40);
147                asBytes[1] = (byte) (longVal >>> 48);
148                asBytes[0] = (byte) (longVal >>> 56);
149 
150                return new BigInteger(1, asBytes);
151        }
152 
153        /** The catalog that was in use when we were created */
154        protected String catalog = null;
155 
156        /** Map column names (and all of their permutations) to column indices */
157        protected Map columnNameToIndex = null;
158 
159        /** Keep track of columns accessed */
160        protected boolean[] columnUsed = null;
161 
162        /** The Connection instance that created us */
163        protected com.mysql.jdbc.Connection connection; // The connection that
164                                                                                                        // created us
165 
166        protected long connectionId = 0;
167        
168        /** The current row #, -1 == before start of result set */
169        protected int currentRow = -1; // Cursor to current row;
170 
171        private TimeZone defaultTimeZone;
172 
173        /** Are we in the middle of doing updates to the current row? */
174        protected boolean doingUpdates = false;
175 
176        protected ProfileEventSink eventSink = null;
177 
178        private Calendar fastDateCal = null;
179 
180        /** The direction to fetch rows (always FETCH_FORWARD) */
181        protected int fetchDirection = FETCH_FORWARD;
182 
183        /** The number of rows to fetch in one go... */
184        protected int fetchSize = 0;
185 
186        /** The fields for this result set */
187        protected Field[] fields; // The fields
188 
189        /**
190         * First character of the query that created this result set...Used to
191         * determine whether or not to parse server info messages in certain
192         * circumstances.
193         */
194        protected char firstCharOfQuery;
195 
196        /** Map of fully-specified column names to column indices */
197        protected Map fullColumnNameToIndex = null;
198 
199        protected boolean hasBuiltIndexMapping = false;
200 
201        /**
202         * Is the data stored as strings (default) or natively (which is the case
203         * with results from PrepStmts)
204         */
205        protected boolean isBinaryEncoded = false;
206 
207        /** Has this result set been closed? */
208        protected boolean isClosed = false;
209 
210        protected ResultSet nextResultSet = null;
211 
212        /** Are we on the insert row? */
213        protected boolean onInsertRow = false;
214 
215        /** The statement that created us */
216        protected com.mysql.jdbc.Statement owningStatement;
217 
218        /**
219         * StackTrace generated where ResultSet was created... used when profiling
220         */
221        protected Throwable pointOfOrigin;
222 
223        /** Are we tracking items for profileSql? */
224        protected boolean profileSql = false;
225 
226        /**
227         * Do we actually contain rows, or just information about
228         * UPDATE/INSERT/DELETE?
229         */
230        protected boolean reallyResult = false;
231 
232        /** The id (used when profiling) to identify us */
233        protected int resultId;
234 
235        /** Are we read-only or updatable? */
236        protected int resultSetConcurrency = 0;
237 
238        /** Are we scroll-sensitive/insensitive? */
239        protected int resultSetType = 0;
240 
241        /** The actual rows */
242        protected RowData rowData; // The results
243 
244        /**
245         * Any info message from the server that was created while generating this
246         * result set (if 'info parsing' is enabled for the connection).
247         */
248        protected String serverInfo = null;
249 
250        private PreparedStatement statementUsedForFetchingRows;
251 
252        /** Pointer to current row data */
253        protected Object[] thisRow = null; // Values for current row
254 
255        // These are longs for
256        // recent versions of the MySQL server.
257        //
258        // They get reduced to ints via the JDBC API,
259        // but can be retrieved through a MySQLStatement
260        // in their entirety.
261        //
262 
263        /** How many rows were affected by UPDATE/INSERT/DELETE? */
264        protected long updateCount;
265 
266        /** Value generated for AUTO_INCREMENT columns */
267        protected long updateId = -1;
268 
269        private boolean useStrictFloatingPoint = false;
270 
271        protected boolean useUsageAdvisor = false;
272 
273        /** The warning chain */
274        protected java.sql.SQLWarning warningChain = null;
275 
276        /** Did the previous value retrieval find a NULL? */
277        protected boolean wasNullFlag = false;
278 
279        protected java.sql.Statement wrapperStatement;
280 
281        protected boolean retainOwningStatement;
282 
283        protected Calendar gmtCalendar = null;
284 
285        /**
286         * Create a result set for an executeUpdate statement.
287         * 
288         * @param updateCount
289         *            the number of rows affected by the update
290         * @param updateID
291         *            the autoincrement value (if any)
292         * @param conn
293         *            DOCUMENT ME!
294         * @param creatorStmt
295         *            DOCUMENT ME!
296         */
297        public ResultSet(long updateCount, long updateID, Connection conn,
298                        Statement creatorStmt) {
299                this.updateCount = updateCount;
300                this.updateId = updateID;
301                this.reallyResult = false;
302                this.fields = new Field[0];
303 
304                this.connection = conn;
305                this.owningStatement = creatorStmt;
306                
307                this.retainOwningStatement = false;
308                
309                if (this.connection != null) {
310                        this.retainOwningStatement = 
311                                this.connection.getRetainStatementAfterResultSetClose();
312                        
313                        this.connectionId = this.connection.getId();
314                }
315        }
316 
317        /**
318         * Creates a new ResultSet object.
319         * 
320         * @param catalog
321         *            the database in use when we were created
322         * @param fields
323         *            an array of Field objects (basically, the ResultSet MetaData)
324         * @param tuples
325         *            actual row data
326         * @param conn
327         *            the Connection that created us.
328         * @param creatorStmt
329         *            DOCUMENT ME!
330         * 
331         * @throws SQLException
332         *             if an error occurs
333         */
334        public ResultSet(String catalog, Field[] fields, RowData tuples,
335                        Connection conn, Statement creatorStmt) throws SQLException {
336                this.connection = conn;
337                
338                this.fastDateCal = new GregorianCalendar(Locale.US);
339                this.fastDateCal.setTimeZone(this.getDefaultTimeZone());
340                
341                if (this.connection != null) {
342                        this.useStrictFloatingPoint = this.connection
343                                        .getStrictFloatingPoint();
344                        this.setDefaultTimeZone(this.connection.getDefaultTimeZone());
345                        this.connectionId = this.connection.getId();
346                }
347 
348                this.owningStatement = creatorStmt;
349 
350                this.catalog = catalog;
351                this.profileSql = this.connection.getProfileSql();
352 
353                this.fields = fields;
354                this.rowData = tuples;
355                this.updateCount = this.rowData.size();
356 
357                if (Driver.DEBUG) {
358                        System.out.println(Messages.getString("ResultSet.Retrieved__1")
359                                        + this.updateCount + " rows"); //$NON-NLS-1$
360                }
361 
362                this.reallyResult = true;
363 
364                // Check for no results
365                if (this.rowData.size() > 0) {
366                        if (this.updateCount == 1) {
367                                if (this.thisRow == null) {
368                                        this.rowData.close(); // empty result set
369                                        this.updateCount = -1;
370                                }
371                        }
372                } else {
373                        this.thisRow = null;
374                }
375 
376                this.rowData.setOwner(this);
377 
378                if (this.profileSql || this.connection.getUseUsageAdvisor()) {
379                        this.columnUsed = new boolean[this.fields.length];
380                        this.pointOfOrigin = new Throwable();
381                        this.resultId = resultCounter++;
382                        this.useUsageAdvisor = this.connection.getUseUsageAdvisor();
383                        this.eventSink = ProfileEventSink.getInstance(this.connection);
384                }
385 
386                if (this.connection.getGatherPerformanceMetrics()) {
387                        this.connection.incrementNumberOfResultSetsCreated();
388 
389                        Map tableNamesMap = new HashMap();
390 
391                        for (int i = 0; i < this.fields.length; i++) {
392                                Field f = this.fields[i];
393 
394                                String tableName = f.getOriginalTableName();
395 
396                                if (tableName == null) {
397                                        tableName = f.getTableName();
398                                }
399 
400                                if (tableName != null) {
401                                        if (this.connection.lowerCaseTableNames()) {
402                                                tableName = tableName.toLowerCase(); // on windows, table
403                                                // names are not case-sens.
404                                        }
405 
406                                        tableNamesMap.put(tableName, null);
407                                }
408                        }
409 
410                        this.connection.reportNumberOfTablesAccessed(tableNamesMap.size());
411                }
412                
413                this.retainOwningStatement = false;
414                
415                if (this.connection != null) {
416                        retainOwningStatement = 
417                                this.connection.getRetainStatementAfterResultSetClose();
418                }
419        }
420 
421        /**
422         * JDBC 2.0
423         * 
424         * <p>
425         * Move to an absolute row number in the result set.
426         * </p>
427         * 
428         * <p>
429         * If row is positive, moves to an absolute row with respect to the
430         * beginning of the result set. The first row is row 1, the second is row 2,
431         * etc.
432         * </p>
433         * 
434         * <p>
435         * If row is negative, moves to an absolute row position with respect to the
436         * end of result set. For example, calling absolute(-1) positions the cursor
437         * on the last row, absolute(-2) indicates the next-to-last row, etc.
438         * </p>
439         * 
440         * <p>
441         * An attempt to position the cursor beyond the first/last row in the result
442         * set, leaves the cursor before/after the first/last row, respectively.
443         * </p>
444         * 
445         * <p>
446         * Note: Calling absolute(1) is the same as calling first(). Calling
447         * absolute(-1) is the same as calling last().
448         * </p>
449         * 
450         * @param row
451         *            the row number to move to
452         * 
453         * @return true if on the result set, false if off.
454         * 
455         * @exception SQLException
456         *                if a database-access error occurs, or row is 0, or result
457         *                set type is TYPE_FORWARD_ONLY.
458         */
459        public boolean absolute(int row) throws SQLException {
460                checkClosed();
461 
462                boolean b;
463 
464                if (this.rowData.size() == 0) {
465                        b = false;
466                } else {
467                        if (row == 0) {
468                                throw SQLError.createSQLException(
469                                                Messages
470                                                                .getString("ResultSet.Cannot_absolute_position_to_row_0_110"), //$NON-NLS-1$
471                                                SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
472                        }
473 
474                        if (this.onInsertRow) {
475                                this.onInsertRow = false;
476                        }
477 
478                        if (this.doingUpdates) {
479                                this.doingUpdates = false;
480                        }
481 
482                        if (row == 1) {
483                                b = first();
484                        } else if (row == -1) {
485                                b = last();
486                        } else if (row > this.rowData.size()) {
487                                afterLast();
488                                b = false;
489                        } else {
490                                if (row < 0) {
491                                        // adjust to reflect after end of result set
492                                        int newRowPosition = this.rowData.size() + row + 1;
493 
494                                        if (newRowPosition <= 0) {
495                                                beforeFirst();
496                                                b = false;
497                                        } else {
498                                                b = absolute(newRowPosition);
499                                        }
500                                } else {
501                                        row--; // adjust for index difference
502                                        this.rowData.setCurrentRow(row);
503                                        this.thisRow = this.rowData.getAt(row);
504                                        b = true;
505                                }
506                        }
507                }
508 
509                return b;
510        }
511 
512        /**
513         * JDBC 2.0
514         * 
515         * <p>
516         * Moves to the end of the result set, just after the last row. Has no
517         * effect if the result set contains no rows.
518         * </p>
519         * 
520         * @exception SQLException
521         *                if a database-access error occurs, or result set type is
522         *                TYPE_FORWARD_ONLY.
523         */
524        public void afterLast() throws SQLException {
525                checkClosed();
526 
527                if (this.onInsertRow) {
528                        this.onInsertRow = false;
529                }
530 
531                if (this.doingUpdates) {
532                        this.doingUpdates = false;
533                }
534 
535                if (this.rowData.size() != 0) {
536                        this.rowData.afterLast();
537                        this.thisRow = null;
538                }
539        }
540 
541        /**
542         * JDBC 2.0
543         * 
544         * <p>
545         * Moves to the front of the result set, just before the first row. Has no
546         * effect if the result set contains no rows.
547         * </p>
548         * 
549         * @exception SQLException
550         *                if a database-access error occurs, or result set type is
551         *                TYPE_FORWARD_ONLY
552         */
553        public void beforeFirst() throws SQLException {
554                checkClosed();
555 
556                if (this.onInsertRow) {
557                        this.onInsertRow = false;
558                }
559 
560                if (this.doingUpdates) {
561                        this.doingUpdates = false;
562                }
563 
564                if (this.rowData.size() == 0) {
565                        return;
566                }
567 
568                this.rowData.beforeFirst();
569                this.thisRow = null;
570        }
571 
572        // ---------------------------------------------------------------------
573        // Traversal/Positioning
574        // ---------------------------------------------------------------------
575 
576        /**
577         * Builds a hash between column names and their indices for fast retrieval.
578         */
579        protected void buildIndexMapping() throws SQLException {
580                int numFields = this.fields.length;
581                this.columnNameToIndex = new HashMap(numFields);
582                this.fullColumnNameToIndex = new HashMap(numFields);
583 
584                // We do this in reverse order, so that the 'first' column
585                // with a given name ends up as the final mapping in the
586                // hashtable...
587                //
588                // Quoting the JDBC Spec:
589                //
590                // "Column names used as input to getter
591                // methods are case insensitive. When a getter method is called with a
592                // column
593                // name and several columns have the same name, the value of the first
594                // matching column will be returned. "
595                //
596                for (int i = numFields - 1; i >= 0; i--) {
597                        Integer index = new Integer(i);
598                        String columnName = this.fields[i].getName();
599                        String fullColumnName = this.fields[i].getFullName();
600 
601                        if (columnName != null) {
602                                this.columnNameToIndex.put(columnName, index);
603                                this.columnNameToIndex.put(columnName.toUpperCase(), index);
604                                this.columnNameToIndex.put(columnName.toLowerCase(), index);
605                        }
606 
607                        if (fullColumnName != null) {
608                                this.fullColumnNameToIndex.put(fullColumnName, index);
609                                this.fullColumnNameToIndex.put(fullColumnName.toUpperCase(),
610                                                index);
611                                this.fullColumnNameToIndex.put(fullColumnName.toLowerCase(),
612                                                index);
613                        }
614                }
615 
616                // set the flag to prevent rebuilding...
617                this.hasBuiltIndexMapping = true;
618        }
619 
620        /**
621         * JDBC 2.0 The cancelRowUpdates() method may be called after calling an
622         * updateXXX() method(s) and before calling updateRow() to rollback the
623         * updates made to a row. If no updates have been made or updateRow() has
624         * already been called, then this method has no effect.
625         * 
626         * @exception SQLException
627         *                if a database-access error occurs, or if called when on
628         *                the insert row.
629         * @throws NotUpdatable
630         *             DOCUMENT ME!
631         */
632        public void cancelRowUpdates() throws SQLException {
633                throw new NotUpdatable();
634        }
635 
636        /**
637         * Ensures that the result set is not closed
638         * 
639         * @throws SQLException
640         *             if the result set is closed
641         */
642        protected final void checkClosed() throws SQLException {
643                if (this.isClosed) {
644                        throw SQLError.createSQLException(
645                                        Messages
646                                                        .getString("ResultSet.Operation_not_allowed_after_ResultSet_closed_144"), //$NON-NLS-1$
647                                        SQLError.SQL_STATE_GENERAL_ERROR);
648                }
649        }
650 
651        /**
652         * Checks if columnIndex is within the number of columns in this result set.
653         * 
654         * @param columnIndex
655         *            the index to check
656         * 
657         * @throws SQLException
658         *             if the index is out of bounds
659         */
660        protected final void checkColumnBounds(int columnIndex) throws SQLException {
661                if ((columnIndex < 1) || (columnIndex > this.fields.length)) {
662                        throw SQLError.createSQLException(Messages.getString(
663                                        "ResultSet.Column_Index_out_of_range", new Object[] {
664                                                        new Integer(columnIndex),
665                                                        new Integer(this.fields.length) }),
666                                        SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$
667                }
668 
669                if (this.profileSql || this.useUsageAdvisor) {
670                        this.columnUsed[columnIndex - 1] = true;
671                }
672        }
673 
674        /**
675         * Ensures that the cursor is positioned on a valid row and that the result
676         * set is not closed
677         * 
678         * @throws SQLException
679         *             if the result set is not in a valid state for traversal
680         */
681        protected void checkRowPos() throws SQLException {
682                checkClosed();
683 
684                if (!this.rowData.isDynamic() && (this.rowData.size() == 0)) {
685                        throw SQLError.createSQLException(
686                                        Messages
687                                                        .getString("ResultSet.Illegal_operation_on_empty_result_set"),
688                                        SQLError.SQL_STATE_GENERAL_ERROR);
689                }
690 
691                if (this.rowData.isBeforeFirst()) {
692                        throw SQLError.createSQLException(Messages
693                                        .getString("ResultSet.Before_start_of_result_set_146"),
694                                        SQLError.SQL_STATE_GENERAL_ERROR); //$NON-NLS-1$
695                }
696 
697                if (this.rowData.isAfterLast()) {
698                        throw SQLError.createSQLException(Messages
699                                        .getString("ResultSet.After_end_of_result_set_148"),
700                                        SQLError.SQL_STATE_GENERAL_ERROR); //$NON-NLS-1$
701                }
702        }
703 
704        /**
705         * We can't do this ourselves, otherwise the contract for
706         * Statement.getMoreResults() won't work correctly.
707         */
708        protected void clearNextResult() {
709                this.nextResultSet = null;
710        }
711 
712        /**
713         * After this call, getWarnings returns null until a new warning is reported
714         * for this ResultSet
715         * 
716         * @exception SQLException
717         *                if a database access error occurs
718         */
719        public void clearWarnings() throws SQLException {
720                this.warningChain = null;
721        }
722 
723        /**
724         * In some cases, it is desirable to immediately release a ResultSet
725         * database and JDBC resources instead of waiting for this to happen when it
726         * is automatically closed. The close method provides this immediate
727         * release.
728         * 
729         * <p>
730         * <B>Note:</B> A ResultSet is automatically closed by the Statement the
731         * Statement that generated it when that Statement is closed, re-executed,
732         * or is used to retrieve the next result from a sequence of multiple
733         * results. A ResultSet is also automatically closed when it is garbage
734         * collected.
735         * </p>
736         * 
737         * @exception SQLException
738         *                if a database access error occurs
739         */
740        public void close() throws SQLException {
741                realClose(true);
742        }
743 
744        /**
745         * @return
746         */
747        private int convertToZeroWithEmptyCheck() throws SQLException {
748                if (this.connection.getEmptyStringsConvertToZero()) {
749                        return 0;
750                }
751 
752                throw SQLError.createSQLException("Can't convert empty string ('') to numeric",
753                                SQLError.SQL_STATE_INVALID_CHARACTER_VALUE_FOR_CAST);
754        }
755        
756        private String convertToZeroLiteralStringWithEmptyCheck()
757                throws SQLException {
758                
759                if (this.connection.getEmptyStringsConvertToZero()) {
760                        return "0";
761                }
762 
763                throw SQLError.createSQLException("Can't convert empty string ('') to numeric",
764                                SQLError.SQL_STATE_INVALID_CHARACTER_VALUE_FOR_CAST);
765        }
766 
767        //
768        // Note, row data is linked between these two result sets
769        //
770        protected final ResultSet copy() throws SQLException {
771                ResultSet rs = new ResultSet(this.catalog, this.fields, this.rowData,
772                                this.connection, this.owningStatement);
773 
774                return rs;
775        }
776 
777        protected void redefineFieldsForDBMD(Field[] f) {
778                this.fields = f;
779                
780                for (int i = 0; i < this.fields.length; i++) {
781                        this.fields[i].setUseOldNameMetadata(true);
782                }
783        }
784 
785        /**
786         * JDBC 2.0 Delete the current row from the result set and the underlying
787         * database. Cannot be called when on the insert row.
788         * 
789         * @exception SQLException
790         *                if a database-access error occurs, or if called when on
791         *                the insert row.
792         * @throws NotUpdatable
793         *             DOCUMENT ME!
794         */
795        public void deleteRow() throws SQLException {
796                throw new NotUpdatable();
797        }
798 
799        /**
800         * @param columnIndex
801         * @param stringVal
802         * @param mysqlType
803         * @return
804         * @throws SQLException
805         */
806        private String extractStringFromNativeColumn(int columnIndex, int mysqlType)
807                        throws SQLException {
808                int columnIndexMinusOne = columnIndex - 1;
809 
810                this.wasNullFlag = false;
811                
812                if (this.thisRow[columnIndexMinusOne] instanceof String) {
813                        return (String) this.thisRow[columnIndexMinusOne];
814                }
815 
816                if (this.thisRow[columnIndexMinusOne] == null) {
817                        this.wasNullFlag = true;
818                        
819                        return null;
820                }
821 
822                this.wasNullFlag = false;
823                
824                String stringVal = null;
825 
826                if ((this.connection != null) && this.connection.getUseUnicode()) {
827                        try {
828                                String encoding = this.fields[columnIndexMinusOne]
829                                                .getCharacterSet();
830 
831                                if (encoding == null) {
832                                        stringVal = new String(
833                                                        (byte[]) this.thisRow[columnIndexMinusOne]);
834                                } else {
835                                        SingleByteCharsetConverter converter = this.connection
836                                                        .getCharsetConverter(encoding);
837 
838                                        if (converter != null) {
839                                                stringVal = converter
840                                                                .toString((byte[]) this.thisRow[columnIndexMinusOne]);
841                                        } else {
842                                                stringVal = new String(
843                                                                (byte[]) this.thisRow[columnIndexMinusOne],
844                                                                encoding);
845                                        }
846                                }
847                        } catch (java.io.UnsupportedEncodingException E) {
848                                throw SQLError.createSQLException(
849                                                Messages
850                                                                .getString("ResultSet.Unsupported_character_encoding____138") //$NON-NLS-1$
851                                                                + this.connection.getEncoding() + "'.", "0S100");
852                        }
853                } else {
854                        stringVal = StringUtils
855                                        .toAsciiString((byte[]) this.thisRow[columnIndexMinusOne]);
856                }
857                
858                return stringVal;
859        }
860 
861        private Date fastDateCreate(Calendar cal, int year, int month,
862                        int day) {
863                if (cal == null) {
864                        cal = this.fastDateCal;
865                }
866 
867                boolean useGmtMillis = this.connection.getUseGmtMillisForDatetimes();
868                                                
869                return TimeUtil.fastDateCreate(useGmtMillis,
870                                useGmtMillis ? getGmtCalendar() : null,
871                                cal, year, month, day);
872        }
873 
874        private Time fastTimeCreate(Calendar cal, int hour,
875                        int minute, int second) {
876                if (cal == null) {
877                        cal = this.fastDateCal;
878                }
879 
880                return TimeUtil.fastTimeCreate(cal, hour, minute, second);
881        }
882 
883        private Timestamp fastTimestampCreate(Calendar cal, int year,
884                        int month, int day, int hour, int minute, int seconds,
885                        int secondsPart) {
886                if (cal == null) {
887                        cal = this.fastDateCal;
888                }
889 
890                boolean useGmtMillis = this.connection.getUseGmtMillisForDatetimes();
891                
892                return TimeUtil.fastTimestampCreate(useGmtMillis,
893                                useGmtMillis ? getGmtCalendar() : null,
894                                cal, year, month, day, hour,
895                                minute, seconds, secondsPart);
896        }
897 
898        /*
899        /**
900         * Required by JDBC spec
901         */
902        /*
903        protected void finalize() throws Throwable {
904                if (!this.isClosed) {
905                        realClose(false);
906                }
907        }
908        */
909 
910        // --------------------------JDBC 2.0-----------------------------------
911        // ---------------------------------------------------------------------
912        // Getter's and Setter's
913        // ---------------------------------------------------------------------
914 
915 
916        /**
917         * Map a ResultSet column name to a ResultSet column index
918         * 
919         * @param columnName
920         *            the name of the column
921         * 
922         * @return the column index
923         * 
924         * @exception SQLException
925         *                if a database access error occurs
926         */
927        public synchronized int findColumn(String columnName) throws SQLException {
928                Integer index;
929 
930                if (!this.hasBuiltIndexMapping) {
931                        buildIndexMapping();
932                }
933 
934                index = (Integer) this.columnNameToIndex.get(columnName);
935 
936                if (index == null) {
937                        index = (Integer) this.fullColumnNameToIndex.get(columnName);
938                }
939 
940                if (index != null) {
941                        return index.intValue() + 1;
942                }
943 
944                // Try this inefficient way, now
945 
946                for (int i = 0; i < this.fields.length; i++) {
947                        if (this.fields[i].getName().equalsIgnoreCase(columnName)) {
948                                return i + 1;
949                        } else if (this.fields[i].getFullName()
950                                        .equalsIgnoreCase(columnName)) {
951                                return i + 1;
952                        }
953                }
954 
955                throw SQLError.createSQLException(Messages.getString("ResultSet.Column____112")
956                                + columnName
957                                + Messages.getString("ResultSet.___not_found._113"), //$NON-NLS-1$ //$NON-NLS-2$
958                                SQLError.SQL_STATE_COLUMN_NOT_FOUND);
959        }
960 
961        /**
962         * JDBC 2.0
963         * 
964         * <p>
965         * Moves to the first row in the result set.
966         * </p>
967         * 
968         * @return true if on a valid row, false if no rows in the result set.
969         * 
970         * @exception SQLException
971         *                if a database-access error occurs, or result set type is
972         *                TYPE_FORWARD_ONLY.
973         */
974        public boolean first() throws SQLException {
975                checkClosed();
976 
977                if (this.rowData.isEmpty()) {
978                        return false;
979                }
980 
981                if (this.onInsertRow) {
982                        this.onInsertRow = false;
983                }
984 
985                if (this.doingUpdates) {
986                        this.doingUpdates = false;
987                }
988 
989                this.rowData.beforeFirst();
990                this.thisRow = this.rowData.next();
991 
992                return true;
993        }
994 
995        /**
996         * JDBC 2.0 Get an array column.
997         * 
998         * @param i
999         *            the first column is 1, the second is 2, ...
1000         * 
1001         * @return an object representing an SQL array
1002         * 
1003         * @throws SQLException
1004         *             if a database error occurs
1005         * @throws NotImplemented
1006         *             DOCUMENT ME!
1007         */
1008        public java.sql.Array getArray(int i) throws SQLException {
1009                checkColumnBounds(i);
1010                
1011                throw new NotImplemented();
1012        }
1013 
1014        /**
1015         * JDBC 2.0 Get an array column.
1016         * 
1017         * @param colName
1018         *            the column name
1019         * 
1020         * @return an object representing an SQL array
1021         * 
1022         * @throws SQLException
1023         *             if a database error occurs
1024         * @throws NotImplemented
1025         *             DOCUMENT ME!
1026         */
1027        public java.sql.Array getArray(String colName) throws SQLException {
1028                return getArray(findColumn(colName));
1029        }
1030 
1031        /**
1032         * A column value can be retrieved as a stream of ASCII characters and then
1033         * read in chunks from the stream. This method is particulary suitable for
1034         * retrieving large LONGVARCHAR values. The JDBC driver will do any
1035         * necessary conversion from the database format into ASCII.
1036         * 
1037         * <p>
1038         * <B>Note:</B> All the data in the returned stream must be read prior to
1039         * getting the value of any other column. The next call to a get method
1040         * implicitly closes the stream. Also, a stream may return 0 for available()
1041         * whether there is data available or not.
1042         * </p>
1043         * 
1044         * @param columnIndex
1045         *            the first column is 1, the second is 2, ...
1046         * 
1047         * @return a Java InputStream that delivers the database column value as a
1048         *         stream of one byte ASCII characters. If the value is SQL NULL
1049         *         then the result is null
1050         * 
1051         * @exception SQLException
1052         *                if a database access error occurs
1053         * 
1054         * @see getBinaryStream
1055         */
1056        public InputStream getAsciiStream(int columnIndex) throws SQLException {
1057                checkRowPos();
1058 
1059                if (!this.isBinaryEncoded) {
1060                        return getBinaryStream(columnIndex);
1061                }
1062 
1063                return getNativeBinaryStream(columnIndex);
1064        }
1065 
1066        /**
1067         * DOCUMENT ME!
1068         * 
1069         * @param columnName
1070         *            DOCUMENT ME!
1071         * 
1072         * @return DOCUMENT ME!
1073         * 
1074         * @throws SQLException
1075         *             DOCUMENT ME!
1076         */
1077        public InputStream getAsciiStream(String columnName) throws SQLException {
1078                return getAsciiStream(findColumn(columnName));
1079        }
1080 
1081        /**
1082         * JDBC 2.0 Get the value of a column in the current row as a
1083         * java.math.BigDecimal object.
1084         * 
1085         * @param columnIndex
1086         *            the first column is 1, the second is 2, ...
1087         * 
1088         * @return the column value (full precision); if the value is SQL NULL, the
1089         *         result is null
1090         * 
1091         * @exception SQLException
1092         *                if a database-access error occurs.
1093         */
1094        public BigDecimal getBigDecimal(int columnIndex) throws SQLException {
1095                if (!this.isBinaryEncoded) {
1096                        String stringVal = getString(columnIndex);
1097                        BigDecimal val;
1098 
1099                        if (stringVal != null) {
1100                                if (stringVal.length() == 0) {
1101                                        
1102                                        val = new BigDecimal(
1103                                                        convertToZeroLiteralStringWithEmptyCheck());
1104 
1105                                        return val;
1106                                }
1107 
1108                                try {
1109                                        val = new BigDecimal(stringVal);
1110 
1111                                        return val;
1112                                } catch (NumberFormatException ex) {
1113                                        throw SQLError.createSQLException(Messages
1114                                                        .getString("ResultSet.Bad_format_for_BigDecimal",
1115                                                                        new Object[] { stringVal,
1116                                                                                        new Integer(columnIndex) }),
1117                                                        SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$
1118                                }
1119                        }
1120 
1121                        return null;
1122                }
1123 
1124                return getNativeBigDecimal(columnIndex);
1125        }
1126 
1127        /**
1128         * Get the value of a column in the current row as a java.math.BigDecimal
1129         * object
1130         * 
1131         * @param columnIndex
1132         *            the first column is 1, the second is 2...
1133         * @param scale
1134         *            the number of digits to the right of the decimal
1135         * 
1136         * @return the column value; if the value is SQL NULL, null
1137         * 
1138         * @exception SQLException
1139         *                if a database access error occurs
1140         * 
1141         * @deprecated
1142         */
1143        public BigDecimal getBigDecimal(int columnIndex, int scale)
1144                        throws SQLException {
1145                if (!this.isBinaryEncoded) {
1146                        String stringVal = getString(columnIndex);
1147                        BigDecimal val;
1148 
1149                        if (stringVal != null) {
1150                                if (stringVal.length() == 0) {
1151                                        val = new BigDecimal(
1152                                                        convertToZeroLiteralStringWithEmptyCheck());
1153 
1154                                        try {
1155                                                return val.setScale(scale);
1156                                        } catch (ArithmeticException ex) {
1157                                                try {
1158                                                        return val
1159                                                                        .setScale(scale, BigDecimal.ROUND_HALF_UP);
1160                                                } catch (ArithmeticException arEx) {
1161                                                        throw SQLError.createSQLException(
1162                                                                        Messages
1163                                                                                        .getString("ResultSet.Bad_format_for_BigDecimal____124") //$NON-NLS-1$
1164                                                                                        + stringVal
1165                                                                                        + Messages
1166                                                                                                        .getString("ResultSet.___in_column__125")
1167                                                                                        + columnIndex
1168                                                                                        + "(" //$NON-NLS-1$
1169                                                                                        + this.fields[columnIndex - 1]
1170                                                                                        + ").",
1171                                                                        SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
1172                                                }
1173                                        }
1174                                }
1175 
1176                                try {
1177                                        val = new BigDecimal(stringVal);
1178                                } catch (NumberFormatException ex) {
1179                                        if (this.fields[columnIndex - 1].getMysqlType() == MysqlDefs.FIELD_TYPE_BIT) {
1180                                                long valueAsLong = getNumericRepresentationOfSQLBitType(columnIndex);
1181 
1182                                                val = new BigDecimal(valueAsLong);
1183                                        } else {
1184                                                throw SQLError.createSQLException(Messages
1185                                                        .getString("ResultSet.Bad_format_for_BigDecimal",
1186                                                                        new Object[] { new Integer(columnIndex),
1187                                                                                        stringVal }),
1188                                                        SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$
1189                                                }
1190                                }
1191 
1192                                try {
1193                                        return val.setScale(scale);
1194                                } catch (ArithmeticException ex) {
1195                                        try {
1196                                                return val.setScale(scale, BigDecimal.ROUND_HALF_UP);
1197                                        } catch (ArithmeticException arithEx) {
1198                                                throw SQLError.createSQLException(Messages.getString(
1199                                                                "ResultSet.Bad_format_for_BigDecimal",
1200                                                                new Object[] { new Integer(columnIndex),
1201                                                                                stringVal }),
1202                                                                SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$
1203                                        }
1204                                }
1205                        }
1206 
1207                        return null;
1208                }
1209 
1210                return getNativeBigDecimal(columnIndex, scale);
1211        }
1212 
1213        /**
1214         * JDBC 2.0 Get the value of a column in the current row as a
1215         * java.math.BigDecimal object.
1216         * 
1217         * @param columnName
1218         *            the name of the column to retrieve the value from
1219         * 
1220         * @return the BigDecimal value in the column
1221         * 
1222         * @throws SQLException
1223         *             if an error occurs
1224         */
1225        public BigDecimal getBigDecimal(String columnName) throws SQLException {
1226                return getBigDecimal(findColumn(columnName));
1227        }
1228 
1229        /**
1230         * DOCUMENT ME!
1231         * 
1232         * @param columnName
1233         *            DOCUMENT ME!
1234         * @param scale
1235         *            DOCUMENT ME!
1236         * 
1237         * @return DOCUMENT ME!
1238         * 
1239         * @throws SQLException
1240         *             DOCUMENT ME!
1241         * 
1242         * @deprecated
1243         */
1244        public BigDecimal getBigDecimal(String columnName, int scale)
1245                        throws SQLException {
1246                return getBigDecimal(findColumn(columnName), scale);
1247        }
1248 
1249        private final BigDecimal getBigDecimalFromString(String stringVal,
1250                        int columnIndex, int scale) throws SQLException {
1251                BigDecimal bdVal;
1252 
1253                if (stringVal != null) {
1254                        if (stringVal.length() == 0) {
1255                                bdVal = new BigDecimal(convertToZeroLiteralStringWithEmptyCheck());
1256 
1257                                try {
1258                                        return bdVal.setScale(scale);
1259                                } catch (ArithmeticException ex) {
1260                                        try {
1261                                                return bdVal.setScale(scale, BigDecimal.ROUND_HALF_UP);
1262                                        } catch (ArithmeticException arEx) {
1263                                                throw new SQLException(Messages
1264                                                                .getString("ResultSet.Bad_format_for_BigDecimal",
1265                                                                                new Object[] { stringVal,
1266                                                                                                new Integer(columnIndex) }),
1267                                                                SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$
1268                                        }
1269                                }
1270                        }
1271 
1272                        try {
1273                                try {
1274                                        return new BigDecimal(stringVal).setScale(scale);
1275                                } catch (ArithmeticException ex) {
1276                                        try {
1277                                                return new BigDecimal(stringVal).setScale(scale,
1278                                                                BigDecimal.ROUND_HALF_UP);
1279                                        } catch (ArithmeticException arEx) {
1280                                                throw new SQLException(Messages
1281                                                                .getString("ResultSet.Bad_format_for_BigDecimal",
1282                                                                                new Object[] { stringVal,
1283                                                                                                new Integer(columnIndex) }),
1284                                                                SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$
1285                                        }
1286                                }
1287                        } catch (NumberFormatException ex) {
1288                                if (this.fields[columnIndex - 1].getMysqlType() == MysqlDefs.FIELD_TYPE_BIT) {
1289                                        long valueAsLong = getNumericRepresentationOfSQLBitType(columnIndex);
1290 
1291                                        try {
1292                                                return new BigDecimal(valueAsLong).setScale(scale);
1293                                        } catch (ArithmeticException arEx1) {
1294                                                try {
1295                                                        return new BigDecimal(valueAsLong).setScale(scale,
1296                                                                        BigDecimal.ROUND_HALF_UP);
1297                                                } catch (ArithmeticException arEx2) {
1298                                                        throw new SQLException(Messages
1299                                                                        .getString("ResultSet.Bad_format_for_BigDecimal",
1300                                                                                        new Object[] { stringVal,
1301                                                                                                        new Integer(columnIndex) }),
1302                                                                        SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$
1303                                                }
1304                                        }
1305                                }
1306                                
1307                                if (this.fields[columnIndex - 1].getMysqlType() == MysqlDefs.FIELD_TYPE_TINY &&
1308                                                this.connection.getTinyInt1isBit() && this.fields[columnIndex - 1].getLength() == 1) {
1309                                        return new BigDecimal(stringVal.equalsIgnoreCase("true") ? 1 : 0).setScale(scale);
1310                                }
1311                                
1312                                throw new SQLException(Messages
1313                                                .getString("ResultSet.Bad_format_for_BigDecimal",
1314                                                                new Object[] { stringVal,
1315                                                                                new Integer(columnIndex) }),
1316                                                SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$
1317                        }
1318                }
1319                
1320                return null;
1321        }
1322 
1323        /**
1324         * A column value can also be retrieved as a binary stream. This method is
1325         * suitable for retrieving LONGVARBINARY values.
1326         * 
1327         * @param columnIndex
1328         *            the first column is 1, the second is 2...
1329         * 
1330         * @return a Java InputStream that delivers the database column value as a
1331         *         stream of bytes. If the value is SQL NULL, then the result is
1332         *         null
1333         * 
1334         * @exception SQLException
1335         *                if a database access error occurs
1336         * 
1337         * @see getAsciiStream
1338         * @see getUnicodeStream
1339         */
1340        public InputStream getBinaryStream(int columnIndex) throws SQLException {
1341                checkRowPos();
1342 
1343                if (!this.isBinaryEncoded) {
1344                        byte[] b = getBytes(columnIndex);
1345 
1346                        if (b != null) {
1347                                return new ByteArrayInputStream(b);
1348                        }
1349 
1350                        return null;
1351                }
1352 
1353                return getNativeBinaryStream(columnIndex);
1354        }
1355 
1356        /**
1357         * DOCUMENT ME!
1358         * 
1359         * @param columnName
1360         *            DOCUMENT ME!
1361         * 
1362         * @return DOCUMENT ME!
1363         * 
1364         * @throws SQLException
1365         *             DOCUMENT ME!
1366         */
1367        public InputStream getBinaryStream(String columnName) throws SQLException {
1368                return getBinaryStream(findColumn(columnName));
1369        }
1370 
1371        /**
1372         * JDBC 2.0 Get a BLOB column.
1373         * 
1374         * @param columnIndex
1375         *            the first column is 1, the second is 2, ...
1376         * 
1377         * @return an object representing a BLOB
1378         * 
1379         * @throws SQLException
1380         *             if an error occurs.
1381         */
1382        public java.sql.Blob getBlob(int columnIndex) throws SQLException {
1383                if (!this.isBinaryEncoded) {
1384                        checkRowPos();
1385 
1386                        checkColumnBounds(columnIndex);
1387                        
1388                        if ((columnIndex < 1) || (columnIndex > this.fields.length)) {
1389                                throw SQLError.createSQLException(Messages.getString(
1390                                                "ResultSet.Column_Index_out_of_range", new Object[] {
1391                                                                new Integer(columnIndex),
1392                                                                new Integer(this.fields.length) }),
1393                                                SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$
1394                        }
1395 
1396                        try {
1397                                if (this.thisRow[columnIndex - 1] == null) {
1398                                        this.wasNullFlag = true;
1399                                } else {
1400                                        this.wasNullFlag = false;
1401                                }
1402                        } catch (NullPointerException ex) {
1403                                this.wasNullFlag = true;
1404                        }
1405 
1406                        if (this.wasNullFlag) {
1407                                return null;
1408                        }
1409 
1410                        if (!this.connection.getEmulateLocators()) {
1411                                return new Blob((byte[]) this.thisRow[columnIndex - 1]);
1412                        }
1413 
1414                        return new BlobFromLocator(this, columnIndex);
1415                }
1416 
1417                return getNativeBlob(columnIndex);
1418        }
1419 
1420        /**
1421         * JDBC 2.0 Get a BLOB column.
1422         * 
1423         * @param colName
1424         *            the column name
1425         * 
1426         * @return an object representing a BLOB
1427         * 
1428         * @throws SQLException
1429         *             if an error occurs.
1430         */
1431        public java.sql.Blob getBlob(String colName) throws SQLException {
1432                return getBlob(findColumn(colName));
1433        }
1434 
1435        /**
1436         * Get the value of a column in the current row as a Java boolean
1437         * 
1438         * @param columnIndex
1439         *            the first column is 1, the second is 2...
1440         * 
1441         * @return the column value, false for SQL NULL
1442         * 
1443         * @exception SQLException
1444         *                if a database access error occurs
1445         */
1446        public boolean getBoolean(int columnIndex) throws SQLException {
1447                if (!this.isBinaryEncoded) {
1448                        checkColumnBounds(columnIndex);
1449 
1450                        //
1451                        // MySQL 5.0 and newer have an actual BIT type,
1452                        // so we need to check for that here...
1453                        //
1454 
1455                        int columnIndexMinusOne = columnIndex - 1;
1456 
1457                        Field field = this.fields[columnIndexMinusOne];
1458 
1459                        if (field.getMysqlType() == MysqlDefs.FIELD_TYPE_BIT) {
1460                                if (this.thisRow[columnIndexMinusOne] == null) {
1461                                        this.wasNullFlag = true;
1462 
1463                                        return false;
1464                                }
1465 
1466                                this.wasNullFlag = false;
1467 
1468                                if (((byte[]) this.thisRow[columnIndexMinusOne]).length == 0) {
1469                                        return false;
1470                                }
1471 
1472                                byte boolVal = ((byte[]) this.thisRow[columnIndexMinusOne])[0];
1473 
1474                                return (boolVal > 0);
1475                        }
1476 
1477                        String stringVal = getString(columnIndex);
1478 
1479                        if ((stringVal != null) && (stringVal.length() > 0)) {
1480                                int c = Character.toLowerCase(stringVal.charAt(0));
1481 
1482                                return ((c == 't') || (c == 'y') || (c == '1') || stringVal
1483                                                .equals("-1"));
1484                        }
1485 
1486                        return false;
1487                }
1488 
1489                return getNativeBoolean(columnIndex);
1490        }
1491 
1492        /**
1493         * DOCUMENT ME!
1494         * 
1495         * @param columnName
1496         *            DOCUMENT ME!
1497         * 
1498         * @return DOCUMENT ME!
1499         * 
1500         * @throws SQLException
1501         *             DOCUMENT ME!
1502         */
1503        public boolean getBoolean(String columnName) throws SQLException {
1504                return getBoolean(findColumn(columnName));
1505        }
1506 
1507        private final boolean getBooleanFromString(String stringVal, int columnIndex)
1508                        throws SQLException {
1509                if ((stringVal != null) && (stringVal.length() > 0)) {
1510                        int c = Character.toLowerCase(stringVal.charAt(0));
1511 
1512                        return ((c == 't') || (c == 'y') || (c == '1') || stringVal
1513                                        .equals("-1"));
1514                }
1515 
1516                return false;
1517        }
1518 
1519        /**
1520         * Get the value of a column in the current row as a Java byte.
1521         * 
1522         * @param columnIndex
1523         *            the first column is 1, the second is 2,...
1524         * 
1525         * @return the column value; 0 if SQL NULL
1526         * 
1527         * @exception SQLException
1528         *                if a database access error occurs
1529         */
1530        public byte getByte(int columnIndex) throws SQLException {
1531                if (!this.isBinaryEncoded) {
1532                        String stringVal = getString(columnIndex);
1533 
1534                        if (this.wasNullFlag || (stringVal == null)) {
1535                                return 0;
1536                        }
1537 
1538                        return getByteFromString(stringVal, columnIndex);
1539                }
1540 
1541                return getNativeByte(columnIndex);
1542        }
1543 
1544        /**
1545         * DOCUMENT ME!
1546         * 
1547         * @param columnName
1548         *            DOCUMENT ME!
1549         * 
1550         * @return DOCUMENT ME!
1551         * 
1552         * @throws SQLException
1553         *             DOCUMENT ME!
1554         */
1555        public byte getByte(String columnName) throws SQLException {
1556                return getByte(findColumn(columnName));
1557        }
1558 
1559        private final byte getByteFromString(String stringVal, int columnIndex)
1560                        throws SQLException {
1561 
1562                if (stringVal != null && stringVal.length() == 0) {
1563                        return (byte) convertToZeroWithEmptyCheck();
1564                }
1565 
1566                //
1567                // JDK-6 doesn't like trailing whitespace
1568                //
1569                // Note this isn't a performance issue, other
1570                // than the iteration over the string, as String.trim()
1571                // will return a new string only if whitespace is present
1572                //
1573                
1574                stringVal = stringVal.trim(); 
1575                
1576                try {
1577                        int decimalIndex = stringVal.indexOf(".");
1578 
1579                        
1580                        if (decimalIndex != -1) {
1581                                double valueAsDouble = Double.parseDouble(stringVal);
1582 
1583                                if (this.connection.getJdbcCompliantTruncationForReads()) {
1584                                        if (valueAsDouble < Byte.MIN_VALUE
1585                                                        || valueAsDouble > Byte.MAX_VALUE) {
1586                                                throwRangeException(stringVal, columnIndex,
1587                                                                Types.TINYINT);
1588                                        }
1589                                }
1590 
1591                                return (byte) valueAsDouble;
1592                        }
1593 
1594                        long valueAsLong = Long.parseLong(stringVal);
1595 
1596                        if (this.connection.getJdbcCompliantTruncationForReads()) {
1597                                if (valueAsLong < Byte.MIN_VALUE
1598                                                || valueAsLong > Byte.MAX_VALUE) {
1599                                        throwRangeException(String.valueOf(valueAsLong),
1600                                                        columnIndex, Types.TINYINT);
1601                                }
1602                        }
1603 
1604                        return (byte) valueAsLong;
1605                } catch (NumberFormatException NFE) {
1606                        throw SQLError.createSQLException(
1607                                        Messages.getString("ResultSet.Value____173")
1608                                                        + stringVal //$NON-NLS-1$
1609                                                        + Messages
1610                                                                        .getString("ResultSet.___is_out_of_range_[-127,127]_174"),
1611                                        SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$
1612                }
1613        }
1614 
1615        /**
1616         * Get the value of a column in the current row as a Java byte array.
1617         * 
1618         * <p>
1619         * <b>Be warned</b> If the blob is huge, then you may run out of memory.
1620         * </p>
1621         * 
1622         * @param columnIndex
1623         *            the first column is 1, the second is 2, ...
1624         * 
1625         * @return the column value; if the value is SQL NULL, the result is null
1626         * 
1627         * @exception SQLException
1628         *                if a database access error occurs
1629         */
1630        public byte[] getBytes(int columnIndex) throws SQLException {
1631                return getBytes(columnIndex, false);
1632        }
1633 
1634        protected byte[] getBytes(int columnIndex, boolean noConversion)
1635                        throws SQLException {
1636                if (!this.isBinaryEncoded) {
1637                        checkRowPos();
1638                        
1639                        checkColumnBounds(columnIndex);
1640                        
1641                        try {
1642                                if (this.thisRow[columnIndex - 1] == null) {
1643                                        this.wasNullFlag = true;
1644                                } else {
1645                                        this.wasNullFlag = false;
1646                                }
1647                        } catch (NullPointerException E) {
1648                                this.wasNullFlag = true;
1649                        } catch (ArrayIndexOutOfBoundsException aioobEx) {
1650                                throw SQLError.createSQLException(Messages.getString(
1651                                                "ResultSet.Column_Index_out_of_range", new Object[] {
1652                                                                new Integer(columnIndex),
1653                                                                new Integer(this.fields.length) }),
1654                                                SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$
1655                        }
1656 
1657                        if (this.wasNullFlag) {
1658                                return null;
1659                        }
1660 
1661                        return (byte[]) this.thisRow[columnIndex - 1];
1662                }
1663 
1664                return getNativeBytes(columnIndex, noConversion);
1665        }
1666 
1667        /**
1668         * DOCUMENT ME!
1669         * 
1670         * @param columnName
1671         *            DOCUMENT ME!
1672         * 
1673         * @return DOCUMENT ME!
1674         * 
1675         * @throws SQLException
1676         *             DOCUMENT ME!
1677         */
1678        public byte[] getBytes(String columnName) throws SQLException {
1679                return getBytes(findColumn(columnName));
1680        }
1681 
1682        private final byte[] getBytesFromString(String stringVal, int columnIndex)
1683                        throws SQLException {
1684                if (stringVal != null) {
1685                        return StringUtils.getBytes(stringVal, this.connection
1686                                        .getEncoding(), this.connection
1687                                        .getServerCharacterEncoding(), this.connection
1688                                        .parserKnowsUnicode(),
1689                                        this.connection);
1690                }
1691 
1692                return null;
1693        }
1694 
1695        /**
1696         * Optimization to only use one calendar per-session, or calculate it for
1697         * each call, depending on user configuration
1698         */
1699        private Calendar getCalendarInstanceForSessionOrNew() {
1700                if (this.connection != null) {
1701                        return this.connection.getCalendarInstanceForSessionOrNew();
1702                } else {
1703                        // punt, no connection around
1704                        return new GregorianCalendar();
1705                }
1706        }
1707 
1708        /**
1709         * JDBC 2.0
1710         * 
1711         * <p>
1712         * Get the value of a column in the current row as a java.io.Reader.
1713         * </p>
1714         * 
1715         * @param columnIndex
1716         *            the column to get the value from
1717         * 
1718         * @return the value in the column as a java.io.Reader.
1719         * 
1720         * @throws SQLException
1721         *             if an error occurs
1722         */
1723        public java.io.Reader getCharacterStream(int columnIndex)
1724                        throws SQLException {
1725                if (!this.isBinaryEncoded) {
1726                        String asString = getStringForClob(columnIndex);
1727 
1728                        if (asString == null) {
1729                                return null;
1730                        }
1731 
1732                        return new StringReader(asString);
1733                }
1734 
1735                return getNativeCharacterStream(columnIndex);
1736        }
1737 
1738        /**
1739         * JDBC 2.0
1740         * 
1741         * <p>
1742         * Get the value of a column in the current row as a java.io.Reader.
1743         * </p>
1744         * 
1745         * @param columnName
1746         *            the column name to retrieve the value from
1747         * 
1748         * @return the value as a java.io.Reader
1749         * 
1750         * @throws SQLException
1751         *             if an error occurs
1752         */
1753        public java.io.Reader getCharacterStream(String columnName)
1754                        throws SQLException {
1755                return getCharacterStream(findColumn(columnName));
1756        }
1757 
1758        private final java.io.Reader getCharacterStreamFromString(String stringVal,
1759                        int columnIndex) throws SQLException {
1760                if (stringVal != null) {
1761                        return new StringReader(stringVal);
1762                }
1763 
1764                return null;
1765        }
1766 
1767        /**
1768         * JDBC 2.0 Get a CLOB column.
1769         * 
1770         * @param i
1771         *            the first column is 1, the second is 2, ...
1772         * 
1773         * @return an object representing a CLOB
1774         * 
1775         * @throws SQLException
1776         *             if an error occurs
1777         */
1778        public java.sql.Clob getClob(int i) throws SQLException {
1779                if (!this.isBinaryEncoded) {
1780                        String asString = getStringForClob(i);
1781                        
1782                        if (asString == null) {
1783                                return null;
1784                        }
1785 
1786                        return new com.mysql.jdbc.Clob(asString);
1787                }
1788 
1789                return getNativeClob(i);
1790        }
1791 
1792        /**
1793         * JDBC 2.0 Get a CLOB column.
1794         * 
1795         * @param colName
1796         *            the column name
1797         * 
1798         * @return an object representing a CLOB
1799         * 
1800         * @throws SQLException
1801         *             if an error occurs
1802         */
1803        public java.sql.Clob getClob(String colName) throws SQLException {
1804                return getClob(findColumn(colName));
1805        }
1806 
1807        private final java.sql.Clob getClobFromString(String stringVal,
1808                        int columnIndex) throws SQLException {
1809                return new com.mysql.jdbc.Clob(stringVal);
1810        }
1811 
1812        /**
1813         * JDBC 2.0 Return the concurrency of this result set. The concurrency used
1814         * is determined by the statement that created the result set.
1815         * 
1816         * @return the concurrency type, CONCUR_READ_ONLY, etc.
1817         * 
1818         * @throws SQLException
1819         *             if a database-access error occurs
1820         */
1821        public int getConcurrency() throws SQLException {
1822                return (CONCUR_READ_ONLY);
1823        }
1824 
1825        /**
1826         * Get the name of the SQL cursor used by this ResultSet
1827         * 
1828         * <p>
1829         * In SQL, a result table is retrieved though a cursor that is named. The
1830         * current row of a result can be updated or deleted using a positioned
1831         * update/delete statement that references the cursor name.
1832         * </p>
1833         * 
1834         * <p>
1835         * JDBC supports this SQL feature by providing the name of the SQL cursor
1836         * used by a ResultSet. The current row of a ResulSet is also the current
1837         * row of this SQL cursor.
1838         * </p>
1839         * 
1840         * <p>
1841         * <B>Note:</B> If positioned update is not supported, a SQLException is
1842         * thrown.
1843         * </p>
1844         * 
1845         * @return the ResultSet's SQL cursor name.
1846         * 
1847         * @exception SQLException
1848         *                if a database access error occurs
1849         */
1850        public String getCursorName() throws SQLException {
1851                throw SQLError.createSQLException(Messages
1852                                .getString("ResultSet.Positioned_Update_not_supported"),
1853                                SQLError.SQL_STATE_DRIVER_NOT_CAPABLE); //$NON-NLS-1$
1854        }
1855 
1856        /**
1857         * Get the value of a column in the current row as a java.sql.Date object
1858         * 
1859         * @param columnIndex
1860         *            the first column is 1, the second is 2...
1861         * 
1862         * @return the column value; null if SQL NULL
1863         * 
1864         * @exception java.sql.SQLException
1865         *                if a database access error occurs
1866         */
1867        public java.sql.Date getDate(int columnIndex) throws java.sql.SQLException {
1868                return getDate(columnIndex, null);
1869        }
1870 
1871        /**
1872         * JDBC 2.0 Get the value of a column in the current row as a java.sql.Date
1873         * object. Use the calendar to construct an appropriate millisecond value
1874         * for the Date, if the underlying database doesn't store timezone
1875         * information.
1876         * 
1877         * @param columnIndex
1878         *            the first column is 1, the second is 2, ...
1879         * @param cal
1880         *            the calendar to use in constructing the date
1881         * 
1882         * @return the column value; if the value is SQL NULL, the result is null
1883         * 
1884         * @exception SQLException
1885         *                if a database-access error occurs.
1886         */
1887        public java.sql.Date getDate(int columnIndex, Calendar cal)
1888                        throws SQLException {
1889                if (this.isBinaryEncoded) {
1890                        return getNativeDate(columnIndex, (cal != null) ? cal.getTimeZone()
1891                                        : this.getDefaultTimeZone());
1892                }
1893 
1894                String stringVal = getStringInternal(columnIndex, false);
1895 
1896                if (stringVal == null) {
1897                        return null;
1898                }
1899 
1900                return getDateFromString(stringVal, columnIndex);
1901        }
1902 
1903        /**
1904         * DOCUMENT ME!
1905         * 
1906         * @param columnName
1907         *            DOCUMENT ME!
1908         * 
1909         * @return DOCUMENT ME!
1910         * 
1911         * @throws java.sql.SQLException
1912         *             DOCUMENT ME!
1913         */
1914        public java.sql.Date getDate(String columnName)
1915                        throws java.sql.SQLException {
1916                return getDate(findColumn(columnName));
1917        }
1918 
1919        /**
1920         * Get the value of a column in the current row as a java.sql.Date object.
1921         * Use the calendar to construct an appropriate millisecond value for the
1922         * Date, if the underlying database doesn't store timezone information.
1923         * 
1924         * @param columnName
1925         *            is the SQL name of the column
1926         * @param cal
1927         *            the calendar to use in constructing the date
1928         * 
1929         * @return the column value; if the value is SQL NULL, the result is null
1930         * 
1931         * @exception SQLException
1932         *                if a database-access error occurs.
1933         */
1934        public java.sql.Date getDate(String columnName, Calendar cal)
1935                        throws SQLException {
1936                return getDate(findColumn(columnName), cal);
1937        }
1938 
1939        private final java.sql.Date getDateFromString(String stringVal,
1940                        int columnIndex) throws SQLException {
1941                int year = 0;
1942                int month = 0;
1943                int day = 0;
1944 
1945                try {
1946                        this.wasNullFlag = false;
1947 
1948                        if (stringVal == null) {
1949                                this.wasNullFlag = true;
1950 
1951                                return null;
1952                        }
1953                        
1954                        //
1955                        // JDK-6 doesn't like trailing whitespace
1956                        //
1957                        // Note this isn't a performance issue, other
1958                        // than the iteration over the string, as String.trim()
1959                        // will return a new string only if whitespace is present
1960                        //
1961                        
1962                        stringVal = stringVal.trim();
1963 
1964                        if (stringVal.equals("0") || stringVal.equals("0000-00-00")
1965                                        || stringVal.equals("0000-00-00 00:00:00")
1966                                        || stringVal.equals("00000000000000")
1967                                        || stringVal.equals("0")) {
1968 
1969                                if (ConnectionProperties.ZERO_DATETIME_BEHAVIOR_CONVERT_TO_NULL
1970                                                .equals(this.connection.getZeroDateTimeBehavior())) {
1971                                        this.wasNullFlag = true;
1972 
1973                                        return null;
1974                                } else if (ConnectionProperties.ZERO_DATETIME_BEHAVIOR_EXCEPTION
1975                                                .equals(this.connection.getZeroDateTimeBehavior())) {
1976                                        throw SQLError.createSQLException("Value '" + stringVal
1977                                                        + "' can not be represented as java.sql.Date",
1978                                                        SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
1979                                }
1980 
1981                                // We're left with the case of 'round' to a date Java _can_
1982                                // represent, which is '0001-01-01'.
1983                                return fastDateCreate(null, 1, 1, 1);
1984 
1985                        } else if (this.fields[columnIndex - 1].getMysqlType() == MysqlDefs.FIELD_TYPE_TIMESTAMP) {
1986                                // Convert from TIMESTAMP
1987                                switch (stringVal.length()) {
1988                                case 21:
1989                                case 19: { // java.sql.Timestamp format
1990                                        year = Integer.parseInt(stringVal.substring(0, 4));
1991                                        month = Integer.parseInt(stringVal.substring(5, 7));
1992                                        day = Integer.parseInt(stringVal.substring(8, 10));
1993 
1994                                        return fastDateCreate(null, year, month, day);
1995                                }
1996 
1997                                case 14:
1998                                case 8: {
1999                                        year = Integer.parseInt(stringVal.substring(0, 4));
2000                                        month = Integer.parseInt(stringVal.substring(4, 6));
2001                                        day = Integer.parseInt(stringVal.substring(6, 8));
2002 
2003                                        return fastDateCreate(null, year, month, day);
2004                                }
2005 
2006                                case 12:
2007                                case 10:
2008                                case 6: {
2009                                        year = Integer.parseInt(stringVal.substring(0, 2));
2010 
2011                                        if (year <= 69) {
2012                                                year = year + 100;
2013                                        }
2014 
2015                                        month = Integer.parseInt(stringVal.substring(2, 4));
2016                                        day = Integer.parseInt(stringVal.substring(4, 6));
2017 
2018                                        return fastDateCreate(null, year + 1900, month, day);
2019                                }
2020 
2021                                case 4: {
2022                                        year = Integer.parseInt(stringVal.substring(0, 4));
2023 
2024                                        if (year <= 69) {
2025                                                year = year + 100;
2026                                        }
2027 
2028                                        month = Integer.parseInt(stringVal.substring(2, 4));
2029 
2030                                        return fastDateCreate(null, year + 1900, month, 1);
2031                                }
2032 
2033                                case 2: {
2034                                        year = Integer.parseInt(stringVal.substring(0, 2));
2035 
2036                                        if (year <= 69) {
2037                                                year = year + 100;
2038                                        }
2039 
2040                                        return fastDateCreate(null, year + 1900, 1, 1);
2041                                }
2042 
2043                                default:
2044                                        throw SQLError.createSQLException(Messages.getString(
2045                                                        "ResultSet.Bad_format_for_Date", new Object[] {
2046                                                                        stringVal, new Integer(columnIndex) }),
2047                                                        SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$
2048                                } /* endswitch */
2049                        } else if (this.fields[columnIndex - 1].getMysqlType() == MysqlDefs.FIELD_TYPE_YEAR) {
2050 
2051                                if (stringVal.length() == 2 || stringVal.length() == 1) {
2052                                        year = Integer.parseInt(stringVal);
2053 
2054                                        if (year <= 69) {
2055                                                year = year + 100;
2056                                        }
2057 
2058                                        year += 1900;
2059                                } else {
2060                                        year = Integer.parseInt(stringVal.substring(0, 4));
2061                                }
2062 
2063                                return fastDateCreate(null, year, 1, 1);
2064                        } else if (this.fields[columnIndex - 1].getMysqlType() == MysqlDefs.FIELD_TYPE_TIME) {
2065                                return fastDateCreate(null, 1970, 1, 1); // Return EPOCH
2066                        } else {
2067                                if (stringVal.length() < 10) {
2068                                        throw SQLError.createSQLException(Messages.getString(
2069                                                        "ResultSet.Bad_format_for_Date", new Object[] {
2070                                                                        stringVal, new Integer(columnIndex) }),
2071                                                        SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$
2072                                }
2073 
2074                                if (stringVal.length() != 18) {
2075                                        year = Integer.parseInt(stringVal.substring(0, 4));
2076                                        month = Integer.parseInt(stringVal.substring(5, 7));
2077                                        day = Integer.parseInt(stringVal.substring(8, 10));
2078                                } else {
2079                                        // JDK-1.3 timestamp format, not real easy to parse positionally :p
2080                                        StringTokenizer st = new StringTokenizer(stringVal, "- ");
2081                                        
2082                                        year = Integer.parseInt(st.nextToken());
2083                                        month = Integer.parseInt(st.nextToken());
2084                                        day = Integer.parseInt(st.nextToken());
2085                                }
2086                        }
2087 
2088                        return fastDateCreate(null, year, month, day);
2089                } catch (SQLException sqlEx) {
2090                        throw sqlEx; // don't re-wrap
2091                } catch (Exception e) {
2092                        throw SQLError.createSQLException(Messages.getString(
2093                                        "ResultSet.Bad_format_for_Date", new Object[] { stringVal,
2094                                                        new Integer(columnIndex) }),
2095                                        SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$
2096                }
2097        }
2098 
2099        private TimeZone getDefaultTimeZone() {
2100                // Worst case we allocate this twice and the other gets GC'd,
2101                // however prevents deadlock
2102                if (this.defaultTimeZone == null) {
2103                        this.defaultTimeZone = TimeZone.getDefault();
2104                }
2105 
2106                return this.defaultTimeZone;
2107        }
2108 
2109        /**
2110         * Get the value of a column in the current row as a Java double.
2111         * 
2112         * @param columnIndex
2113         *            the first column is 1, the second is 2,...
2114         * 
2115         * @return the column value; 0 if SQL NULL
2116         * 
2117         * @exception SQLException
2118         *                if a database access error occurs
2119         */
2120        public double getDouble(int columnIndex) throws SQLException {
2121                if (!this.isBinaryEncoded) {
2122                        return getDoubleInternal(columnIndex);
2123                }
2124 
2125                return getNativeDouble(columnIndex);
2126        }
2127 
2128        /**
2129         * DOCUMENT ME!
2130         * 
2131         * @param columnName
2132         *            DOCUMENT ME!
2133         * 
2134         * @return DOCUMENT ME!
2135         * 
2136         * @throws SQLException
2137         *             DOCUMENT ME!
2138         */
2139        public double getDouble(String columnName) throws SQLException {
2140                return getDouble(findColumn(columnName));
2141        }
2142 
2143        private final double getDoubleFromString(String stringVal, int columnIndex)
2144                        throws SQLException {
2145                return getDoubleInternal(stringVal, columnIndex);
2146        }
2147 
2148        /**
2149         * Converts a string representation of a number to a double. Need a faster
2150         * way to do this.
2151         * 
2152         * @param colIndex
2153         *            the 1-based index of the column to retrieve a double from.
2154         * 
2155         * @return the double value represented by the string in buf
2156         * 
2157         * @throws SQLException
2158         *             if an error occurs
2159         */
2160        protected double getDoubleInternal(int colIndex) throws SQLException {
2161                return getDoubleInternal(getString(colIndex), colIndex);
2162        }
2163 
2164        /**
2165         * Converts a string representation of a number to a double. Need a faster
2166         * way to do this.
2167         * 
2168         * @param stringVal
2169         *            the double as a String
2170         * @param colIndex
2171         *            the 1-based index of the column to retrieve a double from.
2172         * 
2173         * @return the double value represented by the string in buf
2174         * 
2175         * @throws SQLException
2176         *             if an error occurs
2177         */
2178        protected double getDoubleInternal(String stringVal, int colIndex)
2179                        throws SQLException {
2180                try {
2181                        if ((stringVal == null)) {
2182                                return 0;
2183                        }
2184 
2185                        if (stringVal.length() == 0) {
2186                                return convertToZeroWithEmptyCheck();
2187                        }
2188 
2189                        double d = Double.parseDouble(stringVal);
2190 
2191                        if (this.useStrictFloatingPoint) {
2192                                // Fix endpoint rounding precision loss in MySQL server
2193                                if (d == 2.147483648E9) {
2194                                        // Fix Odd end-point rounding on MySQL
2195                                        d = 2.147483647E9;
2196                                } else if (d == 1.0000000036275E-15) {
2197                                        // Fix odd end-point rounding on MySQL
2198                                        d = 1.0E-15;
2199                                } else if (d == 9.999999869911E14) {
2200                                        d = 9.99999999999999E14;
2201                                } else if (d == 1.4012984643248E-45) {
2202                                        d = 1.4E-45;
2203                                } else if (d == 1.4013E-45) {
2204                                        d = 1.4E-45;
2205                                } else if (d == 3.4028234663853E37) {
2206                                        d = 3.4028235E37;
2207                                } else if (d == -2.14748E9) {
2208                                        d = -2.147483648E9;
2209                                } else if (d == 3.40282E37) {
2210                                        d = 3.4028235E37;
2211                                }
2212                        }
2213 
2214                        return d;
2215                } catch (NumberFormatException e) {
2216                        if (this.fields[colIndex - 1].getMysqlType() == MysqlDefs.FIELD_TYPE_BIT) {
2217                                long valueAsLong = getNumericRepresentationOfSQLBitType(colIndex);
2218                                
2219                                return valueAsLong;
2220                        }
2221                        
2222                        throw SQLError.createSQLException(Messages.getString(
2223                                        "ResultSet.Bad_format_for_number", new Object[] {
2224                                                        stringVal, new Integer(colIndex) }),
2225                                        SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
2226                }
2227        }
2228 
2229        /**
2230         * JDBC 2.0 Returns the fetch direction for this result set.
2231         * 
2232         * @return the fetch direction for this result set.
2233         * 
2234         * @exception SQLException
2235         *                if a database-access error occurs
2236         */
2237        public int getFetchDirection() throws SQLException {
2238                return this.fetchDirection;
2239        }
2240 
2241        /**
2242         * JDBC 2.0 Return the fetch size for this result set.
2243         * 
2244         * @return the fetch size for this result set.
2245         * 
2246         * @exception SQLException
2247         *                if a database-access error occurs
2248         */
2249        public int getFetchSize() throws SQLException {
2250                return this.fetchSize;
2251        }
2252 
2253        /**
2254         * Returns the first character of the query that this result set was created
2255         * from.
2256         * 
2257         * @return the first character of the query...uppercased
2258         */
2259        protected char getFirstCharOfQuery() {
2260                return this.firstCharOfQuery;
2261        }
2262 
2263        /**
2264         * Get the value of a column in the current row as a Java float.
2265         * 
2266         * @param columnIndex
2267         *            the first column is 1, the second is 2,...
2268         * 
2269         * @return the column value; 0 if SQL NULL
2270         * 
2271         * @exception SQLException
2272         *                if a database access error occurs
2273         */
2274        public float getFloat(int columnIndex) throws SQLException {
2275                if (!this.isBinaryEncoded) {
2276                        String val = null;
2277 
2278                        val = getString(columnIndex);
2279 
2280                        return getFloatFromString(val, columnIndex);
2281                }
2282 
2283                return getNativeFloat(columnIndex);
2284        }
2285 
2286        /**
2287         * DOCUMENT ME!
2288         * 
2289         * @param columnName
2290         *            DOCUMENT ME!
2291         * 
2292         * @return DOCUMENT ME!
2293         * 
2294         * @throws SQLException
2295         *             DOCUMENT ME!
2296         */
2297        public float getFloat(String columnName) throws SQLException {
2298                return getFloat(findColumn(columnName));
2299        }
2300 
2301        private final float getFloatFromString(String val, int columnIndex)
2302                        throws SQLException {
2303                try {
2304                        if ((val != null)) {
2305                                if (val.length() == 0) {
2306                                        return convertToZeroWithEmptyCheck();
2307                                }
2308 
2309                                float f = Float.parseFloat(val);
2310 
2311                                if (this.connection.getJdbcCompliantTruncationForReads()) {
2312                                        if (f == Float.MIN_VALUE || f == Float.MAX_VALUE) {
2313                                                double valAsDouble = Double.parseDouble(val);
2314 
2315                                                // Straight comparison is not reliable when at
2316                                                // absolute endpoints of Float.MIN_VALUE or 
2317                                                // Float.MAX_VALUE, so use epsillons with DOUBLEs
2318 
2319                                    if ((valAsDouble < Float.MIN_VALUE - MIN_DIFF_PREC)
2320                                        || (valAsDouble > Float.MAX_VALUE - MAX_DIFF_PREC)) {
2321                                      throwRangeException(String.valueOf(valAsDouble), columnIndex,
2322                                          Types.FLOAT);
2323                                    }
2324                                        }
2325                                }
2326 
2327                                return f;
2328                        }
2329 
2330                        return 0; // for NULL
2331                } catch (NumberFormatException nfe) {
2332                        try {
2333                                Double valueAsDouble = new Double(val);
2334                                float valueAsFloat = valueAsDouble.floatValue();
2335                                
2336                                if (this.connection.getJdbcCompliantTruncationForReads()) {
2337 
2338                                        if (this.connection.getJdbcCompliantTruncationForReads() && 
2339                                                        valueAsFloat == Float.NEGATIVE_INFINITY ||
2340                                                        valueAsFloat == Float.POSITIVE_INFINITY) {
2341                                                throwRangeException(valueAsDouble.toString(), 
2342                                                                columnIndex, Types.FLOAT);
2343                                        }
2344                                }
2345 
2346                                return valueAsFloat;
2347                        } catch (NumberFormatException newNfe) {
2348                                ; // ignore, it's not a number
2349                        }
2350 
2351                        throw SQLError.createSQLException(
2352                                        Messages
2353                                                        .getString("ResultSet.Invalid_value_for_getFloat()_-____200")
2354                                                        + val //$NON-NLS-1$
2355                                                        + Messages.getString("ResultSet.___in_column__201")
2356                                                        + columnIndex, SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$
2357                }
2358        }
2359 
2360        /**
2361         * Get the value of a column in the current row as a Java int.
2362         * 
2363         * @param columnIndex
2364         *            the first column is 1, the second is 2,...
2365         * 
2366         * @return the column value; 0 if SQL NULL
2367         * 
2368         * @exception SQLException
2369         *                if a database access error occurs
2370         */
2371        public int getInt(int columnIndex) throws SQLException {
2372                checkRowPos();
2373                
2374                if (!this.isBinaryEncoded) {
2375                        if (this.connection.getUseFastIntParsing()) {
2376                                checkColumnBounds(columnIndex);
2377                                
2378                                try {
2379                                        if (this.thisRow[columnIndex - 1] == null) {
2380                                                this.wasNullFlag = true;
2381                                        } else {
2382                                                this.wasNullFlag = false;
2383                                        }
2384                                } catch (NullPointerException E) {
2385                                        this.wasNullFlag = true;
2386                                } catch (ArrayIndexOutOfBoundsException aioobEx) {
2387                                        throw SQLError.createSQLException(Messages.getString(
2388                                                        "ResultSet.Column_Index_out_of_range",
2389                                                        new Object[] { new Integer(columnIndex),
2390                                                                        new Integer(this.fields.length) }),
2391                                                        SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$
2392                                }
2393 
2394                                if (this.wasNullFlag) {
2395                                        return 0;
2396                                }
2397 
2398                                byte[] intAsBytes = (byte[]) this.thisRow[columnIndex - 1];
2399 
2400                                if (intAsBytes.length == 0) {
2401                                        return convertToZeroWithEmptyCheck();
2402                                }
2403 
2404                                boolean needsFullParse = false;
2405 
2406                                for (int i = 0; i < intAsBytes.length; i++) {
2407                                        if (((char) intAsBytes[i] == 'e')
2408                                                        || ((char) intAsBytes[i] == 'E')) {
2409                                                needsFullParse = true;
2410 
2411                                                break;
2412                                        }
2413                                }
2414 
2415                                if (!needsFullParse) {
2416                                        try {
2417                                                return parseIntWithOverflowCheck(columnIndex,
2418                                                                intAsBytes, null);
2419                                        } catch (NumberFormatException nfe) {
2420                                                try {
2421 
2422                                                        return parseIntAsDouble(columnIndex, new String(
2423                                                                        intAsBytes));
2424                                                } catch (NumberFormatException newNfe) {
2425                                                        ; // ignore, it's not a number
2426                                                }
2427 
2428                                                if (this.fields[columnIndex - 1].getMysqlType() == MysqlDefs.FIELD_TYPE_BIT) {
2429                                                        long valueAsLong = getNumericRepresentationOfSQLBitType(columnIndex);
2430                                                        
2431                                                        if (this.connection.getJdbcCompliantTruncationForReads() &&
2432                                                                        (valueAsLong < Integer.MIN_VALUE
2433                                                                                        || valueAsLong > Integer.MAX_VALUE)) {
2434                                                                throwRangeException(String.valueOf(valueAsLong), columnIndex,
2435                                                                                Types.INTEGER);
2436                                                        }
2437                                                        
2438                                                        return (int)valueAsLong;
2439                                                }
2440                                                
2441                                                throw SQLError.createSQLException(
2442                                                                Messages
2443                                                                                .getString("ResultSet.Invalid_value_for_getInt()_-____74")
2444                                                                                + new String(intAsBytes) //$NON-NLS-1$
2445                                                                                + "'",
2446                                                                SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
2447                                        }
2448                                }
2449                        }
2450 
2451                        String val = null;
2452 
2453                        try {
2454                                val = getString(columnIndex);
2455 
2456                                if ((val != null)) {
2457                                        if (val.length() == 0) {
2458                                                return convertToZeroWithEmptyCheck();
2459                                        }
2460 
2461                                        if ((val.indexOf("e") == -1) && (val.indexOf("E") == -1)
2462                                                        && (val.indexOf(".") == -1)) {
2463                                                return Integer.parseInt(val);
2464                                        }
2465 
2466                                        // Convert floating point
2467                                        return parseIntAsDouble(columnIndex, val);
2468                                }
2469 
2470                                return 0;
2471                        } catch (NumberFormatException nfe) {
2472                                try {
2473                                        return parseIntAsDouble(columnIndex, val);
2474                                } catch (NumberFormatException newNfe) {
2475                                        ; // ignore, it's not a number
2476                                }
2477 
2478                                if (this.fields[columnIndex - 1].getMysqlType() == MysqlDefs.FIELD_TYPE_BIT) {
2479                                        long valueAsLong = getNumericRepresentationOfSQLBitType(columnIndex);
2480                                        
2481                                        if (this.connection.getJdbcCompliantTruncationForReads() &&
2482                                                        (valueAsLong < Integer.MIN_VALUE
2483                                                                        || valueAsLong > Integer.MAX_VALUE)) {
2484                                                throwRangeException(String.valueOf(valueAsLong), columnIndex,
2485                                                                Types.INTEGER);
2486                                        }
2487                                        
2488                                        return (int)valueAsLong;
2489                                }
2490                                
2491                                throw SQLError.createSQLException(
2492                                                Messages
2493                                                                .getString("ResultSet.Invalid_value_for_getInt()_-____74")
2494                                                                + val //$NON-NLS-1$
2495                                                                + "'", SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
2496                        }
2497                }
2498 
2499                return getNativeInt(columnIndex);
2500        }
2501 
2502        /**
2503         * DOCUMENT ME!
2504         * 
2505         * @param columnName
2506         *            DOCUMENT ME!
2507         * 
2508         * @return DOCUMENT ME!
2509         * 
2510         * @throws SQLException
2511         *             DOCUMENT ME!
2512         */
2513        public int getInt(String columnName) throws SQLException {
2514                return getInt(findColumn(columnName));
2515        }
2516 
2517        private final int getIntFromString(String val, int columnIndex)
2518                        throws SQLException {
2519                try {
2520                        if ((val != null)) {
2521 
2522                                if (val.length() == 0) {
2523                                        return convertToZeroWithEmptyCheck();
2524                                }
2525 
2526                                if ((val.indexOf("e") == -1) && (val.indexOf("E") == -1)
2527                                                && (val.indexOf(".") == -1)) {
2528                                        //
2529                                        // JDK-6 doesn't like trailing whitespace
2530                                        //
2531                                        // Note this isn't a performance issue, other
2532                                        // than the iteration over the string, as String.trim()
2533                                        // will return a new string only if whitespace is present
2534                                        //
2535                                        
2536                                        val = val.trim(); 
2537                                        
2538                                        int valueAsInt = Integer.parseInt(val);
2539 
2540                                        if (this.connection.getJdbcCompliantTruncationForReads()) {
2541                                                if (valueAsInt == Integer.MIN_VALUE
2542                                                                || valueAsInt == Integer.MAX_VALUE) {
2543                                                        long valueAsLong = Long.parseLong(val);
2544 
2545                                                        if (valueAsLong < Integer.MIN_VALUE
2546                                                                        || valueAsLong > Integer.MAX_VALUE) {
2547                                                                throwRangeException(
2548                                                                                String.valueOf(valueAsLong),
2549                                                                                columnIndex, Types.INTEGER);
2550                                                        }
2551                                                }
2552                                        }
2553 
2554                                        return valueAsInt;
2555                                }
2556 
2557                                // Convert floating point
2558 
2559                                double valueAsDouble = Double.parseDouble(val);
2560 
2561                                if (this.connection.getJdbcCompliantTruncationForReads()) {
2562                                        if (valueAsDouble < Integer.MIN_VALUE
2563                                                        || valueAsDouble > Integer.MAX_VALUE) {
2564                                                throwRangeException(String.valueOf(valueAsDouble),
2565                                                                columnIndex, Types.INTEGER);
2566                                        }
2567                                }
2568 
2569                                return (int) valueAsDouble;
2570                        }
2571 
2572                        return 0; // for NULL
2573                } catch (NumberFormatException nfe) {
2574                        try {
2575                                double valueAsDouble = Double.parseDouble(val);
2576 
2577                                if (this.connection.getJdbcCompliantTruncationForReads()) {
2578                                        if (valueAsDouble < Integer.MIN_VALUE
2579                                                        || valueAsDouble > Integer.MAX_VALUE) {
2580                                                throwRangeException(String.valueOf(valueAsDouble),
2581                                                                columnIndex, Types.INTEGER);
2582                                        }
2583                                }
2584 
2585                                return (int) valueAsDouble;
2586                        } catch (NumberFormatException newNfe) {
2587                                ; // ignore, it's not a number
2588                        }
2589 
2590                        throw SQLError.createSQLException(Messages
2591                                        .getString("ResultSet.Invalid_value_for_getInt()_-____206")
2592                                        + val //$NON-NLS-1$
2593                                        + Messages.getString("ResultSet.___in_column__207")
2594                                        + columnIndex, SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$
2595                }
2596        }
2597 
2598        /**
2599         * Get the value of a column in the current row as a Java long.
2600         * 
2601         * @param columnIndex
2602         *            the first column is 1, the second is 2,...
2603         * 
2604         * @return the column value; 0 if SQL NULL
2605         * 
2606         * @exception SQLException
2607         *                if a database access error occurs
2608         */
2609        public long getLong(int columnIndex) throws SQLException {
2610                if (!this.isBinaryEncoded) {
2611                        checkRowPos();
2612                        
2613                        if (this.connection.getUseFastIntParsing()) {
2614                        
2615                                checkColumnBounds(columnIndex);
2616                                
2617                                try {
2618                                        if (this.thisRow[columnIndex - 1] == null) {
2619                                                this.wasNullFlag = true;
2620                                        } else {
2621                                                this.wasNullFlag = false;
2622                                        }
2623                                } catch (NullPointerException E) {
2624                                        this.wasNullFlag = true;
2625                                } catch (ArrayIndexOutOfBoundsException aioobEx) {
2626                                        throw SQLError.createSQLException(Messages.getString(
2627                                                        "ResultSet.Column_Index_out_of_range",
2628                                                        new Object[] { new Integer(columnIndex),
2629                                                                        new Integer(this.fields.length) }),
2630                                                        SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$
2631                                }
2632 
2633                                if (this.wasNullFlag) {
2634                                        return 0;
2635                                }
2636 
2637                                byte[] longAsBytes = (byte[]) this.thisRow[columnIndex - 1];
2638 
2639                                if (longAsBytes.length == 0) {
2640                                        return convertToZeroWithEmptyCheck();
2641                                }
2642 
2643                                boolean needsFullParse = false;
2644 
2645                                for (int i = 0; i < longAsBytes.length; i++) {
2646                                        if (((char) longAsBytes[i] == 'e')
2647                                                        || ((char) longAsBytes[i] == 'E')) {
2648                                                needsFullParse = true;
2649 
2650                                                break;
2651                                        }
2652                                }
2653 
2654                                if (!needsFullParse) {
2655                                        try {
2656                                                return parseLongWithOverflowCheck(columnIndex,
2657                                                                longAsBytes, null);
2658                                        } catch (NumberFormatException nfe) {
2659                                                try {
2660                                                        // To do: Warn of over/underflow???
2661                                                        return parseLongAsDouble(columnIndex, new String(
2662                                                                        longAsBytes));
2663                                                } catch (NumberFormatException newNfe) {
2664                                                        // ; // ignore, it's not a number
2665                                                }
2666 
2667                                                if (this.fields[columnIndex - 1].getMysqlType() == MysqlDefs.FIELD_TYPE_BIT) {
2668                                                        return getNumericRepresentationOfSQLBitType(columnIndex);
2669                                                }
2670                                                
2671                                                throw SQLError.createSQLException(
2672                                                                Messages
2673                                                                                .getString("ResultSet.Invalid_value_for_getLong()_-____79")
2674                                                                                + new String(longAsBytes) //$NON-NLS-1$
2675                                                                                + "'",
2676                                                                SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
2677                                        }
2678                                }
2679                        }
2680 
2681                        String val = null;
2682 
2683                        try {
2684                                val = getString(columnIndex);
2685 
2686                                if ((val != null)) {
2687                                        if (val.length() == 0) {
2688                                                return convertToZeroWithEmptyCheck();
2689                                        }
2690 
2691                                        if ((val.indexOf("e") == -1) && (val.indexOf("E") == -1)) {
2692                                                return parseLongWithOverflowCheck(columnIndex, null,
2693                                                                val);
2694                                        }
2695 
2696                                        // Convert floating point
2697                                        return parseLongAsDouble(columnIndex, val);
2698                                }
2699 
2700                                return 0; // for NULL
2701                        } catch (NumberFormatException nfe) {
2702                                try {
2703                                        return parseLongAsDouble(columnIndex, val);
2704                                } catch (NumberFormatException newNfe) {
2705                                        // ; // ignore, it's not a number
2706                                }
2707 
2708                                throw SQLError.createSQLException(
2709                                                Messages
2710                                                                .getString("ResultSet.Invalid_value_for_getLong()_-____79")
2711                                                                + val //$NON-NLS-1$
2712                                                                + "'", SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
2713                        }
2714                }
2715 
2716                return getNativeLong(columnIndex);
2717        }
2718 
2719        /**
2720         * DOCUMENT ME!
2721         * 
2722         * @param columnName
2723         *            DOCUMENT ME!
2724         * 
2725         * @return DOCUMENT ME!
2726         * 
2727         * @throws SQLException
2728         *             DOCUMENT ME!
2729         */
2730        public long getLong(String columnName) throws SQLException {
2731                return getLong(findColumn(columnName));
2732        }
2733 
2734        private final long getLongFromString(String val, int columnIndex)
2735                        throws SQLException {
2736                try {
2737                        if ((val != null)) {
2738 
2739                                if (val.length() == 0) {
2740                                        return convertToZeroWithEmptyCheck();
2741                                }
2742 
2743                                if ((val.indexOf("e") == -1) && (val.indexOf("E") == -1)) {
2744                                        return parseLongWithOverflowCheck(columnIndex, null, val);
2745                                }
2746 
2747                                // Convert floating point
2748                                return parseLongAsDouble(columnIndex, val);
2749                        }
2750 
2751                        return 0; // for NULL
2752                } catch (NumberFormatException nfe) {
2753                        try {
2754                                // To do: Warn of over/underflow???
2755                                return parseLongAsDouble(columnIndex, val);
2756                        } catch (NumberFormatException newNfe) {
2757                                ; // ignore, it's not a number
2758                        }
2759 
2760                        throw SQLError.createSQLException(
2761                                        Messages
2762                                                        .getString("ResultSet.Invalid_value_for_getLong()_-____211")
2763                                                        + val //$NON-NLS-1$
2764                                                        + Messages.getString("ResultSet.___in_column__212")
2765                                                        + columnIndex, SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$
2766                }
2767        }
2768 
2769        /**
2770         * The numbers, types and properties of a ResultSet's columns are provided
2771         * by the getMetaData method
2772         * 
2773         * @return a description of the ResultSet's columns
2774         * 
2775         * @exception SQLException
2776         *                if a database access error occurs
2777         */
2778        public java.sql.ResultSetMetaData getMetaData() throws SQLException {
2779                checkClosed();
2780 
2781                return new com.mysql.jdbc.ResultSetMetaData(this.fields);
2782        }
2783 
2784        /**
2785         * JDBC 2.0 Get an array column.
2786         * 
2787         * @param i
2788         *            the first column is 1, the second is 2, ...
2789         * 
2790         * @return an object representing an SQL array
2791         * 
2792         * @throws SQLException
2793         *             if a database error occurs
2794         * @throws NotImplemented
2795         *             DOCUMENT ME!
2796         */
2797        protected java.sql.Array getNativeArray(int i) throws SQLException {
2798                throw new NotImplemented();
2799        }
2800 
2801        /**
2802         * A column value can be retrieved as a stream of ASCII characters and then
2803         * read in chunks from the stream. This method is particulary suitable for
2804         * retrieving large LONGVARCHAR values. The JDBC driver will do any
2805         * necessary conversion from the database format into ASCII.
2806         * 
2807         * <p>
2808         * <B>Note:</B> All the data in the returned stream must be read prior to
2809         * getting the value of any other column. The next call to a get method
2810         * implicitly closes the stream. Also, a stream may return 0 for available()
2811         * whether there is data available or not.
2812         * </p>
2813         * 
2814         * @param columnIndex
2815         *            the first column is 1, the second is 2, ...
2816         * 
2817         * @return a Java InputStream that delivers the database column value as a
2818         *         stream of one byte ASCII characters. If the value is SQL NULL
2819         *         then the result is null
2820         * 
2821         * @exception SQLException
2822         *                if a database access error occurs
2823         * 
2824         * @see getBinaryStream
2825         */
2826        protected InputStream getNativeAsciiStream(int columnIndex)
2827                        throws SQLException {
2828                checkRowPos();
2829 
2830                return getNativeBinaryStream(columnIndex);
2831        }
2832 
2833        /**
2834         * JDBC 2.0 Get the value of a column in the current row as a
2835         * java.math.BigDecimal object.
2836         * 
2837         * @param columnIndex
2838         *            the first column is 1, the second is 2, ...
2839         * 
2840         * @return the column value (full precision); if the value is SQL NULL, the
2841         *         result is null
2842         * 
2843         * @exception SQLException
2844         *                if a database-access error occurs.
2845         */
2846        protected BigDecimal getNativeBigDecimal(int columnIndex)
2847                        throws SQLException {
2848 
2849                checkColumnBounds(columnIndex);
2850                
2851                int scale = this.fields[columnIndex - 1].getDecimals();
2852                
2853                return getNativeBigDecimal(columnIndex, scale);
2854        }
2855 
2856        /**
2857         * Get the value of a column in the current row as a java.math.BigDecimal
2858         * object
2859         * 
2860         * @param columnIndex
2861         *            the first column is 1, the second is 2...
2862         * @param scale
2863         *            the number of digits to the right of the decimal
2864         * 
2865         * @return the column value; if the value is SQL NULL, null
2866         * 
2867         * @exception SQLException
2868         *                if a database access error occurs
2869         */
2870        protected BigDecimal getNativeBigDecimal(int columnIndex, int scale)
2871                        throws SQLException {
2872                checkColumnBounds(columnIndex);
2873                
2874                String stringVal = null;
2875                
2876                Field f = this.fields[columnIndex - 1];
2877                
2878                if (this.thisRow[columnIndex - 1] == null) {
2879                        this.wasNullFlag = true;
2880                        
2881                        return null;
2882                }
2883                
2884                this.wasNullFlag = false;
2885                
2886                switch (f.getSQLType()) {
2887                        case Types.DECIMAL:
2888                        case Types.NUMERIC:
2889                                stringVal = StringUtils
2890                                                .toAsciiString((byte[]) this.thisRow[columnIndex - 1]);
2891                                break;
2892                        default:
2893                                stringVal = getNativeString(columnIndex);
2894                }
2895 
2896                return getBigDecimalFromString(stringVal, columnIndex, scale);
2897        }
2898 
2899        /**
2900         * A column value can also be retrieved as a binary strea. This method is
2901         * suitable for retrieving LONGVARBINARY values.
2902         * 
2903         * @param columnIndex
2904         *            the first column is 1, the second is 2...
2905         * 
2906         * @return a Java InputStream that delivers the database column value as a
2907         *         stream of bytes. If the value is SQL NULL, then the result is
2908         *         null
2909         * 
2910         * @exception SQLException
2911         *                if a database access error occurs
2912         * 
2913         * @see getAsciiStream
2914         * @see getUnicodeStream
2915         */
2916        protected InputStream getNativeBinaryStream(int columnIndex)
2917                        throws SQLException {
2918                checkRowPos();
2919 
2920                byte[] b = getNativeBytes(columnIndex, false);
2921 
2922                if (b != null) {
2923                        return new ByteArrayInputStream(b);
2924                }
2925 
2926                return null;
2927        }
2928 
2929        /**
2930         * JDBC 2.0 Get a BLOB column.
2931         * 
2932         * @param columnIndex
2933         *            the first column is 1, the second is 2, ...
2934         * 
2935         * @return an object representing a BLOB
2936         * 
2937         * @throws SQLException
2938         *             if an error occurs.
2939         */
2940        protected java.sql.Blob getNativeBlob(int columnIndex) throws SQLException {
2941                checkRowPos();
2942 
2943                checkColumnBounds(columnIndex);
2944 
2945                try {
2946                        if (this.thisRow[columnIndex - 1] == null) {
2947                                this.wasNullFlag = true;
2948                        } else {
2949                                this.wasNullFlag = false;
2950                        }
2951                } catch (NullPointerException ex) {
2952                        this.wasNullFlag = true;
2953                }
2954 
2955                if (this.wasNullFlag) {
2956                        return null;
2957                }
2958 
2959                int mysqlType = this.fields[columnIndex - 1].getMysqlType();
2960 
2961                byte[] dataAsBytes = null;
2962 
2963                switch (mysqlType) {
2964                case MysqlDefs.FIELD_TYPE_TINY_BLOB:
2965                case MysqlDefs.FIELD_TYPE_MEDIUM_BLOB:
2966                case MysqlDefs.FIELD_TYPE_LONG_BLOB:
2967                case MysqlDefs.FIELD_TYPE_BLOB:
2968                        dataAsBytes = (byte[]) this.thisRow[columnIndex - 1];
2969 
2970                default:
2971                        dataAsBytes = getNativeBytes(columnIndex, false);
2972                }
2973 
2974                if (!this.connection.getEmulateLocators()) {
2975                        return new Blob(dataAsBytes);
2976                }
2977 
2978                return new BlobFromLocator(this, columnIndex);
2979        }
2980 
2981        /**
2982         * Get the value of a column in the current row as a Java boolean
2983         * 
2984         * @param columnIndex
2985         *            the first column is 1, the second is 2...
2986         * 
2987         * @return the column value, false for SQL NULL
2988         * 
2989         * @exception SQLException
2990         *                if a database access error occurs
2991         */
2992        protected boolean getNativeBoolean(int columnIndex) throws SQLException {
2993                int columnIndexMinusOne = columnIndex - 1;
2994 
2995                Field field = this.fields[columnIndexMinusOne];
2996 
2997                if (field.getMysqlType() == MysqlDefs.FIELD_TYPE_BIT) {
2998                        if (this.thisRow[columnIndexMinusOne] == null) {
2999                                this.wasNullFlag = true;
3000 
3001                                return false;
3002                        }
3003 
3004                        this.wasNullFlag = false;
3005 
3006                        if (((byte[]) this.thisRow[columnIndexMinusOne]).length == 0) {
3007                                return false;
3008                        }
3009 
3010                        byte boolVal = ((byte[]) this.thisRow[columnIndexMinusOne])[0];
3011 
3012                        return (boolVal == -1 || boolVal > 0);
3013 
3014                }
3015 
3016                this.wasNullFlag = false;
3017                
3018                switch (field.getSQLType()) {
3019                case Types.BIT:
3020                case Types.BOOLEAN:
3021                case Types.TINYINT:
3022                case Types.SMALLINT:
3023                case Types.INTEGER:
3024                case Types.BIGINT:
3025                case Types.DECIMAL:
3026                case Types.NUMERIC:
3027                case Types.REAL:
3028                case Types.FLOAT:
3029                case Types.DOUBLE:
3030                        byte boolVal = getNativeByte(columnIndex);
3031 
3032                        return (boolVal == -1 || boolVal > 0);
3033                default:
3034                        if (this.useUsageAdvisor) {
3035                                issueConversionViaParsingWarning("getBoolean()", columnIndex,
3036                                                this.thisRow[columnIndex], this.fields[columnIndex],
3037                                                new int[] {
3038                                                                MysqlDefs.FIELD_TYPE_BIT,
3039                                                                MysqlDefs.FIELD_TYPE_DOUBLE,
3040                                                                MysqlDefs.FIELD_TYPE_TINY,
3041                                                                MysqlDefs.FIELD_TYPE_SHORT,
3042                                                                MysqlDefs.FIELD_TYPE_LONG,
3043                                                                MysqlDefs.FIELD_TYPE_LONGLONG,
3044                                                                MysqlDefs.FIELD_TYPE_FLOAT });
3045                        }
3046                
3047                        String stringVal = getNativeConvertToString(columnIndex, field);
3048 
3049                        return getBooleanFromString(stringVal, columnIndex);
3050                }
3051        }
3052 
3053        /**
3054         * Get the value of a column in the current row as a Java byte.
3055         * 
3056         * @param columnIndex
3057         *            the first column is 1, the second is 2,...
3058         * 
3059         * @return the column value; 0 if SQL NULL
3060         * 
3061         * @exception SQLException
3062         *                if a database access error occurs
3063         */
3064        protected byte getNativeByte(int columnIndex) throws SQLException {
3065                return getNativeByte(columnIndex, true);
3066        }
3067        
3068        protected byte getNativeByte(int columnIndex, boolean overflowCheck) throws SQLException {
3069                checkRowPos();
3070 
3071                checkColumnBounds(columnIndex);
3072 
3073                if (this.thisRow[columnIndex - 1] == null) {
3074                        this.wasNullFlag = true;
3075 
3076                        return 0;
3077                }
3078 
3079                try {
3080                        if (this.thisRow[columnIndex - 1] == null) {
3081                                this.wasNullFlag = true;
3082                        } else {
3083                                this.wasNullFlag = false;
3084                        }
3085                } catch (NullPointerException E) {
3086                        this.wasNullFlag = true;
3087                }
3088 
3089                if (this.wasNullFlag) {
3090                        return 0;
3091                }
3092 
3093                columnIndex--;
3094 
3095                Field field = this.fields[columnIndex];
3096 
3097                switch (field.getMysqlType()) {
3098                case MysqlDefs.FIELD_TYPE_BIT:
3099                        long valueAsLong = getNumericRepresentationOfSQLBitType(columnIndex + 1);
3100                        
3101                        if (overflowCheck && this.connection.getJdbcCompliantTruncationForReads() &&
3102                                        (valueAsLong < Byte.MIN_VALUE
3103                                                        || valueAsLong > Byte.MAX_VALUE)) {
3104                                throwRangeException(String.valueOf(valueAsLong), columnIndex + 1,
3105                                                Types.TINYINT);
3106                        }
3107                        
3108                        return (byte)valueAsLong;
3109                case MysqlDefs.FIELD_TYPE_TINY:
3110                        byte valueAsByte = ((byte[]) this.thisRow[columnIndex])[0];
3111                        
3112                        if (!field.isUnsigned()) {
3113                                return valueAsByte;
3114                        }
3115 
3116                        short valueAsShort = (valueAsByte >= 0) ? 
3117                                        valueAsByte : (short)(valueAsByte + (short)256);
3118                        
3119                        if (overflowCheck && this.connection.getJdbcCompliantTruncationForReads()) {
3120                                if (valueAsShort > Byte.MAX_VALUE) {
3121                                        throwRangeException(String.valueOf(valueAsShort),
3122                                                        columnIndex + 1, Types.TINYINT);
3123                                }
3124                        }
3125                        
3126                        return (byte)valueAsShort;
3127 
3128                case MysqlDefs.FIELD_TYPE_SHORT:
3129                case MysqlDefs.FIELD_TYPE_YEAR:
3130                        valueAsShort = getNativeShort(columnIndex + 1);
3131 
3132                        if (overflowCheck && this.connection.getJdbcCompliantTruncationForReads()) {
3133                                if (valueAsShort < Byte.MIN_VALUE
3134                                                || valueAsShort > Byte.MAX_VALUE) {
3135                                        throwRangeException(String.valueOf(valueAsShort),
3136                                                        columnIndex + 1, Types.TINYINT);
3137                                }
3138                        }
3139 
3140                        return (byte) valueAsShort;
3141                case MysqlDefs.FIELD_TYPE_INT24:
3142                case MysqlDefs.FIELD_TYPE_LONG:
3143                        int valueAsInt = getNativeInt(columnIndex + 1, false);
3144 
3145                        if (overflowCheck && this.connection.getJdbcCompliantTruncationForReads()) {
3146                                if (valueAsInt < Byte.MIN_VALUE || valueAsInt > Byte.MAX_VALUE) {
3147                                        throwRangeException(String.valueOf(valueAsInt),
3148                                                        columnIndex + 1, Types.TINYINT);
3149                                }
3150                        }
3151 
3152                        return (byte) valueAsInt;
3153 
3154                case MysqlDefs.FIELD_TYPE_FLOAT:
3155                        float valueAsFloat = getNativeFloat(columnIndex + 1);
3156 
3157                        if (overflowCheck && this.connection.getJdbcCompliantTruncationForReads()) {
3158                                if (valueAsFloat < Byte.MIN_VALUE
3159                                                || valueAsFloat > Byte.MAX_VALUE) {
3160 
3161                                        throwRangeException(String.valueOf(valueAsFloat),
3162                                                        columnIndex + 1, Types.TINYINT);
3163                                }
3164                        }
3165 
3166                        return (byte) valueAsFloat;
3167 
3168                case MysqlDefs.FIELD_TYPE_DOUBLE:
3169                        double valueAsDouble = getNativeDouble(columnIndex + 1);
3170 
3171                        if (overflowCheck && this.connection.getJdbcCompliantTruncationForReads()) {
3172                                if (valueAsDouble < Byte.MIN_VALUE
3173                                                || valueAsDouble > Byte.MAX_VALUE) {
3174                                        throwRangeException(String.valueOf(valueAsDouble),
3175                                                        columnIndex + 1, Types.TINYINT);
3176                                }
3177                        }
3178 
3179                        return (byte) valueAsDouble;
3180 
3181                case MysqlDefs.FIELD_TYPE_LONGLONG:
3182                        valueAsLong = getNativeLong(columnIndex + 1, false, true);
3183 
3184                        if (overflowCheck && this.connection.getJdbcCompliantTruncationForReads()) {
3185                                if (valueAsLong < Byte.MIN_VALUE
3186                                                || valueAsLong > Byte.MAX_VALUE) {
3187                                        throwRangeException(String.valueOf(valueAsLong),
3188                                                        columnIndex + 1, Types.TINYINT);
3189                                }
3190                        }
3191 
3192                        return (byte) valueAsLong;
3193 
3194                default:
3195                        if (this.useUsageAdvisor) {
3196                                issueConversionViaParsingWarning("getByte()", columnIndex,
3197                                                this.thisRow[columnIndex], this.fields[columnIndex],
3198                                                new int[] { MysqlDefs.FIELD_TYPE_DOUBLE,
3199                                                                MysqlDefs.FIELD_TYPE_TINY,
3200                                                                MysqlDefs.FIELD_TYPE_SHORT,
3201                                                                MysqlDefs.FIELD_TYPE_LONG,
3202                                                                MysqlDefs.FIELD_TYPE_LONGLONG,
3203                                                                MysqlDefs.FIELD_TYPE_FLOAT });
3204                        }
3205 
3206                        return getByteFromString(getNativeString(columnIndex + 1),
3207                                        columnIndex + 1);
3208                }
3209        }
3210 
3211        /**
3212         * Get the value of a column in the current row as a Java byte array.
3213         * 
3214         * <p>
3215         * <b>Be warned</b> If the blob is huge, then you may run out of memory.
3216         * </p>
3217         * 
3218         * @param columnIndex
3219         *            the first column is 1, the second is 2, ...
3220         * 
3221         * @return the column value; if the value is SQL NULL, the result is null
3222         * 
3223         * @exception SQLException
3224         *                if a database access error occurs
3225         */
3226        protected byte[] getNativeBytes(int columnIndex, boolean noConversion)
3227                        throws SQLException {
3228                checkRowPos();
3229 
3230                checkColumnBounds(columnIndex);
3231 
3232                try {
3233                        if (this.thisRow[columnIndex - 1] == null) {
3234                                this.wasNullFlag = true;
3235                        } else {
3236                                this.wasNullFlag = false;
3237                        }
3238                } catch (NullPointerException E) {
3239                        this.wasNullFlag = true;
3240                }
3241 
3242                if (this.wasNullFlag) {
3243                        return null;
3244                }
3245 
3246                Field field = this.fields[columnIndex - 1];
3247                
3248                int mysqlType = field.getMysqlType();
3249 
3250                // Workaround for emulated locators in servers > 4.1,
3251                // as server returns SUBSTRING(blob) as STRING type...
3252                if (noConversion) {
3253                        mysqlType = MysqlDefs.FIELD_TYPE_BLOB;
3254                }
3255 
3256                switch (mysqlType) {
3257                case MysqlDefs.FIELD_TYPE_TINY_BLOB:
3258                case MysqlDefs.FIELD_TYPE_MEDIUM_BLOB:
3259                case MysqlDefs.FIELD_TYPE_LONG_BLOB:
3260                case MysqlDefs.FIELD_TYPE_BLOB:
3261                case MysqlDefs.FIELD_TYPE_BIT:
3262                        return (byte[]) this.thisRow[columnIndex - 1];
3263 
3264                default:
3265                        int sqlType = field.getSQLType();
3266                
3267                        if (sqlType == Types.VARBINARY || sqlType == Types.BINARY) {
3268                                return (byte[]) this.thisRow[columnIndex - 1];
3269                        }
3270                
3271                        return getBytesFromString(getNativeString(columnIndex), columnIndex);
3272                }
3273        }
3274 
3275        /**
3276         * JDBC 2.0
3277         * 
3278         * <p>
3279         * Get the value of a column in the current row as a java.io.Reader.
3280         * </p>
3281         * 
3282         * @param columnIndex
3283         *            the column to get the value from
3284         * 
3285         * @return the value in the column as a java.io.Reader.
3286         * 
3287         * @throws SQLException
3288         *             if an error occurs
3289         */
3290        protected java.io.Reader getNativeCharacterStream(int columnIndex)
3291                        throws SQLException {
3292                String asString = null;
3293                
3294                asString = getStringForClob(columnIndex);
3295 
3296                if (asString == null) {
3297                        return null;
3298                }
3299                return getCharacterStreamFromString(asString, columnIndex);
3300        }
3301 
3302        /**
3303         * JDBC 2.0 Get a CLOB column.
3304         * 
3305         * @param columnIndex
3306         *            the first column is 1, the second is 2, ...
3307         * 
3308         * @return an object representing a CLOB
3309         * 
3310         * @throws SQLException
3311         *             if an error occurs
3312         */
3313        protected java.sql.Clob getNativeClob(int columnIndex) throws SQLException {
3314                String stringVal = getStringForClob(columnIndex);
3315 
3316                if (stringVal == null) {
3317                        return null;
3318                }
3319 
3320                return getClobFromString(stringVal, columnIndex);
3321        }
3322 
3323        private String getNativeConvertToString(int columnIndex, 
3324                        Field field)
3325                        throws SQLException {
3326 
3327                
3328                int sqlType = field.getSQLType();
3329                int mysqlType = field.getMysqlType();
3330 
3331                switch (sqlType) {
3332                case Types.BIT:
3333                        return String.valueOf(getNumericRepresentationOfSQLBitType(columnIndex));
3334                case Types.BOOLEAN:
3335                        boolean booleanVal = getNativeBoolean(columnIndex);
3336 
3337                        if (this.wasNullFlag) {
3338                                return null;
3339                        }
3340 
3341                        return String.valueOf(booleanVal);
3342 
3343                case Types.TINYINT:
3344                        byte tinyintVal = getNativeByte(columnIndex, false);
3345 
3346                        if (this.wasNullFlag) {
3347                                return null;
3348                        }
3349 
3350                        if (!field.isUnsigned() || tinyintVal >= 0) {
3351                                return String.valueOf(tinyintVal);
3352                        }
3353 
3354                        short unsignedTinyVal = (short) (tinyintVal & 0xff);
3355 
3356                        return String.valueOf(unsignedTinyVal);
3357 
3358                case Types.SMALLINT:
3359 
3360                        int intVal = getNativeInt(columnIndex, false);
3361 
3362                        if (this.wasNullFlag) {
3363                                return null;
3364                        }
3365 
3366                        if (!field.isUnsigned() || intVal >= 0) {
3367                                return String.valueOf(intVal);
3368                        }
3369 
3370                        intVal = intVal & 0xffff;
3371 
3372                        return String.valueOf(intVal);
3373 
3374                case Types.INTEGER:
3375                        intVal = getNativeInt(columnIndex, false);
3376 
3377                        if (this.wasNullFlag) {
3378                                return null;
3379                        }
3380 
3381                        if (!field.isUnsigned() || intVal >= 0
3382                                        || field.getMysqlType() == MysqlDefs.FIELD_TYPE_INT24) {
3383 
3384                                return String.valueOf(intVal);
3385                        }
3386 
3387                        long longVal = intVal & 0xffffffffL;
3388 
3389                        return String.valueOf(longVal);
3390 
3391                case Types.BIGINT:
3392 
3393                        if (!field.isUnsigned()) {
3394                                longVal = getNativeLong(columnIndex, false, true);
3395 
3396                                if (this.wasNullFlag) {
3397                                        return null;
3398                                }
3399 
3400                                return String.valueOf(longVal);
3401                        }
3402 
3403                        longVal = getNativeLong(columnIndex, false, false);
3404 
3405                        if (this.wasNullFlag) {
3406                                return null;
3407                        }
3408 
3409                        return String.valueOf(convertLongToUlong(longVal));
3410                case Types.REAL:
3411                        float floatVal = getNativeFloat(columnIndex);
3412 
3413                        if (this.wasNullFlag) {
3414                                return null;
3415                        }
3416 
3417                        return String.valueOf(floatVal);
3418 
3419                case Types.FLOAT:
3420                case Types.DOUBLE:
3421                        double doubleVal = getNativeDouble(columnIndex);
3422 
3423                        if (this.wasNullFlag) {
3424                                return null;
3425                        }
3426 
3427                        return String.valueOf(doubleVal);
3428 
3429                case Types.DECIMAL:
3430                case Types.NUMERIC:
3431                        String stringVal = StringUtils
3432                                        .toAsciiString((byte[]) this.thisRow[columnIndex - 1]);
3433 
3434                        BigDecimal val;
3435 
3436                        if (stringVal != null) {
3437                                this.wasNullFlag = false;
3438                                
3439                                if (stringVal.length() == 0) {
3440                                        val = new BigDecimal(0);
3441 
3442                                        return val.toString();
3443                                }
3444 
3445                                try {
3446                                        val = new BigDecimal(stringVal);
3447                                } catch (NumberFormatException ex) {
3448                                        throw SQLError.createSQLException(
3449                                                        Messages
3450                                                                        .getString("ResultSet.Bad_format_for_BigDecimal____86") //$NON-NLS-1$
3451                                                                        + stringVal
3452                                                                        + Messages
3453                                                                                        .getString("ResultSet.___in_column__87")
3454                                                                        + columnIndex + "(" //$NON-NLS-1$
3455                                                                        + this.fields[columnIndex - 1] + ").",
3456                                                        SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
3457                                }
3458 
3459                                return val.toString();
3460                        }
3461 
3462                        this.wasNullFlag = true;
3463                        
3464                        return null;
3465 
3466                case Types.CHAR:
3467                case Types.VARCHAR:
3468                case Types.LONGVARCHAR:
3469 
3470                        return extractStringFromNativeColumn(columnIndex, mysqlType);
3471                case Types.BINARY:
3472                case Types.VARBINARY:
3473                case Types.LONGVARBINARY:
3474 
3475                        if (!field.isBlob()) {
3476                                return extractStringFromNativeColumn(columnIndex, mysqlType);
3477                        } else if (!field.isBinary()) {
3478                                return extractStringFromNativeColumn(columnIndex, mysqlType);
3479                        } else {
3480                                byte[] data = getBytes(columnIndex);
3481                                Object obj = data;
3482 
3483                                if ((data != null) && (data.length >= 2)) {
3484                                        if ((data[0] == -84) && (data[1] == -19)) {
3485                                                // Serialized object?
3486                                                try {
3487                                                        ByteArrayInputStream bytesIn = new ByteArrayInputStream(
3488                                                                        data);
3489                                                        ObjectInputStream objIn = new ObjectInputStream(
3490                                                                        bytesIn);
3491                                                        obj = objIn.readObject();
3492                                                        objIn.close();
3493                                                        bytesIn.close();
3494                                                } catch (ClassNotFoundException cnfe) {
3495                                                        throw SQLError.createSQLException(
3496                                                                        Messages
3497                                                                                        .getString("ResultSet.Class_not_found___91") //$NON-NLS-1$
3498                                                                                        + cnfe.toString()
3499                                                                                        + Messages
3500                                                                                                        .getString("ResultSet._while_reading_serialized_object_92")); //$NON-NLS-1$
3501                                                } catch (IOException ex) {
3502                                                        obj = data; // not serialized?
3503                                                }
3504                                        }
3505 
3506                                        return obj.toString();
3507                                }
3508 
3509                                return extractStringFromNativeColumn(columnIndex, mysqlType);
3510                        }
3511 
3512                case Types.DATE:
3513 
3514                        // The YEAR datatype needs to be handled differently here.
3515                        if (mysqlType == MysqlDefs.FIELD_TYPE_YEAR) {
3516                                short shortVal = getNativeShort(columnIndex);
3517 
3518                                if (!this.connection.getYearIsDateType()) {
3519 
3520                                        if (this.wasNullFlag) {
3521                                                return null;
3522                                        }
3523 
3524                                        return String.valueOf(shortVal);
3525                                }
3526 
3527                                if (field.getLength() == 2) {
3528 
3529                                        if (shortVal <= 69) {
3530                                                shortVal = (short) (shortVal + 100);
3531                                        }
3532 
3533                                        shortVal += 1900;
3534                                }
3535 
3536                                return fastDateCreate(null, shortVal, 1, 1).toString();
3537 
3538                        }
3539 
3540                        Date dt = getNativeDate(columnIndex);
3541 
3542                        if (dt == null) {
3543                                return null;
3544                        }
3545 
3546                        return String.valueOf(dt);
3547 
3548                case Types.TIME:
3549                        Time tm = getNativeTime(columnIndex, null, this.defaultTimeZone, false);
3550 
3551                        if (tm == null) {
3552                                return null;
3553                        }
3554 
3555                        return String.valueOf(tm);
3556 
3557                case Types.TIMESTAMP:
3558                        Timestamp tstamp = getNativeTimestamp(columnIndex,
3559                                        null, this.defaultTimeZone, false);
3560 
3561                        if (tstamp == null) {
3562                                return null;
3563                        }
3564 
3565                        String result = String.valueOf(tstamp);
3566 
3567                        if (!this.connection.getNoDatetimeStringSync()) {
3568                                return result;
3569                        }
3570 
3571                        if (result.endsWith(".0")) {
3572                                return result.substring(0, result.length() - 2);
3573                        }
3574 
3575                default:
3576                        return extractStringFromNativeColumn(columnIndex, mysqlType);
3577                }
3578        }
3579 
3580        /**
3581         * Get the value of a column in the current row as a java.sql.Date object
3582         * 
3583         * @param columnIndex
3584         *            the first column is 1, the second is 2...
3585         * 
3586         * @return the column value; null if SQL NULL
3587         * 
3588         * @exception SQLException
3589         *                if a database access error occurs
3590         */
3591        protected java.sql.Date getNativeDate(int columnIndex) throws SQLException {
3592                return getNativeDate(columnIndex, null);
3593        }
3594 
3595        /**
3596         * JDBC 2.0 Get the value of a column in the current row as a java.sql.Date
3597         * object. Use the calendar to construct an appropriate millisecond value
3598         * for the Date, if the underlying database doesn't store timezone
3599         * information.
3600         * 
3601         * @param columnIndex
3602         *            the first column is 1, the second is 2, ...
3603         * @param tz
3604         *            the calendar to use in constructing the date
3605         * 
3606         * @return the column value; if the value is SQL NULL, the result is null
3607         * 
3608         * @exception SQLException
3609         *                if a database-access error occurs.
3610         */
3611        protected java.sql.Date getNativeDate(int columnIndex, TimeZone tz)
3612                        throws SQLException {
3613                checkRowPos();
3614                checkColumnBounds(columnIndex);
3615 
3616                int mysqlType = this.fields[columnIndex - 1].getMysqlType();
3617                
3618                if (mysqlType == MysqlDefs.FIELD_TYPE_DATE) {
3619                        byte[] bits = (byte[]) this.thisRow[columnIndex - 1];
3620 
3621                        if (bits == null) {
3622                                this.wasNullFlag = true;
3623 
3624                                return null;
3625                        }
3626 
3627                        this.wasNullFlag = false;
3628 
3629                        java.sql.Date dateToReturn = null;
3630 
3631                        int year = 0;
3632                        int month = 0;
3633                        int day = 0;
3634 
3635                        int hour = 0;
3636                        int minute = 0;
3637                        int seconds = 0;
3638 
3639                        if (bits.length != 0) {
3640                                year = (bits[0] & 0xff) | ((bits[1] & 0xff) << 8);
3641 
3642                                month = bits[2];
3643                                day = bits[3];
3644                        }
3645 
3646                        if ((year == 0) && (month == 0) && (day == 0)) {
3647                                if (ConnectionProperties.ZERO_DATETIME_BEHAVIOR_CONVERT_TO_NULL
3648                                                .equals(this.connection.getZeroDateTimeBehavior())) {
3649                                        this.wasNullFlag = true;
3650 
3651                                        return null;
3652                                } else if (ConnectionProperties.ZERO_DATETIME_BEHAVIOR_EXCEPTION
3653                                                .equals(this.connection.getZeroDateTimeBehavior())) {
3654                                        throw SQLError.createSQLException(
3655                                                        "Value '0000-00-00' can not be represented as java.sql.Date",
3656                                                        SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
3657                                }
3658 
3659                                year = 1;
3660                                month = 1;
3661                                day = 1;
3662                        }
3663 
3664                        return fastDateCreate(
3665                                        getCalendarInstanceForSessionOrNew(), year, month, day);
3666                }
3667 
3668                boolean rollForward = (tz != null && !tz.equals(this.getDefaultTimeZone()));
3669 
3670                return (Date)getNativeDateTimeValue(columnIndex, null, Types.DATE, mysqlType, 
3671                                        tz, rollForward);
3672        }
3673 
3674        private java.sql.Date getNativeDateViaParseConversion(int columnIndex) throws SQLException {
3675                if (this.useUsageAdvisor) {
3676                        issueConversionViaParsingWarning("getDate()", columnIndex,
3677                                        this.thisRow[columnIndex - 1], this.fields[columnIndex - 1],
3678                                        new int[] { MysqlDefs.FIELD_TYPE_DATE });
3679                }
3680 
3681                String stringVal = getNativeString(columnIndex);
3682 
3683                return getDateFromString(stringVal, columnIndex);
3684        }
3685 
3686        /**
3687         * Get the value of a column in the current row as a Java double.
3688         * 
3689         * @param columnIndex
3690         *            the first column is 1, the second is 2,...
3691         * 
3692         * @return the column value; 0 if SQL NULL
3693         * 
3694         * @exception SQLException
3695         *                if a database access error occurs
3696         */
3697        protected double getNativeDouble(int columnIndex) throws SQLException {
3698                checkRowPos();
3699                checkColumnBounds(columnIndex);
3700 
3701                columnIndex--; // / JDBC is 1-based
3702 
3703                if (this.thisRow[columnIndex] == null) {
3704                        this.wasNullFlag = true;
3705 
3706                        return 0;
3707                }
3708 
3709                this.wasNullFlag = false;
3710 
3711                Field f= this.fields[columnIndex];
3712                
3713                switch (f.getMysqlType()) {
3714                case MysqlDefs.FIELD_TYPE_DOUBLE:
3715                        byte[] bits = (byte[]) this.thisRow[columnIndex];
3716 
3717                        long valueAsLong = (bits[0] & 0xff)
3718                                        | ((long) (bits[1] & 0xff) << 8)
3719                                        | ((long) (bits[2] & 0xff) << 16)
3720                                        | ((long) (bits[3] & 0xff) << 24)
3721                                        | ((long) (bits[4] & 0xff) << 32)
3722                                        | ((long) (bits[5] & 0xff) << 40)
3723                                        | ((long) (bits[6] & 0xff) << 48)
3724                                        | ((long) (bits[7] & 0xff) << 56);
3725 
3726                        return Double.longBitsToDouble(valueAsLong);
3727                case MysqlDefs.FIELD_TYPE_TINY:
3728                        if (!f.isUnsigned()) {
3729                                return (double) getNativeByte(columnIndex + 1);
3730                        }
3731                        
3732                        return (double) getNativeShort(columnIndex + 1);
3733                case MysqlDefs.FIELD_TYPE_SHORT:
3734                case MysqlDefs.FIELD_TYPE_YEAR:
3735                        if (!f.isUnsigned()) {
3736                                return (double) getNativeShort(columnIndex + 1);
3737                        }
3738                        
3739                        return (double) getNativeInt(columnIndex + 1);
3740                case MysqlDefs.FIELD_TYPE_INT24:
3741                case MysqlDefs.FIELD_TYPE_LONG:
3742                        if (!f.isUnsigned()) {
3743                                return (double) getNativeInt(columnIndex + 1);
3744                        }
3745                        
3746                        return (double) getNativeLong(columnIndex + 1);
3747                case MysqlDefs.FIELD_TYPE_LONGLONG:
3748                        valueAsLong = getNativeLong(columnIndex + 1);
3749                        
3750                        if (!f.isUnsigned()) {
3751                                return (double) valueAsLong;
3752                        }
3753                        
3754                        BigInteger asBigInt = convertLongToUlong(valueAsLong);
3755                        
3756                        // TODO: Check for overflow
3757                        
3758                        return asBigInt.doubleValue();
3759                case MysqlDefs.FIELD_TYPE_FLOAT:
3760                        return (double) getNativeFloat(columnIndex + 1);
3761                case MysqlDefs.FIELD_TYPE_BIT:
3762                        return getNumericRepresentationOfSQLBitType(columnIndex + 1);
3763                default:
3764 
3765                        if (this.useUsageAdvisor) {
3766                                issueConversionViaParsingWarning("getDouble()", columnIndex,
3767                                                this.thisRow[columnIndex], this.fields[columnIndex],
3768                                                new int[] { MysqlDefs.FIELD_TYPE_DOUBLE,
3769                                                                MysqlDefs.FIELD_TYPE_TINY,
3770                                                                MysqlDefs.FIELD_TYPE_SHORT,
3771                                                                MysqlDefs.FIELD_TYPE_LONG,
3772                                                                MysqlDefs.FIELD_TYPE_LONGLONG,
3773                                                                MysqlDefs.FIELD_TYPE_FLOAT });
3774                        }
3775 
3776                        String stringVal = getNativeString(columnIndex + 1);
3777 
3778                        return getDoubleFromString(stringVal, columnIndex + 1);
3779                }
3780        }
3781 
3782        /**
3783         * Get the value of a column in the current row as a Java float.
3784         * 
3785         * @param columnIndex
3786         *            the first column is 1, the second is 2,...
3787         * 
3788         * @return the column value; 0 if SQL NULL
3789         * 
3790         * @exception SQLException
3791         *                if a database access error occurs
3792         */
3793        protected float getNativeFloat(int columnIndex) throws SQLException {
3794                checkRowPos();
3795                checkColumnBounds(columnIndex);
3796 
3797                columnIndex--; // / JDBC is 1-based
3798 
3799                if (this.thisRow[columnIndex] == null) {
3800                        this.wasNullFlag = true;
3801 
3802                        return 0;
3803                }
3804 
3805                this.wasNullFlag = false;
3806 
3807                Field f = this.fields[columnIndex];
3808                
3809                switch (f.getMysqlType()) {
3810                case MysqlDefs.FIELD_TYPE_BIT:
3811                        long valueAsLong = getNumericRepresentationOfSQLBitType(columnIndex + 1);
3812 
3813                        return valueAsLong;
3814                case MysqlDefs.FIELD_TYPE_DOUBLE:
3815                        
3816                        // Only foolproof way to check for overflow
3817                        // Not efficient, but if you don't want to be inefficient, use the
3818                        // correct binding for the type!
3819                        
3820                        Double valueAsDouble = new Double(getNativeDouble(columnIndex + 1));
3821                        
3822                        float valueAsFloat = valueAsDouble.floatValue();
3823                        
3824                        if (this.connection.getJdbcCompliantTruncationForReads() && 
3825                                        valueAsFloat == Float.NEGATIVE_INFINITY ||
3826                                        valueAsFloat == Float.POSITIVE_INFINITY) {
3827                                throwRangeException(valueAsDouble.toString(), 
3828                                                columnIndex + 1, Types.FLOAT);
3829                        }
3830 
3831                        return (float) getNativeDouble(columnIndex + 1);
3832                case MysqlDefs.FIELD_TYPE_TINY:
3833                        if (!f.isUnsigned()) {
3834                                return (float) getNativeByte(columnIndex + 1);
3835                        }
3836                        
3837                        return (float) getNativeShort(columnIndex + 1);
3838                case MysqlDefs.FIELD_TYPE_SHORT:
3839                case MysqlDefs.FIELD_TYPE_YEAR:
3840                        if (!f.isUnsigned()) {
3841                                return (float) getNativeShort(columnIndex + 1);
3842                        }
3843                        
3844                        return (float) getNativeInt(columnIndex + 1);
3845                case MysqlDefs.FIELD_TYPE_INT24:
3846                case MysqlDefs.FIELD_TYPE_LONG:
3847                        if (!f.isUnsigned()) {
3848                                return (float) getNativeInt(columnIndex + 1);
3849                        }
3850                        
3851                        return (float) getNativeLong(columnIndex + 1);
3852                case MysqlDefs.FIELD_TYPE_LONGLONG:
3853                        valueAsLong = getNativeLong(columnIndex + 1);
3854                        
3855                        if (!f.isUnsigned()) {
3856                                return (float) valueAsLong;
3857                        }
3858                        
3859                        BigInteger asBigInt = convertLongToUlong(valueAsLong);
3860                        
3861                        // TODO: Check for overflow
3862                        
3863                        return asBigInt.floatValue();
3864                case MysqlDefs.FIELD_TYPE_FLOAT:
3865                        byte[] bits = (byte[]) this.thisRow[columnIndex];
3866 
3867                        int asInt = (bits[0] & 0xff) | ((bits[1] & 0xff) << 8)
3868                                        | ((bits[2] & 0xff) << 16) | ((bits[3] & 0xff) << 24);
3869 
3870                        return Float.intBitsToFloat(asInt);
3871 
3872                default:
3873 
3874                        if (this.useUsageAdvisor) {
3875                                issueConversionViaParsingWarning("getFloat()", columnIndex,
3876                                                this.thisRow[columnIndex], this.fields[columnIndex],
3877                                                new int[] { MysqlDefs.FIELD_TYPE_DOUBLE,
3878                                                                MysqlDefs.FIELD_TYPE_TINY,
3879                                                                MysqlDefs.FIELD_TYPE_SHORT,
3880                                                                MysqlDefs.FIELD_TYPE_LONG,
3881                                                                MysqlDefs.FIELD_TYPE_LONGLONG,
3882                                                                MysqlDefs.FIELD_TYPE_FLOAT });
3883                        }
3884 
3885                        String stringVal = getNativeString(columnIndex + 1);
3886 
3887                        return getFloatFromString(stringVal, columnIndex + 1);
3888                }
3889        }
3890 
3891        /**
3892         * Get the value of a column in the current row as a Java int.
3893         * 
3894         * @param columnIndex
3895         *            the first column is 1, the second is 2,...
3896         * 
3897         * @return the column value; 0 if SQL NULL
3898         * 
3899         * @exception SQLException
3900         *                if a database access error occurs
3901         */
3902        protected int getNativeInt(int columnIndex) throws SQLException {
3903                return getNativeInt(columnIndex, true);
3904        }
3905        
3906        protected int getNativeInt(int columnIndex, boolean overflowCheck) throws SQLException {
3907                checkRowPos();
3908                checkColumnBounds(columnIndex);
3909 
3910                columnIndex--; // / JDBC is 1-based
3911 
3912                if (this.thisRow[columnIndex] == null) {
3913                        this.wasNullFlag = true;
3914 
3915                        return 0;
3916                }
3917 
3918                this.wasNullFlag = false;
3919 
3920                Field f = this.fields[columnIndex];
3921 
3922                switch (f.getMysqlType()) {
3923                case MysqlDefs.FIELD_TYPE_BIT:
3924                        long valueAsLong = getNumericRepresentationOfSQLBitType(columnIndex + 1);
3925                        
3926                        if (overflowCheck && this.connection.getJdbcCompliantTruncationForReads() &&
3927                                        (valueAsLong < Integer.MIN_VALUE
3928                                                        || valueAsLong > Integer.MAX_VALUE)) {
3929                                throwRangeException(String.valueOf(valueAsLong), columnIndex + 1,
3930                                                Types.INTEGER);
3931                        }
3932                        
3933                        return (short)valueAsLong;
3934                case MysqlDefs.FIELD_TYPE_TINY:
3935                        byte tinyintVal = getNativeByte(columnIndex + 1, false);
3936                        
3937                        if (!f.isUnsigned() || tinyintVal >= 0) {
3938                                return tinyintVal;
3939                        }
3940 
3941                        return tinyintVal + 256;
3942                case MysqlDefs.FIELD_TYPE_SHORT:
3943                case MysqlDefs.FIELD_TYPE_YEAR:
3944                        short asShort = getNativeShort(columnIndex + 1, false);
3945                        
3946                        if (!f.isUnsigned() || asShort >= 0) {
3947                                return asShort;
3948                        }
3949 
3950                        return asShort + 65536;
3951                case MysqlDefs.FIELD_TYPE_INT24:
3952                case MysqlDefs.FIELD_TYPE_LONG:
3953                        byte[] bits = (byte[]) this.thisRow[columnIndex];
3954 
3955                        int valueAsInt = (bits[0] & 0xff) | ((bits[1] & 0xff) << 8)
3956                                        | ((bits[2] & 0xff) << 16) | ((bits[3] & 0xff) << 24);
3957 
3958                        if (!f.isUnsigned()) {        
3959                                return valueAsInt;
3960                        }
3961                        
3962                        valueAsLong = (valueAsInt >= 0) ? 
3963                                        valueAsInt : valueAsInt + 4294967296L; 
3964                        
3965                        if (overflowCheck && this.connection.getJdbcCompliantTruncationForReads() &&
3966                                        valueAsLong > Integer.MAX_VALUE) {
3967                                throwRangeException(String.valueOf(valueAsLong),
3968                                                columnIndex + 1, Types.INTEGER);
3969                        }
3970                        
3971                        return (int)valueAsLong;
3972                case MysqlDefs.FIELD_TYPE_LONGLONG:
3973                        valueAsLong = getNativeLong(columnIndex + 1, false, true);
3974 
3975                        if (overflowCheck && this.connection.getJdbcCompliantTruncationForReads()) {
3976                                if (valueAsLong < Integer.MIN_VALUE
3977                                                || valueAsLong > Integer.MAX_VALUE) {
3978                                        throwRangeException(String.valueOf(valueAsLong),
3979                                                        columnIndex + 1, Types.INTEGER);
3980                                }
3981                        }
3982 
3983                        return (int) valueAsLong;
3984                case MysqlDefs.FIELD_TYPE_DOUBLE:
3985                        double valueAsDouble = getNativeDouble(columnIndex + 1);
3986 
3987                        if (overflowCheck && this.connection.getJdbcCompliantTruncationForReads()) {
3988                                if (valueAsDouble < Integer.MIN_VALUE
3989                                                || valueAsDouble > Integer.MAX_VALUE) {
3990                                        throwRangeException(String.valueOf(valueAsDouble),
3991                                                        columnIndex + 1, Types.INTEGER);
3992                                }
3993                        }
3994 
3995                        return (int) valueAsDouble;
3996                case MysqlDefs.FIELD_TYPE_FLOAT:
3997                        valueAsDouble = getNativeFloat(columnIndex + 1);
3998 
3999                        if (overflowCheck && this.connection.getJdbcCompliantTruncationForReads()) {
4000                                if (valueAsDouble < Integer.MIN_VALUE
4001                                                || valueAsDouble > Integer.MAX_VALUE) {
4002                                        throwRangeException(String.valueOf(valueAsDouble),
4003                                                        columnIndex + 1, Types.INTEGER);
4004                                }
4005                        }
4006 
4007                        return (int) valueAsDouble;
4008 
4009                default:
4010 
4011                        if (this.useUsageAdvisor) {
4012                                issueConversionViaParsingWarning("getInt()", columnIndex,
4013                                                this.thisRow[columnIndex], this.fields[columnIndex],
4014                                                new int[] { MysqlDefs.FIELD_TYPE_DOUBLE,
4015                                                                MysqlDefs.FIELD_TYPE_TINY,
4016                                                                MysqlDefs.FIELD_TYPE_SHORT,
4017                                                                MysqlDefs.FIELD_TYPE_LONG,
4018                                                                MysqlDefs.FIELD_TYPE_LONGLONG,
4019                                                                MysqlDefs.FIELD_TYPE_FLOAT });
4020                        }
4021 
4022                        String stringVal = getNativeString(columnIndex + 1);
4023 
4024                        return getIntFromString(stringVal, columnIndex + 1);
4025                }
4026        }
4027 
4028        /**
4029         * Get the value of a column in the current row as a Java long.
4030         * 
4031         * @param columnIndex
4032         *            the first column is 1, the second is 2,...
4033         * 
4034         * @return the column value; 0 if SQL NULL
4035         * 
4036         * @exception SQLException
4037         *                if a database access error occurs
4038         */
4039        protected long getNativeLong(int columnIndex) throws SQLException {
4040                return getNativeLong(columnIndex, true, true);
4041        }
4042        
4043        protected long getNativeLong(int columnIndex, boolean overflowCheck, 
4044                        boolean expandUnsignedLong) throws SQLException {
4045                checkRowPos();
4046                checkColumnBounds(columnIndex);
4047 
4048                columnIndex--; // / JDBC is 1-based
4049 
4050                if (this.thisRow[columnIndex] == null) {
4051                        this.wasNullFlag = true;
4052 
4053                        return 0;
4054                }
4055 
4056                this.wasNullFlag = false;
4057 
4058                Field f = this.fields[columnIndex];
4059 
4060                switch (f.getMysqlType()) {
4061                case MysqlDefs.FIELD_TYPE_BIT:
4062                        return getNumericRepresentationOfSQLBitType(columnIndex + 1);
4063                case MysqlDefs.FIELD_TYPE_TINY:
4064                        if (!f.isUnsigned()) {
4065                                return getNativeByte(columnIndex + 1);
4066                        }
4067 
4068                        return getNativeInt(columnIndex + 1);
4069                case MysqlDefs.FIELD_TYPE_SHORT:
4070                        if (!f.isUnsigned()) {
4071                                return getNativeShort(columnIndex + 1);
4072                        }
4073 
4074                        return getNativeInt(columnIndex + 1, false);
4075                case MysqlDefs.FIELD_TYPE_YEAR:
4076 
4077                        return getNativeShort(columnIndex + 1);
4078                case MysqlDefs.FIELD_TYPE_INT24:
4079                case MysqlDefs.FIELD_TYPE_LONG:
4080                        int asInt = getNativeInt(columnIndex + 1, false);
4081                        
4082                        if (!f.isUnsigned() || asInt >= 0) {
4083                                return asInt;
4084                        }
4085 
4086                        return asInt + 4294967296L;
4087                case MysqlDefs.FIELD_TYPE_LONGLONG:
4088 
4089                        byte[] bits = (byte[]) this.thisRow[columnIndex];
4090 
4091                        long valueAsLong = (bits[0] & 0xff)
4092                                        | ((long) (bits[1] & 0xff) << 8)
4093                                        | ((long) (bits[2] & 0xff) << 16)
4094                                        | ((long) (bits[3] & 0xff) << 24)
4095                                        | ((long) (bits[4] & 0xff) << 32)
4096                                        | ((long) (bits[5] & 0xff) << 40)
4097                                        | ((long) (bits[6] & 0xff) << 48)
4098                                        | ((long) (bits[7] & 0xff) << 56);
4099 
4100                        if (!f.isUnsigned() || !expandUnsignedLong) {
4101                                return valueAsLong;
4102                        }
4103                        
4104                        BigInteger asBigInt = convertLongToUlong(valueAsLong);
4105                        
4106                        if (overflowCheck && this.connection.getJdbcCompliantTruncationForReads() && 
4107                                        ((asBigInt.compareTo(new BigInteger(String.valueOf(Long.MAX_VALUE))) > 0 ) ||
4108                                         (asBigInt.compareTo(new BigInteger(String.valueOf(Long.MIN_VALUE))) < 0))) {
4109                                throwRangeException(asBigInt.toString(),
4110                                                columnIndex + 1, Types.BIGINT);
4111                        }
4112                        
4113                        return getLongFromString(asBigInt.toString(), columnIndex + 1);
4114 
4115                case MysqlDefs.FIELD_TYPE_DOUBLE:
4116                        double valueAsDouble = getNativeDouble(columnIndex + 1);
4117 
4118                        if (overflowCheck && this.connection.getJdbcCompliantTruncationForReads()) {
4119                                if (valueAsDouble < Long.MIN_VALUE
4120                                                || valueAsDouble > Long.MAX_VALUE) {
4121                                        throwRangeException(String.valueOf(valueAsDouble),
4122                                                        columnIndex + 1, Types.BIGINT);
4123                                }
4124                        }
4125 
4126                        return (long) valueAsDouble;
4127                case MysqlDefs.FIELD_TYPE_FLOAT:
4128                        valueAsDouble = getNativeFloat(columnIndex + 1);
4129 
4130                        if (overflowCheck && this.connection.getJdbcCompliantTruncationForReads()) {
4131                                if (valueAsDouble < Long.MIN_VALUE
4132                                                || valueAsDouble > Long.MAX_VALUE) {
4133                                        throwRangeException(String.valueOf(valueAsDouble),
4134                                                        columnIndex + 1, Types.BIGINT);
4135                                }
4136                        }
4137 
4138                        return (long) valueAsDouble;
4139                default:
4140 
4141                        if (this.useUsageAdvisor) {
4142                                issueConversionViaParsingWarning("getLong()", columnIndex,
4143                                                this.thisRow[columnIndex], this.fields[columnIndex],
4144                                                new int[] { MysqlDefs.FIELD_TYPE_DOUBLE,
4145                                                                MysqlDefs.FIELD_TYPE_TINY,
4146                                                                MysqlDefs.FIELD_TYPE_SHORT,
4147                                                                MysqlDefs.FIELD_TYPE_LONG,
4148                                                                MysqlDefs.FIELD_TYPE_LONGLONG,
4149                                                                MysqlDefs.FIELD_TYPE_FLOAT });
4150                        }
4151 
4152                        String stringVal = getNativeString(columnIndex + 1);
4153 
4154                        return getLongFromString(stringVal, columnIndex + 1);
4155                }
4156        }
4157 
4158        /**
4159         * JDBC 2.0 Get a REF(&lt;structured-type&gt;) column.
4160         * 
4161         * @param i
4162         *            the first column is 1, the second is 2, ...
4163         * 
4164         * @return an object representing data of an SQL REF type
4165         * 
4166         * @throws SQLException
4167         *             as this is not implemented
4168         * @throws NotImplemented
4169         *             DOCUMENT ME!
4170         */
4171        protected java.sql.Ref getNativeRef(int i) throws SQLException {
4172                throw new NotImplemented();
4173        }
4174 
4175        /**
4176         * Get the value of a column in the current row as a Java short.
4177         * 
4178         * @param columnIndex
4179         *            the first column is 1, the second is 2,...
4180         * 
4181         * @return the column value; 0 if SQL NULL
4182         * 
4183         * @exception SQLException
4184         *                if a database access error occurs
4185         */
4186        protected short getNativeShort(int columnIndex) throws SQLException {
4187                return getNativeShort(columnIndex, true);
4188        }
4189        
4190        protected short getNativeShort(int columnIndex, boolean overflowCheck) throws SQLException {
4191                checkRowPos();
4192                checkColumnBounds(columnIndex);
4193 
4194                columnIndex--; // / JDBC is 1-based
4195 
4196                if (this.thisRow[columnIndex] == null) {
4197                        this.wasNullFlag = true;
4198 
4199                        return 0;
4200                }
4201 
4202                this.wasNullFlag = false;
4203 
4204                Field f = this.fields[columnIndex];
4205 
4206                switch (f.getMysqlType()) {
4207 
4208                case MysqlDefs.FIELD_TYPE_TINY:
4209                        byte tinyintVal = getNativeByte(columnIndex + 1, false);
4210                        
4211                        if (!f.isUnsigned() || tinyintVal >= 0) {
4212                     return tinyintVal;
4213                        }
4214                        
4215                        return (short)(tinyintVal + (short)256);
4216                case MysqlDefs.FIELD_TYPE_SHORT:
4217                case MysqlDefs.FIELD_TYPE_YEAR:
4218                        byte[] bits = (byte[]) this.thisRow[columnIndex];
4219                        
4220                        short asShort = (short) ((bits[0] & 0xff) | ((bits[1] & 0xff) << 8));
4221 
4222                        if (!f.isUnsigned()) {
4223                                return asShort;
4224                        }
4225                        
4226                        int valueAsInt = asShort & 0xffff;
4227                        
4228                        if (overflowCheck && this.connection.getJdbcCompliantTruncationForReads() &&
4229                                        valueAsInt > Short.MAX_VALUE) {
4230                                throwRangeException(String.valueOf(valueAsInt),
4231                                                columnIndex + 1, Types.SMALLINT);
4232                        }
4233                        
4234                        return (short)valueAsInt;
4235                case MysqlDefs.FIELD_TYPE_INT24:
4236                case MysqlDefs.FIELD_TYPE_LONG:
4237                        if (!f.isUnsigned()) {
4238                                valueAsInt = getNativeInt(columnIndex + 1, false);
4239                                
4240                                if (overflowCheck && this.connection.getJdbcCompliantTruncationForReads() &&
4241                                                valueAsInt > Short.MAX_VALUE ||
4242                                                valueAsInt < Short.MIN_VALUE) {
4243                                        throwRangeException(String.valueOf(valueAsInt),
4244                                                        columnIndex + 1, Types.SMALLINT);
4245                                }
4246                                
4247                                return (short)valueAsInt;
4248                        }
4249                        
4250                        long valueAsLong = getNativeLong(columnIndex + 1, false, true);
4251                        
4252                        if (overflowCheck && this.connection.getJdbcCompliantTruncationForReads() &&
4253                                        valueAsLong > Short.MAX_VALUE) {
4254                                throwRangeException(String.valueOf(valueAsLong),
4255                                                columnIndex + 1, Types.SMALLINT);
4256                        }
4257                        
4258                        return (short)valueAsLong;
4259                        
4260                case MysqlDefs.FIELD_TYPE_LONGLONG:
4261                        valueAsLong = getNativeLong(columnIndex + 1, false, false);
4262                        
4263                        if (!f.isUnsigned()) {
4264                                if (overflowCheck && this.connection.getJdbcCompliantTruncationForReads()) {
4265                                        if (valueAsLong < Short.MIN_VALUE
4266                                                        || valueAsLong > Short.MAX_VALUE) {
4267                                                throwRangeException(String.valueOf(valueAsLong),
4268                                                                columnIndex + 1, Types.SMALLINT);
4269                                        }
4270                                }
4271        
4272                                return (short) valueAsLong;
4273                        }
4274                        
4275                        BigInteger asBigInt = convertLongToUlong(valueAsLong);
4276                        
4277                        if (overflowCheck && this.connection.getJdbcCompliantTruncationForReads() && 
4278                                        ((asBigInt.compareTo(new BigInteger(String.valueOf(Short.MAX_VALUE))) > 0 ) ||
4279                                         (asBigInt.compareTo(new BigInteger(String.valueOf(Short.MIN_VALUE))) < 0))) {
4280                                throwRangeException(asBigInt.toString(),
4281                                                columnIndex + 1, Types.SMALLINT);
4282                        }
4283                        
4284                        return (short)getIntFromString(asBigInt.toString(), columnIndex + 1);
4285 
4286                case MysqlDefs.FIELD_TYPE_DOUBLE:
4287                        double valueAsDouble = getNativeDouble(columnIndex + 1);
4288 
4289                        if (overflowCheck && this.connection.getJdbcCompliantTruncationForReads()) {
4290                                if (valueAsDouble < Short.MIN_VALUE
4291                                                || valueAsDouble > Short.MAX_VALUE) {
4292                                        throwRangeException(String.valueOf(valueAsDouble),
4293                                                        columnIndex + 1, Types.SMALLINT);
4294                                }
4295                        }
4296 
4297                        return (short) valueAsDouble;
4298                case MysqlDefs.FIELD_TYPE_FLOAT:
4299                        float valueAsFloat = getNativeFloat(columnIndex + 1);
4300 
4301                        if (overflowCheck && this.connection.getJdbcCompliantTruncationForReads()) {
4302                                if (valueAsFloat < Short.MIN_VALUE
4303                                                || valueAsFloat > Short.MAX_VALUE) {
4304                                        throwRangeException(String.valueOf(valueAsFloat),
4305                                                        columnIndex + 1, Types.SMALLINT);
4306                                }
4307                        }
4308 
4309                        return (short) valueAsFloat;
4310                default:
4311 
4312                        if (this.useUsageAdvisor) {
4313                                issueConversionViaParsingWarning("getShort()", columnIndex,
4314                                                this.thisRow[columnIndex], this.fields[columnIndex],
4315                                                new int[] { MysqlDefs.FIELD_TYPE_DOUBLE,
4316                                                                MysqlDefs.FIELD_TYPE_TINY,
4317                                                                MysqlDefs.FIELD_TYPE_SHORT,
4318                                                                MysqlDefs.FIELD_TYPE_LONG,
4319                                                                MysqlDefs.FIELD_TYPE_LONGLONG,
4320                                                                MysqlDefs.FIELD_TYPE_FLOAT });
4321                        }
4322 
4323                        String stringVal = getNativeString(columnIndex + 1);
4324 
4325                        return getShortFromString(stringVal, columnIndex + 1);
4326                }
4327        }
4328 
4329        /**
4330         * Get the value of a column in the current row as a Java String
4331         * 
4332         * @param columnIndex
4333         *            the first column is 1, the second is 2...
4334         * 
4335         * @return the column value, null for SQL NULL
4336         * 
4337         * @exception SQLException
4338         *                if a database access error occurs
4339         */
4340        protected String getNativeString(int columnIndex) throws SQLException {
4341                checkRowPos();
4342                checkColumnBounds(columnIndex);
4343 
4344                if (this.fields == null) {
4345                        throw SQLError.createSQLException(
4346                                        Messages
4347                                                        .getString("ResultSet.Query_generated_no_fields_for_ResultSet_133"), //$NON-NLS-1$
4348                                        SQLError.SQL_STATE_INVALID_COLUMN_NUMBER);
4349                }
4350 
4351                try {
4352                        if (this.thisRow[columnIndex - 1] == null) {
4353                                this.wasNullFlag = true;
4354 
4355                                return null;
4356                        }
4357 
4358                        this.wasNullFlag = false;
4359                } catch (NullPointerException E) {
4360                        this.wasNullFlag = true;
4361 
4362                        return null;
4363                }
4364 
4365                String stringVal = null;
4366 
4367                if (this.thisRow[columnIndex - 1] instanceof String) {
4368                        return (String) this.thisRow[columnIndex - 1];
4369                }
4370 
4371                Field field = this.fields[columnIndex - 1];
4372 
4373                // TODO: Check Types Here.
4374                stringVal = getNativeConvertToString(columnIndex, field);
4375 
4376                if (field.isZeroFill() && (stringVal != null)) {
4377                        int origLength = stringVal.length();
4378 
4379                        StringBuffer zeroFillBuf = new StringBuffer(origLength);
4380 
4381                        long numZeros = field.getLength() - origLength;
4382 
4383                        for (long i = 0; i < numZeros; i++) {
4384                                zeroFillBuf.append('0');
4385                        }
4386 
4387                        zeroFillBuf.append(stringVal);
4388 
4389                        stringVal = zeroFillBuf.toString();
4390                }
4391 
4392                return stringVal;
4393                // }
4394        }
4395 
4396        private Time getNativeTime(int columnIndex, Calendar targetCalendar,
4397                        TimeZone tz, boolean rollForward)
4398                        throws SQLException {
4399                checkRowPos();
4400                checkColumnBounds(columnIndex);
4401 
4402                if (this.thisRow[columnIndex - 1] == null) {
4403                        this.wasNullFlag = true;
4404 
4405                        return null;
4406                } else {
4407                        this.wasNullFlag = false;
4408                }
4409 
4410                int mysqlType = this.fields[columnIndex - 1].getMysqlType();
4411 
4412                if (mysqlType == MysqlDefs.FIELD_TYPE_TIME) {
4413 
4414                        byte[] bits = (byte[]) this.thisRow[columnIndex - 1];
4415 
4416                        int length = bits.length;
4417                        int hour = 0;
4418                        int minute = 0;
4419                        int seconds = 0;
4420 
4421                        if (length != 0) {
4422                                // bits[0] // skip tm->neg
4423                                // binaryData.readLong(); // skip daysPart
4424                                hour = bits[5];
4425                                minute = bits[6];
4426                                seconds = bits[7];
4427                        }
4428 
4429                        Calendar sessionCalendar = getCalendarInstanceForSessionOrNew();
4430                        
4431                        synchronized (sessionCalendar) {
4432                                Time time = TimeUtil
4433                                                .fastTimeCreate(sessionCalendar, hour,
4434                                                                minute, seconds);
4435        
4436                                Time adjustedTime = TimeUtil.changeTimezone(this.connection, 
4437                                                sessionCalendar,
4438                                                targetCalendar,
4439                                                time,
4440                                                this.connection.getServerTimezoneTZ(), tz, rollForward);
4441 
4442                                return adjustedTime;
4443                        }
4444                }
4445 
4446                return (Time)getNativeDateTimeValue(columnIndex, targetCalendar,
4447                                Types.TIME, mysqlType, 
4448                                tz, rollForward);
4449        }
4450        
4451        private Time getNativeTimeViaParseConversion(int columnIndex, Calendar targetCalendar,
4452                        TimeZone tz, boolean rollForward) throws SQLException {
4453                if (this.useUsageAdvisor) {
4454                        issueConversionViaParsingWarning("getTime()", columnIndex,
4455                                        this.thisRow[columnIndex - 1], this.fields[columnIndex - 1],
4456                                        new int[] { MysqlDefs.FIELD_TYPE_TIME });
4457                }
4458        
4459                String strTime = getNativeString(columnIndex);
4460        
4461                return getTimeFromString(strTime, targetCalendar, columnIndex, tz, rollForward);
4462        }
4463 
4464        private Timestamp getNativeTimestamp(int columnIndex, 
4465                        Calendar targetCalendar,
4466                        TimeZone tz,
4467                        boolean rollForward) throws SQLException {
4468                checkRowPos();
4469                checkColumnBounds(columnIndex);
4470 
4471                if (this.thisRow[columnIndex - 1] == null) {
4472                        this.wasNullFlag = true;
4473 
4474                        return null;
4475                }
4476 
4477                this.wasNullFlag = false;
4478 
4479                int mysqlType = this.fields[columnIndex - 1].getMysqlType();
4480 
4481                switch (mysqlType) {
4482                case MysqlDefs.FIELD_TYPE_DATETIME:
4483                case MysqlDefs.FIELD_TYPE_TIMESTAMP:
4484                        byte[] bits = (byte[]) this.thisRow[columnIndex - 1];
4485 
4486                        int length = bits.length;
4487 
4488                        int year = 0;
4489                        int month = 0;
4490                        int day = 0;
4491 
4492                        int hour = 0;
4493                        int minute = 0;
4494                        int seconds = 0;
4495 
4496                        int nanos = 0;
4497 
4498                        if (length != 0) {
4499                                year = (bits[0] & 0xff) | ((bits[1] & 0xff) << 8);
4500                                month = bits[2];
4501                                day = bits[3];
4502 
4503                                if (length > 4) {
4504                                        hour = bits[4];
4505                                        minute = bits[5];
4506                                        seconds = bits[6];
4507                                }
4508 
4509                                if (length > 7) {
4510                                        nanos = (bits[7] & 0xff) | ((bits[8] & 0xff) << 8)
4511                                                        | ((bits[9] & 0xff) << 16)
4512                                                        | ((bits[10] & 0xff) << 24);
4513                                }
4514                        }
4515 
4516                        if ((year == 0) && (month == 0) && (day == 0)) {
4517                                if (ConnectionProperties.ZERO_DATETIME_BEHAVIOR_CONVERT_TO_NULL
4518                                                .equals(this.connection.getZeroDateTimeBehavior())) {
4519                                        this.wasNullFlag = true;
4520 
4521                                        return null;
4522                                } else if (ConnectionProperties.ZERO_DATETIME_BEHAVIOR_EXCEPTION
4523                                                .equals(this.connection.getZeroDateTimeBehavior())) {
4524                                        throw SQLError.createSQLException(
4525                                                        "Value '0000-00-00' can not be represented as java.sql.Timestamp",
4526                                                        SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
4527                                }
4528 
4529                                year = 1;
4530                                month = 1;
4531                                day = 1;
4532                        }
4533 
4534                        Calendar sessionCalendar = this.connection.getUseJDBCCompliantTimezoneShift() ?
4535                                        this.connection.getUtcCalendar() : 
4536                                                getCalendarInstanceForSessionOrNew();
4537                        
4538                        synchronized (sessionCalendar) {
4539                                Timestamp ts = fastTimestampCreate(
4540                                                sessionCalendar, year, month, day,
4541                                                hour, minute, seconds, nanos);
4542        
4543                                Timestamp adjustedTs = TimeUtil.changeTimezone(
4544                                                this.connection, sessionCalendar,
4545                                                targetCalendar,
4546                                                ts,
4547                                                this.connection.getServerTimezoneTZ(), tz, rollForward);
4548                                
4549                                return adjustedTs;
4550                        }
4551 
4552                default:
4553                        return (Timestamp)getNativeDateTimeValue(columnIndex, targetCalendar,
4554                                        Types.TIMESTAMP, mysqlType, 
4555                                        tz, rollForward);
4556                }
4557        }
4558 
4559        private Timestamp getNativeTimestampViaParseConversion(int columnIndex, Calendar targetCalendar, 
4560                        TimeZone tz, boolean rollForward) throws SQLException {
4561                if (this.useUsageAdvisor) {
4562                        issueConversionViaParsingWarning("getTimestamp()", columnIndex,
4563                                        this.thisRow[columnIndex - 1], this.fields[columnIndex - 1],
4564                                        new int[] { MysqlDefs.FIELD_TYPE_TIMESTAMP,
4565                                                        MysqlDefs.FIELD_TYPE_DATETIME });
4566                }
4567 
4568                String strTimestamp = getNativeString(columnIndex);
4569 
4570                return getTimestampFromString(columnIndex, targetCalendar, strTimestamp, tz,
4571                                rollForward);
4572        }
4573 
4574        // ---------------------------------------------------------------------
4575        // Updates
4576        // ---------------------------------------------------------------------
4577 
4578        /**
4579         * A column value can also be retrieved as a stream of Unicode characters.
4580         * We implement this as a binary stream.
4581         * 
4582         * @param columnIndex
4583         *            the first column is 1, the second is 2...
4584         * 
4585         * @return a Java InputStream that delivers the database column value as a
4586         *         stream of two byte Unicode characters. If the value is SQL NULL,
4587         *         then the result is null
4588         * 
4589         * @exception SQLException
4590         *                if a database access error occurs
4591         * 
4592         * @see getAsciiStream
4593         * @see getBinaryStream
4594         */
4595        protected InputStream getNativeUnicodeStream(int columnIndex)
4596                        throws SQLException {
4597                checkRowPos();
4598 
4599                return getBinaryStream(columnIndex);
4600        }
4601 
4602        /**
4603         * @see ResultSet#getURL(int)
4604         */
4605        protected URL getNativeURL(int colIndex) throws SQLException {
4606                String val = getString(colIndex);
4607 
4608                if (val == null) {
4609                        return null;
4610                }
4611 
4612                try {
4613                        return new URL(val);
4614                } catch (MalformedURLException mfe) {
4615                        throw SQLError.createSQLException(Messages
4616                                        .getString("ResultSet.Malformed_URL____141")
4617                                        + val + "'", SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$
4618                }
4619        }
4620 
4621        /**
4622         * DOCUMENT ME!
4623         * 
4624         * @return Returns the nextResultSet, if any, null if none exists.
4625         */
4626        protected ResultSet getNextResultSet() {
4627                return this.nextResultSet;
4628        }
4629 
4630        /**
4631         * Get the value of a column in the current row as a Java object
4632         * 
4633         * <p>
4634         * This method will return the value of the given column as a Java object.
4635         * The type of the Java object will be the default Java Object type
4636         * corresponding to the column's SQL type, following the mapping specified
4637         * in the JDBC specification.
4638         * </p>
4639         * 
4640         * <p>
4641         * This method may also be used to read database specific abstract data
4642         * types.
4643         * </p>
4644         * 
4645         * @param columnIndex
4646         *            the first column is 1, the second is 2...
4647         * 
4648         * @return a Object holding the column value
4649         * 
4650         * @exception SQLException
4651         *                if a database access error occurs
4652         */
4653        public Object getObject(int columnIndex) throws SQLException {
4654                checkRowPos();
4655 
4656                try {
4657                        if (this.thisRow[columnIndex - 1] == null) {
4658                                this.wasNullFlag = true;
4659 
4660                                return null;
4661                        }
4662                } catch (ArrayIndexOutOfBoundsException aioobEx) {
4663                        throw SQLError.createSQLException(Messages.getString(
4664                                        "ResultSet.Column_Index_out_of_range", new Object[] {
4665                                                        new Integer(columnIndex),
4666                                                        new Integer(this.fields.length) }),
4667                                        SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$
4668                }
4669 
4670                this.wasNullFlag = false;
4671 
4672                Field field;
4673                field = this.fields[columnIndex - 1];
4674 
4675                //
4676                // If they come from a binary-encode result set,
4677                // no need to create another new object to represent
4678                // the value, just return it directly, unless it's
4679                // a byte[], which means it could be a string or blob.
4680                //
4681                if (this.isBinaryEncoded
4682                                && !(this.thisRow[columnIndex - 1] instanceof byte[])) {
4683 
4684                        //
4685                        // Special case here...If this is a 'bit' type, it will actually
4686                        // have
4687                        // been returned as an Integer by the server...
4688                        //
4689                        if (field.getSQLType() == Types.BIT && field.getLength() > 0) {
4690                                // valueOf would be nicer here, but it isn't
4691                                // present in JDK-1.3.1, which is what the CTS
4692                                // uses.
4693                                return new Boolean(getBoolean(columnIndex));
4694                        }
4695 
4696                        Object columnValue = this.thisRow[columnIndex - 1];
4697 
4698                        if (columnValue == null) {
4699                                this.wasNullFlag = true;
4700 
4701                                return null;
4702                        }
4703 
4704                        return columnValue;
4705                }
4706 
4707                switch (field.getSQLType()) {
4708                case Types.BIT:
4709                case Types.BOOLEAN:
4710                        if (field.getMysqlType() == MysqlDefs.FIELD_TYPE_BIT
4711                                        && !field.isSingleBit()) {
4712                                return getBytes(columnIndex);
4713                        }
4714 
4715                        // valueOf would be nicer here, but it isn't
4716                        // present in JDK-1.3.1, which is what the CTS
4717                        // uses.
4718                        return new Boolean(getBoolean(columnIndex));
4719 
4720                case Types.TINYINT:
4721                        if (!field.isUnsigned()) {
4722                                return new Integer(getByte(columnIndex));
4723                        }
4724 
4725                        return new Integer(getInt(columnIndex));
4726 
4727                case Types.SMALLINT:
4728 
4729                        return new Integer(getInt(columnIndex));
4730 
4731                case Types.INTEGER:
4732 
4733                        if (!field.isUnsigned() || 
4734                                        field.getMysqlType() == MysqlDefs.FIELD_TYPE_INT24) {
4735                                return new Integer(getInt(columnIndex));
4736                        }
4737 
4738                        return new Long(getLong(columnIndex));
4739                        
4740                case Types.BIGINT:
4741 
4742                        if (!field.isUnsigned()) {
4743                                return new Long(getLong(columnIndex));
4744                        }
4745 
4746                        String stringVal = getString(columnIndex);
4747 
4748                        if (stringVal == null) {
4749                                return null;
4750                        }
4751 
4752                        try {
4753                                return new BigInteger(stringVal);
4754                        } catch (NumberFormatException nfe) {
4755                                throw SQLError.createSQLException(Messages.getString(
4756                                                "ResultSet.Bad_format_for_BigInteger", new Object[] {
4757                                                                new Integer(columnIndex), stringVal }),
4758                                                SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$
4759                        }
4760 
4761                case Types.DECIMAL:
4762                case Types.NUMERIC:
4763                        stringVal = getString(columnIndex);
4764 
4765                        BigDecimal val;
4766 
4767                        if (stringVal != null) {
4768                                if (stringVal.length() == 0) {
4769                                        val = new BigDecimal(0);
4770 
4771                                        return val;
4772                                }
4773 
4774                                try {
4775                                        val = new BigDecimal(stringVal);
4776                                } catch (NumberFormatException ex) {
4777                                        throw SQLError.createSQLException(
4778                                                        Messages
4779                                                                        .getString("ResultSet.Bad_format_for_BigDecimal____86") //$NON-NLS-1$
4780                                                                        + stringVal
4781                                                                        + Messages
4782                                                                                        .getString("ResultSet.___in_column__87")
4783                                                                        + columnIndex + "(" //$NON-NLS-1$
4784                                                                        + this.fields[columnIndex - 1] + ").",
4785                                                        SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
4786                                }
4787 
4788                                return val;
4789                        }
4790 
4791                        return null;
4792 
4793                case Types.REAL:
4794                        return new Float(getFloat(columnIndex));
4795 
4796                case Types.FLOAT:
4797                case Types.DOUBLE:
4798                        return new Double(getDouble(columnIndex));
4799 
4800                case Types.CHAR:
4801                case Types.VARCHAR:
4802                        if (!field.isOpaqueBinary()) {
4803                                return getString(columnIndex);
4804                        }
4805 
4806                        return getBytes(columnIndex);
4807                case Types.LONGVARCHAR:
4808                        if (!field.isOpaqueBinary()) {
4809                                return getStringForClob(columnIndex);
4810                        }
4811 
4812                        return getBytes(columnIndex);
4813 
4814                case Types.BINARY:
4815                case Types.VARBINARY:
4816                case Types.LONGVARBINARY:
4817                        if (field.getMysqlType() == MysqlDefs.FIELD_TYPE_GEOMETRY) {
4818                                return getBytes(columnIndex);
4819                        } else if (field.isBinary() || field.isBlob()) {
4820                                byte[] data = getBytes(columnIndex);
4821 
4822                                if (this.connection.getAutoDeserialize()) {
4823                                        Object obj = data;
4824 
4825                                        if ((data != null) && (data.length >= 2)) {
4826                                                if ((data[0] == -84) && (data[1] == -19)) {
4827                                                        // Serialized object?
4828                                                        try {
4829                                                                ByteArrayInputStream bytesIn = new ByteArrayInputStream(
4830                                                                                data);
4831                                                                ObjectInputStream objIn = new ObjectInputStream(
4832                                                                                bytesIn);
4833                                                                obj = objIn.readObject();
4834                                                                objIn.close();
4835                                                                bytesIn.close();
4836                                                        } catch (ClassNotFoundException cnfe) {
4837                                                                throw SQLError.createSQLException(
4838                                                                                Messages
4839                                                                                                .getString("ResultSet.Class_not_found___91") //$NON-NLS-1$
4840                                                                                                + cnfe.toString()
4841                                                                                                + Messages
4842                                                                                                                .getString("ResultSet._while_reading_serialized_object_92")); //$NON-NLS-1$
4843                                                        } catch (IOException ex) {
4844                                                                obj = data; // not serialized?
4845                                                        }
4846                                                } else {
4847                                                        return getString(columnIndex);
4848                                                }
4849                                        }
4850 
4851                                        return obj;
4852                                }
4853 
4854                                return data;
4855                        }
4856 
4857                case Types.DATE:
4858                        if (field.getMysqlType() == MysqlDefs.FIELD_TYPE_YEAR
4859                                        && !this.connection.getYearIsDateType()) {
4860                                return new Short(getShort(columnIndex));
4861                        }
4862 
4863                        return getDate(columnIndex);
4864 
4865                case Types.TIME:
4866                        return getTime(columnIndex);
4867 
4868                case Types.TIMESTAMP:
4869                        return getTimestamp(columnIndex);
4870 
4871                default:
4872                        return getString(columnIndex);
4873                }
4874        }
4875 
4876        /**
4877         * JDBC 2.0 Returns the value of column i as a Java object. Use the map to
4878         * determine the class from which to construct data of SQL structured and
4879         * distinct types.
4880         * 
4881         * @param i
4882         *            the first column is 1, the second is 2, ...
4883         * @param map
4884         *            the mapping from SQL type names to Java classes
4885         * 
4886         * @return an object representing the SQL value
4887         * 
4888         * @throws SQLException
4889         *             because this is not implemented
4890         */
4891        public Object getObject(int i, java.util.Map map) throws SQLException {
4892                return getObject(i);
4893        }
4894 
4895        /**
4896         * Get the value of a column in the current row as a Java object
4897         * 
4898         * <p>
4899         * This method will return the value of the given column as a Java object.
4900         * The type of the Java object will be the default Java Object type
4901         * corresponding to the column's SQL type, following the mapping specified
4902         * in the JDBC specification.
4903         * </p>
4904         * 
4905         * <p>
4906         * This method may also be used to read database specific abstract data
4907         * types.
4908         * </p>
4909         * 
4910         * @param columnName
4911         *            is the SQL name of the column
4912         * 
4913         * @return a Object holding the column value
4914         * 
4915         * @exception SQLException
4916         *                if a database access error occurs
4917         */
4918        public Object getObject(String columnName) throws SQLException {
4919                return getObject(findColumn(columnName));
4920        }
4921 
4922        /**
4923         * JDBC 2.0 Returns the value of column i as a Java object. Use the map to
4924         * determine the class from which to construct data of SQL structured and
4925         * distinct types.
4926         * 
4927         * @param colName
4928         *            the column name
4929         * @param map
4930         *            the mapping from SQL type names to Java classes
4931         * 
4932         * @return an object representing the SQL value
4933         * 
4934         * @throws SQLException
4935         *             as this is not implemented
4936         */
4937        public Object getObject(String colName, java.util.Map map)
4938                        throws SQLException {
4939                return getObject(findColumn(colName), map);
4940        }
4941 
4942        protected Object getObjectStoredProc(int columnIndex, int desiredSqlType)
4943                        throws SQLException {
4944                checkRowPos();
4945 
4946                try {
4947                        if (this.thisRow[columnIndex - 1] == null) {
4948                                this.wasNullFlag = true;
4949 
4950                                return null;
4951                        }
4952                } catch (ArrayIndexOutOfBoundsException aioobEx) {
4953                        throw SQLError.createSQLException(Messages.getString(
4954                                        "ResultSet.Column_Index_out_of_range", new Object[] {
4955                                                        new Integer(columnIndex),
4956                                                        new Integer(this.fields.length) }),
4957                                        SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$
4958                }
4959 
4960                this.wasNullFlag = false;
4961 
4962                Field field;
4963                field = this.fields[columnIndex - 1];
4964 
4965                switch (desiredSqlType) {
4966                case Types.BIT:
4967                case Types.BOOLEAN:
4968                        // valueOf would be nicer here, but it isn't
4969                        // present in JDK-1.3.1, which is what the CTS
4970                        // uses.
4971                        return new Boolean(getBoolean(columnIndex));
4972 
4973                case Types.TINYINT:
4974                        return new Integer(getInt(columnIndex));
4975 
4976                case Types.SMALLINT:
4977                        return new Integer(getInt(columnIndex));
4978 
4979                case Types.INTEGER:
4980 
4981                        if (!field.isUnsigned() || 
4982                                        field.getMysqlType() == MysqlDefs.FIELD_TYPE_INT24) {
4983                                return new Integer(getInt(columnIndex));
4984                        }
4985 
4986                        return new Long(getLong(columnIndex));
4987 
4988                case Types.BIGINT:
4989 
4990                        if (field.isUnsigned()) {
4991                                return getBigDecimal(columnIndex);
4992                        }
4993 
4994                        return new Long(getLong(columnIndex));
4995 
4996                case Types.DECIMAL:
4997                case Types.NUMERIC:
4998 
4999                        String stringVal = getString(columnIndex);
5000                        BigDecimal val;
5001 
5002                        if (stringVal != null) {
5003                                if (stringVal.length() == 0) {
5004                                        val = new BigDecimal(0);
5005 
5006                                        return val;
5007                                }
5008 
5009                                try {
5010                                        val = new BigDecimal(stringVal);
5011                                } catch (NumberFormatException ex) {
5012                                        throw SQLError.createSQLException(
5013                                                        Messages
5014                                                                        .getString("ResultSet.Bad_format_for_BigDecimal____86") //$NON-NLS-1$
5015                                                                        + stringVal
5016                                                                        + Messages
5017                                                                                        .getString("ResultSet.___in_column__87")
5018                                                                        + columnIndex + "(" //$NON-NLS-1$
5019                                                                        + this.fields[columnIndex - 1] + ").",
5020                                                        SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
5021                                }
5022 
5023                                return val;
5024                        }
5025 
5026                        return null;
5027 
5028                case Types.REAL:
5029                        return new Float(getFloat(columnIndex));
5030 
5031                case Types.FLOAT:
5032 
5033                        if (!this.connection.getRunningCTS13()) {
5034                                return new Double(getFloat(columnIndex));
5035                        } else {
5036                                return new Float(getFloat(columnIndex)); // NB - bug in JDBC
5037                                                                                                                        // compliance test,
5038                                                                                                                        // according
5039                                // to JDBC spec, FLOAT type should return DOUBLE
5040                                // but causes ClassCastException in CTS :(
5041                        }
5042                case Types.DOUBLE:
5043                        return new Double(getDouble(columnIndex));
5044 
5045                case Types.CHAR:
5046                case Types.VARCHAR:
5047                        return getString(columnIndex);
5048                case Types.LONGVARCHAR:
5049                        return getStringForClob(columnIndex);
5050                case Types.BINARY:
5051                case Types.VARBINARY:
5052                case Types.LONGVARBINARY:
5053                        return getBytes(columnIndex);
5054 
5055                case Types.DATE:
5056                        if (field.getMysqlType() == MysqlDefs.FIELD_TYPE_YEAR
5057                                        && !this.connection.getYearIsDateType()) {
5058                                return new Short(getShort(columnIndex));
5059                        }
5060 
5061                        return getDate(columnIndex);
5062 
5063                case Types.TIME:
5064                        return getTime(columnIndex);
5065 
5066                case Types.TIMESTAMP:
5067                        return getTimestamp(columnIndex);
5068 
5069                default:
5070                        return getString(columnIndex);
5071                }
5072        }
5073 
5074        protected Object getObjectStoredProc(int i, java.util.Map map,
5075                        int desiredSqlType) throws SQLException {
5076                return getObjectStoredProc(i, desiredSqlType);
5077        }
5078 
5079        protected Object getObjectStoredProc(String columnName, int desiredSqlType)
5080                        throws SQLException {
5081                return getObjectStoredProc(findColumn(columnName), desiredSqlType);
5082        }
5083 
5084        protected Object getObjectStoredProc(String colName, java.util.Map map,
5085                        int desiredSqlType) throws SQLException {
5086                return getObjectStoredProc(findColumn(colName), map, desiredSqlType);
5087        }
5088 
5089        /**
5090         * JDBC 2.0 Get a REF(&lt;structured-type&gt;) column.
5091         * 
5092         * @param i
5093         *            the first column is 1, the second is 2, ...
5094         * 
5095         * @return an object representing data of an SQL REF type
5096         * 
5097         * @throws SQLException
5098         *             as this is not implemented
5099         * @throws NotImplemented
5100         *             DOCUMENT ME!
5101         */
5102        public java.sql.Ref getRef(int i) throws SQLException {
5103                checkColumnBounds(i);
5104                throw new NotImplemented();
5105        }
5106 
5107        /**
5108         * JDBC 2.0 Get a REF(&lt;structured-type&gt;) column.
5109         * 
5110         * @param colName
5111         *            the column name
5112         * 
5113         * @return an object representing data of an SQL REF type
5114         * 
5115         * @throws SQLException
5116         *             as this method is not implemented.
5117         * @throws NotImplemented
5118         *             DOCUMENT ME!
5119         */
5120        public java.sql.Ref getRef(String colName) throws SQLException {
5121                return getRef(findColumn(colName));
5122        }
5123 
5124        /**
5125         * JDBC 2.0
5126         * 
5127         * <p>
5128         * Determine the current row number. The first row is number 1, the second
5129         * number 2, etc.
5130         * </p>
5131         * 
5132         * @return the current row number, else return 0 if there is no current row
5133         * 
5134         * @exception SQLException
5135         *                if a database-access error occurs.
5136         */
5137        public int getRow() throws SQLException {
5138                checkClosed();
5139 
5140                int currentRowNumber = this.rowData.getCurrentRowNumber();
5141                int row = 0;
5142 
5143                // Non-dynamic result sets can be interrogated
5144                // for this information
5145                if (!this.rowData.isDynamic()) {
5146                        if ((currentRowNumber < 0) || this.rowData.isAfterLast()
5147                                        || this.rowData.isEmpty()) {
5148                                row = 0;
5149                        } else {
5150                                row = currentRowNumber + 1;
5151                        }
5152                } else {
5153                        // dynamic (streaming) can not
5154                        row = currentRowNumber + 1;
5155                }
5156 
5157                return row;
5158        }
5159 
5160        /**
5161         * Returns the server info (if any), or null if none.
5162         * 
5163         * @return server info created for this ResultSet
5164         */
5165        protected String getServerInfo() {
5166                return this.serverInfo;
5167        }
5168 
5169        private long getNumericRepresentationOfSQLBitType(int columnIndex) throws SQLException {
5170                
5171                if (this.fields[columnIndex - 1].isSingleBit() || 
5172                                ((byte[])this.thisRow[columnIndex - 1]).length == 1) {
5173                        return ((byte[])this.thisRow[columnIndex - 1])[0];
5174                }
5175                
5176                
5177                byte[] asBytes = (byte[])this.thisRow[columnIndex - 1];
5178                
5179                
5180                int shift = 0;
5181                
5182                long[] steps = new long[asBytes.length];
5183                
5184                for (int i = asBytes.length - 1; i >= 0; i--) {
5185                        steps[i] = (long)(asBytes[i] & 0xff) << shift;
5186                        shift += 8;
5187                }
5188                
5189                long valueAsLong = 0;
5190                
5191                for (int i = 0; i < asBytes.length; i++) {
5192                        valueAsLong |= steps[i];
5193                }
5194                
5195                return valueAsLong;
5196        }
5197 
5198        /**
5199         * Get the value of a column in the current row as a Java short.
5200         * 
5201         * @param columnIndex
5202         *            the first column is 1, the second is 2,...
5203         * 
5204         * @return the column value; 0 if SQL NULL
5205         * 
5206         * @exception SQLException
5207         *                if a database access error occurs
5208         */
5209        public short getShort(int columnIndex) throws SQLException {
5210                if (!this.isBinaryEncoded) {
5211                        checkRowPos();
5212                        
5213                        if (this.connection.getUseFastIntParsing()) {
5214                                
5215                                checkColumnBounds(columnIndex);
5216                                
5217                                try {
5218                                        if (this.thisRow[columnIndex - 1] == null) {
5219                                                this.wasNullFlag = true;
5220                                        } else {
5221                                                this.wasNullFlag = false;
5222                                        }
5223                                } catch (NullPointerException E) {
5224                                        this.wasNullFlag = true;
5225                                } catch (ArrayIndexOutOfBoundsException aioobEx) {
5226                                        throw SQLError.createSQLException(Messages.getString(
5227                                                        "ResultSet.Column_Index_out_of_range",
5228                                                        new Object[] { new Integer(columnIndex),
5229                                                                        new Integer(this.fields.length) }),
5230                                                        SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$
5231                                }
5232 
5233                                if (this.wasNullFlag) {
5234                                        return 0;
5235                                }
5236 
5237                                byte[] shortAsBytes = (byte[]) this.thisRow[columnIndex - 1];
5238 
5239                                if (shortAsBytes.length == 0) {
5240                                        return (short) convertToZeroWithEmptyCheck();
5241                                }
5242 
5243                                boolean needsFullParse = false;
5244 
5245                                for (int i = 0; i < shortAsBytes.length; i++) {
5246                                        if (((char) shortAsBytes[i] == 'e')
5247                                                        || ((char) shortAsBytes[i] == 'E')) {
5248                                                needsFullParse = true;
5249 
5250                                                break;
5251                                        }
5252                                }
5253 
5254                                if (!needsFullParse) {
5255                                        try {
5256                                                return parseShortWithOverflowCheck(columnIndex,
5257                                                                shortAsBytes, null);
5258                                        } catch (NumberFormatException nfe) {
5259                                                try {
5260                                                        // To do: Warn of over/underflow???
5261                                                        return parseShortAsDouble(columnIndex, new String(
5262                                                                        shortAsBytes));
5263                                                } catch (NumberFormatException newNfe) {
5264                                                        ; // ignore, it's not a number
5265                                                }
5266 
5267                                                if (this.fields[columnIndex - 1].getMysqlType() == MysqlDefs.FIELD_TYPE_BIT) {
5268                                                        long valueAsLong = getNumericRepresentationOfSQLBitType(columnIndex);
5269                                                        
5270                                                        if (this.connection.getJdbcCompliantTruncationForReads() &&
5271                                                                        (valueAsLong < Short.MIN_VALUE
5272                                                                                        || valueAsLong > Short.MAX_VALUE)) {
5273                                                                throwRangeException(String.valueOf(valueAsLong), columnIndex,
5274                                                                                Types.SMALLINT);
5275                                                        }
5276                                                        
5277                                                        return (short)valueAsLong;
5278                                                }
5279                                                
5280                                                throw SQLError.createSQLException(
5281                                                                Messages
5282                                                                                .getString("ResultSet.Invalid_value_for_getShort()_-____96")
5283                                                                                + new String(shortAsBytes) //$NON-NLS-1$
5284                                                                                + "'",
5285                                                                SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
5286                                        }
5287                                }
5288                        }
5289 
5290                        String val = null;
5291 
5292                        try {
5293                                val = getString(columnIndex);
5294 
5295                                if ((val != null)) {
5296 
5297                                        if (val.length() == 0) {
5298                                                return (short) convertToZeroWithEmptyCheck();
5299                                        }
5300 
5301                                        if ((val.indexOf("e") == -1) && (val.indexOf("E") == -1)
5302                                                        && (val.indexOf(".") == -1)) {
5303                                                return parseShortWithOverflowCheck(columnIndex, null,
5304                                                                val);
5305                                        }
5306 
5307                                        // Convert floating point
5308                                        return parseShortAsDouble(columnIndex, val);
5309                                }
5310 
5311                                return 0; // for NULL
5312                        } catch (NumberFormatException nfe) {
5313                                try {
5314                                        return parseShortAsDouble(columnIndex, val);
5315                                } catch (NumberFormatException newNfe) {
5316                                        ; // ignore, it's not a number
5317                                }
5318 
5319                                if (this.fields[columnIndex - 1].getMysqlType() == MysqlDefs.FIELD_TYPE_BIT) {
5320                                        long valueAsLong = getNumericRepresentationOfSQLBitType(columnIndex);
5321                                        
5322                                        if (this.connection.getJdbcCompliantTruncationForReads() &&
5323                                                        (valueAsLong < Short.MIN_VALUE
5324                                                                        || valueAsLong > Short.MAX_VALUE)) {
5325                                                throwRangeException(String.valueOf(valueAsLong), columnIndex,
5326                                                                Types.SMALLINT);
5327                                        }
5328                                        
5329                                        return (short)valueAsLong;
5330                                }
5331                                
5332                                throw SQLError.createSQLException(
5333                                                Messages
5334                                                                .getString("ResultSet.Invalid_value_for_getShort()_-____96")
5335                                                                + val //$NON-NLS-1$
5336                                                                + "'", SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
5337                        }
5338                }
5339 
5340                return getNativeShort(columnIndex);
5341        }
5342 
5343        /**
5344         * DOCUMENT ME!
5345         * 
5346         * @param columnName
5347         *            DOCUMENT ME!
5348         * 
5349         * @return DOCUMENT ME!
5350         * 
5351         * @throws SQLException
5352         *             DOCUMENT ME!
5353         */
5354        public short getShort(String columnName) throws SQLException {
5355                return getShort(findColumn(columnName));
5356        }
5357 
5358        private final short getShortFromString(String val, int columnIndex)
5359                        throws SQLException {
5360                try {
5361                        if ((val != null)) {
5362 
5363                                if (val.length() == 0) {
5364                                        return (short) convertToZeroWithEmptyCheck();
5365                                }
5366 
5367                                if ((val.indexOf("e") == -1) && (val.indexOf("E") == -1)
5368                                                && (val.indexOf(".") == -1)) {
5369                                        return parseShortWithOverflowCheck(columnIndex, null, val);
5370                                }
5371 
5372                                // Convert floating point
5373                                return parseShortAsDouble(columnIndex, val);
5374                        }
5375 
5376                        return 0; // for NULL
5377                } catch (NumberFormatException nfe) {
5378                        try {
5379                                return parseShortAsDouble(columnIndex, val);
5380                        } catch (NumberFormatException newNfe) {
5381                                ; // ignore, it's not a number
5382                        }
5383 
5384                        throw SQLError.createSQLException(
5385                                        Messages
5386                                                        .getString("ResultSet.Invalid_value_for_getShort()_-____217")
5387                                                        + val //$NON-NLS-1$
5388                                                        + Messages.getString("ResultSet.___in_column__218")
5389                                                        + columnIndex, SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$
5390                }
5391        }
5392 
5393        /**
5394         * JDBC 2.0 Return the Statement that produced the ResultSet.
5395         * 
5396         * @return the Statment that produced the result set, or null if the result
5397         *         was produced some other way.
5398         * 
5399         * @exception SQLException
5400         *                if a database-access error occurs
5401         */
5402        public java.sql.Statement getStatement() throws SQLException {
5403                if (this.isClosed && !this.retainOwningStatement) {
5404                        throw SQLError.createSQLException(
5405                                        "Operation not allowed on closed ResultSet. Statements "
5406                                                        + "can be retained over result set closure by setting the connection property "
5407                                                        + "\"retainStatementAfterResultSetClose\" to \"true\".",
5408                                        SQLError.SQL_STATE_GENERAL_ERROR);
5409 
5410                }
5411                
5412                if (this.wrapperStatement != null) {
5413                        return this.wrapperStatement;
5414                }
5415 
5416                return this.owningStatement;
5417        }
5418 
5419        /**
5420         * Get the value of a column in the current row as a Java String
5421         * 
5422         * @param columnIndex
5423         *            the first column is 1, the second is 2...
5424         * 
5425         * @return the column value, null for SQL NULL
5426         * 
5427         * @exception SQLException
5428         *                if a database access error occurs
5429         */
5430        public String getString(int columnIndex) throws SQLException {
5431                return getStringInternal(columnIndex, true);
5432        }
5433 
5434        /**
5435         * The following routines simply convert the columnName into a columnIndex
5436         * and then call the appropriate routine above.
5437         * 
5438         * @param columnName
5439         *            is the SQL name of the column
5440         * 
5441         * @return the column value
5442         * 
5443         * @exception SQLException
5444         *                if a database access error occurs
5445         */
5446        public String getString(String columnName) throws SQLException {
5447                return getString(findColumn(columnName));
5448        }
5449 
5450        private String getStringForClob(int columnIndex) throws SQLException {
5451                String asString = null;
5452                
5453                String forcedEncoding = 
5454                        this.connection.getClobCharacterEncoding();
5455                
5456                if (forcedEncoding == null) {
5457                        if (!this.isBinaryEncoded) {
5458                                asString = getString(columnIndex);
5459                        } else {
5460                                asString = getNativeString(columnIndex);
5461                        }
5462                } else {
5463                        try {
5464                                byte[] asBytes = null;
5465                                
5466                                if (!this.isBinaryEncoded) {
5467                                        asBytes = getBytes(columnIndex);
5468                                } else {
5469                                        asBytes = getNativeBytes(columnIndex, true);
5470                                }
5471                                
5472                                if (asBytes != null) {
5473                                        asString = new String(asBytes, forcedEncoding);
5474                                }
5475                        } catch (UnsupportedEncodingException uee) {
5476                                throw SQLError.createSQLException("Unsupported character encoding " + 
5477                                                forcedEncoding, SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
5478                        }
5479                }
5480                
5481                return asString;
5482        }
5483 
5484        protected String getStringInternal(int columnIndex, boolean checkDateTypes)
5485                        throws SQLException {
5486                if (!this.isBinaryEncoded) {
5487                        checkRowPos();
5488                        checkColumnBounds(columnIndex);
5489 
5490                        if (this.fields == null) {
5491                                throw SQLError.createSQLException(
5492                                                Messages
5493                                                                .getString("ResultSet.Query_generated_no_fields_for_ResultSet_99"), //$NON-NLS-1$
5494                                                SQLError.SQL_STATE_INVALID_COLUMN_NUMBER);
5495                        }
5496 
5497                        try {
5498                                if (this.thisRow[columnIndex - 1] == null) {
5499                                        this.wasNullFlag = true;
5500 
5501                                        return null;
5502                                }
5503 
5504                                this.wasNullFlag = false;
5505                        } catch (NullPointerException E) {
5506                                this.wasNullFlag = true;
5507 
5508                                return null;
5509                        }
5510 
5511                        String stringVal = null;
5512                        columnIndex--; // JDBC is 1-based, Java is not !?
5513 
5514                        if (this.fields[columnIndex].getMysqlType() == MysqlDefs.FIELD_TYPE_BIT) {
5515                                if (this.fields[columnIndex].isSingleBit()) {
5516                                        byte[] asBytes = (byte[])this.thisRow[columnIndex];
5517                                        
5518                                        if (asBytes.length == 0) {
5519                                                return String.valueOf(convertToZeroWithEmptyCheck());
5520                                        }
5521                                        
5522                                        return String.valueOf(asBytes[0]);
5523                                }
5524                                
5525                                return String.valueOf(getNumericRepresentationOfSQLBitType(columnIndex + 1));
5526                        }
5527                        
5528                        String encoding = this.fields[columnIndex].getCharacterSet();
5529 
5530                        if ((this.connection != null) && this.connection.getUseUnicode()) {
5531                                try {
5532                                        if (encoding == null) {
5533                                                stringVal = new String(
5534                                                                (byte[]) this.thisRow[columnIndex]);
5535                                        } else {
5536                                                SingleByteCharsetConverter converter = this.connection
5537                                                                .getCharsetConverter(encoding);
5538 
5539                                                if (converter != null) {
5540                                                        stringVal = converter
5541                                                                        .toString((byte[]) this.thisRow[columnIndex]);
5542                                                } else {
5543                                                        stringVal = new String(
5544                                                                        (byte[]) this.thisRow[columnIndex],
5545                                                                        encoding);
5546                                                }
5547                                        }
5548                                } catch (java.io.UnsupportedEncodingException E) {
5549                                        throw SQLError.createSQLException(
5550                                                        Messages
5551                                                                        .getString("ResultSet.Unsupported_character_encoding____101") //$NON-NLS-1$
5552                                                                        + encoding + "'.", "0S100");
5553                                }
5554                        } else {
5555                                stringVal = StringUtils
5556                                                .toAsciiString((byte[]) this.thisRow[columnIndex]);
5557                        }
5558 
5559                        //
5560                        // Special handling for YEAR type from mysql, some people
5561                        // want it as a DATE, others want to treat it as a SHORT
5562                        //
5563 
5564                        if (this.fields[columnIndex].getMysqlType() == MysqlDefs.FIELD_TYPE_YEAR) {
5565                                if (!this.connection.getYearIsDateType()) {
5566                                        return stringVal;
5567                                }
5568 
5569                                Date dt = getDateFromString(stringVal, columnIndex + 1);
5570 
5571                                if (dt == null) {
5572                                        this.wasNullFlag = true;
5573 
5574                                        return null;
5575                                }
5576 
5577                                this.wasNullFlag = false;
5578 
5579                                return dt.toString();
5580                        }
5581 
5582                        // Handles timezone conversion and zero-date behavior
5583 
5584                        if (checkDateTypes && !this.connection.getNoDatetimeStringSync()) {
5585                                switch (this.fields[columnIndex].getSQLType()) {
5586                                case Types.TIME:
5587                                        Time tm = getTimeFromString(stringVal, null, columnIndex + 1,
5588                                                        this.getDefaultTimeZone(), false);
5589 
5590                                        if (tm == null) {
5591                                                this.wasNullFlag = true;
5592 
5593                                                return null;
5594                                        }
5595 
5596                                        this.wasNullFlag = false;
5597 
5598                                        return tm.toString();
5599                                case Types.DATE:
5600 
5601                                        Date dt = getDateFromString(stringVal, columnIndex + 1);
5602 
5603                                        if (dt == null) {
5604                                                this.wasNullFlag = true;
5605 
5606                                                return null;
5607                                        }
5608 
5609                                        this.wasNullFlag = false;
5610 
5611                                        return dt.toString();
5612                                case Types.TIMESTAMP:
5613                                        Timestamp ts = getTimestampFromString(columnIndex + 1,
5614                                                        null, stringVal, this.getDefaultTimeZone(), false);
5615 
5616                                        if (ts == null) {
5617                                                this.wasNullFlag = true;
5618 
5619                                                return null;
5620                                        }
5621 
5622                                        this.wasNullFlag = false;
5623 
5624                                        return ts.toString();
5625                                default:
5626                                        break;
5627                                }
5628                        }
5629 
5630                        return stringVal;
5631                }
5632 
5633                return getNativeString(columnIndex);
5634        }
5635 
5636        /**
5637         * Get the value of a column in the current row as a java.sql.Time object
5638         * 
5639         * @param columnIndex
5640         *            the first column is 1, the second is 2...
5641         * 
5642         * @return the column value; null if SQL NULL
5643         * 
5644         * @throws java.sql.SQLException
5645         *             if a database access error occurs
5646         */
5647        public Time getTime(int columnIndex) throws java.sql.SQLException {
5648                return getTimeInternal(columnIndex, null, this.getDefaultTimeZone(), false);
5649        }
5650 
5651        /**
5652         * Get the value of a column in the current row as a java.sql.Time object.
5653         * Use the calendar to construct an appropriate millisecond value for the
5654         * Time, if the underlying database doesn't store timezone information.
5655         * 
5656         * @param columnIndex
5657         *            the first column is 1, the second is 2, ...
5658         * @param cal
5659         *            the calendar to use in constructing the time
5660         * 
5661         * @return the column value; if the value is SQL NULL, the result is null
5662         * 
5663         * @exception SQLException
5664         *                if a database-access error occurs.
5665         */
5666        public java.sql.Time getTime(int columnIndex, Calendar cal)
5667                        throws SQLException {
5668                return getTimeInternal(columnIndex, cal, cal.getTimeZone(), true);
5669        }
5670 
5671        /**
5672         * Get the value of a column in the current row as a java.sql.Time object.
5673         * 
5674         * @param columnName
5675         *            is the SQL name of the column
5676         * 
5677         * @return the column value; if the value is SQL NULL, the result is null
5678         * 
5679         * @throws java.sql.SQLException
5680         *             if a database-access error occurs.
5681         */
5682        public Time getTime(String columnName) throws java.sql.SQLException {
5683                return getTime(findColumn(columnName));
5684        }
5685 
5686        /**
5687         * Get the value of a column in the current row as a java.sql.Time object.
5688         * Use the calendar to construct an appropriate millisecond value for the
5689         * Time, if the underlying database doesn't store timezone information.
5690         * 
5691         * @param columnName
5692         *            is the SQL name of the column
5693         * @param cal
5694         *            the calendar to use in constructing the time
5695         * 
5696         * @return the column value; if the value is SQL NULL, the result is null
5697         * 
5698         * @exception SQLException
5699         *                if a database-access error occurs.
5700         */
5701        public java.sql.Time getTime(String columnName, Calendar cal)
5702                        throws SQLException {
5703                return getTime(findColumn(columnName), cal);
5704        }
5705 
5706        private Time getTimeFromString(String timeAsString, Calendar targetCalendar,
5707                        int columnIndex,
5708                        TimeZone tz, 
5709                        boolean rollForward) throws SQLException {
5710                int hr = 0;
5711                int min = 0;
5712                int sec = 0;
5713 
5714                try {
5715                        
5716                        if (timeAsString == null) {
5717                                this.wasNullFlag = true;
5718 
5719                                return null;
5720                        } 
5721                        
5722                        //
5723                        // JDK-6 doesn't like trailing whitespace
5724                        //
5725                        // Note this isn't a performance issue, other
5726                        // than the iteration over the string, as String.trim()
5727                        // will return a new string only if whitespace is present
5728                        //
5729                        
5730                        timeAsString = timeAsString.trim();
5731                        
5732                        if (timeAsString.equals("0")
5733                                        || timeAsString.equals("0000-00-00")
5734                                        || timeAsString.equals("0000-00-00 00:00:00")
5735                                        || timeAsString.equals("00000000000000")) {
5736                                if (ConnectionProperties.ZERO_DATETIME_BEHAVIOR_CONVERT_TO_NULL
5737                                                .equals(this.connection.getZeroDateTimeBehavior())) {
5738                                        this.wasNullFlag = true;
5739 
5740                                        return null;
5741                                } else if (ConnectionProperties.ZERO_DATETIME_BEHAVIOR_EXCEPTION
5742                                                .equals(this.connection.getZeroDateTimeBehavior())) {
5743                                        throw SQLError.createSQLException("Value '" + timeAsString
5744                                                        + " can not be represented as java.sql.Time",
5745                                                        SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
5746                                }
5747 
5748                                // We're left with the case of 'round' to a time Java _can_
5749                                // represent, which is '00:00:00'
5750                                return fastTimeCreate(null, 0, 0, 0);
5751                        }
5752 
5753                        this.wasNullFlag = false;
5754 
5755                        Field timeColField = this.fields[columnIndex - 1];
5756 
5757                        if (timeColField.getMysqlType() == MysqlDefs.FIELD_TYPE_TIMESTAMP) {
5758                                // It's a timestamp
5759                                int length = timeAsString.length();
5760 
5761                                switch (length) {
5762                                case 14:
5763                                case 12: {
5764                                        hr = Integer.parseInt(timeAsString.substring(length - 6,
5765                                                        length - 4));
5766                                        min = Integer.parseInt(timeAsString.substring(length - 4,
5767                                                        length - 2));
5768                                        sec = Integer.parseInt(timeAsString.substring(length - 2,
5769                                                        length));
5770                                }
5771 
5772                                        break;
5773 
5774                                case 10: {
5775                                        hr = Integer.parseInt(timeAsString.substring(6, 8));
5776                                        min = Integer.parseInt(timeAsString.substring(8, 10));
5777                                        sec = 0;
5778                                }
5779 
5780                                        break;
5781 
5782                                default:
5783                                        throw SQLError.createSQLException(
5784                                                        Messages
5785                                                                        .getString("ResultSet.Timestamp_too_small_to_convert_to_Time_value_in_column__257") //$NON-NLS-1$
5786                                                                        + columnIndex
5787                                                                        + "("
5788                                                                        + this.fields[columnIndex - 1] + ").",
5789                                                        SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
5790                                } /* endswitch */
5791 
5792                                SQLWarning precisionLost = new SQLWarning(
5793                                                Messages
5794                                                                .getString("ResultSet.Precision_lost_converting_TIMESTAMP_to_Time_with_getTime()_on_column__261") //$NON-NLS-1$
5795                                                                + columnIndex
5796                                                                + "("
5797                                                                + this.fields[columnIndex - 1] + ").");
5798 
5799                                if (this.warningChain == null) {
5800                                        this.warningChain = precisionLost;
5801                                } else {
5802                                        this.warningChain.setNextWarning(precisionLost);
5803                                }
5804                        } else if (timeColField.getMysqlType() == MysqlDefs.FIELD_TYPE_DATETIME) {
5805                                hr = Integer.parseInt(timeAsString.substring(11, 13));
5806                                min = Integer.parseInt(timeAsString.substring(14, 16));
5807                                sec = Integer.parseInt(timeAsString.substring(17, 19));
5808 
5809                                SQLWarning precisionLost = new SQLWarning(
5810                                                Messages
5811                                                                .getString("ResultSet.Precision_lost_converting_DATETIME_to_Time_with_getTime()_on_column__264") //$NON-NLS-1$
5812                                                                + columnIndex
5813                                                                + "("
5814                                                                + this.fields[columnIndex - 1] + ").");
5815 
5816                                if (this.warningChain == null) {
5817                                        this.warningChain = precisionLost;
5818                                } else {
5819                                        this.warningChain.setNextWarning(precisionLost);
5820                                }
5821                        } else if (timeColField.getMysqlType() == MysqlDefs.FIELD_TYPE_DATE) {
5822                                return fastTimeCreate(null, 0, 0, 0); // midnight on the given
5823                                                                                                                // date
5824                        } else {
5825                                // convert a String to a Time
5826                                if ((timeAsString.length() != 5)
5827                                                && (timeAsString.length() != 8)) {
5828                                        throw SQLError.createSQLException(Messages
5829                                                        .getString("ResultSet.Bad_format_for_Time____267") //$NON-NLS-1$
5830                                                        + timeAsString
5831                                                        + Messages.getString("ResultSet.___in_column__268")
5832                                                        + columnIndex, SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
5833                                }
5834 
5835                                hr = Integer.parseInt(timeAsString.substring(0, 2));
5836                                min = Integer.parseInt(timeAsString.substring(3, 5));
5837                                sec = (timeAsString.length() == 5) ? 0 : Integer
5838                                                .parseInt(timeAsString.substring(6));
5839                        }
5840 
5841                        Calendar sessionCalendar = this.getCalendarInstanceForSessionOrNew();
5842                        
5843                        synchronized (sessionCalendar) {
5844                                return TimeUtil.changeTimezone(this.connection, 
5845                                                sessionCalendar,
5846                                                targetCalendar, 
5847                                                fastTimeCreate(
5848                                                sessionCalendar, hr, min, sec), 
5849                                                this.connection.getServerTimezoneTZ(),
5850                                                tz, rollForward);
5851                        }
5852                } catch (Exception ex) {
5853                        throw SQLError.createSQLException(ex.toString(),
5854                                        SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
5855                }
5856        }
5857 
5858        /**
5859         * Get the value of a column in the current row as a java.sql.Time object in
5860         * the given timezone
5861         * 
5862         * @param columnIndex
5863         *            the first column is 1, the second is 2...
5864         * @param tz
5865         *            the Timezone to use
5866         * 
5867         * @return the column value; null if SQL NULL
5868         * 
5869         * @exception java.sql.SQLException
5870         *                if a database access error occurs
5871         */
5872        private Time getTimeInternal(int columnIndex, Calendar targetCalendar,
5873                        TimeZone tz,
5874                        boolean rollForward) throws java.sql.SQLException {
5875                if (this.isBinaryEncoded) {
5876                        return getNativeTime(columnIndex, targetCalendar, tz, rollForward);
5877                }
5878 
5879                String timeAsString = getStringInternal(columnIndex, false);
5880 
5881                return getTimeFromString(timeAsString, targetCalendar,
5882                                columnIndex, tz, rollForward);
5883        }
5884 
5885        /**
5886         * Get the value of a column in the current row as a java.sql.Timestamp
5887         * object
5888         * 
5889         * @param columnIndex
5890         *            the first column is 1, the second is 2...
5891         * 
5892         * @return the column value; null if SQL NULL
5893         * 
5894         * @exception java.sql.SQLException
5895         *                if a database access error occurs
5896         */
5897        public Timestamp getTimestamp(int columnIndex) throws java.sql.SQLException {
5898                return getTimestampInternal(columnIndex, null, this.getDefaultTimeZone(),
5899                                false);
5900        }
5901 
5902        /**
5903         * Get the value of a column in the current row as a java.sql.Timestamp
5904         * object. Use the calendar to construct an appropriate millisecond value
5905         * for the Timestamp, if the underlying database doesn't store timezone
5906         * information.
5907         * 
5908         * @param columnIndex
5909         *            the first column is 1, the second is 2, ...
5910         * @param cal
5911         *            the calendar to use in constructing the timestamp
5912         * 
5913         * @return the column value; if the value is SQL NULL, the result is null
5914         * 
5915         * @exception SQLException
5916         *                if a database-access error occurs.
5917         */
5918        public java.sql.Timestamp getTimestamp(int columnIndex, Calendar cal)
5919                        throws SQLException {
5920                return getTimestampInternal(columnIndex, cal, cal.getTimeZone(), true);
5921        }
5922 
5923        /**
5924         * DOCUMENT ME!
5925         * 
5926         * @param columnName
5927         *            DOCUMENT ME!
5928         * 
5929         * @return DOCUMENT ME!
5930         * 
5931         * @throws java.sql.SQLException
5932         *             DOCUMENT ME!
5933         */
5934        public Timestamp getTimestamp(String columnName)
5935                        throws java.sql.SQLException {
5936                return getTimestamp(findColumn(columnName));
5937        }
5938 
5939        /**
5940         * Get the value of a column in the current row as a java.sql.Timestamp
5941         * object. Use the calendar to construct an appropriate millisecond value
5942         * for the Timestamp, if the underlying database doesn't store timezone
5943         * information.
5944         * 
5945         * @param columnName
5946         *            is the SQL name of the column
5947         * @param cal
5948         *            the calendar to use in constructing the timestamp
5949         * 
5950         * @return the column value; if the value is SQL NULL, the result is null
5951         * 
5952         * @exception SQLException
5953         *                if a database-access error occurs.
5954         */
5955        public java.sql.Timestamp getTimestamp(String columnName, Calendar cal)
5956                        throws SQLException {
5957                return getTimestamp(findColumn(columnName), cal);
5958        }
5959 
5960        private Timestamp getTimestampFromString(int columnIndex,
5961                        Calendar targetCalendar,
5962                        String timestampValue, TimeZone tz, boolean rollForward)
5963        throws java.sql.SQLException {
5964                try {
5965                        this.wasNullFlag = false;
5966                        
5967                        if (timestampValue == null) {
5968                                this.wasNullFlag = true;
5969                                
5970                                return null;
5971                        }
5972                        
5973                        //
5974                        // JDK-6 doesn't like trailing whitespace
5975                        //
5976                        // Note this isn't a performance issue, other
5977                        // than the iteration over the string, as String.trim()
5978                        // will return a new string only if whitespace is present
5979                        //
5980                        
5981                        timestampValue = timestampValue.trim();
5982                        
5983                        int length = timestampValue.length();
5984                        
5985                        Calendar sessionCalendar = this.connection.getUseJDBCCompliantTimezoneShift() ?
5986                                        this.connection.getUtcCalendar() : 
5987                                                getCalendarInstanceForSessionOrNew();
5988                        
5989                        synchronized (sessionCalendar) {
5990                                if ((length > 0)
5991                                                && (timestampValue.charAt(0) == '0')
5992                                                && (timestampValue.equals("0000-00-00")
5993                                                                || timestampValue.equals("0000-00-00 00:00:00")
5994                                                                || timestampValue.equals("00000000000000") || timestampValue
5995                                                                .equals("0"))) {
5996                                        
5997                                        if (ConnectionProperties.ZERO_DATETIME_BEHAVIOR_CONVERT_TO_NULL
5998                                                        .equals(this.connection.getZeroDateTimeBehavior())) {
5999                                                this.wasNullFlag = true;
6000                                                
6001                                                return null;
6002                                        } else if (ConnectionProperties.ZERO_DATETIME_BEHAVIOR_EXCEPTION
6003                                                        .equals(this.connection.getZeroDateTimeBehavior())) {
6004                                                throw SQLError.createSQLException("Value '" + timestampValue
6005                                                                + " can not be represented as java.sql.Timestamp",
6006                                                                SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
6007                                        }
6008                                        
6009                                        // We're left with the case of 'round' to a date Java _can_
6010                                        // represent, which is '0001-01-01'.
6011                                        return fastTimestampCreate(null, 1, 1, 1, 0, 0, 0, 0);
6012                                        
6013                                } else if (this.fields[columnIndex - 1].getMysqlType() == MysqlDefs.FIELD_TYPE_YEAR) {
6014                                        
6015                                        return TimeUtil.changeTimezone(this.connection,
6016                                                        sessionCalendar, 
6017                                                        targetCalendar,
6018                                                        fastTimestampCreate(sessionCalendar, 
6019                                                                        Integer
6020                                                                        .parseInt(timestampValue.substring(0, 4)), 1,
6021                                                                        1, 0, 0, 0, 0), this.connection
6022                                                                        .getServerTimezoneTZ(), tz, rollForward);
6023                                        
6024                                } else {
6025                                        if (timestampValue.endsWith(".")) {
6026                                                timestampValue = timestampValue.substring(0, timestampValue
6027                                                                .length() - 1);
6028                                        }
6029                                        
6030                                        // Convert from TIMESTAMP or DATE
6031                                        switch (length) {
6032                                        case 26:
6033                                        case 25:
6034                                        case 24:
6035                                        case 23:
6036                                        case 22:
6037                                        case 21:
6038                                        case 20:
6039                                        case 19: {
6040                                                int year = Integer.parseInt(timestampValue.substring(0, 4));
6041                                                int month = Integer
6042                                                .parseInt(timestampValue.substring(5, 7));
6043                                                int day = Integer.parseInt(timestampValue.substring(8, 10));
6044                                                int hour = Integer.parseInt(timestampValue
6045                                                                .substring(11, 13));
6046                                                int minutes = Integer.parseInt(timestampValue.substring(14,
6047                                                                16));
6048                                                int seconds = Integer.parseInt(timestampValue.substring(17,
6049                                                                19));
6050                                                
6051                                                int nanos = 0;
6052                                                
6053                                                if (length > 19) {
6054                                                        int decimalIndex = timestampValue.lastIndexOf('.');
6055                                                        
6056                                                        if (decimalIndex != -1) {
6057                                                                if ((decimalIndex + 2) <= timestampValue.length()) {
6058                                                                        nanos = Integer.parseInt(timestampValue
6059                                                                                        .substring(decimalIndex + 1));
6060                                                                } else {
6061                                                                        throw new IllegalArgumentException(); // re-thrown
6062                                                                        // further
6063                                                                        // down
6064                                                                        // with
6065                                                                        // a
6066                                                                        // much better error message
6067                                                                }
6068                                                        }
6069                                                }
6070                                                
6071                                                return TimeUtil.changeTimezone(this.connection,
6072                                                                sessionCalendar,
6073                                                                targetCalendar,
6074                                                                fastTimestampCreate(sessionCalendar, year, month, day, hour,
6075                                                                                minutes, seconds, nanos), this.connection
6076                                                                                .getServerTimezoneTZ(), tz, rollForward);
6077                                        }
6078                                        
6079                                        case 14: {
6080                                                int year = Integer.parseInt(timestampValue.substring(0, 4));
6081                                                int month = Integer
6082                                                .parseInt(timestampValue.substring(4, 6));
6083                                                int day = Integer.parseInt(timestampValue.substring(6, 8));
6084                                                int hour = Integer
6085                                                .parseInt(timestampValue.substring(8, 10));
6086                                                int minutes = Integer.parseInt(timestampValue.substring(10,
6087                                                                12));
6088                                                int seconds = Integer.parseInt(timestampValue.substring(12,
6089                                                                14));
6090                                                
6091                                                return TimeUtil.changeTimezone(this.connection,
6092                                                                sessionCalendar, 
6093                                                                targetCalendar,
6094                                                                fastTimestampCreate(sessionCalendar, year, month, day, hour,
6095                                                                                minutes, seconds, 0), this.connection
6096                                                                                .getServerTimezoneTZ(), tz, rollForward);
6097                                        }
6098                                        
6099                                        case 12: {
6100                                                int year = Integer.parseInt(timestampValue.substring(0, 2));
6101                                                
6102                                                if (year <= 69) {
6103                                                        year = (year + 100);
6104                                                }
6105                                                
6106                                                int month = Integer
6107                                                .parseInt(timestampValue.substring(2, 4));
6108                                                int day = Integer.parseInt(timestampValue.substring(4, 6));
6109                                                int hour = Integer.parseInt(timestampValue.substring(6, 8));
6110                                                int minutes = Integer.parseInt(timestampValue.substring(8,
6111                                                                10));
6112                                                int seconds = Integer.parseInt(timestampValue.substring(10,
6113                                                                12));
6114                                                
6115                                                return TimeUtil.changeTimezone(this.connection,
6116                                                                sessionCalendar,
6117                                                                targetCalendar,
6118                                                                fastTimestampCreate(sessionCalendar, year + 1900, month, day,
6119                                                                                hour, minutes, seconds, 0), this.connection
6120                                                                                .getServerTimezoneTZ(), tz, rollForward);
6121                                        }
6122                                        
6123                                        case 10: {
6124                                                int year;
6125                                                int month;
6126                                                int day;
6127                                                int hour;
6128                                                int minutes;
6129                                                
6130                                                if ((this.fields[columnIndex - 1].getMysqlType() == MysqlDefs.FIELD_TYPE_DATE)
6131                                                                || (timestampValue.indexOf("-") != -1)) {
6132                                                        year = Integer.parseInt(timestampValue.substring(0, 4));
6133                                                        month = Integer
6134                                                        .parseInt(timestampValue.substring(5, 7));
6135                                                        day = Integer.parseInt(timestampValue.substring(8, 10));
6136                                                        hour = 0;
6137                                                        minutes = 0;
6138                                                } else {
6139                                                        year = Integer.parseInt(timestampValue.substring(0, 2));
6140                                                        
6141                                                        if (year <= 69) {
6142                                                                year = (year + 100);
6143                                                        }
6144                                                        
6145                                                        month = Integer
6146                                                        .parseInt(timestampValue.substring(2, 4));
6147                                                        day = Integer.parseInt(timestampValue.substring(4, 6));
6148                                                        hour = Integer.parseInt(timestampValue.substring(6, 8));
6149                                                        minutes = Integer.parseInt(timestampValue.substring(8,
6150                                                                        10));
6151                                                        
6152                                                        year += 1900; // two-digit year
6153                                                }
6154                                                
6155                                                return TimeUtil.changeTimezone(this.connection,
6156                                                                sessionCalendar,
6157                                                                targetCalendar,
6158                                                                fastTimestampCreate(sessionCalendar, year, month, day, hour,
6159                                                                                minutes, 0, 0), this.connection
6160                                                                                .getServerTimezoneTZ(), tz, rollForward);
6161                                        }
6162                                        
6163                                        case 8: {
6164                                                if (timestampValue.indexOf(":") != -1) {
6165                                                        int hour = Integer.parseInt(timestampValue.substring(0,
6166                                                                        2));
6167                                                        int minutes = Integer.parseInt(timestampValue
6168                                                                        .substring(3, 5));
6169                                                        int seconds = Integer.parseInt(timestampValue
6170                                                                        .substring(6, 8));
6171                                                        
6172                                                        return TimeUtil
6173                                                        .changeTimezone(this.connection,
6174                                                                        sessionCalendar,
6175                                                                        targetCalendar,
6176                                                                        fastTimestampCreate(sessionCalendar, 70, 0, 1,
6177                                                                                        hour, minutes, seconds, 0),
6178                                                                                        this.connection.getServerTimezoneTZ(),
6179                                                                                        tz, rollForward);
6180                                                        
6181                                                }
6182                                                
6183                                                int year = Integer.parseInt(timestampValue.substring(0, 4));
6184                                                int month = Integer
6185                                                .parseInt(timestampValue.substring(4, 6));
6186                                                int day = Integer.parseInt(timestampValue.substring(6, 8));
6187                                                
6188                                                return TimeUtil.changeTimezone(this.connection,
6189                                                                sessionCalendar,
6190                                                                targetCalendar,
6191                                                                fastTimestampCreate(sessionCalendar, year - 1900, month - 1,
6192                                                                                day, 0, 0, 0, 0), this.connection
6193                                                                                .getServerTimezoneTZ(), tz, rollForward);
6194                                        }
6195                                        
6196                                        case 6: {
6197                                                int year = Integer.parseInt(timestampValue.substring(0, 2));
6198                                                
6199                                                if (year <= 69) {
6200                                                        year = (year + 100);
6201                                                }
6202                                                
6203                                                int month = Integer
6204                                                .parseInt(timestampValue.substring(2, 4));
6205                                                int day = Integer.parseInt(timestampValue.substring(4, 6));
6206                                                
6207                                                return TimeUtil.changeTimezone(this.connection,
6208                                                                sessionCalendar,
6209                                                                targetCalendar,
6210                                                                fastTimestampCreate(sessionCalendar, year + 1900, month, day,
6211                                                                                0, 0, 0, 0), this.connection
6212                                                                                .getServerTimezoneTZ(), tz, rollForward);
6213                                        }
6214                                        
6215                                        case 4: {
6216                                                int year = Integer.parseInt(timestampValue.substring(0, 2));
6217                                                
6218                                                if (year <= 69) {
6219                                                        year = (year + 100);
6220                                                }
6221                                                
6222                                                int month = Integer
6223                                                .parseInt(timestampValue.substring(2, 4));
6224                                                
6225                                                return TimeUtil.changeTimezone(this.connection,
6226                                                                sessionCalendar,
6227                                                                targetCalendar,
6228                                                                fastTimestampCreate(sessionCalendar, year + 1900, month, 1, 0,
6229                                                                                0, 0, 0), this.connection
6230                                                                                .getServerTimezoneTZ(), tz, rollForward);
6231                                        }
6232                                        
6233                                        case 2: {
6234                                                int year = Integer.parseInt(timestampValue.substring(0, 2));
6235                                                
6236                                                if (year <= 69) {
6237                                                        year = (year + 100);
6238                                                }
6239                                                
6240                                                return TimeUtil.changeTimezone(this.connection,
6241                                                                sessionCalendar,
6242                                                                targetCalendar,
6243                                                                fastTimestampCreate(null, year + 1900, 1, 1, 0, 0,
6244                                                                                0, 0), this.connection
6245                                                                                .getServerTimezoneTZ(), tz, rollForward);
6246                                        }
6247                                        
6248                                        default:
6249                                                throw new java.sql.SQLException(
6250                                                                "Bad format for Timestamp '" + timestampValue
6251                                                                + "' in column " + columnIndex + ".",
6252                                                                SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
6253                                        }
6254                                }
6255                        }
6256                } catch (Exception e) {
6257                        throw new java.sql.SQLException("Cannot convert value '"
6258                                        + timestampValue + "' from column " + columnIndex
6259                                        + " to TIMESTAMP.", SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
6260                }
6261                
6262        }
6263 
6264        /**
6265         * Get the value of a column in the current row as a java.sql.Timestamp
6266         * object in the given timezone
6267         * 
6268         * @param columnIndex
6269         *            the first column is 1, the second is 2...
6270         * @param tz
6271         *            the timezone to use
6272         * 
6273         * @return the column value; null if SQL NULL
6274         * 
6275         * @exception java.sql.SQLException
6276         *                if a database access error occurs
6277         */
6278        private Timestamp getTimestampInternal(int columnIndex, Calendar targetCalendar,
6279                        TimeZone tz,
6280                        boolean rollForward) throws java.sql.SQLException {
6281                if (this.isBinaryEncoded) {
6282                        return getNativeTimestamp(columnIndex, targetCalendar, tz, rollForward);
6283                }
6284 
6285                String timestampValue = getStringInternal(columnIndex, false);
6286 
6287                return getTimestampFromString(columnIndex, targetCalendar, 
6288                                timestampValue, tz,
6289                                rollForward);
6290        }
6291 
6292        /**
6293         * JDBC 2.0 Return the type of this result set. The type is determined based
6294         * on the statement that created the result set.
6295         * 
6296         * @return TYPE_FORWARD_ONLY, TYPE_SCROLL_INSENSITIVE, or
6297         *         TYPE_SCROLL_SENSITIVE
6298         * 
6299         * @exception SQLException
6300         *                if a database-access error occurs
6301         */
6302        public int getType() throws SQLException {
6303                return this.resultSetType;
6304        }
6305 
6306        /**
6307         * A column value can also be retrieved as a stream of Unicode characters.
6308         * We implement this as a binary stream.
6309         * 
6310         * @param columnIndex
6311         *            the first column is 1, the second is 2...
6312         * 
6313         * @return a Java InputStream that delivers the database column value as a
6314         *         stream of two byte Unicode characters. If the value is SQL NULL,
6315         *         then the result is null
6316         * 
6317         * @exception SQLException
6318         *                if a database access error occurs
6319         * 
6320         * @see getAsciiStream
6321         * @see getBinaryStream
6322         * @deprecated
6323         */
6324        public InputStream getUnicodeStream(int columnIndex) throws SQLException {
6325                if (!this.isBinaryEncoded) {
6326                        checkRowPos();
6327 
6328                        return getBinaryStream(columnIndex);
6329                }
6330 
6331                return getNativeBinaryStream(columnIndex);
6332        }
6333 
6334        /**
6335         * DOCUMENT ME!
6336         * 
6337         * @param columnName
6338         *            DOCUMENT ME!
6339         * 
6340         * @return DOCUMENT ME!
6341         * 
6342         * @throws SQLException
6343         *             DOCUMENT ME!
6344         * 
6345         * @deprecated
6346         */
6347        public InputStream getUnicodeStream(String columnName) throws SQLException {
6348                return getUnicodeStream(findColumn(columnName));
6349        }
6350 
6351        long getUpdateCount() {
6352                return this.updateCount;
6353        }
6354 
6355        long getUpdateID() {
6356                return this.updateId;
6357        }
6358 
6359        /**
6360         * @see ResultSet#getURL(int)
6361         */
6362        public URL getURL(int colIndex) throws SQLException {
6363                String val = getString(colIndex);
6364 
6365                if (val == null) {
6366                        return null;
6367                }
6368 
6369                try {
6370                        return new URL(val);
6371                } catch (MalformedURLException mfe) {
6372                        throw SQLError.createSQLException(Messages
6373                                        .getString("ResultSet.Malformed_URL____104")
6374                                        + val + "'", SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$
6375                }
6376        }
6377 
6378        /**
6379         * @see ResultSet#getURL(String)
6380         */
6381        public URL getURL(String colName) throws SQLException {
6382                String val = getString(colName);
6383 
6384                if (val == null) {
6385                        return null;
6386                }
6387 
6388                try {
6389                        return new URL(val);
6390                } catch (MalformedURLException mfe) {
6391                        throw SQLError.createSQLException(Messages
6392                                        .getString("ResultSet.Malformed_URL____107")
6393                                        + val + "'", SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$
6394                }
6395        }
6396 
6397        /**
6398         * The first warning reported by calls on this ResultSet is returned.
6399         * Subsequent ResultSet warnings will be chained to this
6400         * java.sql.SQLWarning.
6401         * 
6402         * <p>
6403         * The warning chain is automatically cleared each time a new row is read.
6404         * </p>
6405         * 
6406         * <p>
6407         * <B>Note:</B> This warning chain only covers warnings caused by ResultSet
6408         * methods. Any warnings caused by statement methods (such as reading OUT
6409         * parameters) will be chained on the Statement object.
6410         * </p>
6411         * 
6412         * @return the first java.sql.SQLWarning or null;
6413         * 
6414         * @exception SQLException
6415         *                if a database access error occurs.
6416         */
6417        public java.sql.SQLWarning getWarnings() throws SQLException {
6418                return this.warningChain;
6419        }
6420 
6421        /**
6422         * JDBC 2.0 Insert the contents of the insert row into the result set and
6423         * the database. Must be on the insert row when this method is called.
6424         * 
6425         * @exception SQLException
6426         *                if a database-access error occurs, if called when not on
6427         *                the insert row, or if all non-nullable columns in the
6428         *                insert row have not been given a value
6429         * @throws NotUpdatable
6430         *             DOCUMENT ME!
6431         */
6432        public void insertRow() throws SQLException {
6433                throw new NotUpdatable();
6434        }
6435 
6436        /**
6437         * JDBC 2.0
6438         * 
6439         * <p>
6440         * Determine if the cursor is after the last row in the result set.
6441         * </p>
6442         * 
6443         * @return true if after the last row, false otherwise. Returns false when
6444         *         the result set contains no rows.
6445         * 
6446         * @exception SQLException
6447         *                if a database-access error occurs.
6448         */
6449        public boolean isAfterLast() throws SQLException {
6450                checkClosed();
6451 
6452                boolean b = this.rowData.isAfterLast();
6453 
6454                return b;
6455        }
6456 
6457        /**
6458         * JDBC 2.0
6459         * 
6460         * <p>
6461         * Determine if the cursor is before the first row in the result set.
6462         * </p>
6463         * 
6464         * @return true if before the first row, false otherwise. Returns false when
6465         *         the result set contains no rows.
6466         * 
6467         * @exception SQLException
6468         *                if a database-access error occurs.
6469         */
6470        public boolean isBeforeFirst() throws SQLException {
6471                checkClosed();
6472 
6473                return this.rowData.isBeforeFirst();
6474        }
6475 
6476        /**
6477         * JDBC 2.0
6478         * 
6479         * <p>
6480         * Determine if the cursor is on the first row of the result set.
6481         * </p>
6482         * 
6483         * @return true if on the first row, false otherwise.
6484         * 
6485         * @exception SQLException
6486         *                if a database-access error occurs.
6487         */
6488        public boolean isFirst() throws SQLException {
6489                checkClosed();
6490 
6491                return this.rowData.isFirst();
6492        }
6493 
6494        /**
6495         * JDBC 2.0
6496         * 
6497         * <p>
6498         * Determine if the cursor is on the last row of the result set. Note:
6499         * Calling isLast() may be expensive since the JDBC driver might need to
6500         * fetch ahead one row in order to determine whether the current row is the
6501         * last row in the result set.
6502         * </p>
6503         * 
6504         * @return true if on the last row, false otherwise.
6505         * 
6506         * @exception SQLException
6507         *                if a database-access error occurs.
6508         */
6509        public boolean isLast() throws SQLException {
6510                checkClosed();
6511 
6512                return this.rowData.isLast();
6513        }
6514 
6515        /**
6516         * @param string
6517         * @param mysqlType
6518         * @param s
6519         */
6520        private void issueConversionViaParsingWarning(String methodName,
6521                        int columnIndex, Object value, Field fieldInfo,
6522                        int[] typesWithNoParseConversion) throws SQLException {
6523                StringBuffer message = new StringBuffer();
6524                message
6525                                .append("ResultSet type conversion via parsing detected when calling ");
6526                message.append(methodName);
6527                message.append(" for column ");
6528                message.append((columnIndex + 1));
6529                message.append(", (column named '");
6530                message.append(fieldInfo.getOriginalName());
6531                message.append("' in table '");
6532                message.append(fieldInfo.getOriginalTableName());
6533                if (this.owningStatement != null
6534                                && this.owningStatement instanceof com.mysql.jdbc.PreparedStatement) {
6535                        message.append("' created from query:\n\n");
6536                        message
6537                                        .append(((com.mysql.jdbc.PreparedStatement) this.owningStatement).originalSql);
6538                        message.append("\n\n");
6539                } else {
6540                        message.append(". ");
6541                }
6542 
6543                message.append("Java class of column type is '");
6544                
6545                if (value != null) {
6546                        message.append(value.getClass().getName());
6547                } else {
6548                        message.append(ResultSetMetaData.getClassNameForJavaType(fieldInfo.getSQLType(), 
6549                                        fieldInfo.isUnsigned(), 
6550                                        fieldInfo.getMysqlType(), 
6551                                        fieldInfo.isBinary() || fieldInfo.isBlob(),
6552                                        fieldInfo.isOpaqueBinary()));
6553                }
6554                
6555                message.append("', MySQL field type is ");
6556                message.append(MysqlDefs.typeToName(fieldInfo.getMysqlType()));
6557                message
6558                                .append(".\n\nTypes that could be converted directly without parsing are:\n");
6559 
6560                for (int i = 0; i < typesWithNoParseConversion.length; i++) {
6561                        message.append(MysqlDefs.typeToName(typesWithNoParseConversion[i]));
6562                        message.append("\n");
6563                }
6564 
6565                this.eventSink.consumeEvent(new ProfilerEvent(ProfilerEvent.TYPE_WARN,
6566                                "", (this.owningStatement == null) ? "N/A"
6567                                                : this.owningStatement.currentCatalog, 
6568                                                this.connectionId, (this.owningStatement == null) ? (-1)
6569                                                : this.owningStatement.getId(), this.resultId, System
6570                                                .currentTimeMillis(), 0, null, this.pointOfOrigin,
6571                                message.toString()));
6572 
6573        }
6574 
6575        private void issueDataTruncationWarningIfConfigured(int columnIndex,
6576                        int readSize, int truncatedToSize) {
6577                DataTruncation dt = new DataTruncation(columnIndex, false, true,
6578                                readSize, truncatedToSize);
6579        }
6580 
6581        /**
6582         * JDBC 2.0
6583         * 
6584         * <p>
6585         * Moves to the last row in the result set.
6586         * </p>
6587         * 
6588         * @return true if on a valid row, false if no rows in the result set.
6589         * 
6590         * @exception SQLException
6591         *                if a database-access error occurs, or result set type is
6592         *                TYPE_FORWARD_ONLY.
6593         */
6594        public boolean last() throws SQLException {
6595                checkClosed();
6596 
6597                if (this.rowData.size() == 0) {
6598                        return false;
6599                }
6600 
6601                if (this.onInsertRow) {
6602                        this.onInsertRow = false;
6603                }
6604 
6605                if (this.doingUpdates) {
6606                        this.doingUpdates = false;
6607                }
6608 
6609                this.rowData.beforeLast();
6610                this.thisRow = this.rowData.next();
6611 
6612                return true;
6613        }
6614 
6615        // /////////////////////////////////////////
6616        //
6617        // These number conversion routines save
6618        // a ton of "new()s", especially for the heavily
6619        // used getInt() and getDouble() methods
6620        //
6621        // /////////////////////////////////////////
6622 
6623        /**
6624         * JDBC 2.0 Move the cursor to the remembered cursor position, usually the
6625         * current row. Has no effect unless the cursor is on the insert row.
6626         * 
6627         * @exception SQLException
6628         *                if a database-access error occurs, or the result set is
6629         *                not updatable
6630         * @throws NotUpdatable
6631         *             DOCUMENT ME!
6632         */
6633        public void moveToCurrentRow() throws SQLException {
6634                throw new NotUpdatable();
6635        }
6636 
6637        /**
6638         * JDBC 2.0 Move to the insert row. The current cursor position is
6639         * remembered while the cursor is positioned on the insert row. The insert
6640         * row is a special row associated with an updatable result set. It is
6641         * essentially a buffer where a new row may be constructed by calling the
6642         * updateXXX() methods prior to inserting the row into the result set. Only
6643         * the updateXXX(), getXXX(), and insertRow() methods may be called when the
6644         * cursor is on the insert row. All of the columns in a result set must be
6645         * given a value each time this method is called before calling insertRow().
6646         * UpdateXXX()must be called before getXXX() on a column.
6647         * 
6648         * @exception SQLException
6649         *                if a database-access error occurs, or the result set is
6650         *                not updatable
6651         * @throws NotUpdatable
6652         *             DOCUMENT ME!
6653         */
6654        public void moveToInsertRow() throws SQLException {
6655                throw new NotUpdatable();
6656        }
6657 
6658        /**
6659         * A ResultSet is initially positioned before its first row, the first call
6660         * to next makes the first row the current row; the second call makes the
6661         * second row the current row, etc.
6662         * 
6663         * <p>
6664         * If an input stream from the previous row is open, it is implicitly
6665         * closed. The ResultSet's warning chain is cleared when a new row is read
6666         * </p>
6667         * 
6668         * @return true if the new current is valid; false if there are no more rows
6669         * 
6670         * @exception SQLException
6671         *                if a database access error occurs
6672         */
6673        public boolean next() throws SQLException {
6674                checkClosed();
6675 
6676                if (this.onInsertRow) {
6677                        this.onInsertRow = false;
6678                }
6679 
6680                if (this.doingUpdates) {
6681                        this.doingUpdates = false;
6682                }
6683 
6684                boolean b;
6685 
6686                if (!reallyResult()) {
6687                        throw SQLError.createSQLException(
6688                                        Messages
6689                                                        .getString("ResultSet.ResultSet_is_from_UPDATE._No_Data_115"),
6690                                        SQLError.SQL_STATE_GENERAL_ERROR); //$NON-NLS-1$
6691                }
6692 
6693                if (this.rowData.size() == 0) {
6694                        b = false;
6695                } else {
6696                        if (!this.rowData.hasNext()) {
6697                                // force scroll past end
6698                                this.rowData.next();
6699                                b = false;
6700                        } else {
6701                                clearWarnings();
6702                                this.thisRow = this.rowData.next();
6703                                b = true;
6704                        }
6705                }
6706 
6707                return b;
6708        }
6709 
6710        private int parseIntAsDouble(int columnIndex, String val)
6711                        throws NumberFormatException, SQLException {
6712                if (val == null) {
6713                        return 0;
6714                }
6715 
6716                double valueAsDouble = Double.parseDouble(val);
6717 
6718                if (this.connection.getJdbcCompliantTruncationForReads()) {
6719                        if (valueAsDouble < Integer.MIN_VALUE
6720                                        || valueAsDouble > Integer.MAX_VALUE) {
6721                                throwRangeException(String.valueOf(valueAsDouble), columnIndex,
6722                                                Types.INTEGER);
6723                        }
6724                }
6725 
6726                return (int) valueAsDouble;
6727        }
6728 
6729        private int parseIntWithOverflowCheck(int columnIndex, byte[] valueAsBytes,
6730                        String valueAsString) throws NumberFormatException, SQLException {
6731 
6732                int intValue = 0;
6733 
6734                if (valueAsBytes == null && valueAsString == null) {
6735                        return 0;
6736                }
6737 
6738                if (valueAsBytes != null) {
6739                        intValue = StringUtils.getInt(valueAsBytes);
6740                } else {
6741                        //
6742                        // JDK-6 doesn't like trailing whitespace
6743                        //
6744                        // Note this isn't a performance issue, other
6745                        // than the iteration over the string, as String.trim()
6746                        // will return a new string only if whitespace is present
6747                        //
6748                        
6749                        valueAsString = valueAsString.trim(); 
6750                        
6751                        intValue = Integer.parseInt(valueAsString);
6752                }
6753 
6754                if (this.connection.getJdbcCompliantTruncationForReads()) {
6755                        if (intValue == Integer.MIN_VALUE || intValue == Integer.MAX_VALUE) {
6756                                long valueAsLong = Long
6757                                                .parseLong(valueAsString == null ? new String(
6758                                                                valueAsBytes) : valueAsString);
6759 
6760                                if (valueAsLong < Integer.MIN_VALUE
6761                                                || valueAsLong > Integer.MAX_VALUE) {
6762                                        throwRangeException(valueAsString == null ? new String(
6763                                                        valueAsBytes) : valueAsString, columnIndex,
6764                                                        Types.INTEGER);
6765                                }
6766                        }
6767                }
6768 
6769                return intValue;
6770        }
6771 
6772        private long parseLongAsDouble(int columnIndex, String val)
6773                        throws NumberFormatException, SQLException {
6774                if (val == null) {
6775                        return 0;
6776                }
6777 
6778                double valueAsDouble = Double.parseDouble(val);
6779 
6780                if (this.connection.getJdbcCompliantTruncationForReads()) {
6781                        if (valueAsDouble < Long.MIN_VALUE
6782                                        || valueAsDouble > Long.MAX_VALUE) {
6783                                throwRangeException(val, columnIndex, Types.BIGINT);
6784                        }
6785                }
6786 
6787                return (long) valueAsDouble;
6788        }
6789 
6790        private long parseLongWithOverflowCheck(int columnIndex,
6791                        byte[] valueAsBytes, String valueAsString)
6792                        throws NumberFormatException, SQLException {
6793 
6794                long longValue = 0;
6795 
6796                if (valueAsBytes == null && valueAsString == null) {
6797                        return 0;
6798                }
6799 
6800                if (valueAsBytes != null) {
6801                        longValue = StringUtils.getLong(valueAsBytes);
6802                } else {
6803                        //
6804                        // JDK-6 doesn't like trailing whitespace
6805                        //
6806                        // Note this isn't a performance issue, other
6807                        // than the iteration over the string, as String.trim()
6808                        // will return a new string only if whitespace is present
6809                        //
6810                        
6811                        valueAsString = valueAsString.trim();
6812                        
6813                        longValue = Long.parseLong(valueAsString);
6814                }
6815 
6816                if (this.connection.getJdbcCompliantTruncationForReads()) {
6817                        if (longValue == Integer.MIN_VALUE
6818                                        || longValue == Integer.MAX_VALUE) {
6819                                double valueAsDouble = Double
6820                                                .parseDouble(valueAsString == null ? new String(
6821                                                                valueAsBytes) : valueAsString);
6822 
6823                                if (valueAsDouble < Long.MIN_VALUE
6824                                                || valueAsDouble > Long.MAX_VALUE) {
6825                                        throwRangeException(valueAsString == null ? new String(
6826                                                        valueAsBytes) : valueAsString, columnIndex,
6827                                                        Types.BIGINT);
6828                                }
6829                        }
6830                }
6831 
6832                return longValue;
6833        }
6834 
6835        private short parseShortAsDouble(int columnIndex, String val)
6836                        throws NumberFormatException, SQLException {
6837                if (val == null) {
6838                        return 0;
6839                }
6840 
6841                double valueAsDouble = Double.parseDouble(val);
6842 
6843                if (this.connection.getJdbcCompliantTruncationForReads()) {
6844                        if (valueAsDouble < Short.MIN_VALUE
6845                                        || valueAsDouble > Short.MAX_VALUE) {
6846                                throwRangeException(String.valueOf(valueAsDouble), columnIndex,
6847                                                Types.SMALLINT);
6848                        }
6849                }
6850 
6851                return (short) valueAsDouble;
6852        }
6853 
6854        private short parseShortWithOverflowCheck(int columnIndex,
6855                        byte[] valueAsBytes, String valueAsString)
6856                        throws NumberFormatException, SQLException {
6857 
6858                short shortValue = 0;
6859 
6860                if (valueAsBytes == null && valueAsString == null) {
6861                        return 0;
6862                }
6863 
6864                if (valueAsBytes != null) {
6865                        shortValue = StringUtils.getShort(valueAsBytes);
6866                } else {
6867                        //
6868                        // JDK-6 doesn't like trailing whitespace
6869                        //
6870                        // Note this isn't a performance issue, other
6871                        // than the iteration over the string, as String.trim()
6872                        // will return a new string only if whitespace is present
6873                        //
6874                        
6875                        valueAsString = valueAsString.trim();
6876                
6877                        shortValue = Short.parseShort(valueAsString);
6878                }
6879 
6880                if (this.connection.getJdbcCompliantTruncationForReads()) {
6881                        if (shortValue == Short.MIN_VALUE || shortValue == Short.MAX_VALUE) {
6882                                long valueAsLong = Long
6883                                                .parseLong(valueAsString == null ? new String(
6884                                                                valueAsBytes) : valueAsString);
6885 
6886                                if (valueAsLong < Short.MIN_VALUE
6887                                                || valueAsLong > Short.MAX_VALUE) {
6888                                        throwRangeException(valueAsString == null ? new String(
6889                                                        valueAsBytes) : valueAsString, columnIndex,
6890                                                        Types.SMALLINT);
6891                                }
6892                        }
6893                }
6894 
6895                return shortValue;
6896        }
6897 
6898        // --------------------------JDBC 2.0-----------------------------------
6899        // ---------------------------------------------------------------------
6900        // Getter's and Setter's
6901        // ---------------------------------------------------------------------
6902 
6903        /**
6904         * The prev method is not part of JDBC, but because of the architecture of
6905         * this driver it is possible to move both forward and backward within the
6906         * result set.
6907         * 
6908         * <p>
6909         * If an input stream from the previous row is open, it is implicitly
6910         * closed. The ResultSet's warning chain is cleared when a new row is read
6911         * </p>
6912         * 
6913         * @return true if the new current is valid; false if there are no more rows
6914         * 
6915         * @exception java.sql.SQLException
6916         *                if a database access error occurs
6917         */
6918        public boolean prev() throws java.sql.SQLException {
6919                checkClosed();
6920 
6921                int rowIndex = this.rowData.getCurrentRowNumber();
6922 
6923                if ((rowIndex - 1) >= 0) {
6924                        rowIndex--;
6925                        this.rowData.setCurrentRow(rowIndex);
6926                        this.thisRow = this.rowData.getAt(rowIndex);
6927 
6928                        return true;
6929                } else if ((rowIndex - 1) == -1) {
6930                        rowIndex--;
6931                        this.rowData.setCurrentRow(rowIndex);
6932                        this.thisRow = null;
6933 
6934                        return false;
6935                } else {
6936                        return false;
6937                }
6938        }
6939 
6940        /**
6941         * JDBC 2.0
6942         * 
6943         * <p>
6944         * Moves to the previous row in the result set.
6945         * </p>
6946         * 
6947         * <p>
6948         * Note: previous() is not the same as relative(-1) since it makes sense to
6949         * call previous() when there is no current row.
6950         * </p>
6951         * 
6952         * @return true if on a valid row, false if off the result set.
6953         * 
6954         * @exception SQLException
6955         *                if a database-access error occurs, or result set type is
6956         *                TYPE_FORWAR_DONLY.
6957         */
6958        public boolean previous() throws SQLException {
6959                if (this.onInsertRow) {
6960                        this.onInsertRow = false;
6961                }
6962 
6963                if (this.doingUpdates) {
6964                        this.doingUpdates = false;
6965                }
6966 
6967                return prev();
6968        }
6969 
6970        /**
6971         * Closes this ResultSet and releases resources.
6972         * 
6973         * @param calledExplicitly
6974         *            was this called by close()?
6975         * 
6976         * @throws SQLException
6977         *             if an error occurs
6978         */
6979        protected void realClose(boolean calledExplicitly) throws SQLException {
6980                if (this.isClosed) {
6981                        return;
6982                }
6983 
6984                try {
6985                        if (this.useUsageAdvisor) {
6986                                if (!calledExplicitly) {
6987                                        String message = Messages
6988                                                        .getString("ResultSet.ResultSet_implicitly_closed_by_driver._150") //$NON-NLS-1$
6989                                                        + Messages
6990                                                                        .getString("ResultSet._n_nYou_should_close_ResultSets_explicitly_from_your_code_to_free_up_resources_in_a_more_efficient_manner._151"); //$NON-NLS-1$
6991 
6992                                        this.eventSink.consumeEvent(new ProfilerEvent(
6993                                                        ProfilerEvent.TYPE_WARN, "",
6994                                                        (this.owningStatement == null) ? "N/A"
6995                                                                        : this.owningStatement.currentCatalog,
6996                                                        this.connectionId,
6997                                                        (this.owningStatement == null) ? (-1)
6998                                                                        : this.owningStatement.getId(),
6999                                                        this.resultId, System.currentTimeMillis(), 0, null,
7000                                                        this.pointOfOrigin, message));
7001                                }
7002 
7003                                if (this.rowData instanceof RowDataStatic && !isLast()
7004                                                && !isAfterLast() && (this.rowData.size() != 0)) {
7005                                        StringBuffer messageBuf = new StringBuffer(
7006                                                        Messages
7007                                                                        .getString("ResultSet.Possible_incomplete_traversal_of_result_set._Cursor_was_left_on_row__154")); //$NON-NLS-1$
7008                                        messageBuf.append(getRow());
7009                                        messageBuf.append(Messages.getString("ResultSet._of__155")); //$NON-NLS-1$
7010                                        messageBuf.append(this.rowData.size());
7011                                        messageBuf
7012                                                        .append(Messages
7013                                                                        .getString("ResultSet._rows_when_it_was_closed._156")); //$NON-NLS-1$
7014                                        messageBuf
7015                                                        .append(Messages
7016                                                                        .getString("ResultSet._n_nYou_should_consider_re-formulating_your_query_to_return_only_the_rows_you_are_interested_in_using._157")); //$NON-NLS-1$
7017 
7018                                        this.eventSink.consumeEvent(new ProfilerEvent(
7019                                                        ProfilerEvent.TYPE_WARN, "",
7020                                                        (this.owningStatement == null) ? Messages
7021                                                                        .getString("ResultSet.N/A_159")
7022                                                                        : this.owningStatement.currentCatalog, //$NON-NLS-1$
7023                                                        this.connectionId,
7024                                                        (this.owningStatement == null) ? (-1)
7025                                                                        : this.owningStatement.getId(),
7026                                                        this.resultId, System.currentTimeMillis(), 0, null,
7027                                                        this.pointOfOrigin, messageBuf.toString()));
7028                                }
7029 
7030                                //
7031                                // Report on any columns that were selected but
7032                                // not referenced
7033                                //
7034                                if (this.columnUsed.length > 0) {
7035                                        StringBuffer buf = new StringBuffer(
7036                                                        Messages
7037                                                                        .getString("ResultSet.The_following_columns_were__160")); //$NON-NLS-1$
7038                                        buf
7039                                                        .append(Messages
7040                                                                        .getString("ResultSet._part_of_the_SELECT_statement_for_this_result_set,_but_were_161")); //$NON-NLS-1$
7041                                        buf.append(Messages
7042                                                        .getString("ResultSet._never_referenced___162")); //$NON-NLS-1$
7043 
7044                                        boolean issueWarn = false;
7045 
7046                                        for (int i = 0; i < this.columnUsed.length; i++) {
7047                                                if (!this.columnUsed[i]) {
7048                                                        if (!issueWarn) {
7049                                                                issueWarn = true;
7050                                                        } else {
7051                                                                buf.append(", ");
7052                                                        }
7053 
7054                                                        buf.append(this.fields[i].getFullName());
7055                                                }
7056                                        }
7057 
7058                                        if (issueWarn) {
7059                                                this.eventSink.consumeEvent(new ProfilerEvent(
7060                                                                ProfilerEvent.TYPE_WARN, "",
7061                                                                (this.owningStatement == null) ? "N/A"
7062                                                                                : this.owningStatement.currentCatalog,
7063                                                                this.connectionId,
7064                                                                (this.owningStatement == null) ? (-1)
7065                                                                                : this.owningStatement.getId(), 0,
7066                                                                System.currentTimeMillis(), 0, null,
7067                                                                this.pointOfOrigin, buf.toString()));
7068                                        }
7069                                }
7070                        }
7071                } finally {
7072                        SQLException exceptionDuringClose = null;
7073 
7074                        if (this.rowData != null) {
7075                                try {
7076                                        this.rowData.close();
7077                                } catch (SQLException sqlEx) {
7078                                        exceptionDuringClose = sqlEx;
7079                                }
7080                        }
7081 
7082                        this.rowData = null;
7083                        this.defaultTimeZone = null;
7084                        this.fields = null;
7085                        this.columnNameToIndex = null;
7086                        this.fullColumnNameToIndex = null;
7087                        this.eventSink = null;
7088                        this.warningChain = null;
7089                        
7090                        if (!this.retainOwningStatement) {
7091                                this.owningStatement = null;
7092                        }
7093                        
7094                        this.catalog = null;
7095                        this.serverInfo = null;
7096                        this.thisRow = null;
7097                        this.fastDateCal = null;
7098                        this.connection = null;
7099 
7100                        this.isClosed = true;
7101 
7102                        if (exceptionDuringClose != null) {
7103                                throw exceptionDuringClose;
7104                        }
7105                }
7106        }
7107 
7108        boolean reallyResult() {
7109                if (this.rowData != null) {
7110                        return true;
7111                }
7112 
7113                return this.reallyResult;
7114        }
7115 
7116        /**
7117         * JDBC 2.0 Refresh the value of the current row with its current value in
7118         * the database. Cannot be called when on the insert row. The refreshRow()
7119         * method provides a way for an application to explicitly tell the JDBC
7120         * driver to refetch a row(s) from the database. An application may want to
7121         * call refreshRow() when caching or prefetching is being done by the JDBC
7122         * driver to fetch the latest value of a row from the database. The JDBC
7123         * driver may actually refresh multiple rows at once if the fetch size is
7124         * greater than one. All values are refetched subject to the transaction
7125         * isolation level and cursor sensitivity. If refreshRow() is called after
7126         * calling updateXXX(), but before calling updateRow() then the updates made
7127         * to the row are lost. Calling refreshRow() frequently will likely slow
7128         * performance.
7129         * 
7130         * @exception SQLException
7131         *                if a database-access error occurs, or if called when on
7132         *                the insert row.
7133         * @throws NotUpdatable
7134         *             DOCUMENT ME!
7135         */
7136        public void refreshRow() throws SQLException {
7137                throw new NotUpdatable();
7138        }
7139 
7140        /**
7141         * JDBC 2.0
7142         * 
7143         * <p>
7144         * Moves a relative number of rows, either positive or negative. Attempting
7145         * to move beyond the first/last row in the result set positions the cursor
7146         * before/after the the first/last row. Calling relative(0) is valid, but
7147         * does not change the cursor position.
7148         * </p>
7149         * 
7150         * <p>
7151         * Note: Calling relative(1) is different than calling next() since is makes
7152         * sense to call next() when there is no current row, for example, when the
7153         * cursor is positioned before the first row or after the last row of the
7154         * result set.
7155         * </p>
7156         * 
7157         * @param rows
7158         *            the number of relative rows to move the cursor.
7159         * 
7160         * @return true if on a row, false otherwise.
7161         * 
7162         * @throws SQLException
7163         *             if a database-access error occurs, or there is no current
7164         *             row, or result set type is TYPE_FORWARD_ONLY.
7165         */
7166        public boolean relative(int rows) throws SQLException {
7167                checkClosed();
7168 
7169                if (this.rowData.size() == 0) {
7170                        return false;
7171                }
7172 
7173                this.rowData.moveRowRelative(rows);
7174                this.thisRow = this.rowData.getAt(this.rowData.getCurrentRowNumber());
7175 
7176                return (!this.rowData.isAfterLast() && !this.rowData.isBeforeFirst());
7177        }
7178 
7179        /**
7180         * JDBC 2.0 Determine if this row has been deleted. A deleted row may leave
7181         * a visible "hole" in a result set. This method can be used to detect holes
7182         * in a result set. The value returned depends on whether or not the result
7183         * set can detect deletions.
7184         * 
7185         * @return true if deleted and deletes are detected
7186         * 
7187         * @exception SQLException
7188         *                if a database-access error occurs
7189         * @throws NotImplemented
7190         *             DOCUMENT ME!
7191         * 
7192         * @see DatabaseMetaData#deletesAreDetected
7193         */
7194        public boolean rowDeleted() throws SQLException {
7195                throw new NotImplemented();
7196        }
7197 
7198        /**
7199         * JDBC 2.0 Determine if the current row has been inserted. The value
7200         * returned depends on whether or not the result set can detect visible
7201         * inserts.
7202         * 
7203         * @return true if inserted and inserts are detected
7204         * 
7205         * @exception SQLException
7206         *                if a database-access error occurs
7207         * @throws NotImplemented
7208         *             DOCUMENT ME!
7209         * 
7210         * @see DatabaseMetaData#insertsAreDetected
7211         */
7212        public boolean rowInserted() throws SQLException {
7213                throw new NotImplemented();
7214        }
7215 
7216        /**
7217         * JDBC 2.0 Determine if the current row has been updated. The value
7218         * returned depends on whether or not the result set can detect updates.
7219         * 
7220         * @return true if the row has been visibly updated by the owner or another,
7221         *         and updates are detected
7222         * 
7223         * @exception SQLException
7224         *                if a database-access error occurs
7225         * @throws NotImplemented
7226         *             DOCUMENT ME!
7227         * 
7228         * @see DatabaseMetaData#updatesAreDetected
7229         */
7230        public boolean rowUpdated() throws SQLException {
7231                throw new NotImplemented();
7232        }
7233 
7234        /**
7235         * Flag that this result set is 'binary' encoded (from a PreparedStatement),
7236         * not stored as strings.
7237         */
7238        protected void setBinaryEncoded() {
7239                this.isBinaryEncoded = true;
7240        }
7241 
7242        private void setDefaultTimeZone(TimeZone defaultTimeZone) {
7243                this.defaultTimeZone = defaultTimeZone;
7244        }
7245 
7246        /**
7247         * JDBC 2.0 Give a hint as to the direction in which the rows in this result
7248         * set will be processed. The initial value is determined by the statement
7249         * that produced the result set. The fetch direction may be changed at any
7250         * time.
7251         * 
7252         * @param direction
7253         *            the direction to fetch rows in.
7254         * 
7255         * @exception SQLException
7256         *                if a database-access error occurs, or the result set type
7257         *                is TYPE_FORWARD_ONLY and direction is not FETCH_FORWARD.
7258         *                MM.MySQL actually ignores this, because it has the whole
7259         *                result set anyway, so the direction is immaterial.
7260         */
7261        public void setFetchDirection(int direction) throws SQLException {
7262                if ((direction != FETCH_FORWARD) && (direction != FETCH_REVERSE)
7263                                && (direction != FETCH_UNKNOWN)) {
7264                        throw SQLError.createSQLException(
7265                                        Messages
7266                                                        .getString("ResultSet.Illegal_value_for_fetch_direction_64"),
7267                                        SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$
7268                }
7269 
7270                this.fetchDirection = direction;
7271        }
7272 
7273        /**
7274         * JDBC 2.0 Give the JDBC driver a hint as to the number of rows that should
7275         * be fetched from the database when more rows are needed for this result
7276         * set. If the fetch size specified is zero, then the JDBC driver ignores
7277         * the value, and is free to make its own best guess as to what the fetch
7278         * size should be. The default value is set by the statement that creates
7279         * the result set. The fetch size may be changed at any time.
7280         * 
7281         * @param rows
7282         *            the number of rows to fetch
7283         * 
7284         * @exception SQLException
7285         *                if a database-access error occurs, or the condition 0 lteq
7286         *                rows lteq this.getMaxRows() is not satisfied. Currently
7287         *                ignored by this driver.
7288         */
7289        public void setFetchSize(int rows) throws SQLException {
7290                if (rows < 0) { /* || rows > getMaxRows() */
7291                        throw SQLError.createSQLException(
7292                                        Messages
7293                                                        .getString("ResultSet.Value_must_be_between_0_and_getMaxRows()_66"), //$NON-NLS-1$
7294                                        SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
7295                }
7296 
7297                this.fetchSize = rows;
7298        }
7299 
7300        /**
7301         * Sets the first character of the query that this result set was created
7302         * from.
7303         * 
7304         * @param c
7305         *            the first character of the query...uppercased
7306         */
7307        protected void setFirstCharOfQuery(char c) {
7308                this.firstCharOfQuery = c;
7309        }
7310 
7311        /**
7312         * DOCUMENT ME!
7313         * 
7314         * @param nextResultSet
7315         *            Sets the next result set in the result set chain for multiple
7316         *            result sets.
7317         */
7318        protected void setNextResultSet(ResultSet nextResultSet) {
7319                this.nextResultSet = nextResultSet;
7320        }
7321 
7322        protected void setOwningStatement(com.mysql.jdbc.Statement owningStatement) {
7323                this.owningStatement = owningStatement;
7324        }
7325 
7326        /**
7327         * Sets the concurrency (JDBC2)
7328         * 
7329         * @param concurrencyFlag
7330         *            CONCUR_UPDATABLE or CONCUR_READONLY
7331         */
7332        protected void setResultSetConcurrency(int concurrencyFlag) {
7333                this.resultSetConcurrency = concurrencyFlag;
7334        }
7335 
7336        /**
7337         * Sets the result set type for (JDBC2)
7338         * 
7339         * @param typeFlag
7340         *            SCROLL_SENSITIVE or SCROLL_INSENSITIVE (we only support
7341         *            SCROLL_INSENSITIVE)
7342         */
7343        protected void setResultSetType(int typeFlag) {
7344                this.resultSetType = typeFlag;
7345        }
7346 
7347        /**
7348         * Sets server info (if any)
7349         * 
7350         * @param info
7351         *            the server info message
7352         */
7353        protected void setServerInfo(String info) {
7354                this.serverInfo = info;
7355        }
7356 
7357        void setStatementUsedForFetchingRows(PreparedStatement stmt) {
7358                this.statementUsedForFetchingRows = stmt;
7359        }
7360 
7361        /**
7362         * @param wrapperStatement
7363         *            The wrapperStatement to set.
7364         */
7365        public void setWrapperStatement(java.sql.Statement wrapperStatement) {
7366                this.wrapperStatement = wrapperStatement;
7367        }
7368 
7369        private void throwRangeException(String valueAsString, int columnIndex,
7370                        int jdbcType) throws SQLException {
7371                String datatype = null;
7372 
7373                switch (jdbcType) {
7374                case Types.TINYINT:
7375                        datatype = "TINYINT";
7376                        break;
7377                case Types.SMALLINT:
7378                        datatype = "SMALLINT";
7379                        break;
7380                case Types.INTEGER:
7381                        datatype = "INTEGER";
7382                        break;
7383                case Types.BIGINT:
7384                        datatype = "BIGINT";
7385                        break;
7386                case Types.REAL:
7387                        datatype = "REAL";
7388                        break;
7389                case Types.FLOAT:
7390                        datatype = "FLOAT";
7391                        break;
7392                case Types.DOUBLE:
7393                        datatype = "DOUBLE";
7394                        break;
7395                case Types.DECIMAL:
7396                        datatype = "DECIMAL";
7397                        break;
7398                default:
7399                        datatype = " (JDBC type '" + jdbcType + "')";
7400                }
7401 
7402                throw SQLError.createSQLException("'" + valueAsString + "' in column '"
7403                                + columnIndex + "' is outside valid range for the datatype "
7404                                + datatype + ".", SQLError.SQL_STATE_NUMERIC_VALUE_OUT_OF_RANGE);
7405        }
7406 
7407        /**
7408         * DOCUMENT ME!
7409         * 
7410         * @return DOCUMENT ME!
7411         */
7412        public String toString() {
7413                if (this.reallyResult) {
7414                        return super.toString();
7415                }
7416 
7417                return "Result set representing update count of " + this.updateCount;
7418        }
7419 
7420        /**
7421         * @see ResultSet#updateArray(int, Array)
7422         */
7423        public void updateArray(int arg0, Array arg1) throws SQLException {
7424                throw new NotImplemented();
7425        }
7426 
7427        /**
7428         * @see ResultSet#updateArray(String, Array)
7429         */
7430        public void updateArray(String arg0, Array arg1) throws SQLException {
7431                throw new NotImplemented();
7432        }
7433 
7434        /**
7435         * JDBC 2.0 Update a column with an ascii stream value. The updateXXX()
7436         * methods are used to update column values in the current row, or the
7437         * insert row. The updateXXX() methods do not update the underlying
7438         * database, instead the updateRow() or insertRow() methods are called to
7439         * update the database.
7440         * 
7441         * @param columnIndex
7442         *            the first column is 1, the second is 2, ...
7443         * @param x
7444         *            the new column value
7445         * @param length
7446         *            the length of the stream
7447         * 
7448         * @exception SQLException
7449         *                if a database-access error occurs
7450         * @throws NotUpdatable
7451         *             DOCUMENT ME!
7452         */
7453        public void updateAsciiStream(int columnIndex, java.io.InputStream x,
7454                        int length) throws SQLException {
7455                throw new NotUpdatable();
7456        }
7457 
7458        /**
7459         * JDBC 2.0 Update a column with an ascii stream value. The updateXXX()
7460         * methods are used to update column values in the current row, or the
7461         * insert row. The updateXXX() methods do not update the underlying
7462         * database, instead the updateRow() or insertRow() methods are called to
7463         * update the database.
7464         * 
7465         * @param columnName
7466         *            the name of the column
7467         * @param x
7468         *            the new column value
7469         * @param length
7470         *            of the stream
7471         * 
7472         * @exception SQLException
7473         *                if a database-access error occurs
7474         */
7475        public void updateAsciiStream(String columnName, java.io.InputStream x,
7476                        int length) throws SQLException {
7477                updateAsciiStream(findColumn(columnName), x, length);
7478        }
7479 
7480        /**
7481         * JDBC 2.0 Update a column with a BigDecimal value. The updateXXX() methods
7482         * are used to update column values in the current row, or the insert row.
7483         * The updateXXX() methods do not update the underlying database, instead
7484         * the updateRow() or insertRow() methods are called to update the database.
7485         * 
7486         * @param columnIndex
7487         *            the first column is 1, the second is 2, ...
7488         * @param x
7489         *            the new column value
7490         * 
7491         * @exception SQLException
7492         *                if a database-access error occurs
7493         * @throws NotUpdatable
7494         *             DOCUMENT ME!
7495         */
7496        public void updateBigDecimal(int columnIndex, BigDecimal x)
7497                        throws SQLException {
7498                throw new NotUpdatable();
7499        }
7500 
7501        /**
7502         * JDBC 2.0 Update a column with a BigDecimal value. The updateXXX() methods
7503         * are used to update column values in the current row, or the insert row.
7504         * The updateXXX() methods do not update the underlying database, instead
7505         * the updateRow() or insertRow() methods are called to update the database.
7506         * 
7507         * @param columnName
7508         *            the name of the column
7509         * @param x
7510         *            the new column value
7511         * 
7512         * @exception SQLException
7513         *                if a database-access error occurs
7514         */
7515        public void updateBigDecimal(String columnName, BigDecimal x)
7516                        throws SQLException {
7517                updateBigDecimal(findColumn(columnName), x);
7518        }
7519 
7520        /**
7521         * JDBC 2.0 Update a column with a binary stream value. The updateXXX()
7522         * methods are used to update column values in the current row, or the
7523         * insert row. The updateXXX() methods do not update the underlying
7524         * database, instead the updateRow() or insertRow() methods are called to
7525         * update the database.
7526         * 
7527         * @param columnIndex
7528         *            the first column is 1, the second is 2, ...
7529         * @param x
7530         *            the new column value
7531         * @param length
7532         *            the length of the stream
7533         * 
7534         * @exception SQLException
7535         *                if a database-access error occurs
7536         * @throws NotUpdatable
7537         *             DOCUMENT ME!
7538         */
7539        public void updateBinaryStream(int columnIndex, java.io.InputStream x,
7540                        int length) throws SQLException {
7541                throw new NotUpdatable();
7542        }
7543 
7544        /**
7545         * JDBC 2.0 Update a column with a binary stream value. The updateXXX()
7546         * methods are used to update column values in the current row, or the
7547         * insert row. The updateXXX() methods do not update the underlying
7548         * database, instead the updateRow() or insertRow() methods are called to
7549         * update the database.
7550         * 
7551         * @param columnName
7552         *            the name of the column
7553         * @param x
7554         *            the new column value
7555         * @param length
7556         *            of the stream
7557         * 
7558         * @exception SQLException
7559         *                if a database-access error occurs
7560         */
7561        public void updateBinaryStream(String columnName, java.io.InputStream x,
7562                        int length) throws SQLException {
7563                updateBinaryStream(findColumn(columnName), x, length);
7564        }
7565 
7566        /**
7567         * @see ResultSet#updateBlob(int, Blob)
7568         */
7569        public void updateBlob(int arg0, java.sql.Blob arg1) throws SQLException {
7570                throw new NotUpdatable();
7571        }
7572 
7573        /**
7574         * @see ResultSet#updateBlob(String, Blob)
7575         */
7576        public void updateBlob(String arg0, java.sql.Blob arg1) throws SQLException {
7577                throw new NotUpdatable();
7578        }
7579 
7580        /**
7581         * JDBC 2.0 Update a column with a boolean value. The updateXXX() methods
7582         * are used to update column values in the current row, or the insert row.
7583         * The updateXXX() methods do not update the underlying database, instead
7584         * the updateRow() or insertRow() methods are called to update the database.
7585         * 
7586         * @param columnIndex
7587         *            the first column is 1, the second is 2, ...
7588         * @param x
7589         *            the new column value
7590         * 
7591         * @exception SQLException
7592         *                if a database-access error occurs
7593         * @throws NotUpdatable
7594         *             DOCUMENT ME!
7595         */
7596        public void updateBoolean(int columnIndex, boolean x) throws SQLException {
7597                throw new NotUpdatable();
7598        }
7599 
7600        /**
7601         * JDBC 2.0 Update a column with a boolean value. The updateXXX() methods
7602         * are used to update column values in the current row, or the insert row.
7603         * The updateXXX() methods do not update the underlying database, instead
7604         * the updateRow() or insertRow() methods are called to update the database.
7605         * 
7606         * @param columnName
7607         *            the name of the column
7608         * @param x
7609         *            the new column value
7610         * 
7611         * @exception SQLException
7612         *                if a database-access error occurs
7613         */
7614        public void updateBoolean(String columnName, boolean x) throws SQLException {
7615                updateBoolean(findColumn(columnName), x);
7616        }
7617 
7618        /**
7619         * JDBC 2.0 Update a column with a byte value. The updateXXX() methods are
7620         * used to update column values in the current row, or the insert row. The
7621         * updateXXX() methods do not update the underlying database, instead the
7622         * updateRow() or insertRow() methods are called to update the database.
7623         * 
7624         * @param columnIndex
7625         *            the first column is 1, the second is 2, ...
7626         * @param x
7627         *            the new column value
7628         * 
7629         * @exception SQLException
7630         *                if a database-access error occurs
7631         * @throws NotUpdatable
7632         *             DOCUMENT ME!
7633         */
7634        public void updateByte(int columnIndex, byte x) throws SQLException {
7635                throw new NotUpdatable();
7636        }
7637 
7638        /**
7639         * JDBC 2.0 Update a column with a byte value. The updateXXX() methods are
7640         * used to update column values in the current row, or the insert row. The
7641         * updateXXX() methods do not update the underlying database, instead the
7642         * updateRow() or insertRow() methods are called to update the database.
7643         * 
7644         * @param columnName
7645         *            the name of the column
7646         * @param x
7647         *            the new column value
7648         * 
7649         * @exception SQLException
7650         *                if a database-access error occurs
7651         */
7652        public void updateByte(String columnName, byte x) throws SQLException {
7653                updateByte(findColumn(columnName), x);
7654        }
7655 
7656        /**
7657         * JDBC 2.0 Update a column with a byte array value. The updateXXX() methods
7658         * are used to update column values in the current row, or the insert row.
7659         * The updateXXX() methods do not update the underlying database, instead
7660         * the updateRow() or insertRow() methods are called to update the database.
7661         * 
7662         * @param columnIndex
7663         *            the first column is 1, the second is 2, ...
7664         * @param x
7665         *            the new column value
7666         * 
7667         * @exception SQLException
7668         *                if a database-access error occurs
7669         * @throws NotUpdatable
7670         *             DOCUMENT ME!
7671         */
7672        public void updateBytes(int columnIndex, byte[] x) throws SQLException {
7673                throw new NotUpdatable();
7674        }
7675 
7676        /**
7677         * JDBC 2.0 Update a column with a byte array value. The updateXXX() methods
7678         * are used to update column values in the current row, or the insert row.
7679         * The updateXXX() methods do not update the underlying database, instead
7680         * the updateRow() or insertRow() methods are called to update the database.
7681         * 
7682         * @param columnName
7683         *            the name of the column
7684         * @param x
7685         *            the new column value
7686         * 
7687         * @exception SQLException
7688         *                if a database-access error occurs
7689         */
7690        public void updateBytes(String columnName, byte[] x) throws SQLException {
7691                updateBytes(findColumn(columnName), x);
7692        }
7693 
7694        /**
7695         * JDBC 2.0 Update a column with a character stream value. The updateXXX()
7696         * methods are used to update column values in the current row, or the
7697         * insert row. The updateXXX() methods do not update the underlying
7698         * database, instead the updateRow() or insertRow() methods are called to
7699         * update the database.
7700         * 
7701         * @param columnIndex
7702         *            the first column is 1, the second is 2, ...
7703         * @param x
7704         *            the new column value
7705         * @param length
7706         *            the length of the stream
7707         * 
7708         * @exception SQLException
7709         *                if a database-access error occurs
7710         * @throws NotUpdatable
7711         *             DOCUMENT ME!
7712         */
7713        public void updateCharacterStream(int columnIndex, java.io.Reader x,
7714                        int length) throws SQLException {
7715                throw new NotUpdatable();
7716        }
7717 
7718        /**
7719         * JDBC 2.0 Update a column with a character stream value. The updateXXX()
7720         * methods are used to update column values in the current row, or the
7721         * insert row. The updateXXX() methods do not update the underlying
7722         * database, instead the updateRow() or insertRow() methods are called to
7723         * update the database.
7724         * 
7725         * @param columnName
7726         *            the name of the column
7727         * @param reader
7728         *            the stream to update the column with
7729         * @param length
7730         *            of the stream
7731         * 
7732         * @throws SQLException
7733         *             if a database-access error occurs
7734         */
7735        public void updateCharacterStream(String columnName, java.io.Reader reader,
7736                        int length) throws SQLException {
7737                updateCharacterStream(findColumn(columnName), reader, length);
7738        }
7739 
7740        /**
7741         * @see ResultSet#updateClob(int, Clob)
7742         */
7743        public void updateClob(int arg0, java.sql.Clob arg1) throws SQLException {
7744                throw new NotImplemented();
7745        }
7746 
7747        /**
7748         * @see ResultSet#updateClob(String, Clob)
7749         */
7750        public void updateClob(String columnName, java.sql.Clob clob)
7751                        throws SQLException {
7752                updateClob(findColumn(columnName), clob);
7753        }
7754 
7755        /**
7756         * JDBC 2.0 Update a column with a Date value. The updateXXX() methods are
7757         * used to update column values in the current row, or the insert row. The
7758         * updateXXX() methods do not update the underlying database, instead the
7759         * updateRow() or insertRow() methods are called to update the database.
7760         * 
7761         * @param columnIndex
7762         *            the first column is 1, the second is 2, ...
7763         * @param x
7764         *            the new column value
7765         * 
7766         * @exception SQLException
7767         *                if a database-access error occurs
7768         * @throws NotUpdatable
7769         *             DOCUMENT ME!
7770         */
7771        public void updateDate(int columnIndex, java.sql.Date x)
7772                        throws SQLException {
7773                throw new NotUpdatable();
7774        }
7775 
7776        /**
7777         * JDBC 2.0 Update a column with a Date value. The updateXXX() methods are
7778         * used to update column values in the current row, or the insert row. The
7779         * updateXXX() methods do not update the underlying database, instead the
7780         * updateRow() or insertRow() methods are called to update the database.
7781         * 
7782         * @param columnName
7783         *            the name of the column
7784         * @param x
7785         *            the new column value
7786         * 
7787         * @exception SQLException
7788         *                if a database-access error occurs
7789         */
7790        public void updateDate(String columnName, java.sql.Date x)
7791                        throws SQLException {
7792                updateDate(findColumn(columnName), x);
7793        }
7794 
7795        /**
7796         * JDBC 2.0 Update a column with a Double value. The updateXXX() methods are
7797         * used to update column values in the current row, or the insert row. The
7798         * updateXXX() methods do not update the underlying database, instead the
7799         * updateRow() or insertRow() methods are called to update the database.
7800         * 
7801         * @param columnIndex
7802         *            the first column is 1, the second is 2, ...
7803         * @param x
7804         *            the new column value
7805         * 
7806         * @exception SQLException
7807         *                if a database-access error occurs
7808         * @throws NotUpdatable
7809         *             DOCUMENT ME!
7810         */
7811        public void updateDouble(int columnIndex, double x) throws SQLException {
7812                throw new NotUpdatable();
7813        }
7814 
7815        /**
7816         * JDBC 2.0 Update a column with a double value. The updateXXX() methods are
7817         * used to update column values in the current row, or the insert row. The
7818         * updateXXX() methods do not update the underlying database, instead the
7819         * updateRow() or insertRow() methods are called to update the database.
7820         * 
7821         * @param columnName
7822         *            the name of the column
7823         * @param x
7824         *            the new column value
7825         * 
7826         * @exception SQLException
7827         *                if a database-access error occurs
7828         */
7829        public void updateDouble(String columnName, double x) throws SQLException {
7830                updateDouble(findColumn(columnName), x);
7831        }
7832 
7833        /**
7834         * JDBC 2.0 Update a column with a float value. The updateXXX() methods are
7835         * used to update column values in the current row, or the insert row. The
7836         * updateXXX() methods do not update the underlying database, instead the
7837         * updateRow() or insertRow() methods are called to update the database.
7838         * 
7839         * @param columnIndex
7840         *            the first column is 1, the second is 2, ...
7841         * @param x
7842         *            the new column value
7843         * 
7844         * @exception SQLException
7845         *                if a database-access error occurs
7846         * @throws NotUpdatable
7847         *             DOCUMENT ME!
7848         */
7849        public void updateFloat(int columnIndex, float x) throws SQLException {
7850                throw new NotUpdatable();
7851        }
7852 
7853        /**
7854         * JDBC 2.0 Update a column with a float value. The updateXXX() methods are
7855         * used to update column values in the current row, or the insert row. The
7856         * updateXXX() methods do not update the underlying database, instead the
7857         * updateRow() or insertRow() methods are called to update the database.
7858         * 
7859         * @param columnName
7860         *            the name of the column
7861         * @param x
7862         *            the new column value
7863         * 
7864         * @exception SQLException
7865         *                if a database-access error occurs
7866         */
7867        public void updateFloat(String columnName, float x) throws SQLException {
7868                updateFloat(findColumn(columnName), x);
7869        }
7870 
7871        /**
7872         * JDBC 2.0 Update a column with an integer value. The updateXXX() methods
7873         * are used to update column values in the current row, or the insert row.
7874         * The updateXXX() methods do not update the underlying database, instead
7875         * the updateRow() or insertRow() methods are called to update the database.
7876         * 
7877         * @param columnIndex
7878         *            the first column is 1, the second is 2, ...
7879         * @param x
7880         *            the new column value
7881         * 
7882         * @exception SQLException
7883         *                if a database-access error occurs
7884         * @throws NotUpdatable
7885         *             DOCUMENT ME!
7886         */
7887        public void updateInt(int columnIndex, int x) throws SQLException {
7888                throw new NotUpdatable();
7889        }
7890 
7891        /**
7892         * JDBC 2.0 Update a column with an integer value. The updateXXX() methods
7893         * are used to update column values in the current row, or the insert row.
7894         * The updateXXX() methods do not update the underlying database, instead
7895         * the updateRow() or insertRow() methods are called to update the database.
7896         * 
7897         * @param columnName
7898         *            the name of the column
7899         * @param x
7900         *            the new column value
7901         * 
7902         * @exception SQLException
7903         *                if a database-access error occurs
7904         */
7905        public void updateInt(String columnName, int x) throws SQLException {
7906                updateInt(findColumn(columnName), x);
7907        }
7908 
7909        /**
7910         * JDBC 2.0 Update a column with a long value. The updateXXX() methods are
7911         * used to update column values in the current row, or the insert row. The
7912         * updateXXX() methods do not update the underlying database, instead the
7913         * updateRow() or insertRow() methods are called to update the database.
7914         * 
7915         * @param columnIndex
7916         *            the first column is 1, the second is 2, ...
7917         * @param x
7918         *            the new column value
7919         * 
7920         * @exception SQLException
7921         *                if a database-access error occurs
7922         * @throws NotUpdatable
7923         *             DOCUMENT ME!
7924         */
7925        public void updateLong(int columnIndex, long x) throws SQLException {
7926                throw new NotUpdatable();
7927        }
7928 
7929        /**
7930         * JDBC 2.0 Update a column with a long value. The updateXXX() methods are
7931         * used to update column values in the current row, or the insert row. The
7932         * updateXXX() methods do not update the underlying database, instead the
7933         * updateRow() or insertRow() methods are called to update the database.
7934         * 
7935         * @param columnName
7936         *            the name of the column
7937         * @param x
7938         *            the new column value
7939         * 
7940         * @exception SQLException
7941         *                if a database-access error occurs
7942         */
7943        public void updateLong(String columnName, long x) throws SQLException {
7944                updateLong(findColumn(columnName), x);
7945        }
7946 
7947        /**
7948         * JDBC 2.0 Give a nullable column a null value. The updateXXX() methods are
7949         * used to update column values in the current row, or the insert row. The
7950         * updateXXX() methods do not update the underlying database, instead the
7951         * updateRow() or insertRow() methods are called to update the database.
7952         * 
7953         * @param columnIndex
7954         *            the first column is 1, the second is 2, ...
7955         * 
7956         * @exception SQLException
7957         *                if a database-access error occurs
7958         * @throws NotUpdatable
7959         *             DOCUMENT ME!
7960         */
7961        public void updateNull(int columnIndex) throws SQLException {
7962                throw new NotUpdatable();
7963        }
7964 
7965        /**
7966         * JDBC 2.0 Update a column with a null value. The updateXXX() methods are
7967         * used to update column values in the current row, or the insert row. The
7968         * updateXXX() methods do not update the underlying database, instead the
7969         * updateRow() or insertRow() methods are called to update the database.
7970         * 
7971         * @param columnName
7972         *            the name of the column
7973         * 
7974         * @exception SQLException
7975         *                if a database-access error occurs
7976         */
7977        public void updateNull(String columnName) throws SQLException {
7978                updateNull(findColumn(columnName));
7979        }
7980 
7981        /**
7982         * JDBC 2.0 Update a column with an Object value. The updateXXX() methods
7983         * are used to update column values in the current row, or the insert row.
7984         * The updateXXX() methods do not update the underlying database, instead
7985         * the updateRow() or insertRow() methods are called to update the database.
7986         * 
7987         * @param columnIndex
7988         *            the first column is 1, the second is 2, ...
7989         * @param x
7990         *            the new column value
7991         * 
7992         * @exception SQLException
7993         *                if a database-access error occurs
7994         * @throws NotUpdatable
7995         *             DOCUMENT ME!
7996         */
7997        public void updateObject(int columnIndex, Object x) throws SQLException {
7998                throw new NotUpdatable();
7999        }
8000 
8001        /**
8002         * JDBC 2.0 Update a column with an Object value. The updateXXX() methods
8003         * are used to update column values in the current row, or the insert row.
8004         * The updateXXX() methods do not update the underlying database, instead
8005         * the updateRow() or insertRow() methods are called to update the database.
8006         * 
8007         * @param columnIndex
8008         *            the first column is 1, the second is 2, ...
8009         * @param x
8010         *            the new column value
8011         * @param scale
8012         *            For java.sql.Types.DECIMAL or java.sql.Types.NUMERIC types
8013         *            this is the number of digits after the decimal. For all other
8014         *            types this value will be ignored.
8015         * 
8016         * @exception SQLException
8017         *                if a database-access error occurs
8018         * @throws NotUpdatable
8019         *             DOCUMENT ME!
8020         */
8021        public void updateObject(int columnIndex, Object x, int scale)
8022                        throws SQLException {
8023                throw new NotUpdatable();
8024        }
8025 
8026        /**
8027         * JDBC 2.0 Update a column with an Object value. The updateXXX() methods
8028         * are used to update column values in the current row, or the insert row.
8029         * The updateXXX() methods do not update the underlying database, instead
8030         * the updateRow() or insertRow() methods are called to update the database.
8031         * 
8032         * @param columnName
8033         *            the name of the column
8034         * @param x
8035         *            the new column value
8036         * 
8037         * @exception SQLException
8038         *                if a database-access error occurs
8039         */
8040        public void updateObject(String columnName, Object x) throws SQLException {
8041                updateObject(findColumn(columnName), x);
8042        }
8043 
8044        /**
8045         * JDBC 2.0 Update a column with an Object value. The updateXXX() methods
8046         * are used to update column values in the current row, or the insert row.
8047         * The updateXXX() methods do not update the underlying database, instead
8048         * the updateRow() or insertRow() methods are called to update the database.
8049         * 
8050         * @param columnName
8051         *            the name of the column
8052         * @param x
8053         *            the new column value
8054         * @param scale
8055         *            For java.sql.Types.DECIMAL or java.sql.Types.NUMERIC types
8056         *            this is the number of digits after the decimal. For all other
8057         *            types this value will be ignored.
8058         * 
8059         * @exception SQLException
8060         *                if a database-access error occurs
8061         */
8062        public void updateObject(String columnName, Object x, int scale)
8063                        throws SQLException {
8064                updateObject(findColumn(columnName), x);
8065        }
8066 
8067        /**
8068         * @see ResultSet#updateRef(int, Ref)
8069         */
8070        public void updateRef(int arg0, Ref arg1) throws SQLException {
8071                throw new NotImplemented();
8072        }
8073 
8074        /**
8075         * @see ResultSet#updateRef(String, Ref)
8076         */
8077        public void updateRef(String arg0, Ref arg1) throws SQLException {
8078                throw new NotImplemented();
8079        }
8080 
8081        /**
8082         * JDBC 2.0 Update the underlying database with the new contents of the
8083         * current row. Cannot be called when on the insert row.
8084         * 
8085         * @exception SQLException
8086         *                if a database-access error occurs, or if called when on
8087         *                the insert row
8088         * @throws NotUpdatable
8089         *             DOCUMENT ME!
8090         */
8091        public void updateRow() throws SQLException {
8092                throw new NotUpdatable();
8093        }
8094 
8095        /**
8096         * JDBC 2.0 Update a column with a short value. The updateXXX() methods are
8097         * used to update column values in the current row, or the insert row. The
8098         * updateXXX() methods do not update the underlying database, instead the
8099         * updateRow() or insertRow() methods are called to update the database.
8100         * 
8101         * @param columnIndex
8102         *            the first column is 1, the second is 2, ...
8103         * @param x
8104         *            the new column value
8105         * 
8106         * @exception SQLException
8107         *                if a database-access error occurs
8108         * @throws NotUpdatable
8109         *             DOCUMENT ME!
8110         */
8111        public void updateShort(int columnIndex, short x) throws SQLException {
8112                throw new NotUpdatable();
8113        }
8114 
8115        /**
8116         * JDBC 2.0 Update a column with a short value. The updateXXX() methods are
8117         * used to update column values in the current row, or the insert row. The
8118         * updateXXX() methods do not update the underlying database, instead the
8119         * updateRow() or insertRow() methods are called to update the database.
8120         * 
8121         * @param columnName
8122         *            the name of the column
8123         * @param x
8124         *            the new column value
8125         * 
8126         * @exception SQLException
8127         *                if a database-access error occurs
8128         */
8129        public void updateShort(String columnName, short x) throws SQLException {
8130                updateShort(findColumn(columnName), x);
8131        }
8132 
8133        /**
8134         * JDBC 2.0 Update a column with a String value. The updateXXX() methods are
8135         * used to update column values in the current row, or the insert row. The
8136         * updateXXX() methods do not update the underlying database, instead the
8137         * updateRow() or insertRow() methods are called to update the database.
8138         * 
8139         * @param columnIndex
8140         *            the first column is 1, the second is 2, ...
8141         * @param x
8142         *            the new column value
8143         * 
8144         * @exception SQLException
8145         *                if a database-access error occurs
8146         * @throws NotUpdatable
8147         *             DOCUMENT ME!
8148         */
8149        public void updateString(int columnIndex, String x) throws SQLException {
8150                throw new NotUpdatable();
8151        }
8152 
8153        /**
8154         * JDBC 2.0 Update a column with a String value. The updateXXX() methods are
8155         * used to update column values in the current row, or the insert row. The
8156         * updateXXX() methods do not update the underlying database, instead the
8157         * updateRow() or insertRow() methods are called to update the database.
8158         * 
8159         * @param columnName
8160         *            the name of the column
8161         * @param x
8162         *            the new column value
8163         * 
8164         * @exception SQLException
8165         *                if a database-access error occurs
8166         */
8167        public void updateString(String columnName, String x) throws SQLException {
8168                updateString(findColumn(columnName), x);
8169        }
8170 
8171        /**
8172         * JDBC 2.0 Update a column with a Time value. The updateXXX() methods are
8173         * used to update column values in the current row, or the insert row. The
8174         * updateXXX() methods do not update the underlying database, instead the
8175         * updateRow() or insertRow() methods are called to update the database.
8176         * 
8177         * @param columnIndex
8178         *            the first column is 1, the second is 2, ...
8179         * @param x
8180         *            the new column value
8181         * 
8182         * @exception SQLException
8183         *                if a database-access error occurs
8184         * @throws NotUpdatable
8185         *             DOCUMENT ME!
8186         */
8187        public void updateTime(int columnIndex, java.sql.Time x)
8188                        throws SQLException {
8189                throw new NotUpdatable();
8190        }
8191 
8192        /**
8193         * JDBC 2.0 Update a column with a Time value. The updateXXX() methods are
8194         * used to update column values in the current row, or the insert row. The
8195         * updateXXX() methods do not update the underlying database, instead the
8196         * updateRow() or insertRow() methods are called to update the database.
8197         * 
8198         * @param columnName
8199         *            the name of the column
8200         * @param x
8201         *            the new column value
8202         * 
8203         * @exception SQLException
8204         *                if a database-access error occurs
8205         */
8206        public void updateTime(String columnName, java.sql.Time x)
8207                        throws SQLException {
8208                updateTime(findColumn(columnName), x);
8209        }
8210 
8211        
8212        /**
8213         * JDBC 2.0 Update a column with a Timestamp value. The updateXXX() methods
8214         * are used to update column values in the current row, or the insert row.
8215         * The updateXXX() methods do not update the underlying database, instead
8216         * the updateRow() or insertRow() methods are called to update the database.
8217         * 
8218         * @param columnIndex
8219         *            the first column is 1, the second is 2, ...
8220         * @param x
8221         *            the new column value
8222         * 
8223         * @exception SQLException
8224         *                if a database-access error occurs
8225         * @throws NotUpdatable
8226         *             DOCUMENT ME!
8227         */
8228        public void updateTimestamp(int columnIndex, java.sql.Timestamp x)
8229                        throws SQLException {
8230                throw new NotUpdatable();
8231        }
8232        
8233        /**
8234         * JDBC 2.0 Update a column with a Timestamp value. The updateXXX() methods
8235         * are used to update column values in the current row, or the insert row.
8236         * The updateXXX() methods do not update the underlying database, instead
8237         * the updateRow() or insertRow() methods are called to update the database.
8238         * 
8239         * @param columnName
8240         *            the name of the column
8241         * @param x
8242         *            the new column value
8243         * 
8244         * @exception SQLException
8245         *                if a database-access error occurs
8246         */
8247        public void updateTimestamp(String columnName, java.sql.Timestamp x)
8248                        throws SQLException {
8249                updateTimestamp(findColumn(columnName), x);
8250        }
8251 
8252        /**
8253         * A column may have the value of SQL NULL; wasNull() reports whether the
8254         * last column read had this special value. Note that you must first call
8255         * getXXX on a column to try to read its value and then call wasNull() to
8256         * find if the value was SQL NULL
8257         * 
8258         * @return true if the last column read was SQL NULL
8259         * 
8260         * @exception SQLException
8261         *                if a database access error occurred
8262         */
8263        public boolean wasNull() throws SQLException {
8264                return this.wasNullFlag;
8265        }
8266 
8267        protected Calendar getGmtCalendar() {
8268                
8269                // Worst case we allocate this twice and the other gets GC'd,
8270                // however prevents deadlock
8271                if (this.gmtCalendar == null) {
8272                        this.gmtCalendar = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
8273                }
8274                
8275                return this.gmtCalendar;
8276        }
8277        
8278        private Object getNativeDateTimeValue(int columnIndex, Calendar targetCalendar,
8279                                int jdbcType,
8280                        int mysqlType, TimeZone tz, boolean rollForward)
8281                        throws SQLException {
8282 
8283                int year = 0;
8284                int month = 0;
8285                int day = 0;
8286 
8287                int hour = 0;
8288                int minute = 0;
8289                int seconds = 0;
8290 
8291                int nanos = 0;
8292 
8293                byte[] bits = (byte[]) this.thisRow[columnIndex - 1];
8294 
8295                if (bits == null) {
8296                        this.wasNullFlag = true;
8297 
8298                        return null;
8299                }
8300 
8301                Calendar sessionCalendar = this.connection.getUseJDBCCompliantTimezoneShift() ?
8302                                this.connection.getUtcCalendar() : 
8303                                        getCalendarInstanceForSessionOrNew();
8304                                
8305                this.wasNullFlag = false;
8306                
8307                boolean populatedFromDateTimeValue = false;
8308 
8309                switch (mysqlType) {
8310                case MysqlDefs.FIELD_TYPE_DATETIME:
8311                case MysqlDefs.FIELD_TYPE_TIMESTAMP:
8312                        populatedFromDateTimeValue = true;
8313 
8314                        int length = bits.length;
8315 
8316                        if (length != 0) {
8317                                year = (bits[0] & 0xff) | ((bits[1] & 0xff) << 8);
8318                                month = bits[2];
8319                                day = bits[3];
8320 
8321                                if (length > 4) {
8322                                        hour = bits[4];
8323                                        minute = bits[5];
8324                                        seconds = bits[6];
8325                                }
8326 
8327                                if (length > 7) {
8328                                        nanos = (bits[7] & 0xff) | ((bits[8] & 0xff) << 8)
8329                                                        | ((bits[9] & 0xff) << 16)
8330                                                        | ((bits[10] & 0xff) << 24);
8331                                }
8332                        }
8333 
8334                        break;
8335                case MysqlDefs.FIELD_TYPE_DATE:
8336                        populatedFromDateTimeValue = true;
8337 
8338                        if (bits.length != 0) {
8339                                year = (bits[0] & 0xff) | ((bits[1] & 0xff) << 8);
8340                                month = bits[2];
8341                                day = bits[3];
8342                        }
8343 
8344                        break;
8345                case MysqlDefs.FIELD_TYPE_TIME:
8346                        populatedFromDateTimeValue = true;
8347 
8348                        if (bits.length != 0) {
8349                                // bits[0] // skip tm->neg
8350                                // binaryData.readLong(); // skip daysPart
8351                                hour = bits[5];
8352                                minute = bits[6];
8353                                seconds = bits[7];
8354                        }
8355 
8356                        year = 1970;
8357                        month = 1;
8358                        day = 1;
8359                        
8360                        break;
8361                default:
8362                        populatedFromDateTimeValue = false;
8363                }
8364 
8365                switch (jdbcType) {
8366                case Types.TIME:
8367                        if (populatedFromDateTimeValue) {
8368                                Time time = TimeUtil.fastTimeCreate(
8369                                                getCalendarInstanceForSessionOrNew(), hour, minute,
8370                                                seconds);
8371 
8372                                Time adjustedTime = TimeUtil.changeTimezone(this.connection,
8373                                                sessionCalendar, 
8374                                                targetCalendar,
8375                                                time, this.connection.getServerTimezoneTZ(), tz,
8376                                                rollForward);
8377 
8378                                return adjustedTime;
8379                        }
8380                        
8381                        return getNativeTimeViaParseConversion(columnIndex, targetCalendar,
8382                                        tz, rollForward);
8383 
8384                case Types.DATE:
8385                        if (populatedFromDateTimeValue) {
8386                                if ((year == 0) && (month == 0) && (day == 0)) {
8387                                        if (ConnectionProperties.ZERO_DATETIME_BEHAVIOR_CONVERT_TO_NULL
8388                                                        .equals(this.connection.getZeroDateTimeBehavior())) {
8389                                                this.wasNullFlag = true;
8390 
8391                                                return null;
8392                                        } else if (ConnectionProperties.ZERO_DATETIME_BEHAVIOR_EXCEPTION
8393                                                        .equals(this.connection.getZeroDateTimeBehavior())) {
8394                                                throw new SQLException(
8395                                                                "Value '0000-00-00' can not be represented as java.sql.Date",
8396                                                                SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
8397                                        }
8398 
8399                                        year = 1;
8400                                        month = 1;
8401                                        day = 1;
8402                                }
8403 
8404                                return fastDateCreate(getCalendarInstanceForSessionOrNew(),
8405                                                year, month, day);
8406                        }
8407 
8408                        return getNativeDateViaParseConversion(columnIndex);
8409                case Types.TIMESTAMP:
8410                        if (populatedFromDateTimeValue) {
8411                                if ((year == 0) && (month == 0) && (day == 0)) {
8412                                        if (ConnectionProperties.ZERO_DATETIME_BEHAVIOR_CONVERT_TO_NULL
8413                                                        .equals(this.connection.getZeroDateTimeBehavior())) {
8414                                                this.wasNullFlag = true;
8415 
8416                                                return null;
8417                                        } else if (ConnectionProperties.ZERO_DATETIME_BEHAVIOR_EXCEPTION
8418                                                        .equals(this.connection.getZeroDateTimeBehavior())) {
8419                                                throw new SQLException(
8420                                                                "Value '0000-00-00' can not be represented as java.sql.Timestamp",
8421                                                                SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
8422                                        }
8423 
8424                                        year = 1;
8425                                        month = 1;
8426                                        day = 1;
8427                                }
8428 
8429                                Timestamp ts = fastTimestampCreate(
8430                                                getCalendarInstanceForSessionOrNew(), year, month, day,
8431                                                hour, minute, seconds, nanos);
8432 
8433                                Timestamp adjustedTs = TimeUtil.changeTimezone(this.connection,
8434                                                sessionCalendar, 
8435                                                targetCalendar,
8436                                                ts, this.connection.getServerTimezoneTZ(), tz,
8437                                                rollForward);
8438 
8439                                return adjustedTs;
8440                        }
8441 
8442                        return getNativeTimestampViaParseConversion(columnIndex, targetCalendar, tz, rollForward);
8443                        
8444                default:
8445                        throw new SQLException("Internal error - conversion method doesn't support this type", 
8446                                        SQLError.SQL_STATE_GENERAL_ERROR);
8447                }
8448        }
8449}

[all classes][com.mysql.jdbc]
EMMA 2.0.4217 (C) Vladimir Roubtsov