EMMA Coverage Report (generated Tue Jul 25 14:15:05 CDT 2006)
[all classes][com.mysql.jdbc]

COVERAGE SUMMARY FOR SOURCE FILE [Connection.java]

nameclass, %method, %block, %line, %
Connection.java75%  (3/4)44%  (139/314)67%  (5022/7532)66%  (1196.5/1802)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class Connection$UltraDevWorkAround0%   (0/1)0%   (0/154)0%   (0/681)0%   (0/198)
Connection$UltraDevWorkAround (Connection, PreparedStatement): void 0%   (0/1)0%   (0/12)0%   (0/4)
addBatch (): void 0%   (0/1)0%   (0/4)0%   (0/2)
addBatch (String): void 0%   (0/1)0%   (0/5)0%   (0/2)
cancel (): void 0%   (0/1)0%   (0/4)0%   (0/2)
clearBatch (): void 0%   (0/1)0%   (0/4)0%   (0/2)
clearParameters (): void 0%   (0/1)0%   (0/4)0%   (0/2)
clearWarnings (): void 0%   (0/1)0%   (0/4)0%   (0/2)
close (): void 0%   (0/1)0%   (0/4)0%   (0/2)
execute (): boolean 0%   (0/1)0%   (0/4)0%   (0/1)
execute (String): boolean 0%   (0/1)0%   (0/5)0%   (0/1)
execute (String, String []): boolean 0%   (0/1)0%   (0/6)0%   (0/1)
execute (String, int []): boolean 0%   (0/1)0%   (0/6)0%   (0/1)
execute (String, int): boolean 0%   (0/1)0%   (0/6)0%   (0/1)
executeBatch (): int [] 0%   (0/1)0%   (0/4)0%   (0/1)
executeQuery (): ResultSet 0%   (0/1)0%   (0/4)0%   (0/1)
executeQuery (String): ResultSet 0%   (0/1)0%   (0/5)0%   (0/1)
executeUpdate (): int 0%   (0/1)0%   (0/4)0%   (0/1)
executeUpdate (String): int 0%   (0/1)0%   (0/5)0%   (0/1)
executeUpdate (String, String []): int 0%   (0/1)0%   (0/6)0%   (0/1)
executeUpdate (String, int []): int 0%   (0/1)0%   (0/6)0%   (0/1)
executeUpdate (String, int): int 0%   (0/1)0%   (0/6)0%   (0/1)
getArray (String): Array 0%   (0/1)0%   (0/4)0%   (0/1)
getArray (int): Array 0%   (0/1)0%   (0/3)0%   (0/1)
getBigDecimal (String): BigDecimal 0%   (0/1)0%   (0/2)0%   (0/1)
getBigDecimal (int): BigDecimal 0%   (0/1)0%   (0/3)0%   (0/1)
getBigDecimal (int, int): BigDecimal 0%   (0/1)0%   (0/3)0%   (0/1)
getBlob (String): Blob 0%   (0/1)0%   (0/4)0%   (0/1)
getBlob (int): Blob 0%   (0/1)0%   (0/3)0%   (0/1)
getBoolean (String): boolean 0%   (0/1)0%   (0/4)0%   (0/1)
getBoolean (int): boolean 0%   (0/1)0%   (0/3)0%   (0/1)
getByte (String): byte 0%   (0/1)0%   (0/4)0%   (0/1)
getByte (int): byte 0%   (0/1)0%   (0/3)0%   (0/1)
getBytes (String): byte [] 0%   (0/1)0%   (0/4)0%   (0/1)
getBytes (int): byte [] 0%   (0/1)0%   (0/3)0%   (0/1)
getClob (String): Clob 0%   (0/1)0%   (0/4)0%   (0/1)
getClob (int): Clob 0%   (0/1)0%   (0/3)0%   (0/1)
getConnection (): Connection 0%   (0/1)0%   (0/4)0%   (0/1)
getDate (String): Date 0%   (0/1)0%   (0/4)0%   (0/1)
getDate (String, Calendar): Date 0%   (0/1)0%   (0/4)0%   (0/1)
getDate (int): Date 0%   (0/1)0%   (0/3)0%   (0/1)
getDate (int, Calendar): Date 0%   (0/1)0%   (0/3)0%   (0/1)
getDouble (String): double 0%   (0/1)0%   (0/4)0%   (0/1)
getDouble (int): double 0%   (0/1)0%   (0/3)0%   (0/1)
getFetchDirection (): int 0%   (0/1)0%   (0/4)0%   (0/1)
getFetchSize (): int 0%   (0/1)0%   (0/4)0%   (0/1)
getFloat (String): float 0%   (0/1)0%   (0/4)0%   (0/1)
getFloat (int): float 0%   (0/1)0%   (0/3)0%   (0/1)
getGeneratedKeys (): ResultSet 0%   (0/1)0%   (0/4)0%   (0/1)
getInt (String): int 0%   (0/1)0%   (0/4)0%   (0/1)
getInt (int): int 0%   (0/1)0%   (0/3)0%   (0/1)
getLong (String): long 0%   (0/1)0%   (0/4)0%   (0/1)
getLong (int): long 0%   (0/1)0%   (0/3)0%   (0/1)
getMaxFieldSize (): int 0%   (0/1)0%   (0/4)0%   (0/1)
getMaxRows (): int 0%   (0/1)0%   (0/4)0%   (0/1)
getMetaData (): ResultSetMetaData 0%   (0/1)0%   (0/3)0%   (0/1)
getMoreResults (): boolean 0%   (0/1)0%   (0/4)0%   (0/1)
getMoreResults (int): boolean 0%   (0/1)0%   (0/4)0%   (0/1)
getObject (String): Object 0%   (0/1)0%   (0/4)0%   (0/1)
getObject (String, Map): Object 0%   (0/1)0%   (0/4)0%   (0/1)
getObject (int): Object 0%   (0/1)0%   (0/3)0%   (0/1)
getObject (int, Map): Object 0%   (0/1)0%   (0/3)0%   (0/1)
getParameterMetaData (): ParameterMetaData 0%   (0/1)0%   (0/4)0%   (0/1)
getQueryTimeout (): int 0%   (0/1)0%   (0/4)0%   (0/1)
getRef (String): Ref 0%   (0/1)0%   (0/4)0%   (0/1)
getRef (int): Ref 0%   (0/1)0%   (0/3)0%   (0/1)
getResultSet (): ResultSet 0%   (0/1)0%   (0/4)0%   (0/1)
getResultSetConcurrency (): int 0%   (0/1)0%   (0/4)0%   (0/1)
getResultSetHoldability (): int 0%   (0/1)0%   (0/4)0%   (0/1)
getResultSetType (): int 0%   (0/1)0%   (0/4)0%   (0/1)
getShort (String): short 0%   (0/1)0%   (0/4)0%   (0/1)
getShort (int): short 0%   (0/1)0%   (0/3)0%   (0/1)
getString (String): String 0%   (0/1)0%   (0/4)0%   (0/1)
getString (int): String 0%   (0/1)0%   (0/3)0%   (0/1)
getTime (String): Time 0%   (0/1)0%   (0/4)0%   (0/1)
getTime (String, Calendar): Time 0%   (0/1)0%   (0/4)0%   (0/1)
getTime (int): Time 0%   (0/1)0%   (0/3)0%   (0/1)
getTime (int, Calendar): Time 0%   (0/1)0%   (0/3)0%   (0/1)
getTimestamp (String): Timestamp 0%   (0/1)0%   (0/4)0%   (0/1)
getTimestamp (String, Calendar): Timestamp 0%   (0/1)0%   (0/4)0%   (0/1)
getTimestamp (int): Timestamp 0%   (0/1)0%   (0/3)0%   (0/1)
getTimestamp (int, Calendar): Timestamp 0%   (0/1)0%   (0/3)0%   (0/1)
getURL (String): URL 0%   (0/1)0%   (0/4)0%   (0/1)
getURL (int): URL 0%   (0/1)0%   (0/4)0%   (0/1)
getUpdateCount (): int 0%   (0/1)0%   (0/4)0%   (0/1)
getWarnings (): SQLWarning 0%   (0/1)0%   (0/4)0%   (0/1)
registerOutParameter (String, int): void 0%   (0/1)0%   (0/4)0%   (0/1)
registerOutParameter (String, int, String): void 0%   (0/1)0%   (0/4)0%   (0/1)
registerOutParameter (String, int, int): void 0%   (0/1)0%   (0/4)0%   (0/1)
registerOutParameter (int, int): void 0%   (0/1)0%   (0/3)0%   (0/1)
registerOutParameter (int, int, String): void 0%   (0/1)0%   (0/3)0%   (0/1)
registerOutParameter (int, int, int): void 0%   (0/1)0%   (0/3)0%   (0/1)
setArray (int, Array): void 0%   (0/1)0%   (0/6)0%   (0/2)
setAsciiStream (String, InputStream, int): void 0%   (0/1)0%   (0/4)0%   (0/1)
setAsciiStream (int, InputStream, int): void 0%   (0/1)0%   (0/7)0%   (0/2)
setBigDecimal (String, BigDecimal): void 0%   (0/1)0%   (0/4)0%   (0/1)
setBigDecimal (int, BigDecimal): void 0%   (0/1)0%   (0/6)0%   (0/2)
setBinaryStream (String, InputStream, int): void 0%   (0/1)0%   (0/4)0%   (0/1)
setBinaryStream (int, InputStream, int): void 0%   (0/1)0%   (0/7)0%   (0/2)
setBlob (int, Blob): void 0%   (0/1)0%   (0/6)0%   (0/2)
setBoolean (String, boolean): void 0%   (0/1)0%   (0/4)0%   (0/1)
setBoolean (int, boolean): void 0%   (0/1)0%   (0/6)0%   (0/2)
setByte (String, byte): void 0%   (0/1)0%   (0/4)0%   (0/1)
setByte (int, byte): void 0%   (0/1)0%   (0/6)0%   (0/2)
setBytes (String, byte []): void 0%   (0/1)0%   (0/4)0%   (0/1)
setBytes (int, byte []): void 0%   (0/1)0%   (0/6)0%   (0/2)
setCharacterStream (String, Reader, int): void 0%   (0/1)0%   (0/4)0%   (0/1)
setCharacterStream (int, Reader, int): void 0%   (0/1)0%   (0/7)0%   (0/2)
setClob (int, Clob): void 0%   (0/1)0%   (0/6)0%   (0/2)
setCursorName (String): void 0%   (0/1)0%   (0/3)0%   (0/1)
setDate (String, Date): void 0%   (0/1)0%   (0/4)0%   (0/1)
setDate (String, Date, Calendar): void 0%   (0/1)0%   (0/4)0%   (0/1)
setDate (int, Date): void 0%   (0/1)0%   (0/6)0%   (0/2)
setDate (int, Date, Calendar): void 0%   (0/1)0%   (0/7)0%   (0/2)
setDouble (String, double): void 0%   (0/1)0%   (0/4)0%   (0/1)
setDouble (int, double): void 0%   (0/1)0%   (0/6)0%   (0/2)
setEscapeProcessing (boolean): void 0%   (0/1)0%   (0/5)0%   (0/2)
setFetchDirection (int): void 0%   (0/1)0%   (0/5)0%   (0/2)
setFetchSize (int): void 0%   (0/1)0%   (0/5)0%   (0/2)
setFloat (String, float): void 0%   (0/1)0%   (0/4)0%   (0/1)
setFloat (int, float): void 0%   (0/1)0%   (0/6)0%   (0/2)
setInt (String, int): void 0%   (0/1)0%   (0/4)0%   (0/1)
setInt (int, int): void 0%   (0/1)0%   (0/6)0%   (0/2)
setLong (String, long): void 0%   (0/1)0%   (0/4)0%   (0/1)
setLong (int, long): void 0%   (0/1)0%   (0/6)0%   (0/2)
setMaxFieldSize (int): void 0%   (0/1)0%   (0/5)0%   (0/2)
setMaxRows (int): void 0%   (0/1)0%   (0/5)0%   (0/2)
setNull (String, int): void 0%   (0/1)0%   (0/4)0%   (0/1)
setNull (String, int, String): void 0%   (0/1)0%   (0/4)0%   (0/1)
setNull (int, int): void 0%   (0/1)0%   (0/6)0%   (0/2)
setNull (int, int, String): void 0%   (0/1)0%   (0/7)0%   (0/2)
setObject (String, Object): void 0%   (0/1)0%   (0/4)0%   (0/1)
setObject (String, Object, int): void 0%   (0/1)0%   (0/4)0%   (0/1)
setObject (String, Object, int, int): void 0%   (0/1)0%   (0/4)0%   (0/1)
setObject (int, Object): void 0%   (0/1)0%   (0/6)0%   (0/2)
setObject (int, Object, int): void 0%   (0/1)0%   (0/7)0%   (0/2)
setObject (int, Object, int, int): void 0%   (0/1)0%   (0/8)0%   (0/2)
setQueryTimeout (int): void 0%   (0/1)0%   (0/3)0%   (0/1)
setRef (int, Ref): void 0%   (0/1)0%   (0/3)0%   (0/1)
setShort (String, short): void 0%   (0/1)0%   (0/4)0%   (0/1)
setShort (int, short): void 0%   (0/1)0%   (0/6)0%   (0/2)
setString (String, String): void 0%   (0/1)0%   (0/4)0%   (0/1)
setString (int, String): void 0%   (0/1)0%   (0/6)0%   (0/2)
setTime (String, Time): void 0%   (0/1)0%   (0/4)0%   (0/1)
setTime (String, Time, Calendar): void 0%   (0/1)0%   (0/4)0%   (0/1)
setTime (int, Time): void 0%   (0/1)0%   (0/6)0%   (0/2)
setTime (int, Time, Calendar): void 0%   (0/1)0%   (0/7)0%   (0/2)
setTimestamp (String, Timestamp): void 0%   (0/1)0%   (0/4)0%   (0/1)
setTimestamp (String, Timestamp, Calendar): void 0%   (0/1)0%   (0/4)0%   (0/1)
setTimestamp (int, Timestamp): void 0%   (0/1)0%   (0/6)0%   (0/2)
setTimestamp (int, Timestamp, Calendar): void 0%   (0/1)0%   (0/7)0%   (0/2)
setURL (String, URL): void 0%   (0/1)0%   (0/4)0%   (0/1)
setURL (int, URL): void 0%   (0/1)0%   (0/6)0%   (0/2)
setUnicodeStream (int, InputStream, int): void 0%   (0/1)0%   (0/7)0%   (0/2)
wasNull (): boolean 0%   (0/1)0%   (0/3)0%   (0/1)
     
class Connection$1100% (1/1)100% (2/2)54%  (19/35)42%  (5/12)
removeEldestEntry (Map$Entry): boolean 100% (1/1)43%  (12/28)36%  (4/11)
Connection$1 (Connection, int): void 100% (1/1)100% (7/7)100% (1/1)
     
class Connection100% (1/1)86%  (134/155)73%  (4943/6744)75%  (1179.6/1578)
clearWarnings (): void 0%   (0/1)0%   (0/1)0%   (0/1)
createStatement (int, int, int): Statement 0%   (0/1)0%   (0/15)0%   (0/4)
getHoldability (): int 0%   (0/1)0%   (0/2)0%   (0/1)
getIdleFor (): long 0%   (0/1)0%   (0/16)0%   (0/5)
getServerMajorVersion (): int 0%   (0/1)0%   (0/4)0%   (0/1)
getServerMinorVersion (): int 0%   (0/1)0%   (0/4)0%   (0/1)
getServerSubMinorVersion (): int 0%   (0/1)0%   (0/4)0%   (0/1)
getTypeMap (): Map 0%   (0/1)0%   (0/11)0%   (0/3)
getUser (): String 0%   (0/1)0%   (0/3)0%   (0/1)
getUtcCalendar (): Calendar 0%   (0/1)0%   (0/3)0%   (0/1)
getWarnings (): SQLWarning 0%   (0/1)0%   (0/2)0%   (0/1)
isSameResource (Connection): boolean 0%   (0/1)0%   (0/95)0%   (0/24)
nullSafeCompare (String, String): boolean 0%   (0/1)0%   (0/16)0%   (0/5)
prepareCall (String, int, int, int): CallableStatement 0%   (0/1)0%   (0/19)0%   (0/5)
prepareStatement (String, String []): PreparedStatement 0%   (0/1)0%   (0/17)0%   (0/3)
prepareStatement (String, int []): PreparedStatement 0%   (0/1)0%   (0/17)0%   (0/3)
prepareStatement (String, int, int, int): PreparedStatement 0%   (0/1)0%   (0/16)0%   (0/4)
serverPrepare (String): ServerPreparedStatement 0%   (0/1)0%   (0/8)0%   (0/1)
setHoldability (int): void 0%   (0/1)0%   (0/1)0%   (0/1)
setTypeMap (Map): void 0%   (0/1)0%   (0/4)0%   (0/2)
shutdownServer (): void 0%   (0/1)0%   (0/26)0%   (0/5)
getCharsetConverter (String): SingleByteCharsetConverter 100% (1/1)12%  (9/72)19%  (4/21)
clientPrepareStatement (String, int, int): PreparedStatement 100% (1/1)17%  (23/133)24%  (7/29)
configureCharsetProperties (): void 100% (1/1)20%  (12/60)33%  (5/15)
incrementNumberOfPreparedExecutes (): void 100% (1/1)25%  (4/16)50%  (2/4)
checkServerEncoding (): void 100% (1/1)37%  (46/126)54%  (15.6/29)
checkClosed (): void 100% (1/1)39%  (26/66)44%  (7/16)
rollback (Savepoint): void 100% (1/1)40%  (54/136)47%  (14.2/30)
incrementNumberOfPrepares (): void 100% (1/1)40%  (4/10)67%  (2/3)
rollback (): void 100% (1/1)44%  (29/66)56%  (10.1/18)
extractSqlFromPacket (String, Buffer, int): String 100% (1/1)51%  (35/68)65%  (11/17)
prepareCall (String): CallableStatement 100% (1/1)53%  (9/17)67%  (2/3)
commit (): void 100% (1/1)54%  (35/65)51%  (7.2/14)
setAutoCommit (boolean): void 100% (1/1)66%  (63/96)67%  (13.4/20)
getCharsetNameForIndex (int): String 100% (1/1)66%  (35/53)80%  (12/15)
getActiveStatementCount (): int 100% (1/1)67%  (14/21)60%  (3/5)
getMutex (): Object 100% (1/1)67%  (8/12)75%  (3/4)
useMaxRows (): boolean 100% (1/1)67%  (10/15)67%  (2/3)
setCatalog (String): void 100% (1/1)67%  (61/91)66%  (13.9/21)
setTransactionIsolation (int): void 100% (1/1)68%  (59/87)80%  (20.8/26)
createNewIO (boolean): MysqlIO 100% (1/1)68%  (357/526)72%  (98.5/137)
configureTimezone (): void 100% (1/1)68%  (73/107)82%  (18/22)
getIO (): MysqlIO 100% (1/1)69%  (9/13)67%  (2/3)
setSavepoint (MysqlSavepoint): void 100% (1/1)70%  (49/70)85%  (12.7/15)
getTransactionIsolation (): int 100% (1/1)71%  (75/105)78%  (23.4/30)
realClose (boolean, boolean, boolean, Throwable): void 100% (1/1)74%  (92/124)86%  (31.8/37)
execSQL (Statement, String, int, Buffer, int, int, boolean, String, boolean, ... 100% (1/1)75%  (230/308)77%  (48.4/63)
getCalendarInstanceForSessionOrNew (): Calendar 100% (1/1)75%  (6/8)67%  (2/3)
registerStatement (Statement): void 100% (1/1)75%  (15/20)93%  (3.7/4)
recachePreparedStatement (ServerPreparedStatement): void 100% (1/1)76%  (16/21)94%  (3.8/4)
unregisterStatement (Statement): void 100% (1/1)77%  (17/22)94%  (4.7/5)
Connection (String, int, Properties, String, String): void 100% (1/1)78%  (390/499)79%  (108/136)
getMetadataSafeStatement (): Statement 100% (1/1)79%  (11/14)80%  (4/5)
initializePropsFromServer (): void 100% (1/1)79%  (304/385)73%  (66.8/91)
prepareStatement (String, int, int): PreparedStatement 100% (1/1)80%  (105/132)81%  (28.4/35)
getServerVariable (String): String 100% (1/1)82%  (9/11)67%  (2/3)
loadServerVariables (): void 100% (1/1)82%  (86/105)83%  (24.8/30)
getMaxBytesPerChar (String): int 100% (1/1)83%  (81/98)82%  (23/28)
addToHistogram (int [], long [], long, int, long, long): void 100% (1/1)83%  (24/29)86%  (6/7)
maxRowsChanged (Statement): void 100% (1/1)84%  (26/31)96%  (6.7/7)
reportMetrics (): void 100% (1/1)85%  (398/467)86%  (55.7/65)
canHandleAsServerPreparedStatement (String): boolean 100% (1/1)87%  (52/60)84%  (10.9/13)
buildCollationMapping (): void 100% (1/1)88%  (160/182)87%  (40.1/46)
cleanup (Throwable): void 100% (1/1)88%  (22/25)88%  (7/8)
prepareCall (String, int, int): CallableStatement 100% (1/1)88%  (68/77)90%  (15.4/17)
closeStatement (Statement): void 100% (1/1)89%  (8/9)83%  (5/6)
changeUser (String, String): void 100% (1/1)89%  (33/37)82%  (9/11)
configureClientCharacterSet (): boolean 100% (1/1)89%  (262/293)89%  (44.4/50)
nativeSQL (String): String 100% (1/1)90%  (18/20)83%  (5/6)
repartitionTablesAccessedHistogram (): void 100% (1/1)90%  (18/20)97%  (2.9/3)
canHandleAsServerPreparedStatementNoCache (String): boolean 100% (1/1)91%  (117/129)85%  (24.7/29)
appendMessageToException (SQLException, String): SQLException 100% (1/1)91%  (99/109)82%  (18/22)
addToTablesAccessedHistogram (long, int): void 100% (1/1)91%  (20/22)97%  (2.9/3)
setSessionVariables (): void 100% (1/1)91%  (70/77)91%  (11.8/13)
initializeDriverProperties (Properties): void 100% (1/1)92%  (45/49)92%  (11/12)
prepareStatement (String, int): PreparedStatement 100% (1/1)93%  (14/15)98%  (2.9/3)
checkTransactionIsolationLevel (): void 100% (1/1)94%  (31/33)90%  (9/10)
resetServerState (): void 100% (1/1)96%  (22/23)98%  (2.9/3)
<static initializer> 100% (1/1)100% (65/65)100% (12/12)
addToPerformanceHistogram (long, int): void 100% (1/1)100% (22/22)100% (3/3)
checkAndCreatePerformanceHistogram (): void 100% (1/1)100% (15/15)100% (5/5)
checkAndCreateTablesAccessedHistogram (): void 100% (1/1)100% (15/15)100% (5/5)
clearHasTriedMaster (): void 100% (1/1)100% (4/4)100% (2/2)
clientPrepareStatement (String): PreparedStatement 100% (1/1)100% (6/6)100% (1/1)
close (): void 100% (1/1)100% (7/7)100% (2/2)
closeAllOpenStatements (): void 100% (1/1)100% (51/51)100% (16/16)
createInitialHistogram (long [], long, long): void 100% (1/1)100% (34/34)100% (7/7)
createPreparedStatementCaches (): void 100% (1/1)100% (23/23)100% (5/5)
createStatement (): Statement 100% (1/1)100% (5/5)100% (1/1)
createStatement (int, int): Statement 100% (1/1)100% (17/17)100% (5/5)
dumpTestcaseQuery (String): void 100% (1/1)100% (4/4)100% (2/2)
duplicate (): Connection 100% (1/1)100% (14/14)100% (1/1)
execSQL (Statement, String, int, Buffer, int, int, boolean, String, boolean):... 100% (1/1)100% (13/13)100% (1/1)
finalize (): void 100% (1/1)100% (4/4)100% (2/2)
generateConnectionCommentBlock (StringBuffer): StringBuffer 100% (1/1)100% (15/15)100% (4/4)
getAutoCommit (): boolean 100% (1/1)100% (3/3)100% (1/1)
getCancelTimer (): Timer 100% (1/1)100% (2/2)100% (1/1)
getCatalog (): String 100% (1/1)100% (3/3)100% (1/1)
getCharacterSetMetadata (): String 100% (1/1)100% (3/3)100% (1/1)
getDefaultTimeZone (): TimeZone 100% (1/1)100% (3/3)100% (1/1)
getErrorMessageEncoding (): String 100% (1/1)100% (3/3)100% (1/1)
getId (): long 100% (1/1)100% (3/3)100% (1/1)
getLog (): Log 100% (1/1)100% (3/3)100% (1/1)
getMaxAllowedPacket (): int 100% (1/1)100% (3/3)100% (1/1)
getMetaData (): DatabaseMetaData 100% (1/1)100% (25/25)100% (4/4)
getNetBufferLength (): int 100% (1/1)100% (3/3)100% (1/1)
getNextRoundRobinHostIndex (String, List): int 100% (1/1)100% (46/46)100% (11/11)
getServerCharacterEncoding (): String 100% (1/1)100% (6/6)100% (1/1)
getServerTimezoneTZ (): TimeZone 100% (1/1)100% (3/3)100% (1/1)
getServerVersion (): String 100% (1/1)100% (4/4)100% (1/1)
getSessionLockedCalendar (): Calendar 100% (1/1)100% (3/3)100% (1/1)
getURL (): String 100% (1/1)100% (3/3)100% (1/1)
hasSameProperties (Connection): boolean 100% (1/1)100% (6/6)100% (1/1)
hasTriedMaster (): boolean 100% (1/1)100% (3/3)100% (1/1)
incrementNumberOfResultSetsCreated (): void 100% (1/1)100% (10/10)100% (3/3)
isClientTzUTC (): boolean 100% (1/1)100% (3/3)100% (1/1)
isClosed (): boolean 100% (1/1)100% (3/3)100% (1/1)
isCursorFetchEnabled (): boolean 100% (1/1)100% (13/13)100% (1/1)
isInGlobalTx (): boolean 100% (1/1)100% (3/3)100% (1/1)
isMasterConnection (): boolean 100% (1/1)100% (7/7)100% (1/1)
isNoBackslashEscapesSet (): boolean 100% (1/1)100% (3/3)100% (1/1)
isReadInfoMsgEnabled (): boolean 100% (1/1)100% (3/3)100% (1/1)
isReadOnly (): boolean 100% (1/1)100% (3/3)100% (1/1)
isRunningOnJDK13 (): boolean 100% (1/1)100% (3/3)100% (1/1)
isServerTzUTC (): boolean 100% (1/1)100% (3/3)100% (1/1)
lowerCaseTableNames (): boolean 100% (1/1)100% (3/3)100% (1/1)
parseCallableStatement (String): CallableStatement 100% (1/1)100% (36/36)100% (9/9)
parserKnowsUnicode (): boolean 100% (1/1)100% (3/3)100% (1/1)
ping (): void 100% (1/1)100% (4/4)100% (2/2)
pingInternal (boolean): void 100% (1/1)100% (14/14)100% (4/4)
prepareStatement (String): PreparedStatement 100% (1/1)100% (6/6)100% (1/1)
registerQueryExecutionTime (long): void 100% (1/1)100% (42/42)100% (9/9)
releaseSavepoint (Savepoint): void 100% (1/1)100% (1/1)100% (1/1)
repartitionHistogram (int [], long [], long, long): void 100% (1/1)100% (71/71)100% (11/11)
repartitionPerformanceHistogram (): void 100% (1/1)100% (20/20)100% (3/3)
reportMetricsIfNeeded (): void 100% (1/1)100% (15/15)100% (4/4)
reportNumberOfTablesAccessed (int): void 100% (1/1)100% (28/28)100% (7/7)
rollbackNoChecks (): void 100% (1/1)100% (15/15)100% (2/2)
serverSupportsConvertFn (): boolean 100% (1/1)100% (6/6)100% (1/1)
setFailedOver (boolean): void 100% (1/1)100% (4/4)100% (2/2)
setFailedOverState (): void 100% (1/1)100% (16/16)100% (6/6)
setInGlobalTx (boolean): void 100% (1/1)100% (4/4)100% (2/2)
setPreferSlaveDuringFailover (boolean): void 100% (1/1)100% (4/4)100% (2/2)
setReadInfoMsgEnabled (boolean): void 100% (1/1)100% (4/4)100% (2/2)
setReadOnly (boolean): void 100% (1/1)100% (6/6)100% (3/3)
setSavepoint (): Savepoint 100% (1/1)100% (9/9)100% (3/3)
setSavepoint (String): Savepoint 100% (1/1)100% (10/10)100% (3/3)
setupServerForTruncationChecks (): void 100% (1/1)100% (66/66)100% (12/12)
shouldFallBack (): boolean 100% (1/1)100% (26/26)100% (3/3)
supportsIsolationLevel (): boolean 100% (1/1)100% (3/3)100% (1/1)
supportsQuotedIdentifiers (): boolean 100% (1/1)100% (3/3)100% (1/1)
supportsTransactions (): boolean 100% (1/1)100% (3/3)100% (1/1)
unsetMaxRows (Statement): void 100% (1/1)100% (45/45)100% (8/8)
useAnsiQuotedIdentifiers (): boolean 100% (1/1)100% (3/3)100% (1/1)
versionMeetsMinimum (int, int, int): boolean 100% (1/1)100% (9/9)100% (2/2)
     
class Connection$CompoundCacheKey100% (1/1)100% (3/3)83%  (60/72)85%  (11.9/14)
equals (Object): boolean 100% (1/1)72%  (28/39)74%  (5.9/8)
Connection$CompoundCacheKey (Connection, String, String): void 100% (1/1)97%  (29/30)99%  (5/5)
hashCode (): int 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.log.Log;
28import com.mysql.jdbc.log.LogFactory;
29import com.mysql.jdbc.log.NullLogger;
30import com.mysql.jdbc.profiler.ProfileEventSink;
31import com.mysql.jdbc.profiler.ProfilerEvent;
32import com.mysql.jdbc.util.LRUCache;
33 
34import java.io.IOException;
35import java.io.InputStream;
36import java.io.Reader;
37import java.io.UnsupportedEncodingException;
38 
39import java.lang.reflect.Array;
40import java.lang.reflect.Method;
41import java.math.BigDecimal;
42 
43import java.net.URL;
44 
45import java.sql.Blob;
46import java.sql.Clob;
47import java.sql.Date;
48import java.sql.ParameterMetaData;
49import java.sql.Ref;
50import java.sql.SQLException;
51import java.sql.SQLWarning;
52import java.sql.Savepoint;
53import java.sql.Time;
54import java.sql.Timestamp;
55 
56import java.util.ArrayList;
57import java.util.Calendar;
58import java.util.GregorianCalendar;
59import java.util.HashMap;
60import java.util.Hashtable;
61import java.util.Iterator;
62import java.util.List;
63import java.util.Locale;
64import java.util.Map;
65import java.util.Properties;
66import java.util.Stack;
67import java.util.StringTokenizer;
68import java.util.TimeZone;
69import java.util.Timer;
70import java.util.TreeMap;
71 
72/**
73 * A Connection represents a session with a specific database. Within the
74 * context of a Connection, SQL statements are executed and results are
75 * returned.
76 * <P>
77 * A Connection's database is able to provide information describing its tables,
78 * its supported SQL grammar, its stored procedures, the capabilities of this
79 * connection, etc. This information is obtained with the getMetaData method.
80 * </p>
81 * 
82 * @author Mark Matthews
83 * @version $Id: Connection.java 5444 2006-06-27 20:13:53 +0000 (Tue, 27 Jun 2006) mmatthews $
84 * @see java.sql.Connection
85 */
86public class Connection extends ConnectionProperties implements
87                java.sql.Connection {
88        /**
89         * Used as a key for caching callable statements which (may) depend on
90         * current catalog...In 5.0.x, they don't (currently), but stored procedure
91         * names soon will, so current catalog is a (hidden) component of the name.
92         */
93        class CompoundCacheKey {
94                String componentOne;
95 
96                String componentTwo;
97 
98                int hashCode;
99 
100                CompoundCacheKey(String partOne, String partTwo) {
101                        this.componentOne = partOne;
102                        this.componentTwo = partTwo;
103 
104                        // Handle first component (in most cases, currentCatalog)
105                        // being NULL....
106                        this.hashCode = (((this.componentOne != null) ? this.componentOne
107                                        : "") + this.componentTwo).hashCode();
108                }
109 
110                /*
111                 * (non-Javadoc)
112                 * 
113                 * @see java.lang.Object#equals(java.lang.Object)
114                 */
115                public boolean equals(Object obj) {
116                        if (obj instanceof CompoundCacheKey) {
117                                CompoundCacheKey another = (CompoundCacheKey) obj;
118 
119                                boolean firstPartEqual = false;
120 
121                                if (this.componentOne == null) {
122                                        firstPartEqual = (another.componentOne == null);
123                                } else {
124                                        firstPartEqual = this.componentOne
125                                                        .equals(another.componentOne);
126                                }
127 
128                                return (firstPartEqual && this.componentTwo
129                                                .equals(another.componentTwo));
130                        }
131 
132                        return false;
133                }
134 
135                /*
136                 * (non-Javadoc)
137                 * 
138                 * @see java.lang.Object#hashCode()
139                 */
140                public int hashCode() {
141                        return this.hashCode;
142                }
143        }
144 
145        /**
146         * Wrapper class for UltraDev CallableStatements that are really
147         * PreparedStatments. Nice going, UltraDev developers.
148         */
149        class UltraDevWorkAround implements java.sql.CallableStatement {
150                private java.sql.PreparedStatement delegate = null;
151 
152                UltraDevWorkAround(java.sql.PreparedStatement pstmt) {
153                        this.delegate = pstmt;
154                }
155 
156                public void addBatch() throws SQLException {
157                        this.delegate.addBatch();
158                }
159 
160                public void addBatch(java.lang.String p1) throws SQLException {
161                        this.delegate.addBatch(p1);
162                }
163 
164                public void cancel() throws SQLException {
165                        this.delegate.cancel();
166                }
167 
168                public void clearBatch() throws SQLException {
169                        this.delegate.clearBatch();
170                }
171 
172                public void clearParameters() throws SQLException {
173                        this.delegate.clearParameters();
174                }
175 
176                public void clearWarnings() throws SQLException {
177                        this.delegate.clearWarnings();
178                }
179 
180                public void close() throws SQLException {
181                        this.delegate.close();
182                }
183 
184                public boolean execute() throws SQLException {
185                        return this.delegate.execute();
186                }
187 
188                public boolean execute(java.lang.String p1) throws SQLException {
189                        return this.delegate.execute(p1);
190                }
191 
192                /**
193                 * @see Statement#execute(String, int)
194                 */
195                public boolean execute(String arg0, int arg1) throws SQLException {
196                        return this.delegate.execute(arg0, arg1);
197                }
198 
199                /**
200                 * @see Statement#execute(String, int[])
201                 */
202                public boolean execute(String arg0, int[] arg1) throws SQLException {
203                        return this.delegate.execute(arg0, arg1);
204                }
205 
206                /**
207                 * @see Statement#execute(String, String[])
208                 */
209                public boolean execute(String arg0, String[] arg1) throws SQLException {
210                        return this.delegate.execute(arg0, arg1);
211                }
212 
213                public int[] executeBatch() throws SQLException {
214                        return this.delegate.executeBatch();
215                }
216 
217                public java.sql.ResultSet executeQuery() throws SQLException {
218                        return this.delegate.executeQuery();
219                }
220 
221                public java.sql.ResultSet executeQuery(java.lang.String p1)
222                                throws SQLException {
223                        return this.delegate.executeQuery(p1);
224                }
225 
226                public int executeUpdate() throws SQLException {
227                        return this.delegate.executeUpdate();
228                }
229 
230                public int executeUpdate(java.lang.String p1) throws SQLException {
231                        return this.delegate.executeUpdate(p1);
232                }
233 
234                /**
235                 * @see Statement#executeUpdate(String, int)
236                 */
237                public int executeUpdate(String arg0, int arg1) throws SQLException {
238                        return this.delegate.executeUpdate(arg0, arg1);
239                }
240 
241                /**
242                 * @see Statement#executeUpdate(String, int[])
243                 */
244                public int executeUpdate(String arg0, int[] arg1) throws SQLException {
245                        return this.delegate.executeUpdate(arg0, arg1);
246                }
247 
248                /**
249                 * @see Statement#executeUpdate(String, String[])
250                 */
251                public int executeUpdate(String arg0, String[] arg1)
252                                throws SQLException {
253                        return this.delegate.executeUpdate(arg0, arg1);
254                }
255 
256                public java.sql.Array getArray(int p1) throws SQLException {
257                        throw SQLError.createSQLException("Not supported");
258                }
259 
260                /**
261                 * @see CallableStatement#getArray(String)
262                 */
263                public java.sql.Array getArray(String arg0) throws SQLException {
264                        throw new NotImplemented();
265                }
266 
267                public java.math.BigDecimal getBigDecimal(int p1) throws SQLException {
268                        throw SQLError.createSQLException("Not supported");
269                }
270 
271                /**
272                 * DOCUMENT ME!
273                 * 
274                 * @param p1
275                 *            DOCUMENT ME!
276                 * @param p2
277                 *            DOCUMENT ME!
278                 * @return DOCUMENT ME!
279                 * @throws SQLException
280                 *             DOCUMENT ME!
281                 * @deprecated
282                 */
283                public java.math.BigDecimal getBigDecimal(int p1, int p2)
284                                throws SQLException {
285                        throw SQLError.createSQLException("Not supported");
286                }
287 
288                /**
289                 * @see CallableStatement#getBigDecimal(String)
290                 */
291                public BigDecimal getBigDecimal(String arg0) throws SQLException {
292                        return null;
293                }
294 
295                public java.sql.Blob getBlob(int p1) throws SQLException {
296                        throw SQLError.createSQLException("Not supported");
297                }
298 
299                /**
300                 * @see CallableStatement#getBlob(String)
301                 */
302                public java.sql.Blob getBlob(String arg0) throws SQLException {
303                        throw new NotImplemented();
304                }
305 
306                public boolean getBoolean(int p1) throws SQLException {
307                        throw SQLError.createSQLException("Not supported");
308                }
309 
310                /**
311                 * @see CallableStatement#getBoolean(String)
312                 */
313                public boolean getBoolean(String arg0) throws SQLException {
314                        throw new NotImplemented();
315                }
316 
317                public byte getByte(int p1) throws SQLException {
318                        throw SQLError.createSQLException("Not supported");
319                }
320 
321                /**
322                 * @see CallableStatement#getByte(String)
323                 */
324                public byte getByte(String arg0) throws SQLException {
325                        throw new NotImplemented();
326                }
327 
328                public byte[] getBytes(int p1) throws SQLException {
329                        throw SQLError.createSQLException("Not supported");
330                }
331 
332                /**
333                 * @see CallableStatement#getBytes(String)
334                 */
335                public byte[] getBytes(String arg0) throws SQLException {
336                        throw new NotImplemented();
337                }
338 
339                public java.sql.Clob getClob(int p1) throws SQLException {
340                        throw SQLError.createSQLException("Not supported");
341                }
342 
343                /**
344                 * @see CallableStatement#getClob(String)
345                 */
346                public Clob getClob(String arg0) throws SQLException {
347                        throw new NotImplemented();
348                }
349 
350                public java.sql.Connection getConnection() throws SQLException {
351                        return this.delegate.getConnection();
352                }
353 
354                public java.sql.Date getDate(int p1) throws SQLException {
355                        throw SQLError.createSQLException("Not supported");
356                }
357 
358                public java.sql.Date getDate(int p1, final Calendar p2)
359                                throws SQLException {
360                        throw SQLError.createSQLException("Not supported");
361                }
362 
363                /**
364                 * @see CallableStatement#getDate(String)
365                 */
366                public Date getDate(String arg0) throws SQLException {
367                        throw new NotImplemented();
368                }
369 
370                /**
371                 * @see CallableStatement#getDate(String, Calendar)
372                 */
373                public Date getDate(String arg0, Calendar arg1) throws SQLException {
374                        throw new NotImplemented();
375                }
376 
377                public double getDouble(int p1) throws SQLException {
378                        throw SQLError.createSQLException("Not supported");
379                }
380 
381                /**
382                 * @see CallableStatement#getDouble(String)
383                 */
384                public double getDouble(String arg0) throws SQLException {
385                        throw new NotImplemented();
386                }
387 
388                public int getFetchDirection() throws SQLException {
389                        return this.delegate.getFetchDirection();
390                }
391 
392                public int getFetchSize() throws java.sql.SQLException {
393                        return this.delegate.getFetchSize();
394                }
395 
396                public float getFloat(int p1) throws SQLException {
397                        throw SQLError.createSQLException("Not supported");
398                }
399 
400                /**
401                 * @see CallableStatement#getFloat(String)
402                 */
403                public float getFloat(String arg0) throws SQLException {
404                        throw new NotImplemented();
405                }
406 
407                /**
408                 * @see Statement#getGeneratedKeys()
409                 */
410                public java.sql.ResultSet getGeneratedKeys() throws SQLException {
411                        return this.delegate.getGeneratedKeys();
412                }
413 
414                public int getInt(int p1) throws SQLException {
415                        throw SQLError.createSQLException("Not supported");
416                }
417 
418                /**
419                 * @see CallableStatement#getInt(String)
420                 */
421                public int getInt(String arg0) throws SQLException {
422                        throw new NotImplemented();
423                }
424 
425                public long getLong(int p1) throws SQLException {
426                        throw SQLError.createSQLException("Not supported");
427                }
428 
429                /**
430                 * @see CallableStatement#getLong(String)
431                 */
432                public long getLong(String arg0) throws SQLException {
433                        throw new NotImplemented();
434                }
435 
436                public int getMaxFieldSize() throws SQLException {
437                        return this.delegate.getMaxFieldSize();
438                }
439 
440                public int getMaxRows() throws SQLException {
441                        return this.delegate.getMaxRows();
442                }
443 
444                public java.sql.ResultSetMetaData getMetaData() throws SQLException {
445                        throw SQLError.createSQLException("Not supported");
446                }
447 
448                public boolean getMoreResults() throws SQLException {
449                        return this.delegate.getMoreResults();
450                }
451 
452                /**
453                 * @see Statement#getMoreResults(int)
454                 */
455                public boolean getMoreResults(int arg0) throws SQLException {
456                        return this.delegate.getMoreResults();
457                }
458 
459                public java.lang.Object getObject(int p1) throws SQLException {
460                        throw SQLError.createSQLException("Not supported");
461                }
462 
463                public java.lang.Object getObject(int p1, final java.util.Map p2)
464                                throws SQLException {
465                        throw SQLError.createSQLException("Not supported");
466                }
467 
468                /**
469                 * @see CallableStatement#getObject(String)
470                 */
471                public Object getObject(String arg0) throws SQLException {
472                        throw new NotImplemented();
473                }
474 
475                /**
476                 * @see CallableStatement#getObject(String, Map)
477                 */
478                public Object getObject(String arg0, Map arg1) throws SQLException {
479                        throw new NotImplemented();
480                }
481 
482                /**
483                 * @see PreparedStatement#getParameterMetaData()
484                 */
485                public ParameterMetaData getParameterMetaData() throws SQLException {
486                        return this.delegate.getParameterMetaData();
487                }
488 
489                public int getQueryTimeout() throws SQLException {
490                        return this.delegate.getQueryTimeout();
491                }
492 
493                public java.sql.Ref getRef(int p1) throws SQLException {
494                        throw SQLError.createSQLException("Not supported");
495                }
496 
497                /**
498                 * @see CallableStatement#getRef(String)
499                 */
500                public Ref getRef(String arg0) throws SQLException {
501                        throw new NotImplemented();
502                }
503 
504                public java.sql.ResultSet getResultSet() throws SQLException {
505                        return this.delegate.getResultSet();
506                }
507 
508                public int getResultSetConcurrency() throws SQLException {
509                        return this.delegate.getResultSetConcurrency();
510                }
511 
512                /**
513                 * @see Statement#getResultSetHoldability()
514                 */
515                public int getResultSetHoldability() throws SQLException {
516                        return this.delegate.getResultSetHoldability();
517                }
518 
519                public int getResultSetType() throws SQLException {
520                        return this.delegate.getResultSetType();
521                }
522 
523                public short getShort(int p1) throws SQLException {
524                        throw SQLError.createSQLException("Not supported");
525                }
526 
527                /**
528                 * @see CallableStatement#getShort(String)
529                 */
530                public short getShort(String arg0) throws SQLException {
531                        throw new NotImplemented();
532                }
533 
534                public java.lang.String getString(int p1) throws SQLException {
535                        throw SQLError.createSQLException("Not supported");
536                }
537 
538                /**
539                 * @see CallableStatement#getString(String)
540                 */
541                public String getString(String arg0) throws SQLException {
542                        throw new NotImplemented();
543                }
544 
545                public java.sql.Time getTime(int p1) throws SQLException {
546                        throw SQLError.createSQLException("Not supported");
547                }
548 
549                public java.sql.Time getTime(int p1, final java.util.Calendar p2)
550                                throws SQLException {
551                        throw SQLError.createSQLException("Not supported");
552                }
553 
554                /**
555                 * @see CallableStatement#getTime(String)
556                 */
557                public Time getTime(String arg0) throws SQLException {
558                        throw new NotImplemented();
559                }
560 
561                /**
562                 * @see CallableStatement#getTime(String, Calendar)
563                 */
564                public Time getTime(String arg0, Calendar arg1) throws SQLException {
565                        throw new NotImplemented();
566                }
567 
568                public java.sql.Timestamp getTimestamp(int p1) throws SQLException {
569                        throw SQLError.createSQLException("Not supported");
570                }
571 
572                public java.sql.Timestamp getTimestamp(int p1,
573                                final java.util.Calendar p2) throws SQLException {
574                        throw SQLError.createSQLException("Not supported");
575                }
576 
577                /**
578                 * @see CallableStatement#getTimestamp(String)
579                 */
580                public Timestamp getTimestamp(String arg0) throws SQLException {
581                        throw new NotImplemented();
582                }
583 
584                /**
585                 * @see CallableStatement#getTimestamp(String, Calendar)
586                 */
587                public Timestamp getTimestamp(String arg0, Calendar arg1)
588                                throws SQLException {
589                        throw new NotImplemented();
590                }
591 
592                public int getUpdateCount() throws SQLException {
593                        return this.delegate.getUpdateCount();
594                }
595 
596                /**
597                 * @see CallableStatement#getURL(int)
598                 */
599                public URL getURL(int arg0) throws SQLException {
600                        throw new NotImplemented();
601                }
602 
603                /**
604                 * @see CallableStatement#getURL(String)
605                 */
606                public URL getURL(String arg0) throws SQLException {
607                        throw new NotImplemented();
608                }
609 
610                public java.sql.SQLWarning getWarnings() throws SQLException {
611                        return this.delegate.getWarnings();
612                }
613 
614                public void registerOutParameter(int p1, int p2) throws SQLException {
615                        throw SQLError.createSQLException("Not supported");
616                }
617 
618                public void registerOutParameter(int p1, int p2, int p3)
619                                throws SQLException {
620                        throw SQLError.createSQLException("Not supported");
621                }
622 
623                public void registerOutParameter(int p1, int p2, java.lang.String p3)
624                                throws SQLException {
625                        throw SQLError.createSQLException("Not supported");
626                }
627 
628                /**
629                 * @see CallableStatement#registerOutParameter(String, int)
630                 */
631                public void registerOutParameter(String arg0, int arg1)
632                                throws SQLException {
633                        throw new NotImplemented();
634                }
635 
636                /**
637                 * @see CallableStatement#registerOutParameter(String, int, int)
638                 */
639                public void registerOutParameter(String arg0, int arg1, int arg2)
640                                throws SQLException {
641                        throw new NotImplemented();
642                }
643 
644                /**
645                 * @see CallableStatement#registerOutParameter(String, int, String)
646                 */
647                public void registerOutParameter(String arg0, int arg1, String arg2)
648                                throws SQLException {
649                        throw new NotImplemented();
650                }
651 
652                public void setArray(int p1, final java.sql.Array p2)
653                                throws SQLException {
654                        this.delegate.setArray(p1, p2);
655                }
656 
657                public void setAsciiStream(int p1, final java.io.InputStream p2, int p3)
658                                throws SQLException {
659                        this.delegate.setAsciiStream(p1, p2, p3);
660                }
661 
662                /**
663                 * @see CallableStatement#setAsciiStream(String, InputStream, int)
664                 */
665                public void setAsciiStream(String arg0, InputStream arg1, int arg2)
666                                throws SQLException {
667                        throw new NotImplemented();
668                }
669 
670                public void setBigDecimal(int p1, final java.math.BigDecimal p2)
671                                throws SQLException {
672                        this.delegate.setBigDecimal(p1, p2);
673                }
674 
675                /**
676                 * @see CallableStatement#setBigDecimal(String, BigDecimal)
677                 */
678                public void setBigDecimal(String arg0, BigDecimal arg1)
679                                throws SQLException {
680                        throw new NotImplemented();
681                }
682 
683                public void setBinaryStream(int p1, final java.io.InputStream p2, int p3)
684                                throws SQLException {
685                        this.delegate.setBinaryStream(p1, p2, p3);
686                }
687 
688                /**
689                 * @see CallableStatement#setBinaryStream(String, InputStream, int)
690                 */
691                public void setBinaryStream(String arg0, InputStream arg1, int arg2)
692                                throws SQLException {
693                        throw new NotImplemented();
694                }
695 
696                public void setBlob(int p1, final java.sql.Blob p2) throws SQLException {
697                        this.delegate.setBlob(p1, p2);
698                }
699 
700                public void setBoolean(int p1, boolean p2) throws SQLException {
701                        this.delegate.setBoolean(p1, p2);
702                }
703 
704                /**
705                 * @see CallableStatement#setBoolean(String, boolean)
706                 */
707                public void setBoolean(String arg0, boolean arg1) throws SQLException {
708                        throw new NotImplemented();
709                }
710 
711                public void setByte(int p1, byte p2) throws SQLException {
712                        this.delegate.setByte(p1, p2);
713                }
714 
715                /**
716                 * @see CallableStatement#setByte(String, byte)
717                 */
718                public void setByte(String arg0, byte arg1) throws SQLException {
719                        throw new NotImplemented();
720                }
721 
722                public void setBytes(int p1, byte[] p2) throws SQLException {
723                        this.delegate.setBytes(p1, p2);
724                }
725 
726                /**
727                 * @see CallableStatement#setBytes(String, byte[])
728                 */
729                public void setBytes(String arg0, byte[] arg1) throws SQLException {
730                        throw new NotImplemented();
731                }
732 
733                public void setCharacterStream(int p1, final java.io.Reader p2, int p3)
734                                throws SQLException {
735                        this.delegate.setCharacterStream(p1, p2, p3);
736                }
737 
738                /**
739                 * @see CallableStatement#setCharacterStream(String, Reader, int)
740                 */
741                public void setCharacterStream(String arg0, Reader arg1, int arg2)
742                                throws SQLException {
743                        throw new NotImplemented();
744                }
745 
746                public void setClob(int p1, final java.sql.Clob p2) throws SQLException {
747                        this.delegate.setClob(p1, p2);
748                }
749 
750                public void setCursorName(java.lang.String p1) throws SQLException {
751                        throw SQLError.createSQLException("Not supported");
752                }
753 
754                public void setDate(int p1, final java.sql.Date p2) throws SQLException {
755                        this.delegate.setDate(p1, p2);
756                }
757 
758                public void setDate(int p1, final java.sql.Date p2,
759                                final java.util.Calendar p3) throws SQLException {
760                        this.delegate.setDate(p1, p2, p3);
761                }
762 
763                /**
764                 * @see CallableStatement#setDate(String, Date)
765                 */
766                public void setDate(String arg0, Date arg1) throws SQLException {
767                        throw new NotImplemented();
768                }
769 
770                /**
771                 * @see CallableStatement#setDate(String, Date, Calendar)
772                 */
773                public void setDate(String arg0, Date arg1, Calendar arg2)
774                                throws SQLException {
775                        throw new NotImplemented();
776                }
777 
778                public void setDouble(int p1, double p2) throws SQLException {
779                        this.delegate.setDouble(p1, p2);
780                }
781 
782                /**
783                 * @see CallableStatement#setDouble(String, double)
784                 */
785                public void setDouble(String arg0, double arg1) throws SQLException {
786                        throw new NotImplemented();
787                }
788 
789                public void setEscapeProcessing(boolean p1) throws SQLException {
790                        this.delegate.setEscapeProcessing(p1);
791                }
792 
793                public void setFetchDirection(int p1) throws SQLException {
794                        this.delegate.setFetchDirection(p1);
795                }
796 
797                public void setFetchSize(int p1) throws SQLException {
798                        this.delegate.setFetchSize(p1);
799                }
800 
801                public void setFloat(int p1, float p2) throws SQLException {
802                        this.delegate.setFloat(p1, p2);
803                }
804 
805                /**
806                 * @see CallableStatement#setFloat(String, float)
807                 */
808                public void setFloat(String arg0, float arg1) throws SQLException {
809                        throw new NotImplemented();
810                }
811 
812                public void setInt(int p1, int p2) throws SQLException {
813                        this.delegate.setInt(p1, p2);
814                }
815 
816                /**
817                 * @see CallableStatement#setInt(String, int)
818                 */
819                public void setInt(String arg0, int arg1) throws SQLException {
820                        throw new NotImplemented();
821                }
822 
823                public void setLong(int p1, long p2) throws SQLException {
824                        this.delegate.setLong(p1, p2);
825                }
826 
827                /**
828                 * @see CallableStatement#setLong(String, long)
829                 */
830                public void setLong(String arg0, long arg1) throws SQLException {
831                        throw new NotImplemented();
832                }
833 
834                public void setMaxFieldSize(int p1) throws SQLException {
835                        this.delegate.setMaxFieldSize(p1);
836                }
837 
838                public void setMaxRows(int p1) throws SQLException {
839                        this.delegate.setMaxRows(p1);
840                }
841 
842                public void setNull(int p1, int p2) throws SQLException {
843                        this.delegate.setNull(p1, p2);
844                }
845 
846                public void setNull(int p1, int p2, java.lang.String p3)
847                                throws SQLException {
848                        this.delegate.setNull(p1, p2, p3);
849                }
850 
851                /**
852                 * @see CallableStatement#setNull(String, int)
853                 */
854                public void setNull(String arg0, int arg1) throws SQLException {
855                        throw new NotImplemented();
856                }
857 
858                /**
859                 * @see CallableStatement#setNull(String, int, String)
860                 */
861                public void setNull(String arg0, int arg1, String arg2)
862                                throws SQLException {
863                        throw new NotImplemented();
864                }
865 
866                public void setObject(int p1, final java.lang.Object p2)
867                                throws SQLException {
868                        this.delegate.setObject(p1, p2);
869                }
870 
871                public void setObject(int p1, final java.lang.Object p2, int p3)
872                                throws SQLException {
873                        this.delegate.setObject(p1, p2, p3);
874                }
875 
876                public void setObject(int p1, final java.lang.Object p2, int p3, int p4)
877                                throws SQLException {
878                        this.delegate.setObject(p1, p2, p3, p4);
879                }
880 
881                /**
882                 * @see CallableStatement#setObject(String, Object)
883                 */
884                public void setObject(String arg0, Object arg1) throws SQLException {
885                        throw new NotImplemented();
886                }
887 
888                /**
889                 * @see CallableStatement#setObject(String, Object, int)
890                 */
891                public void setObject(String arg0, Object arg1, int arg2)
892                                throws SQLException {
893                        throw new NotImplemented();
894                }
895 
896                /**
897                 * @see CallableStatement#setObject(String, Object, int, int)
898                 */
899                public void setObject(String arg0, Object arg1, int arg2, int arg3)
900                                throws SQLException {
901                        throw new NotImplemented();
902                }
903 
904                public void setQueryTimeout(int p1) throws SQLException {
905                        throw SQLError.createSQLException("Not supported");
906                }
907 
908                public void setRef(int p1, final Ref p2) throws SQLException {
909                        throw SQLError.createSQLException("Not supported");
910                }
911 
912                public void setShort(int p1, short p2) throws SQLException {
913                        this.delegate.setShort(p1, p2);
914                }
915 
916                /**
917                 * @see CallableStatement#setShort(String, short)
918                 */
919                public void setShort(String arg0, short arg1) throws SQLException {
920                        throw new NotImplemented();
921                }
922 
923                public void setString(int p1, java.lang.String p2)
924                                throws java.sql.SQLException {
925                        this.delegate.setString(p1, p2);
926                }
927 
928                /**
929                 * @see CallableStatement#setString(String, String)
930                 */
931                public void setString(String arg0, String arg1) throws SQLException {
932                        throw new NotImplemented();
933                }
934 
935                public void setTime(int p1, final java.sql.Time p2) throws SQLException {
936                        this.delegate.setTime(p1, p2);
937                }
938 
939                public void setTime(int p1, final java.sql.Time p2,
940                                final java.util.Calendar p3) throws SQLException {
941                        this.delegate.setTime(p1, p2, p3);
942                }
943 
944                /**
945                 * @see CallableStatement#setTime(String, Time)
946                 */
947                public void setTime(String arg0, Time arg1) throws SQLException {
948                        throw new NotImplemented();
949                }
950 
951                /**
952                 * @see CallableStatement#setTime(String, Time, Calendar)
953                 */
954                public void setTime(String arg0, Time arg1, Calendar arg2)
955                                throws SQLException {
956                        throw new NotImplemented();
957                }
958 
959                public void setTimestamp(int p1, final java.sql.Timestamp p2)
960                                throws SQLException {
961                        this.delegate.setTimestamp(p1, p2);
962                }
963 
964                public void setTimestamp(int p1, final java.sql.Timestamp p2,
965                                final java.util.Calendar p3) throws SQLException {
966                        this.delegate.setTimestamp(p1, p2, p3);
967                }
968 
969                /**
970                 * @see CallableStatement#setTimestamp(String, Timestamp)
971                 */
972                public void setTimestamp(String arg0, Timestamp arg1)
973                                throws SQLException {
974                        throw new NotImplemented();
975                }
976 
977                /**
978                 * @see CallableStatement#setTimestamp(String, Timestamp, Calendar)
979                 */
980                public void setTimestamp(String arg0, Timestamp arg1, Calendar arg2)
981                                throws SQLException {
982                        throw new NotImplemented();
983                }
984 
985                /**
986                 * DOCUMENT ME!
987                 * 
988                 * @param p1
989                 *            DOCUMENT ME!
990                 * @param p2
991                 *            DOCUMENT ME!
992                 * @param p3
993                 *            DOCUMENT ME!
994                 * @throws SQLException
995                 *             DOCUMENT ME!
996                 * @deprecated
997                 */
998                public void setUnicodeStream(int p1, final java.io.InputStream p2,
999                                int p3) throws SQLException {
1000                        this.delegate.setUnicodeStream(p1, p2, p3);
1001                }
1002 
1003                /**
1004                 * @see PreparedStatement#setURL(int, URL)
1005                 */
1006                public void setURL(int arg0, URL arg1) throws SQLException {
1007                        this.delegate.setURL(arg0, arg1);
1008                }
1009 
1010                /**
1011                 * @see CallableStatement#setURL(String, URL)
1012                 */
1013                public void setURL(String arg0, URL arg1) throws SQLException {
1014                        throw new NotImplemented();
1015                }
1016 
1017                public boolean wasNull() throws SQLException {
1018                        throw SQLError.createSQLException("Not supported");
1019                }
1020        }
1021 
1022        /**
1023         * Marker for character set converter not being available (not written,
1024         * multibyte, etc) Used to prevent multiple instantiation requests.
1025         */
1026        private static final Object CHARSET_CONVERTER_NOT_AVAILABLE_MARKER = new Object();
1027 
1028        /**
1029         * The mapping between MySQL charset names and Java charset names.
1030         * Initialized by loadCharacterSetMapping()
1031         */
1032        public static Map charsetMap;
1033 
1034        /** Default logger class name */
1035        protected static final String DEFAULT_LOGGER_CLASS = "com.mysql.jdbc.log.StandardLogger";
1036 
1037        private final static int HISTOGRAM_BUCKETS = 20;
1038 
1039        /** Logger instance name */
1040        private static final String LOGGER_INSTANCE_NAME = "MySQL";
1041 
1042        /**
1043         * Map mysql transaction isolation level name to
1044         * java.sql.Connection.TRANSACTION_XXX
1045         */
1046        private static Map mapTransIsolationNameToValue = null;
1047 
1048        /** Null logger shared by all connections at startup */
1049        private static final Log NULL_LOGGER = new NullLogger(LOGGER_INSTANCE_NAME);
1050 
1051        private static Map roundRobinStatsMap;
1052 
1053        private static final Map serverCollationByUrl = new HashMap();
1054 
1055        private static final Map serverConfigByUrl = new HashMap();
1056 
1057        private static Timer cancelTimer;
1058 
1059        static {
1060                mapTransIsolationNameToValue = new HashMap(8);
1061                mapTransIsolationNameToValue.put("READ-UNCOMMITED", new Integer(
1062                                TRANSACTION_READ_UNCOMMITTED));
1063                mapTransIsolationNameToValue.put("READ-UNCOMMITTED", new Integer(
1064                                TRANSACTION_READ_UNCOMMITTED));
1065                mapTransIsolationNameToValue.put("READ-COMMITTED", new Integer(
1066                                TRANSACTION_READ_COMMITTED));
1067                mapTransIsolationNameToValue.put("REPEATABLE-READ", new Integer(
1068                                TRANSACTION_REPEATABLE_READ));
1069                mapTransIsolationNameToValue.put("SERIALIZABLE", new Integer(
1070                                TRANSACTION_SERIALIZABLE));
1071        }
1072 
1073        protected static SQLException appendMessageToException(SQLException sqlEx,
1074                        String messageToAppend) {
1075                String origMessage = sqlEx.getMessage();
1076                String sqlState = sqlEx.getSQLState();
1077                int vendorErrorCode = sqlEx.getErrorCode();
1078 
1079                StringBuffer messageBuf = new StringBuffer(origMessage.length()
1080                                + messageToAppend.length());
1081                messageBuf.append(origMessage);
1082                messageBuf.append(messageToAppend);
1083 
1084                SQLException sqlExceptionWithNewMessage = SQLError.createSQLException(messageBuf
1085                                .toString(), sqlState, vendorErrorCode);
1086 
1087                //
1088                // Try and maintain the original stack trace,
1089                // only works on JDK-1.4 and newer
1090                //
1091 
1092                try {
1093                        // Have to do this with reflection, otherwise older JVMs croak
1094                        Method getStackTraceMethod = null;
1095                        Method setStackTraceMethod = null;
1096                        Object theStackTraceAsObject = null;
1097 
1098                        Class stackTraceElementClass = Class
1099                                        .forName("java.lang.StackTraceElement");
1100                        Class stackTraceElementArrayClass = Array.newInstance(
1101                                        stackTraceElementClass, new int[] { 0 }).getClass();
1102 
1103                        getStackTraceMethod = Throwable.class.getMethod("getStackTrace",
1104                                        new Class[] {});
1105 
1106                        setStackTraceMethod = Throwable.class.getMethod("setStackTrace",
1107                                        new Class[] { stackTraceElementArrayClass });
1108 
1109                        if (getStackTraceMethod != null && setStackTraceMethod != null) {
1110                                theStackTraceAsObject = getStackTraceMethod.invoke(sqlEx,
1111                                                new Object[0]);
1112                                setStackTraceMethod.invoke(sqlExceptionWithNewMessage,
1113                                                new Object[] { theStackTraceAsObject });
1114                        }
1115                } catch (NoClassDefFoundError noClassDefFound) {
1116 
1117                } catch (NoSuchMethodException noSuchMethodEx) {
1118 
1119                } catch (Throwable catchAll) {
1120 
1121                }
1122 
1123                return sqlExceptionWithNewMessage;
1124        }
1125 
1126        protected static Timer getCancelTimer() {
1127                return cancelTimer;
1128        }
1129 
1130        private static synchronized int getNextRoundRobinHostIndex(String url,
1131                        List hostList) {
1132                if (roundRobinStatsMap == null) {
1133                        roundRobinStatsMap = new HashMap();
1134                }
1135 
1136                int[] index = (int[]) roundRobinStatsMap.get(url);
1137 
1138                if (index == null) {
1139                        index = new int[1];
1140                        index[0] = -1;
1141 
1142                        roundRobinStatsMap.put(url, index);
1143                }
1144 
1145                index[0]++;
1146 
1147                if (index[0] >= hostList.size()) {
1148                        index[0] = 0;
1149                }
1150 
1151                return index[0];
1152        }
1153 
1154        private static boolean nullSafeCompare(String s1, String s2) {
1155                if (s1 == null && s2 == null) {
1156                        return true;
1157                }
1158 
1159                if (s1 == null && s2 != null) {
1160                        return false;
1161                }
1162 
1163                return s1.equals(s2);
1164        }
1165 
1166        /** Are we in autoCommit mode? */
1167        private boolean autoCommit = true;
1168 
1169        /** A map of SQL to parsed prepared statement parameters. */
1170        private Map cachedPreparedStatementParams;
1171 
1172        /**
1173         * For servers > 4.1.0, what character set is the metadata returned in?
1174         */
1175        private String characterSetMetadata = null;
1176 
1177        /**
1178         * The character set we want results and result metadata returned in (null ==
1179         * results in any charset, metadata in UTF-8).
1180         */
1181        private String characterSetResultsOnServer = null;
1182 
1183        /**
1184         * Holds cached mappings to charset converters to avoid static
1185         * synchronization and at the same time save memory (each charset converter
1186         * takes approx 65K of static data).
1187         */
1188        private Map charsetConverterMap = new HashMap(CharsetMapping
1189                        .getNumberOfCharsetsConfigured());
1190 
1191        /**
1192         * The mapping between MySQL charset names and the max number of chars in
1193         * them. Lazily instantiated via getMaxBytesPerChar().
1194         */
1195        private Map charsetToNumBytesMap;
1196 
1197        /** The point in time when this connection was created */
1198        private long connectionCreationTimeMillis = 0;
1199 
1200        /** ID used when profiling */
1201        private long connectionId;
1202 
1203        /** The database we're currently using (called Catalog in JDBC terms). */
1204        private String database = null;
1205 
1206        /** Internal DBMD to use for various database-version specific features */
1207        private DatabaseMetaData dbmd = null;
1208 
1209        private TimeZone defaultTimeZone;
1210 
1211        /** The event sink to use for profiling */
1212        private ProfileEventSink eventSink;
1213 
1214        private boolean executingFailoverReconnect = false;
1215 
1216        /** Are we failed-over to a non-master host */
1217        private boolean failedOver = false;
1218 
1219        /** Why was this connection implicitly closed, if known? (for diagnostics) */
1220        private Throwable forceClosedReason;
1221 
1222        /** Where was this connection implicitly closed? (for diagnostics) */
1223        private Throwable forcedClosedLocation;
1224 
1225        /** Does the server suuport isolation levels? */
1226        private boolean hasIsolationLevels = false;
1227 
1228        /** Does this version of MySQL support quoted identifiers? */
1229        private boolean hasQuotedIdentifiers = false;
1230 
1231        /** The hostname we're connected to */
1232        private String host = null;
1233 
1234        /** The list of host(s) to try and connect to */
1235        private List hostList = null;
1236 
1237        /** How many hosts are in the host list? */
1238        private int hostListSize = 0;
1239 
1240        /**
1241         * We need this 'bootstrapped', because 4.1 and newer will send fields back
1242         * with this even before we fill this dynamically from the server.
1243         */
1244        private String[] indexToCharsetMapping = CharsetMapping.INDEX_TO_CHARSET;
1245 
1246        /** The I/O abstraction interface (network conn to MySQL server */
1247        private MysqlIO io = null;
1248        
1249        private boolean isClientTzUTC = false;
1250        
1251        /** Has this connection been closed? */
1252        private boolean isClosed = true;
1253 
1254        /** Is this connection associated with a global tx? */
1255        private boolean isInGlobalTx = false;
1256 
1257        /** Is this connection running inside a JDK-1.3 VM? */
1258        private boolean isRunningOnJDK13 = false;
1259 
1260        /** isolation level */
1261        private int isolationLevel = java.sql.Connection.TRANSACTION_READ_COMMITTED;
1262 
1263        private boolean isServerTzUTC = false;
1264 
1265        /** When did the last query finish? */
1266        private long lastQueryFinishedTime = 0;
1267 
1268        /** The logger we're going to use */
1269        private Log log = NULL_LOGGER;
1270 
1271        /**
1272         * If gathering metrics, what was the execution time of the longest query so
1273         * far ?
1274         */
1275        private long longestQueryTimeMs = 0;
1276 
1277        /** Is the server configured to use lower-case table names only? */
1278        private boolean lowerCaseTableNames = false;
1279 
1280        /** When did the master fail? */
1281        private long masterFailTimeMillis = 0L;
1282 
1283        /**
1284         * The largest packet we can send (changed once we know what the server
1285         * supports, we get this at connection init).
1286         */
1287        private int maxAllowedPacket = 65536;
1288 
1289        private long maximumNumberTablesAccessed = 0;
1290 
1291        /** Has the max-rows setting been changed from the default? */
1292        private boolean maxRowsChanged = false;
1293 
1294        /** When was the last time we reported metrics? */
1295        private long metricsLastReportedMs;
1296 
1297        private long minimumNumberTablesAccessed = Long.MAX_VALUE;
1298 
1299        /** Mutex */
1300        private final Object mutex = new Object();
1301 
1302        /** The JDBC URL we're using */
1303        private String myURL = null;
1304 
1305        /** Does this connection need to be tested? */
1306        private boolean needsPing = false;
1307 
1308        private int netBufferLength = 16384;
1309 
1310        private boolean noBackslashEscapes = false;
1311 
1312        private long numberOfPreparedExecutes = 0;
1313 
1314        private long numberOfPrepares = 0;
1315 
1316        private long numberOfQueriesIssued = 0;
1317 
1318        private long numberOfResultSetsCreated = 0;
1319 
1320        private long[] numTablesMetricsHistBreakpoints;
1321 
1322        private int[] numTablesMetricsHistCounts;
1323 
1324        private long[] oldHistBreakpoints = null;
1325 
1326        private int[] oldHistCounts = null;
1327 
1328        /** A map of currently open statements */
1329        private Map openStatements;
1330 
1331        private LRUCache parsedCallableStatementCache;
1332 
1333        private boolean parserKnowsUnicode = false;
1334 
1335        /** The password we used */
1336        private String password = null;
1337 
1338        private long[] perfMetricsHistBreakpoints;
1339 
1340        private int[] perfMetricsHistCounts;
1341 
1342        /** Point of origin where this Connection was created */
1343        private Throwable pointOfOrigin;
1344 
1345        /** The port number we're connected to (defaults to 3306) */
1346        private int port = 3306;
1347 
1348        /**
1349         * Used only when testing failover functionality for regressions, causes the
1350         * failover code to not retry the master first
1351         */
1352        private boolean preferSlaveDuringFailover = false;
1353 
1354        /** Properties for this connection specified by user */
1355        private Properties props = null;
1356 
1357        /** Number of queries we've issued since the master failed */
1358        private long queriesIssuedFailedOver = 0;
1359 
1360        /** Should we retrieve 'info' messages from the server? */
1361        private boolean readInfoMsg = false;
1362 
1363        /** Are we in read-only mode? */
1364        private boolean readOnly = false;
1365 
1366        /** The timezone of the server */
1367        private TimeZone serverTimezoneTZ = null;
1368 
1369        /** The map of server variables that we retrieve at connection init. */
1370        private Map serverVariables = null;
1371 
1372        private long shortestQueryTimeMs = Long.MAX_VALUE;
1373 
1374        /** A map of statements that have had setMaxRows() called on them */
1375        private Map statementsUsingMaxRows;
1376 
1377        private double totalQueryTimeMs = 0;
1378 
1379        /** Are transactions supported by the MySQL server we are connected to? */
1380        private boolean transactionsSupported = false;
1381 
1382        /**
1383         * The type map for UDTs (not implemented, but used by some third-party
1384         * vendors, most notably IBM WebSphere)
1385         */
1386        private Map typeMap;
1387 
1388        /** Has ANSI_QUOTES been enabled on the server? */
1389        private boolean useAnsiQuotes = false;
1390 
1391        /** The user we're connected as */
1392        private String user = null;
1393 
1394        /**
1395         * Should we use server-side prepared statements? (auto-detected, but can be
1396         * disabled by user)
1397         */
1398        private boolean useServerPreparedStmts = false;
1399        
1400        private LRUCache serverSideStatementCheckCache;
1401 
1402        private LRUCache serverSideStatementCache;
1403        private Calendar sessionCalendar;
1404        private Calendar utcCalendar;
1405        
1406        private String origHostToConnectTo;
1407        
1408        private int origPortToConnectTo;
1409 
1410        // we don't want to be able to publicly clone this...
1411        
1412        private String origDatabaseToConnectTo;
1413 
1414        private String errorMessageEncoding = "Cp1252"; // to begin with, changes after we talk to the server
1415 
1416        private boolean usePlatformCharsetConverters;
1417        
1418        
1419        /**
1420         * Creates a connection to a MySQL Server.
1421         * 
1422         * @param hostToConnectTo
1423         *            the hostname of the database server
1424         * @param portToConnectTo
1425         *            the port number the server is listening on
1426         * @param info
1427         *            a Properties[] list holding the user and password
1428         * @param databaseToConnectTo
1429         *            the database to connect to
1430         * @param url
1431         *            the URL of the connection
1432         * @param d
1433         *            the Driver instantation of the connection
1434         * @exception SQLException
1435         *                if a database access error occurs
1436         */
1437        Connection(String hostToConnectTo, int portToConnectTo, Properties info,
1438                        String databaseToConnectTo, String url)
1439                        throws SQLException {
1440                this.charsetToNumBytesMap = new HashMap();
1441                this.cancelTimer = new Timer(true);
1442                this.connectionCreationTimeMillis = System.currentTimeMillis();
1443                this.pointOfOrigin = new Throwable();
1444                
1445                // Stash away for later, used to clone this connection for Statement.cancel
1446                // and Statement.setQueryTimeout().
1447                //
1448                
1449                this.origHostToConnectTo = hostToConnectTo;
1450                this.origPortToConnectTo = portToConnectTo;
1451                this.origDatabaseToConnectTo = databaseToConnectTo;
1452 
1453                try {
1454                        Blob.class.getMethod("truncate", new Class[] {Long.TYPE});
1455                        
1456                        this.isRunningOnJDK13 = false;
1457                } catch (NoSuchMethodException nsme) {
1458                        this.isRunningOnJDK13 = true;
1459                }
1460                
1461                this.sessionCalendar = new GregorianCalendar();
1462                this.utcCalendar = new GregorianCalendar();
1463                this.utcCalendar.setTimeZone(TimeZone.getTimeZone("GMT"));
1464                
1465                //
1466                // Normally, this code would be in initializeDriverProperties,
1467                // but we need to do this as early as possible, so we can start
1468                // logging to the 'correct' place as early as possible...this.log
1469                // points to 'NullLogger' for every connection at startup to avoid
1470                // NPEs and the overhead of checking for NULL at every logging call.
1471                //
1472                // We will reset this to the configured logger during properties
1473                // initialization.
1474                //
1475                this.log = LogFactory.getLogger(getLogger(), LOGGER_INSTANCE_NAME);
1476 
1477                // We store this per-connection, due to static synchronization
1478                // issues in Java's built-in TimeZone class...
1479                this.defaultTimeZone = TimeZone.getDefault();
1480                if ("GMT".equalsIgnoreCase(this.defaultTimeZone.getID())) {
1481                        this.isClientTzUTC = true;
1482                } else {
1483                        this.isClientTzUTC = false;
1484                }
1485 
1486                this.openStatements = new HashMap();
1487                this.serverVariables = new HashMap();
1488                this.hostList = new ArrayList();
1489 
1490                if (hostToConnectTo == null) {
1491                        this.host = "localhost";
1492                        this.hostList.add(this.host);
1493                } else if (hostToConnectTo.indexOf(",") != -1) {
1494                        // multiple hosts separated by commas (failover)
1495                        StringTokenizer hostTokenizer = new StringTokenizer(
1496                                        hostToConnectTo, ",", false);
1497 
1498                        while (hostTokenizer.hasMoreTokens()) {
1499                                this.hostList.add(hostTokenizer.nextToken().trim());
1500                        }
1501                } else {
1502                        this.host = hostToConnectTo;
1503                        this.hostList.add(this.host);
1504                }
1505 
1506                this.hostListSize = this.hostList.size();
1507                this.port = portToConnectTo;
1508 
1509                if (databaseToConnectTo == null) {
1510                        databaseToConnectTo = "";
1511                }
1512 
1513                this.database = databaseToConnectTo;
1514                this.myURL = url;
1515                this.user = info.getProperty(NonRegisteringDriver.USER_PROPERTY_KEY);
1516                this.password = info
1517                                .getProperty(NonRegisteringDriver.PASSWORD_PROPERTY_KEY);
1518 
1519                if ((this.user == null) || this.user.equals("")) {
1520                        this.user = "";
1521                }
1522 
1523                if (this.password == null) {
1524                        this.password = "";
1525                }
1526 
1527                this.props = info;
1528                initializeDriverProperties(info);
1529 
1530                try {
1531                        createNewIO(false);
1532                        this.connectionId = this.io.getThreadId();
1533                        this.dbmd = new DatabaseMetaData(this, this.database);
1534                } catch (SQLException ex) {
1535                        cleanup(ex);
1536 
1537                        // don't clobber SQL exceptions
1538                        throw ex;
1539                } catch (Exception ex) {
1540                        cleanup(ex);
1541 
1542                        StringBuffer mesg = new StringBuffer();
1543 
1544                        if (getParanoid()) {
1545                                mesg.append("Cannot connect to MySQL server on ");
1546                                mesg.append(this.host);
1547                                mesg.append(":");
1548                                mesg.append(this.port);
1549                                mesg.append(".\n\n");
1550                                mesg.append("Make sure that there is a MySQL server ");
1551                                mesg.append("running on the machine/port you are trying ");
1552                                mesg
1553                                                .append("to connect to and that the machine this software is "
1554                                                                + "running on ");
1555                                mesg.append("is able to connect to this host/port "
1556                                                + "(i.e. not firewalled). ");
1557                                mesg
1558                                                .append("Also make sure that the server has not been started "
1559                                                                + "with the --skip-networking ");
1560                                mesg.append("flag.\n\n");
1561                        } else {
1562                                mesg.append("Unable to connect to database.");
1563                        }
1564 
1565                        mesg.append("Underlying exception: \n\n");
1566                        mesg.append(ex.getClass().getName());
1567 
1568                        if (!getParanoid()) {
1569                                mesg.append(Util.stackTraceToString(ex));
1570                        }
1571 
1572                        throw SQLError.createSQLException(mesg.toString(),
1573                                        SQLError.SQL_STATE_COMMUNICATION_LINK_FAILURE);
1574                }
1575        }
1576 
1577        private void addToHistogram(int[] histogramCounts,
1578                        long[] histogramBreakpoints, long value, int numberOfTimes,
1579                        long currentLowerBound, long currentUpperBound) {
1580                if (histogramCounts == null) {
1581                        createInitialHistogram(histogramBreakpoints,
1582                                        currentLowerBound, currentUpperBound);
1583                }
1584 
1585                for (int i = 0; i < HISTOGRAM_BUCKETS; i++) {
1586                        if (histogramBreakpoints[i] >= value) {
1587                                histogramCounts[i] += numberOfTimes;
1588 
1589                                break;
1590                        }
1591                }
1592        }
1593 
1594        private void addToPerformanceHistogram(long value, int numberOfTimes) {
1595                checkAndCreatePerformanceHistogram();
1596 
1597                addToHistogram(this.perfMetricsHistCounts,
1598                                this.perfMetricsHistBreakpoints, value, numberOfTimes,
1599                                this.shortestQueryTimeMs == Long.MAX_VALUE ? 0
1600                                                : this.shortestQueryTimeMs, this.longestQueryTimeMs);
1601        }
1602 
1603        private void addToTablesAccessedHistogram(long value, int numberOfTimes) {
1604                checkAndCreateTablesAccessedHistogram();
1605 
1606                addToHistogram(this.numTablesMetricsHistCounts,
1607                                this.numTablesMetricsHistBreakpoints, value, numberOfTimes,
1608                                this.minimumNumberTablesAccessed == Long.MAX_VALUE ? 0
1609                                                : this.minimumNumberTablesAccessed,
1610                                this.maximumNumberTablesAccessed);
1611        }
1612 
1613        /**
1614         * Builds the map needed for 4.1.0 and newer servers that maps field-level
1615         * charset/collation info to a java character encoding name.
1616         * 
1617         * @throws SQLException
1618         *             DOCUMENT ME!
1619         */
1620        private void buildCollationMapping() throws SQLException {
1621                if (versionMeetsMinimum(4, 1, 0)) {
1622 
1623                        TreeMap sortedCollationMap = null;
1624 
1625                        if (getCacheServerConfiguration()) {
1626                                synchronized (serverConfigByUrl) {
1627                                        sortedCollationMap = (TreeMap) serverCollationByUrl
1628                                                        .get(getURL());
1629                                }
1630                        }
1631 
1632                        com.mysql.jdbc.Statement stmt = null;
1633                        com.mysql.jdbc.ResultSet results = null;
1634 
1635                        try {
1636                                if (sortedCollationMap == null) {
1637                                        sortedCollationMap = new TreeMap();
1638 
1639                                        stmt = (com.mysql.jdbc.Statement) createStatement();
1640 
1641                                        if (stmt.getMaxRows() != 0) {
1642                                                stmt.setMaxRows(0);
1643                                        }
1644 
1645                                        results = (com.mysql.jdbc.ResultSet) stmt
1646                                                        .executeQuery("SHOW COLLATION");
1647 
1648                                        while (results.next()) {
1649                                                String charsetName = results.getString(2);
1650                                                Integer charsetIndex = new Integer(results.getInt(3));
1651 
1652                                                sortedCollationMap.put(charsetIndex, charsetName);
1653                                        }
1654 
1655                                        if (getCacheServerConfiguration()) {
1656                                                synchronized (serverConfigByUrl) {
1657                                                        serverCollationByUrl.put(getURL(),
1658                                                                        sortedCollationMap);
1659                                                }
1660                                        }
1661 
1662                                }
1663 
1664                                // Now, merge with what we already know
1665                                int highestIndex = ((Integer) sortedCollationMap.lastKey())
1666                                                .intValue();
1667 
1668                                if (CharsetMapping.INDEX_TO_CHARSET.length > highestIndex) {
1669                                        highestIndex = CharsetMapping.INDEX_TO_CHARSET.length;
1670                                }
1671 
1672                                this.indexToCharsetMapping = new String[highestIndex + 1];
1673 
1674                                for (int i = 0; i < CharsetMapping.INDEX_TO_CHARSET.length; i++) {
1675                                        this.indexToCharsetMapping[i] = CharsetMapping.INDEX_TO_CHARSET[i];
1676                                }
1677 
1678                                for (Iterator indexIter = sortedCollationMap.entrySet()
1679                                                .iterator(); indexIter.hasNext();) {
1680                                        Map.Entry indexEntry = (Map.Entry) indexIter.next();
1681 
1682                                        String mysqlCharsetName = (String) indexEntry.getValue();
1683 
1684                                        this.indexToCharsetMapping[((Integer) indexEntry.getKey())
1685                                                        .intValue()] = CharsetMapping
1686                                                        .getJavaEncodingForMysqlEncoding(mysqlCharsetName,
1687                                                                        this);
1688                                }
1689                        } catch (java.sql.SQLException e) {
1690                                throw e;
1691                        } finally {
1692                                if (results != null) {
1693                                        try {
1694                                                results.close();
1695                                        } catch (java.sql.SQLException sqlE) {
1696                                                ;
1697                                        }
1698                                }
1699 
1700                                if (stmt != null) {
1701                                        try {
1702                                                stmt.close();
1703                                        } catch (java.sql.SQLException sqlE) {
1704                                                ;
1705                                        }
1706                                }
1707                        }
1708                } else {
1709                        // Safety, we already do this as an initializer, but this makes
1710                        // the intent more clear
1711                        this.indexToCharsetMapping = CharsetMapping.INDEX_TO_CHARSET;
1712                }
1713        }
1714        
1715        private boolean canHandleAsServerPreparedStatement(String sql) 
1716                throws SQLException {
1717                if (sql == null || sql.length() == 0) {
1718                        return true;
1719                }
1720 
1721                if (getCachePreparedStatements()) {
1722                        synchronized (this.serverSideStatementCheckCache) {
1723                                Boolean flag = (Boolean)this.serverSideStatementCheckCache.get(sql);
1724                                
1725                                if (flag != null) {
1726                                        return flag.booleanValue();
1727                                }
1728                                        
1729                                boolean canHandle = canHandleAsServerPreparedStatementNoCache(sql);
1730                                
1731                                if (sql.length() < getPreparedStatementCacheSqlLimit()) {
1732                                        this.serverSideStatementCheckCache.put(sql, 
1733                                                        canHandle ? Boolean.TRUE : Boolean.FALSE);
1734                                }
1735                                        
1736                                return canHandle;
1737                        }
1738                }
1739                
1740                return canHandleAsServerPreparedStatementNoCache(sql);
1741        }
1742 
1743        private boolean canHandleAsServerPreparedStatementNoCache(String sql) 
1744                throws SQLException {
1745                boolean canHandleAsStatement = true;
1746                
1747                if (!versionMeetsMinimum(5, 0, 7) && 
1748                                (StringUtils.startsWithIgnoreCaseAndNonAlphaNumeric(sql, "SELECT")
1749                                || StringUtils.startsWithIgnoreCaseAndNonAlphaNumeric(sql,
1750                                                "DELETE")
1751                                || StringUtils.startsWithIgnoreCaseAndNonAlphaNumeric(sql,
1752                                                "INSERT")
1753                                || StringUtils.startsWithIgnoreCaseAndNonAlphaNumeric(sql,
1754                                                "UPDATE")
1755                                || StringUtils.startsWithIgnoreCaseAndNonAlphaNumeric(sql,
1756                                                "REPLACE"))) {
1757 
1758                        // check for limit ?[,?]
1759 
1760                        /*
1761                         * The grammar for this (from the server) is: ULONG_NUM | ULONG_NUM
1762                         * ',' ULONG_NUM | ULONG_NUM OFFSET_SYM ULONG_NUM
1763                         */
1764 
1765                        int currentPos = 0;
1766                        int statementLength = sql.length();
1767                        int lastPosToLook = statementLength - 7; // "LIMIT ".length()
1768                        boolean allowBackslashEscapes = !this.noBackslashEscapes;
1769                        char quoteChar = this.useAnsiQuotes ? '"' : '\'';
1770                        boolean foundLimitWithPlaceholder = false;
1771 
1772                        while (currentPos < lastPosToLook) {
1773                                int limitStart = StringUtils.indexOfIgnoreCaseRespectQuotes(
1774                                                currentPos, sql, "LIMIT ", quoteChar,
1775                                                allowBackslashEscapes);
1776 
1777                                if (limitStart == -1) {
1778                                        break;
1779                                }
1780 
1781                                currentPos = limitStart + 7;
1782 
1783                                while (currentPos < statementLength) {
1784                                        char c = sql.charAt(currentPos);
1785 
1786                                        //
1787                                        // Have we reached the end
1788                                        // of what can be in a LIMIT clause?
1789                                        //
1790 
1791                                        if (!Character.isDigit(c) && !Character.isWhitespace(c)
1792                                                        && c != ',' && c != '?') {
1793                                                break;
1794                                        }
1795 
1796                                        if (c == '?') {
1797                                                foundLimitWithPlaceholder = true;
1798                                                break;
1799                                        }
1800 
1801                                        currentPos++;
1802                                }
1803                        }
1804 
1805                        canHandleAsStatement = !foundLimitWithPlaceholder;
1806                } else if (StringUtils.startsWithIgnoreCaseAndWs(sql, "CREATE TABLE")) {
1807                        canHandleAsStatement = false;
1808                } else if (StringUtils.startsWithIgnoreCaseAndWs(sql, "DO")) {
1809                        canHandleAsStatement = false;
1810                } else if (StringUtils.startsWithIgnoreCaseAndWs(sql, "SET")) {
1811                        canHandleAsStatement = false;
1812                }
1813 
1814                
1815                
1816                return canHandleAsStatement;
1817        }
1818 
1819        /**
1820         * Changes the user on this connection by performing a re-authentication. If
1821         * authentication fails, the connection will remain under the context of the
1822         * current user.
1823         * 
1824         * @param userName
1825         *            the username to authenticate with
1826         * @param newPassword
1827         *            the password to authenticate with
1828         * @throws SQLException
1829         *             if authentication fails, or some other error occurs while
1830         *             performing the command.
1831         */
1832        public void changeUser(String userName, String newPassword)
1833                        throws SQLException {
1834                if ((userName == null) || userName.equals("")) {
1835                        userName = "";
1836                }
1837 
1838                if (newPassword == null) {
1839                        newPassword = "";
1840                }
1841 
1842                this.io.changeUser(userName, newPassword, this.database);
1843                this.user = userName;
1844                this.password = newPassword;
1845 
1846                if (versionMeetsMinimum(4, 1, 0)) {
1847                        configureClientCharacterSet();
1848                }
1849                
1850                setupServerForTruncationChecks();
1851        }
1852 
1853        private void checkAndCreatePerformanceHistogram() {
1854                if (this.perfMetricsHistCounts == null) {
1855                        this.perfMetricsHistCounts = new int[HISTOGRAM_BUCKETS];
1856                }
1857 
1858                if (this.perfMetricsHistBreakpoints == null) {
1859                        this.perfMetricsHistBreakpoints = new long[HISTOGRAM_BUCKETS];
1860                }
1861        }
1862 
1863        private void checkAndCreateTablesAccessedHistogram() {
1864                if (this.numTablesMetricsHistCounts == null) {
1865                        this.numTablesMetricsHistCounts = new int[HISTOGRAM_BUCKETS];
1866                }
1867 
1868                if (this.numTablesMetricsHistBreakpoints == null) {
1869                        this.numTablesMetricsHistBreakpoints = new long[HISTOGRAM_BUCKETS];
1870                }
1871        }
1872 
1873        private void checkClosed() throws SQLException {
1874                if (this.isClosed) {
1875                        StringBuffer messageBuf = new StringBuffer(
1876                                        "No operations allowed after connection closed.");
1877 
1878                        if (this.forcedClosedLocation != null || this.forceClosedReason != null) {
1879                                messageBuf
1880                                .append("Connection was implicitly closed ");
1881                        }
1882                        
1883                        if (this.forcedClosedLocation != null) {
1884                                messageBuf.append("\n\n");
1885                                messageBuf
1886                                                .append(" at (stack trace):\n");
1887                                messageBuf.append(Util
1888                                                .stackTraceToString(this.forcedClosedLocation));
1889                        }
1890 
1891                        if (this.forceClosedReason != null) {
1892                                if (this.forcedClosedLocation != null) {
1893                                        messageBuf.append("\n\nDue ");
1894                                } else {
1895                                        messageBuf.append("due ");
1896                                }
1897                                
1898                                messageBuf.append("to underlying exception/error:\n");
1899                                messageBuf.append(Util
1900                                                .stackTraceToString(this.forceClosedReason));
1901                        }
1902 
1903                        throw SQLError.createSQLException(messageBuf.toString(),
1904                                        SQLError.SQL_STATE_CONNECTION_NOT_OPEN);
1905                }
1906        }
1907 
1908        /**
1909         * If useUnicode flag is set and explicit client character encoding isn't
1910         * specified then assign encoding from server if any.
1911         * 
1912         * @throws SQLException
1913         *             DOCUMENT ME!
1914         */
1915        private void checkServerEncoding() throws SQLException {
1916                if (getUseUnicode() && (getEncoding() != null)) {
1917                        // spec'd by client, don't map
1918                        return;
1919                }
1920 
1921                String serverEncoding = (String) this.serverVariables
1922                                .get("character_set");
1923 
1924                if (serverEncoding == null) {
1925                        // must be 4.1.1 or newer?
1926                        serverEncoding = (String) this.serverVariables
1927                                        .get("character_set_server");
1928                }
1929 
1930                String mappedServerEncoding = null;
1931 
1932                if (serverEncoding != null) {
1933                        mappedServerEncoding = CharsetMapping
1934                                        .getJavaEncodingForMysqlEncoding(serverEncoding
1935                                                        .toUpperCase(Locale.ENGLISH), this);
1936                }
1937 
1938                //
1939                // First check if we can do the encoding ourselves
1940                //
1941                if (!getUseUnicode() && (mappedServerEncoding != null)) {
1942                        SingleByteCharsetConverter converter = getCharsetConverter(mappedServerEncoding);
1943 
1944                        if (converter != null) { // we know how to convert this ourselves
1945                                setUseUnicode(true); // force the issue
1946                                setEncoding(mappedServerEncoding);
1947 
1948                                return;
1949                        }
1950                }
1951 
1952                //
1953                // Now, try and find a Java I/O converter that can do
1954                // the encoding for us
1955                //
1956                if (serverEncoding != null) {
1957                        if (mappedServerEncoding == null) {
1958                                // We don't have a mapping for it, so try
1959                                // and canonicalize the name....
1960                                if (Character.isLowerCase(serverEncoding.charAt(0))) {
1961                                        char[] ach = serverEncoding.toCharArray();
1962                                        ach[0] = Character.toUpperCase(serverEncoding.charAt(0));
1963                                        setEncoding(new String(ach));
1964                                }
1965                        }
1966 
1967                        if (mappedServerEncoding == null) {
1968                                throw SQLError.createSQLException("Unknown character encoding on server '"
1969                                                + serverEncoding
1970                                                + "', use 'characterEncoding=' property "
1971                                                + " to provide correct mapping",
1972                                                SQLError.SQL_STATE_INVALID_CONNECTION_ATTRIBUTE);
1973                        }
1974 
1975                        //
1976                        // Attempt to use the encoding, and bail out if it
1977                        // can't be used
1978                        //
1979                        try {
1980                                "abc".getBytes(mappedServerEncoding);
1981                                setEncoding(mappedServerEncoding);
1982                                setUseUnicode(true);
1983                        } catch (UnsupportedEncodingException UE) {
1984                                throw SQLError.createSQLException(
1985                                                "The driver can not map the character encoding '"
1986                                                                + getEncoding()
1987                                                                + "' that your server is using "
1988                                                                + "to a character encoding your JVM understands. You "
1989                                                                + "can specify this mapping manually by adding \"useUnicode=true\" "
1990                                                                + "as well as \"characterEncoding=[an_encoding_your_jvm_understands]\" "
1991                                                                + "to your JDBC URL.", "0S100");
1992                        }
1993                }
1994        }
1995 
1996        /**
1997         * Set transaction isolation level to the value received from server if any.
1998         * Is called by connectionInit(...)
1999         * 
2000         * @throws SQLException
2001         *             DOCUMENT ME!
2002         */
2003        private void checkTransactionIsolationLevel() throws SQLException {
2004                String txIsolationName = null;
2005 
2006                if (versionMeetsMinimum(4, 0, 3)) {
2007                        txIsolationName = "tx_isolation";
2008                } else {
2009                        txIsolationName = "transaction_isolation";
2010                }
2011 
2012                String s = (String) this.serverVariables.get(txIsolationName);
2013 
2014                if (s != null) {
2015                        Integer intTI = (Integer) mapTransIsolationNameToValue.get(s);
2016 
2017                        if (intTI != null) {
2018                                this.isolationLevel = intTI.intValue();
2019                        }
2020                }
2021        }
2022 
2023        /**
2024         * Destroys this connection and any underlying resources
2025         * 
2026         * @param fromWhere
2027         *            DOCUMENT ME!
2028         * @param whyCleanedUp
2029         *            DOCUMENT ME!
2030         */
2031        private void cleanup(Throwable whyCleanedUp) {
2032                try {
2033                        if ((this.io != null) && !isClosed()) {
2034                                realClose(false, false, false, whyCleanedUp);
2035                        } else if (this.io != null) {
2036                                this.io.forceClose();
2037                        }
2038                } catch (SQLException sqlEx) {
2039                        // ignore, we're going away.
2040                        ;
2041                }
2042 
2043                this.isClosed = true;
2044        }
2045 
2046        /**
2047         * After this call, getWarnings returns null until a new warning is reported
2048         * for this connection.
2049         * 
2050         * @exception SQLException
2051         *                if a database access error occurs
2052         */
2053        public void clearWarnings() throws SQLException {
2054                // firstWarning = null;
2055        }
2056 
2057        /**
2058         * DOCUMENT ME!
2059         * 
2060         * @param sql
2061         *            DOCUMENT ME!
2062         * @return DOCUMENT ME!
2063         * @throws SQLException
2064         *             DOCUMENT ME!
2065         */
2066        public PreparedStatement clientPrepareStatement(String sql)
2067                        throws SQLException {
2068                return clientPrepareStatement(sql,
2069                                java.sql.ResultSet.TYPE_SCROLL_SENSITIVE,
2070                                java.sql.ResultSet.CONCUR_READ_ONLY);
2071        }
2072 
2073        /**
2074         * DOCUMENT ME!
2075         * 
2076         * @param sql
2077         *            DOCUMENT ME!
2078         * @param resultSetType
2079         *            DOCUMENT ME!
2080         * @param resultSetConcurrency
2081         *            DOCUMENT ME!
2082         * @return DOCUMENT ME!
2083         * @throws SQLException
2084         *             DOCUMENT ME!
2085         */
2086        public PreparedStatement clientPrepareStatement(String sql,
2087                        int resultSetType, int resultSetConcurrency) throws SQLException {
2088                checkClosed();
2089 
2090                PreparedStatement pStmt = null;
2091 
2092                if (getCachePreparedStatements()) {
2093                        synchronized (this.cachedPreparedStatementParams) {
2094                                PreparedStatement.ParseInfo pStmtInfo = (PreparedStatement.ParseInfo) this.cachedPreparedStatementParams
2095                                                .get(sql);
2096        
2097                                if (pStmtInfo == null) {
2098                                        pStmt = new com.mysql.jdbc.PreparedStatement(this, 
2099                                                        getProcessEscapeCodesForPrepStmts() ? nativeSQL(sql): sql,
2100                                                        this.database);
2101        
2102                                        PreparedStatement.ParseInfo parseInfo = pStmt.getParseInfo();
2103        
2104                                        if (parseInfo.statementLength < getPreparedStatementCacheSqlLimit()) {
2105                                                if (this.cachedPreparedStatementParams.size() >= getPreparedStatementCacheSize()) {
2106                                                        Iterator oldestIter = this.cachedPreparedStatementParams
2107                                                                        .keySet().iterator();
2108                                                        long lruTime = Long.MAX_VALUE;
2109                                                        String oldestSql = null;
2110        
2111                                                        while (oldestIter.hasNext()) {
2112                                                                String sqlKey = (String) oldestIter.next();
2113                                                                PreparedStatement.ParseInfo lruInfo = (PreparedStatement.ParseInfo) this.cachedPreparedStatementParams
2114                                                                                .get(sqlKey);
2115        
2116                                                                if (lruInfo.lastUsed < lruTime) {
2117                                                                        lruTime = lruInfo.lastUsed;
2118                                                                        oldestSql = sqlKey;
2119                                                                }
2120                                                        }
2121        
2122                                                        if (oldestSql != null) {
2123                                                                this.cachedPreparedStatementParams
2124                                                                                .remove(oldestSql);
2125                                                        }
2126                                                }
2127        
2128                                                this.cachedPreparedStatementParams.put(sql, pStmt
2129                                                                .getParseInfo());
2130                                        }
2131                                } else {
2132                                        pStmtInfo.lastUsed = System.currentTimeMillis();
2133                                        pStmt = new com.mysql.jdbc.PreparedStatement(this, sql,
2134                                                        this.database, pStmtInfo);
2135                                }
2136                        }
2137                } else {
2138                        pStmt = new com.mysql.jdbc.PreparedStatement(this, sql,
2139                                        this.database);
2140                }
2141 
2142                pStmt.setResultSetType(resultSetType);
2143                pStmt.setResultSetConcurrency(resultSetConcurrency);
2144 
2145                return pStmt;
2146        }
2147 
2148        /**
2149         * In some cases, it is desirable to immediately release a Connection's
2150         * database and JDBC resources instead of waiting for them to be
2151         * automatically released (cant think why off the top of my head) <B>Note:</B>
2152         * A Connection is automatically closed when it is garbage collected.
2153         * Certain fatal errors also result in a closed connection.
2154         * 
2155         * @exception SQLException
2156         *                if a database access error occurs
2157         */
2158        public void close() throws SQLException {
2159                realClose(true, true, false, null);
2160        }
2161 
2162        /**
2163         * Closes all currently open statements.
2164         * 
2165         * @throws SQLException
2166         *             DOCUMENT ME!
2167         */
2168        private void closeAllOpenStatements() throws SQLException {
2169                SQLException postponedException = null;
2170 
2171                if (this.openStatements != null) {
2172                        List currentlyOpenStatements = new ArrayList(); // we need this to
2173                        // avoid
2174                        // ConcurrentModificationEx
2175 
2176                        for (Iterator iter = this.openStatements.keySet().iterator(); iter
2177                                        .hasNext();) {
2178                                currentlyOpenStatements.add(iter.next());
2179                        }
2180 
2181                        int numStmts = currentlyOpenStatements.size();
2182 
2183                        for (int i = 0; i < numStmts; i++) {
2184                                Statement stmt = (Statement) currentlyOpenStatements.get(i);
2185 
2186                                try {
2187                                        stmt.realClose(false, true);
2188                                } catch (SQLException sqlEx) {
2189                                        postponedException = sqlEx; // throw it later, cleanup all
2190                                        // statements first
2191                                }
2192                        }
2193 
2194                        if (postponedException != null) {
2195                                throw postponedException;
2196                        }
2197                }
2198        }
2199 
2200        private void closeStatement(java.sql.Statement stmt) {
2201                if (stmt != null) {
2202                        try {
2203                                stmt.close();
2204                        } catch (SQLException sqlEx) {
2205                                ; // ignore
2206                        }
2207 
2208                        stmt = null;
2209                }
2210        }
2211 
2212        // --------------------------JDBC 2.0-----------------------------
2213 
2214        /**
2215         * The method commit() makes all changes made since the previous
2216         * commit/rollback permanent and releases any database locks currently held
2217         * by the Connection. This method should only be used when auto-commit has
2218         * been disabled.
2219         * <p>
2220         * <b>Note:</b> MySQL does not support transactions, so this method is a
2221         * no-op.
2222         * </p>
2223         * 
2224         * @exception SQLException
2225         *                if a database access error occurs
2226         * @see setAutoCommit
2227         */
2228        public void commit() throws SQLException {
2229                synchronized (getMutex()) {
2230                        checkClosed();
2231        
2232                        try {
2233                                // no-op if _relaxAutoCommit == true
2234                                if (this.autoCommit && !getRelaxAutoCommit()) {
2235                                        throw SQLError.createSQLException("Can't call commit when autocommit=true");
2236                                } else if (this.transactionsSupported) {
2237                                        execSQL(null, "commit", -1, null,
2238                                                        java.sql.ResultSet.TYPE_FORWARD_ONLY,
2239                                                        java.sql.ResultSet.CONCUR_READ_ONLY, false,
2240                                                        this.database, true,
2241                                                        false);
2242                                }
2243                        } catch (SQLException sqlException) {
2244                                if (SQLError.SQL_STATE_COMMUNICATION_LINK_FAILURE
2245                                                .equals(sqlException.getSQLState())) {
2246                                        throw SQLError.createSQLException(
2247                                                        "Communications link failure during commit(). Transaction resolution unknown.",
2248                                                        SQLError.SQL_STATE_TRANSACTION_RESOLUTION_UNKNOWN);
2249                                }
2250        
2251                                throw sqlException;
2252                        } finally {
2253                                this.needsPing = this.getReconnectAtTxEnd();
2254                        }
2255        
2256                        return;
2257                }
2258        }
2259 
2260        /**
2261         * Configures client-side properties for character set information.
2262         * 
2263         * @throws SQLException
2264         *             if unable to configure the specified character set.
2265         */
2266        private void configureCharsetProperties() throws SQLException {
2267                if (getEncoding() != null) {
2268                        // Attempt to use the encoding, and bail out if it
2269                        // can't be used
2270                        try {
2271                                String testString = "abc";
2272                                testString.getBytes(getEncoding());
2273                        } catch (UnsupportedEncodingException UE) {
2274                                // Try the MySQL character encoding, then....
2275                                String oldEncoding = getEncoding();
2276 
2277                                setEncoding(CharsetMapping.getJavaEncodingForMysqlEncoding(
2278                                                oldEncoding, this));
2279 
2280                                if (getEncoding() == null) {
2281                                        throw SQLError.createSQLException(
2282                                                        "Java does not support the MySQL character encoding "
2283                                                                        + " " + "encoding '" + oldEncoding + "'.",
2284                                                        SQLError.SQL_STATE_INVALID_CONNECTION_ATTRIBUTE);
2285                                }
2286 
2287                                try {
2288                                        String testString = "abc";
2289                                        testString.getBytes(getEncoding());
2290                                } catch (UnsupportedEncodingException encodingEx) {
2291                                        throw SQLError.createSQLException("Unsupported character "
2292                                                        + "encoding '" + getEncoding() + "'.",
2293                                                        SQLError.SQL_STATE_INVALID_CONNECTION_ATTRIBUTE);
2294                                }
2295                        }
2296                }
2297        }
2298 
2299        /**
2300         * Sets up client character set for MySQL-4.1 and newer if the user This
2301         * must be done before any further communication with the server!
2302         * 
2303         * @return true if this routine actually configured the client character
2304         *         set, or false if the driver needs to use 'older' methods to
2305         *         detect the character set, as it is connected to a MySQL server
2306         *         older than 4.1.0
2307         * @throws SQLException
2308         *             if an exception happens while sending 'SET NAMES' to the
2309         *             server, or the server sends character set information that
2310         *             the client doesn't know about.
2311         */
2312        private boolean configureClientCharacterSet() throws SQLException {
2313                String realJavaEncoding = getEncoding();
2314                boolean characterSetAlreadyConfigured = false;
2315 
2316                try {
2317                        if (versionMeetsMinimum(4, 1, 0)) {
2318                                characterSetAlreadyConfigured = true;
2319 
2320                                setUseUnicode(true);
2321 
2322                                configureCharsetProperties();
2323                                realJavaEncoding = getEncoding(); // we need to do this again
2324                                // to grab this for
2325                                // versions > 4.1.0
2326 
2327                                try {
2328                                        String serverEncodingToSet = 
2329                                                CharsetMapping.INDEX_TO_CHARSET[this.io.serverCharsetIndex];
2330                                        
2331                                        if (versionMeetsMinimum(4, 1, 0) && 
2332                                                        "ISO8859_1".equalsIgnoreCase(serverEncodingToSet)) {
2333                                                serverEncodingToSet = "Cp1252";
2334                                        }
2335                                        
2336                                        setEncoding(serverEncodingToSet);
2337                                } catch (ArrayIndexOutOfBoundsException outOfBoundsEx) {
2338                                        if (realJavaEncoding != null) {
2339                                                // user knows best, try it
2340                                                setEncoding(realJavaEncoding);
2341                                        } else {
2342                                                throw SQLError.createSQLException(
2343                                                                "Unknown initial character set index '"
2344                                                                                + this.io.serverCharsetIndex
2345                                                                                + "' received from server. Initial client character set can be forced via the 'characterEncoding' property.",
2346                                                                SQLError.SQL_STATE_GENERAL_ERROR);
2347                                        }
2348                                }
2349 
2350                                if (getEncoding() == null) {
2351                                        // punt?
2352                                        setEncoding("ISO8859_1");
2353                                }
2354 
2355                                //
2356                                // Has the user has 'forced' the character encoding via
2357                                // driver properties?
2358                                //
2359                                if (getUseUnicode()) {
2360                                        if (realJavaEncoding != null) {
2361 
2362                                                //
2363                                                // Now, inform the server what character set we
2364                                                // will be using from now-on...
2365                                                //
2366                                                if (realJavaEncoding.equalsIgnoreCase("UTF-8")
2367                                                                || realJavaEncoding.equalsIgnoreCase("UTF8")) {
2368                                                        // charset names are case-sensitive
2369 
2370                                                        if (!getUseOldUTF8Behavior()) {
2371                                                                execSQL(null, "SET NAMES utf8", -1, null,
2372                                                                                java.sql.ResultSet.TYPE_FORWARD_ONLY,
2373                                                                                java.sql.ResultSet.CONCUR_READ_ONLY,
2374                                                                                false, this.database, true, false);
2375                                                        }
2376 
2377                                                        setEncoding(realJavaEncoding);
2378                                                } /* not utf-8 */else {
2379                                                        String mysqlEncodingName = CharsetMapping
2380                                                                        .getMysqlEncodingForJavaEncoding(
2381                                                                                        realJavaEncoding
2382                                                                                                        .toUpperCase(Locale.ENGLISH),
2383                                                                                        this);
2384 
2385                                                        /*
2386                                                         * if ("koi8_ru".equals(mysqlEncodingName)) { //
2387                                                         * This has a _different_ name in 4.1...
2388                                                         * mysqlEncodingName = "ko18r"; } else if
2389                                                         * ("euc_kr".equals(mysqlEncodingName)) { //
2390                                                         * Different name in 4.1 mysqlEncodingName =
2391                                                         * "euckr"; }
2392                                                         */
2393 
2394                                                        if (mysqlEncodingName != null) {
2395                                                                execSQL(null, "SET NAMES " + mysqlEncodingName,
2396                                                                                -1, null,
2397                                                                                java.sql.ResultSet.TYPE_FORWARD_ONLY,
2398                                                                                java.sql.ResultSet.CONCUR_READ_ONLY,
2399                                                                                false, this.database, true, false);
2400                                                        }
2401 
2402                                                        // Switch driver's encoding now, since the server
2403                                                        // knows what we're sending...
2404                                                        //
2405                                                        setEncoding(realJavaEncoding);
2406                                                }
2407                                        } else if (getEncoding() != null) {
2408                                                // Tell the server we'll use the server default charset
2409                                                // to send our
2410                                                // queries from now on....
2411                                                String mysqlEncodingName = CharsetMapping
2412                                                                .getMysqlEncodingForJavaEncoding(getEncoding()
2413                                                                                .toUpperCase(Locale.ENGLISH), this);
2414 
2415                                                execSQL(null, "SET NAMES " + mysqlEncodingName, -1,
2416                                                                null, java.sql.ResultSet.TYPE_FORWARD_ONLY,
2417                                                                java.sql.ResultSet.CONCUR_READ_ONLY, false,
2418                                                                this.database, true, false);
2419 
2420                                                realJavaEncoding = getEncoding();
2421                                        }
2422 
2423                                }
2424 
2425                                //
2426                                // We know how to deal with any charset coming back from
2427                                // the database, so tell the server not to do conversion
2428                                // if the user hasn't 'forced' a result-set character set
2429                                //
2430 
2431                                if (getCharacterSetResults() == null) {
2432                                        execSQL(null, "SET character_set_results = NULL", -1, null,
2433                                                        java.sql.ResultSet.TYPE_FORWARD_ONLY,
2434                                                        java.sql.ResultSet.CONCUR_READ_ONLY, false,
2435                                                        this.database, true, 
2436                                                        false);
2437                                } else {
2438                                        String charsetResults = getCharacterSetResults();
2439                                        String mysqlEncodingName = null;
2440 
2441                                        if ("UTF-8".equalsIgnoreCase(charsetResults)
2442                                                        || "UTF8".equalsIgnoreCase(charsetResults)) {
2443                                                mysqlEncodingName = "utf8";
2444                                        } else {
2445                                                mysqlEncodingName = CharsetMapping
2446                                                                .getMysqlEncodingForJavaEncoding(charsetResults
2447                                                                                .toUpperCase(Locale.ENGLISH), this);
2448                                        }
2449 
2450                                        StringBuffer setBuf = new StringBuffer(
2451                                                        "SET character_set_results = ".length()
2452                                                                        + mysqlEncodingName.length());
2453                                        setBuf.append("SET character_set_results = ").append(
2454                                                        mysqlEncodingName);
2455 
2456                                        execSQL(null, setBuf.toString(), -1, null,
2457                                                        java.sql.ResultSet.TYPE_FORWARD_ONLY,
2458                                                        java.sql.ResultSet.CONCUR_READ_ONLY, false,
2459                                                        this.database, true, false);
2460                                }
2461 
2462                                if (getConnectionCollation() != null) {
2463                                        StringBuffer setBuf = new StringBuffer(
2464                                                        "SET collation_connection = ".length()
2465                                                                        + getConnectionCollation().length());
2466                                        setBuf.append("SET collation_connection = ").append(
2467                                                        getConnectionCollation());
2468 
2469                                        execSQL(null, setBuf.toString(), -1, null,
2470                                                        java.sql.ResultSet.TYPE_FORWARD_ONLY,
2471                                                        java.sql.ResultSet.CONCUR_READ_ONLY, false,
2472                                                        this.database, true, false);
2473                                }
2474                        } else {
2475                                // Use what the server has specified
2476                                realJavaEncoding = getEncoding(); // so we don't get
2477                                // swapped out in the finally
2478                                // block....
2479                        }
2480                } finally {
2481                        // Failsafe, make sure that the driver's notion of character
2482                        // encoding matches what the user has specified.
2483                        //
2484                        setEncoding(realJavaEncoding);
2485                }
2486 
2487                return characterSetAlreadyConfigured;
2488        }
2489 
2490        /**
2491         * Configures the client's timezone if required.
2492         * 
2493         * @throws SQLException
2494         *             if the timezone the server is configured to use can't be
2495         *             mapped to a Java timezone.
2496         */
2497        private void configureTimezone() throws SQLException {
2498                String configuredTimeZoneOnServer = (String) this.serverVariables
2499                                .get("timezone");
2500 
2501                if (configuredTimeZoneOnServer == null) {
2502                        configuredTimeZoneOnServer = (String) this.serverVariables
2503                                        .get("time_zone");
2504 
2505                        if ("SYSTEM".equalsIgnoreCase(configuredTimeZoneOnServer)) {
2506                                configuredTimeZoneOnServer = (String) this.serverVariables
2507                                                .get("system_time_zone");
2508                        }
2509                }
2510 
2511                if (getUseTimezone() && configuredTimeZoneOnServer != null) {
2512                        // user can specify/override as property
2513                        String canoncicalTimezone = getServerTimezone();
2514 
2515                        if ((canoncicalTimezone == null)
2516                                        || (canoncicalTimezone.length() == 0)) {
2517                                String serverTimezoneStr = configuredTimeZoneOnServer;
2518 
2519                                try {
2520                                        canoncicalTimezone = TimeUtil
2521                                                        .getCanoncialTimezone(serverTimezoneStr);
2522 
2523                                        if (canoncicalTimezone == null) {
2524                                                throw SQLError.createSQLException("Can't map timezone '"
2525                                                                + serverTimezoneStr + "' to "
2526                                                                + " canonical timezone.",
2527                                                                SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
2528                                        }
2529                                } catch (IllegalArgumentException iae) {
2530                                        throw SQLError.createSQLException(iae.getMessage(),
2531                                                        SQLError.SQL_STATE_GENERAL_ERROR);
2532                                }
2533                        }
2534 
2535                        this.serverTimezoneTZ = TimeZone.getTimeZone(canoncicalTimezone);
2536 
2537                        //
2538                        // The Calendar class has the behavior of mapping
2539                        // unknown timezones to 'GMT' instead of throwing an
2540                        // exception, so we must check for this...
2541                        //
2542                        if (!canoncicalTimezone.equalsIgnoreCase("GMT")
2543                                        && this.serverTimezoneTZ.getID().equals("GMT")) {
2544                                throw SQLError.createSQLException("No timezone mapping entry for '"
2545                                                + canoncicalTimezone + "'",
2546                                                SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
2547                        }
2548 
2549                        if ("GMT".equalsIgnoreCase(this.serverTimezoneTZ.getID())) {
2550                                this.isServerTzUTC = true;
2551                        } else {
2552                                this.isServerTzUTC = false;
2553                        }
2554                }
2555        }
2556 
2557        private void createInitialHistogram(long[] breakpoints,
2558                        long lowerBound, long upperBound) {
2559 
2560                double bucketSize = (((double) upperBound - (double) lowerBound) / HISTOGRAM_BUCKETS) * 1.25;
2561 
2562                if (bucketSize < 1) {
2563                        bucketSize = 1;
2564                }
2565 
2566                for (int i = 0; i < HISTOGRAM_BUCKETS; i++) {
2567                        breakpoints[i] = lowerBound;
2568                        lowerBound += bucketSize;
2569                }
2570        }
2571 
2572        /**
2573         * Creates an IO channel to the server
2574         * 
2575         * @param isForReconnect
2576         *            is this request for a re-connect
2577         * @return a new MysqlIO instance connected to a server
2578         * @throws SQLException
2579         *             if a database access error occurs
2580         * @throws CommunicationsException
2581         *             DOCUMENT ME!
2582         */
2583        protected com.mysql.jdbc.MysqlIO createNewIO(boolean isForReconnect)
2584                        throws SQLException {
2585                MysqlIO newIo = null;
2586 
2587                Properties mergedProps = new Properties();
2588 
2589                mergedProps = exposeAsProperties(this.props);
2590 
2591                long queriesIssuedFailedOverCopy = this.queriesIssuedFailedOver;
2592                this.queriesIssuedFailedOver = 0;
2593 
2594                try {
2595                        if (!getHighAvailability() && !this.failedOver) {
2596                                int hostIndex = 0;
2597 
2598                                //
2599                                // TODO: Eventually, when there's enough metadata
2600                                // on the server to support it, we should come up
2601                                // with a smarter way to pick what server to connect
2602                                // to...perhaps even making it 'pluggable'
2603                                //
2604                                if (getRoundRobinLoadBalance()) {
2605                                        hostIndex = getNextRoundRobinHostIndex(getURL(),
2606                                                        this.hostList);
2607                                }
2608 
2609                                for (; hostIndex < this.hostListSize; hostIndex++) {
2610                                        if (hostIndex == 0) {
2611                                                this.hasTriedMasterFlag = true;
2612                                        }
2613                                        
2614                                        try {
2615                                                String newHostPortPair = (String) this.hostList
2616                                                                .get(hostIndex);
2617 
2618                                                int newPort = 3306;
2619 
2620                                                String[] hostPortPair = NonRegisteringDriver
2621                                                                .parseHostPortPair(newHostPortPair);
2622                                                String newHost = hostPortPair[NonRegisteringDriver.HOST_NAME_INDEX];
2623 
2624                                                if (newHost == null || newHost.trim().length() == 0) {
2625                                                        newHost = "localhost";
2626                                                }
2627 
2628                                                if (hostPortPair[NonRegisteringDriver.PORT_NUMBER_INDEX] != null) {
2629                                                        try {
2630                                                                newPort = Integer
2631                                                                                .parseInt(hostPortPair[NonRegisteringDriver.PORT_NUMBER_INDEX]);
2632                                                        } catch (NumberFormatException nfe) {
2633                                                                throw SQLError.createSQLException(
2634                                                                                "Illegal connection port value '"
2635                                                                                                + hostPortPair[NonRegisteringDriver.PORT_NUMBER_INDEX]
2636                                                                                                + "'",
2637                                                                                SQLError.SQL_STATE_INVALID_CONNECTION_ATTRIBUTE);
2638                                                        }
2639                                                }
2640 
2641                                                this.io = new MysqlIO(newHost, newPort, mergedProps,
2642                                                                getSocketFactoryClassName(), this,
2643                                                                getSocketTimeout());
2644                                                this.io.doHandshake(this.user, this.password,
2645                                                                this.database);
2646                                                this.isClosed = false;
2647 
2648                                                // save state from old connection
2649                                                boolean oldAutoCommit = getAutoCommit();
2650                                                int oldIsolationLevel = this.isolationLevel;
2651                                                boolean oldReadOnly = isReadOnly();
2652                                                String oldCatalog = getCatalog();
2653 
2654                                                // Server properties might be different
2655                                                // from previous connection, so initialize
2656                                                // again...
2657                                                initializePropsFromServer();
2658 
2659                                                if (isForReconnect) {
2660                                                        // Restore state from old connection
2661                                                        setAutoCommit(oldAutoCommit);
2662 
2663                                                        if (this.hasIsolationLevels) {
2664                                                                setTransactionIsolation(oldIsolationLevel);
2665                                                        }
2666 
2667                                                        setCatalog(oldCatalog);
2668                                                }
2669 
2670                                                if (hostIndex != 0) {
2671                                                        setFailedOverState();
2672                                                        queriesIssuedFailedOverCopy = 0;
2673                                                } else {
2674                                                        this.failedOver = false;
2675                                                        queriesIssuedFailedOverCopy = 0;
2676 
2677                                                        if (this.hostListSize > 1) {
2678                                                                setReadOnly(false);
2679                                                        } else {
2680                                                                setReadOnly(oldReadOnly);
2681                                                        }
2682                                                }
2683 
2684                                                break; // low-level connection succeeded
2685                                        } catch (SQLException sqlEx) {
2686                                                if (this.io != null) {
2687                                                        this.io.forceClose();
2688                                                }
2689 
2690                                                String sqlState = sqlEx.getSQLState();
2691 
2692                                                if ((sqlState == null)
2693                                                                || !sqlState
2694                                                                                .equals(SQLError.SQL_STATE_COMMUNICATION_LINK_FAILURE)) {
2695                                                        throw sqlEx;
2696                                                }
2697 
2698                                                if ((this.hostListSize - 1) == hostIndex) {
2699                                                        throw sqlEx;
2700                                                }
2701                                        } catch (Exception unknownException) {
2702                                                if (this.io != null) {
2703                                                        this.io.forceClose();
2704                                                }
2705 
2706                                                if ((this.hostListSize - 1) == hostIndex) {
2707                                                        throw new CommunicationsException(this,
2708                                                                        (this.io != null) ? this.io
2709                                                                                        .getLastPacketSentTimeMs() : 0,
2710                                                                        unknownException);
2711                                                }
2712                                        }
2713                                }
2714                        } else {
2715                                double timeout = getInitialTimeout();
2716                                boolean connectionGood = false;
2717 
2718                                Exception connectionException = null;
2719 
2720                                int hostIndex = 0;
2721 
2722                                if (getRoundRobinLoadBalance()) {
2723                                        hostIndex = getNextRoundRobinHostIndex(getURL(),
2724                                                        this.hostList);
2725                                }
2726 
2727                                for (; (hostIndex < this.hostListSize) && !connectionGood; hostIndex++) {
2728                                        if (hostIndex == 0) {
2729                                                this.hasTriedMasterFlag = true;
2730                                        }
2731                                        
2732                                        if (this.preferSlaveDuringFailover && hostIndex == 0) {
2733                                                hostIndex++;
2734                                        }
2735 
2736                                        for (int attemptCount = 0; (attemptCount < getMaxReconnects())
2737                                                        && !connectionGood; attemptCount++) {
2738                                                try {
2739                                                        if (this.io != null) {
2740                                                                this.io.forceClose();
2741                                                        }
2742 
2743                                                        String newHostPortPair = (String) this.hostList
2744                                                                        .get(hostIndex);
2745 
2746                                                        int newPort = 3306;
2747 
2748                                                        String[] hostPortPair = NonRegisteringDriver
2749                                                                        .parseHostPortPair(newHostPortPair);
2750                                                        String newHost = hostPortPair[NonRegisteringDriver.HOST_NAME_INDEX];
2751 
2752                                                        if (newHost == null || newHost.trim().length() == 0) {
2753                                                                newHost = "localhost";
2754                                                        }
2755 
2756                                                        if (hostPortPair[NonRegisteringDriver.PORT_NUMBER_INDEX] != null) {
2757                                                                try {
2758                                                                        newPort = Integer
2759                                                                                        .parseInt(hostPortPair[NonRegisteringDriver.PORT_NUMBER_INDEX]);
2760                                                                } catch (NumberFormatException nfe) {
2761                                                                        throw SQLError.createSQLException(
2762                                                                                        "Illegal connection port value '"
2763                                                                                                        + hostPortPair[NonRegisteringDriver.PORT_NUMBER_INDEX]
2764                                                                                                        + "'",
2765                                                                                        SQLError.SQL_STATE_INVALID_CONNECTION_ATTRIBUTE);
2766                                                                }
2767                                                        }
2768 
2769                                                        this.io = new MysqlIO(newHost, newPort,
2770                                                                        mergedProps, getSocketFactoryClassName(),
2771                                                                        this, getSocketTimeout());
2772                                                        this.io.doHandshake(this.user, this.password,
2773                                                                        this.database);
2774 
2775                                                        pingInternal(false);
2776                                                        this.isClosed = false;
2777 
2778                                                        // save state from old connection
2779                                                        boolean oldAutoCommit = getAutoCommit();
2780                                                        int oldIsolationLevel = this.isolationLevel;
2781                                                        boolean oldReadOnly = isReadOnly();
2782                                                        String oldCatalog = getCatalog();
2783 
2784                                                        // Server properties might be different
2785                                                        // from previous connection, so initialize
2786                                                        // again...
2787                                                        initializePropsFromServer();
2788 
2789                                                        if (isForReconnect) {
2790                                                                // Restore state from old connection
2791                                                                setAutoCommit(oldAutoCommit);
2792 
2793                                                                if (this.hasIsolationLevels) {
2794                                                                        setTransactionIsolation(oldIsolationLevel);
2795                                                                }
2796 
2797                                                                setCatalog(oldCatalog);
2798                                                        }
2799 
2800                                                        connectionGood = true;
2801 
2802                                                        if (hostIndex != 0) {
2803                                                                setFailedOverState();
2804                                                                queriesIssuedFailedOverCopy = 0;
2805                                                        } else {
2806                                                                this.failedOver = false;
2807                                                                queriesIssuedFailedOverCopy = 0;
2808 
2809                                                                if (this.hostListSize > 1) {
2810                                                                        setReadOnly(false);
2811                                                                } else {
2812                                                                        setReadOnly(oldReadOnly);
2813                                                                }
2814                                                        }
2815 
2816                                                        break;
2817                                                } catch (Exception EEE) {
2818                                                        connectionException = EEE;
2819                                                        connectionGood = false;
2820                                                }
2821 
2822                                                if (connectionGood) {
2823                                                        break;
2824                                                }
2825 
2826                                                if (attemptCount > 0) {
2827                                                        try {
2828                                                                Thread.sleep((long) timeout * 1000);
2829                                                        } catch (InterruptedException IE) {
2830                                                                ;
2831                                                        }
2832                                                }
2833                                        } // end attempts for a single host
2834                                } // end iterator for list of hosts
2835 
2836                                if (!connectionGood) {
2837                                        // We've really failed!
2838                                        throw SQLError.createSQLException(
2839                                                        "Server connection failure during transaction. Due to underlying exception: '"
2840                                                                        + connectionException
2841                                                                        + "'."
2842                                                                        + (getParanoid() ? ""
2843                                                                                        : Util
2844                                                                                                        .stackTraceToString(connectionException))
2845                                                                        + "\nAttempted reconnect "
2846                                                                        + getMaxReconnects() + " times. Giving up.",
2847                                                        SQLError.SQL_STATE_UNABLE_TO_CONNECT_TO_DATASOURCE);
2848                                }
2849                        }
2850 
2851                        if (getParanoid() && !getHighAvailability()
2852                                        && (this.hostListSize <= 1)) {
2853                                this.password = null;
2854                                this.user = null;
2855                        }
2856 
2857                        if (isForReconnect) {
2858                                //
2859                                // Retrieve any 'lost' prepared statements if re-connecting
2860                                //
2861                                Iterator statementIter = this.openStatements.values()
2862                                                .iterator();
2863 
2864                                //
2865                                // We build a list of these outside the map of open statements,
2866                                // because
2867                                // in the process of re-preparing, we might end up having to
2868                                // close
2869                                // a prepared statement, thus removing it from the map, and
2870                                // generating
2871                                // a ConcurrentModificationException
2872                                //
2873                                Stack serverPreparedStatements = null;
2874 
2875                                while (statementIter.hasNext()) {
2876                                        Object statementObj = statementIter.next();
2877 
2878                                        if (statementObj instanceof ServerPreparedStatement) {
2879                                                if (serverPreparedStatements == null) {
2880                                                        serverPreparedStatements = new Stack();
2881                                                }
2882 
2883                                                serverPreparedStatements.add(statementObj);
2884                                        }
2885                                }
2886 
2887                                if (serverPreparedStatements != null) {
2888                                        while (!serverPreparedStatements.isEmpty()) {
2889                                                ((ServerPreparedStatement) serverPreparedStatements
2890                                                                .pop()).rePrepare();
2891                                        }
2892                                }
2893                        }
2894 
2895                        return newIo;
2896                } finally {
2897                        this.queriesIssuedFailedOver = queriesIssuedFailedOverCopy;
2898                }
2899        }
2900 
2901        private void createPreparedStatementCaches() {
2902                int cacheSize = getPreparedStatementCacheSize();
2903                
2904                this.cachedPreparedStatementParams = new HashMap(cacheSize);
2905                
2906                this.serverSideStatementCheckCache = new LRUCache(cacheSize);
2907                
2908                this.serverSideStatementCache = new LRUCache(cacheSize) {
2909                        protected boolean removeEldestEntry(java.util.Map.Entry eldest) {
2910                                if (this.maxElements <= 1) {
2911                                        return false;
2912                                }
2913                                
2914                                boolean removeIt = super.removeEldestEntry(eldest);
2915                                
2916                                if (removeIt) {
2917                                        ServerPreparedStatement ps = 
2918                                                (ServerPreparedStatement)eldest.getValue();
2919                                        ps.isCached = false;
2920                                        ps.setClosed(false);
2921                                        
2922                                        try {
2923                                                ps.close();
2924                                        } catch (SQLException sqlEx) {
2925                                                // punt
2926                                        }
2927                                }
2928                                
2929                                return removeIt;
2930                        }
2931                };
2932        }
2933 
2934        /**
2935         * SQL statements without parameters are normally executed using Statement
2936         * objects. If the same SQL statement is executed many times, it is more
2937         * efficient to use a PreparedStatement
2938         * 
2939         * @return a new Statement object
2940         * @throws SQLException
2941         *             passed through from the constructor
2942         */
2943        public java.sql.Statement createStatement() throws SQLException {
2944                return createStatement(java.sql.ResultSet.TYPE_FORWARD_ONLY,
2945                                java.sql.ResultSet.CONCUR_READ_ONLY);
2946        }
2947 
2948        /**
2949         * JDBC 2.0 Same as createStatement() above, but allows the default result
2950         * set type and result set concurrency type to be overridden.
2951         * 
2952         * @param resultSetType
2953         *            a result set type, see ResultSet.TYPE_XXX
2954         * @param resultSetConcurrency
2955         *            a concurrency type, see ResultSet.CONCUR_XXX
2956         * @return a new Statement object
2957         * @exception SQLException
2958         *                if a database-access error occurs.
2959         */
2960        public java.sql.Statement createStatement(int resultSetType,
2961                        int resultSetConcurrency) throws SQLException {
2962                checkClosed();
2963 
2964                Statement stmt = new com.mysql.jdbc.Statement(this, this.database);
2965                stmt.setResultSetType(resultSetType);
2966                stmt.setResultSetConcurrency(resultSetConcurrency);
2967 
2968                return stmt;
2969        }
2970 
2971        /**
2972         * @see Connection#createStatement(int, int, int)
2973         */
2974        public java.sql.Statement createStatement(int resultSetType,
2975                        int resultSetConcurrency, int resultSetHoldability)
2976                        throws SQLException {
2977                if (getPedantic()) {
2978                        if (resultSetHoldability != java.sql.ResultSet.HOLD_CURSORS_OVER_COMMIT) {
2979                                throw SQLError.createSQLException(
2980                                                "HOLD_CUSRORS_OVER_COMMIT is only supported holdability level",
2981                                                SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
2982                        }
2983                }
2984 
2985                return createStatement(resultSetType, resultSetConcurrency);
2986        }
2987 
2988        protected void dumpTestcaseQuery(String query) {
2989                System.err.println(query);
2990        }
2991 
2992        protected Connection duplicate() throws SQLException {
2993                return new Connection(        this.origHostToConnectTo, 
2994                                this.origPortToConnectTo,
2995                                this.props,
2996                                this.origDatabaseToConnectTo,
2997                                this.myURL);
2998        }
2999 
3000        /**
3001         * Send a query to the server. Returns one of the ResultSet objects. This is
3002         * synchronized, so Statement's queries will be serialized.
3003         * 
3004         * @param callingStatement
3005         *            DOCUMENT ME!
3006         * @param sql
3007         *            the SQL statement to be executed
3008         * @param maxRows
3009         *            DOCUMENT ME!
3010         * @param packet
3011         *            DOCUMENT ME!
3012         * @param resultSetType
3013         *            DOCUMENT ME!
3014         * @param resultSetConcurrency
3015         *            DOCUMENT ME!
3016         * @param streamResults
3017         *            DOCUMENT ME!
3018         * @param queryIsSelectOnly
3019         *            DOCUMENT ME!
3020         * @param catalog
3021         *            DOCUMENT ME!
3022         * @param unpackFields
3023         *            DOCUMENT ME!
3024         * @return a ResultSet holding the results
3025         * @exception SQLException
3026         *                if a database error occurs
3027         */
3028 
3029        // ResultSet execSQL(Statement callingStatement, String sql,
3030        // int maxRowsToRetreive, String catalog) throws SQLException {
3031        // return execSQL(callingStatement, sql, maxRowsToRetreive, null,
3032        // java.sql.ResultSet.TYPE_FORWARD_ONLY,
3033        // java.sql.ResultSet.CONCUR_READ_ONLY, catalog);
3034        // }
3035        // ResultSet execSQL(Statement callingStatement, String sql, int maxRows,
3036        // int resultSetType, int resultSetConcurrency, boolean streamResults,
3037        // boolean queryIsSelectOnly, String catalog, boolean unpackFields) throws
3038        // SQLException {
3039        // return execSQL(callingStatement, sql, maxRows, null, resultSetType,
3040        // resultSetConcurrency, streamResults, queryIsSelectOnly, catalog,
3041        // unpackFields);
3042        // }
3043        ResultSet execSQL(Statement callingStatement, String sql, int maxRows,
3044                        Buffer packet, int resultSetType, int resultSetConcurrency,
3045                        boolean streamResults, String catalog,
3046                        boolean unpackFields) throws SQLException {
3047                return execSQL(callingStatement, sql, maxRows, packet, resultSetType,
3048                                resultSetConcurrency, streamResults,
3049                                catalog, unpackFields, false);
3050        }
3051 
3052        ResultSet execSQL(Statement callingStatement, String sql, int maxRows,
3053                        Buffer packet, int resultSetType, int resultSetConcurrency,
3054                        boolean streamResults, String catalog,
3055                        boolean unpackFields,
3056                        boolean isBatch) throws SQLException {
3057                //
3058                // Fall-back if the master is back online if we've
3059                // issued queriesBeforeRetryMaster queries since
3060                // we failed over
3061                //
3062                synchronized (this.mutex) {
3063                        long queryStartTime = 0;
3064 
3065                        int endOfQueryPacketPosition = 0;
3066 
3067                        if (packet != null) {
3068                                endOfQueryPacketPosition = packet.getPosition();
3069                        }
3070 
3071                        if (getGatherPerformanceMetrics()) {
3072                                queryStartTime = System.currentTimeMillis();
3073                        }
3074 
3075                        this.lastQueryFinishedTime = 0; // we're busy!
3076 
3077                        if (this.failedOver && this.autoCommit && !isBatch) {
3078                                if (shouldFallBack() && !this.executingFailoverReconnect) {
3079                                        try {
3080                                                this.executingFailoverReconnect = true;
3081 
3082                                                createNewIO(true);
3083 
3084                                                String connectedHost = this.io.getHost();
3085 
3086                                                if ((connectedHost != null)
3087                                                                && this.hostList.get(0).equals(connectedHost)) {
3088                                                        this.failedOver = false;
3089                                                        this.queriesIssuedFailedOver = 0;
3090                                                        setReadOnly(false);
3091                                                }
3092                                        } finally {
3093                                                this.executingFailoverReconnect = false;
3094                                        }
3095                                }
3096                        }
3097 
3098                        if ((getHighAvailability() || this.failedOver)
3099                                        && (this.autoCommit || getAutoReconnectForPools())
3100                                        && this.needsPing && !isBatch) {
3101                                try {
3102                                        pingInternal(false);
3103 
3104                                        this.needsPing = false;
3105                                } catch (Exception Ex) {
3106                                        createNewIO(true);
3107                                }
3108                        }
3109 
3110                        try {
3111                                if (packet == null) {
3112                                        String encoding = null;
3113 
3114                                        if (getUseUnicode()) {
3115                                                encoding = getEncoding();
3116                                        }
3117 
3118                                        return this.io.sqlQueryDirect(callingStatement, sql,
3119                                                        encoding, null, maxRows, this, resultSetType,
3120                                                        resultSetConcurrency, streamResults, catalog,
3121                                                        unpackFields);
3122                                }
3123 
3124                                return this.io.sqlQueryDirect(callingStatement, null, null,
3125                                                packet, maxRows, this, resultSetType,
3126                                                resultSetConcurrency, streamResults, catalog,
3127                                                unpackFields);
3128                        } catch (java.sql.SQLException sqlE) {
3129                                // don't clobber SQL exceptions
3130 
3131                                if (getDumpQueriesOnException()) {
3132                                        String extractedSql = extractSqlFromPacket(sql, packet,
3133                                                        endOfQueryPacketPosition);
3134                                        StringBuffer messageBuf = new StringBuffer(extractedSql
3135                                                        .length() + 32);
3136                                        messageBuf
3137                                                        .append("\n\nQuery being executed when exception was thrown:\n\n");
3138                                        messageBuf.append(extractedSql);
3139 
3140                                        sqlE = appendMessageToException(sqlE, messageBuf.toString());
3141                                }
3142 
3143                                if ((getHighAvailability() || this.failedOver)) {
3144                                        this.needsPing = true;
3145                                } else {
3146                                        String sqlState = sqlE.getSQLState();
3147 
3148                                        if ((sqlState != null)
3149                                                        && sqlState
3150                                                                        .equals(SQLError.SQL_STATE_COMMUNICATION_LINK_FAILURE)) {
3151                                                cleanup(sqlE);
3152                                        }
3153                                }
3154 
3155                                throw sqlE;
3156                        } catch (Exception ex) {
3157                                if ((getHighAvailability() || this.failedOver)) {
3158                                        this.needsPing = true;
3159                                } else if (ex instanceof IOException) {
3160                                        cleanup(ex);
3161                                }
3162 
3163                                String exceptionType = ex.getClass().getName();
3164                                String exceptionMessage = ex.getMessage();
3165 
3166                                if (!getParanoid()) {
3167                                        exceptionMessage += "\n\nNested Stack Trace:\n";
3168                                        exceptionMessage += Util.stackTraceToString(ex);
3169                                }
3170 
3171                                throw new java.sql.SQLException(
3172                                                "Error during query: Unexpected Exception: "
3173                                                                + exceptionType + " message given: "
3174                                                                + exceptionMessage,
3175                                                SQLError.SQL_STATE_GENERAL_ERROR);
3176                        } finally {
3177                                if (getMaintainTimeStats()) {
3178                                        this.lastQueryFinishedTime = System.currentTimeMillis();
3179                                }
3180 
3181                                if (this.failedOver) {
3182                                        this.queriesIssuedFailedOver++;
3183                                }
3184 
3185                                if (getGatherPerformanceMetrics()) {
3186                                        long queryTime = System.currentTimeMillis()
3187                                                        - queryStartTime;
3188 
3189                                        registerQueryExecutionTime(queryTime);
3190                                }
3191                        }
3192                }
3193        }
3194 
3195        protected String extractSqlFromPacket(String possibleSqlQuery,
3196                        Buffer queryPacket, int endOfQueryPacketPosition)
3197                        throws SQLException {
3198 
3199                String extractedSql = null;
3200 
3201                if (possibleSqlQuery != null) {
3202                        if (possibleSqlQuery.length() > getMaxQuerySizeToLog()) {
3203                                StringBuffer truncatedQueryBuf = new StringBuffer(
3204                                                possibleSqlQuery.substring(0, getMaxQuerySizeToLog()));
3205                                truncatedQueryBuf.append(Messages.getString("MysqlIO.25"));
3206                                extractedSql = truncatedQueryBuf.toString();
3207                        } else {
3208                                extractedSql = possibleSqlQuery;
3209                        }
3210                }
3211 
3212                if (extractedSql == null) {
3213                        // This is probably from a client-side prepared
3214                        // statement
3215 
3216                        int extractPosition = endOfQueryPacketPosition;
3217 
3218                        boolean truncated = false;
3219 
3220                        if (endOfQueryPacketPosition > getMaxQuerySizeToLog()) {
3221                                extractPosition = getMaxQuerySizeToLog();
3222                                truncated = true;
3223                        }
3224 
3225                        extractedSql = new String(queryPacket.getByteBuffer(), 5,
3226                                        (extractPosition - 5));
3227 
3228                        if (truncated) {
3229                                extractedSql += Messages.getString("MysqlIO.25"); //$NON-NLS-1$
3230                        }
3231                }
3232 
3233                return extractedSql;
3234 
3235        }
3236 
3237        /**
3238         * DOCUMENT ME!
3239         * 
3240         * @throws Throwable
3241         *             DOCUMENT ME!
3242         */
3243        protected void finalize() throws Throwable {
3244                cleanup(null);
3245        }
3246 
3247        protected StringBuffer generateConnectionCommentBlock(StringBuffer buf) {
3248                buf.append("/* conn id ");
3249                buf.append(getId());
3250                buf.append(" */ ");
3251 
3252                return buf;
3253        }
3254 
3255        public int getActiveStatementCount() {
3256                // Might not have one of these if
3257                // not tracking open resources
3258                if (this.openStatements != null) {
3259                        synchronized (this.openStatements) {
3260                                return this.openStatements.size();
3261                        }
3262                }
3263 
3264                return 0;
3265        }
3266 
3267        /**
3268         * Gets the current auto-commit state
3269         * 
3270         * @return Current state of auto-commit
3271         * @exception SQLException
3272         *                if an error occurs
3273         * @see setAutoCommit
3274         */
3275        public boolean getAutoCommit() throws SQLException {
3276                return this.autoCommit;
3277        }
3278 
3279        /**
3280         * Optimization to only use one calendar per-session, or calculate it for
3281         * each call, depending on user configuration
3282         */
3283        protected Calendar getCalendarInstanceForSessionOrNew() {
3284                if (getDynamicCalendars()) {
3285                        return Calendar.getInstance();
3286                }
3287 
3288                return getSessionLockedCalendar();
3289        }
3290 
3291        /**
3292         * Return the connections current catalog name, or null if no catalog name
3293         * is set, or we dont support catalogs.
3294         * <p>
3295         * <b>Note:</b> MySQL's notion of catalogs are individual databases.
3296         * </p>
3297         * 
3298         * @return the current catalog name or null
3299         * @exception SQLException
3300         *                if a database access error occurs
3301         */
3302        public String getCatalog() throws SQLException {
3303                return this.database;
3304        }
3305 
3306        /**
3307         * @return Returns the characterSetMetadata.
3308         */
3309        protected String getCharacterSetMetadata() {
3310                return characterSetMetadata;
3311        }
3312 
3313        /**
3314         * Returns the locally mapped instance of a charset converter (to avoid
3315         * overhead of static synchronization).
3316         * 
3317         * @param javaEncodingName
3318         *            the encoding name to retrieve
3319         * @return a character converter, or null if one couldn't be mapped.
3320         */
3321        SingleByteCharsetConverter getCharsetConverter(
3322                        String javaEncodingName) throws SQLException {
3323                if (javaEncodingName == null) {
3324                        return null;
3325                }
3326 
3327                if (this.usePlatformCharsetConverters) {
3328                        return null; // we'll use Java's built-in routines for this
3329                                     // they're finally fast enough
3330                }
3331                
3332                SingleByteCharsetConverter converter = null;
3333                
3334                synchronized (this.charsetConverterMap) {
3335                        Object asObject = this.charsetConverterMap
3336                        .get(javaEncodingName);
3337 
3338                        if (asObject == CHARSET_CONVERTER_NOT_AVAILABLE_MARKER) {
3339                                return null;
3340                        }
3341                        
3342                        converter = (SingleByteCharsetConverter)asObject;
3343                        
3344                        if (converter == null) {
3345                                try {
3346                                        converter = SingleByteCharsetConverter.getInstance(
3347                                                        javaEncodingName, this);
3348 
3349                                        if (converter == null) {
3350                                                this.charsetConverterMap.put(javaEncodingName,
3351                                                                CHARSET_CONVERTER_NOT_AVAILABLE_MARKER);
3352                                        } else {
3353                                                this.charsetConverterMap.put(javaEncodingName, converter);
3354                                        }
3355                                } catch (UnsupportedEncodingException unsupEncEx) {
3356                                        this.charsetConverterMap.put(javaEncodingName,
3357                                                        CHARSET_CONVERTER_NOT_AVAILABLE_MARKER);
3358 
3359                                        converter = null;
3360                                }
3361                        }
3362                }
3363 
3364                return converter;
3365        }
3366 
3367        /**
3368         * Returns the Java character encoding name for the given MySQL server
3369         * charset index
3370         * 
3371         * @param charsetIndex
3372         * @return the Java character encoding name for the given MySQL server
3373         *         charset index
3374         * @throws SQLException
3375         *             if the character set index isn't known by the driver
3376         */
3377        protected String getCharsetNameForIndex(int charsetIndex)
3378                        throws SQLException {
3379                String charsetName = null;
3380 
3381                if (getUseOldUTF8Behavior()) {
3382                        return getEncoding();
3383                }
3384 
3385                if (charsetIndex != MysqlDefs.NO_CHARSET_INFO) {
3386                        try {
3387                                charsetName = this.indexToCharsetMapping[charsetIndex];
3388 
3389                                if ("sjis".equalsIgnoreCase(charsetName)) {
3390                                        // Use our encoding so that code pages like Cp932 work
3391                                        if (CharsetMapping.isAliasForSjis(getEncoding())) {
3392                                                charsetName = getEncoding();
3393                                        }
3394                                }
3395                        } catch (ArrayIndexOutOfBoundsException outOfBoundsEx) {
3396                                throw SQLError.createSQLException(
3397                                                "Unknown character set index for field '"
3398                                                                + charsetIndex + "' received from server.",
3399                                                SQLError.SQL_STATE_GENERAL_ERROR);
3400                        }
3401 
3402                        // Punt
3403                        if (charsetName == null) {
3404                                charsetName = getEncoding();
3405                        }
3406                } else {
3407                        charsetName = getEncoding();
3408                }
3409 
3410                return charsetName;
3411        }
3412 
3413        /**
3414         * DOCUMENT ME!
3415         * 
3416         * @return Returns the defaultTimeZone.
3417         */
3418        protected TimeZone getDefaultTimeZone() {
3419                return this.defaultTimeZone;
3420        }
3421 
3422        /**
3423         * @see Connection#getHoldability()
3424         */
3425        public int getHoldability() throws SQLException {
3426                return java.sql.ResultSet.CLOSE_CURSORS_AT_COMMIT;
3427        }
3428 
3429        long getId() {
3430                return this.connectionId;
3431        }
3432 
3433        /**
3434         * NOT JDBC-Compliant, but clients can use this method to determine how long
3435         * this connection has been idle. This time (reported in milliseconds) is
3436         * updated once a query has completed.
3437         * 
3438         * @return number of ms that this connection has been idle, 0 if the driver
3439         *         is busy retrieving results.
3440         */
3441        public long getIdleFor() {
3442                if (this.lastQueryFinishedTime == 0) {
3443                        return 0;
3444                }
3445 
3446                long now = System.currentTimeMillis();
3447                long idleTime = now - this.lastQueryFinishedTime;
3448 
3449                return idleTime;
3450        }
3451 
3452        /**
3453         * Returns the IO channel to the server
3454         * 
3455         * @return the IO channel to the server
3456         * @throws SQLException
3457         *             if the connection is closed.
3458         */
3459        protected MysqlIO getIO() throws SQLException {
3460                if ((this.io == null) || this.isClosed) {
3461                        throw SQLError.createSQLException(
3462                                        "Operation not allowed on closed connection",
3463                                        SQLError.SQL_STATE_CONNECTION_NOT_OPEN);
3464                }
3465 
3466                return this.io;
3467        }
3468 
3469        /**
3470         * Returns the log mechanism that should be used to log information from/for
3471         * this Connection.
3472         * 
3473         * @return the Log instance to use for logging messages.
3474         * @throws SQLException
3475         *             if an error occurs
3476         */
3477        public Log getLog() throws SQLException {
3478                return this.log;
3479        }
3480 
3481        /**
3482         * Returns the maximum packet size the MySQL server will accept
3483         * 
3484         * @return DOCUMENT ME!
3485         */
3486        int getMaxAllowedPacket() {
3487                return this.maxAllowedPacket;
3488        }
3489 
3490        protected int getMaxBytesPerChar(String javaCharsetName)
3491                        throws SQLException {
3492                // TODO: Check if we can actually run this query at this point in time
3493                String charset = CharsetMapping.getMysqlEncodingForJavaEncoding(
3494                                javaCharsetName, this);
3495 
3496                if (versionMeetsMinimum(4, 1, 0)) {
3497                        synchronized (this.charsetToNumBytesMap) {
3498                                if (this.charsetToNumBytesMap.isEmpty()) {
3499                                        
3500                                        java.sql.Statement stmt = null;
3501                                        java.sql.ResultSet rs = null;
3502        
3503                                        try {
3504                                                stmt = getMetadataSafeStatement();
3505        
3506                                                rs = stmt.executeQuery("SHOW CHARACTER SET");
3507        
3508                                                while (rs.next()) {
3509                                                        this.charsetToNumBytesMap.put(rs.getString("Charset"),
3510                                                                        new Integer(rs.getInt("Maxlen")));
3511                                                }
3512        
3513                                                rs.close();
3514                                                rs = null;
3515        
3516                                                stmt.close();
3517        
3518                                                stmt = null;
3519                                        } finally {
3520                                                if (rs != null) {
3521                                                        rs.close();
3522                                                        rs = null;
3523                                                }
3524        
3525                                                if (stmt != null) {
3526                                                        stmt.close();
3527                                                        stmt = null;
3528                                                }
3529                                        }
3530                                }
3531                        }
3532 
3533                        Integer mbPerChar = (Integer) this.charsetToNumBytesMap
3534                                        .get(charset);
3535 
3536                        if (mbPerChar != null) {
3537                                return mbPerChar.intValue();
3538                        }
3539 
3540                        return 1; // we don't know
3541                }
3542 
3543                return 1; // we don't know
3544        }
3545 
3546        /**
3547         * A connection's database is able to provide information describing its
3548         * tables, its supported SQL grammar, its stored procedures, the
3549         * capabilities of this connection, etc. This information is made available
3550         * through a DatabaseMetaData object.
3551         * 
3552         * @return a DatabaseMetaData object for this connection
3553         * @exception SQLException
3554         *                if a database access error occurs
3555         */
3556        public java.sql.DatabaseMetaData getMetaData() throws SQLException {
3557                checkClosed();
3558 
3559                if (getUseInformationSchema() &&
3560                                this.versionMeetsMinimum(5, 0, 7)) {
3561                        return new DatabaseMetaDataUsingInfoSchema(this, this.database);
3562                }
3563                        
3564                return new DatabaseMetaData(this, this.database);
3565        }
3566 
3567        protected java.sql.Statement getMetadataSafeStatement() throws SQLException {
3568                java.sql.Statement stmt = createStatement();
3569 
3570                if (stmt.getMaxRows() != 0) {
3571                        stmt.setMaxRows(0);
3572                }
3573 
3574                stmt.setEscapeProcessing(false);
3575 
3576                return stmt;
3577        }
3578 
3579        /**
3580         * Returns the Mutex all queries are locked against
3581         * 
3582         * @return DOCUMENT ME!
3583         * @throws SQLException
3584         *             DOCUMENT ME!
3585         */
3586        Object getMutex() throws SQLException {
3587                if (this.io == null) {
3588                        throw SQLError.createSQLException(
3589                                        "Connection.close() has already been called. Invalid operation in this state.",
3590                                        SQLError.SQL_STATE_CONNECTION_NOT_OPEN);
3591                }
3592 
3593                reportMetricsIfNeeded();
3594 
3595                return this.mutex;
3596        }
3597 
3598        /**
3599         * Returns the packet buffer size the MySQL server reported upon connection
3600         * 
3601         * @return DOCUMENT ME!
3602         */
3603        int getNetBufferLength() {
3604                return this.netBufferLength;
3605        }
3606 
3607        /**
3608         * Returns the server's character set
3609         * 
3610         * @return the server's character set.
3611         */
3612        protected String getServerCharacterEncoding() {
3613                return (String) this.serverVariables.get("character_set");
3614        }
3615 
3616        int getServerMajorVersion() {
3617                return this.io.getServerMajorVersion();
3618        }
3619 
3620        int getServerMinorVersion() {
3621                return this.io.getServerMinorVersion();
3622        }
3623 
3624        int getServerSubMinorVersion() {
3625                return this.io.getServerSubMinorVersion();
3626        }
3627 
3628        /**
3629         * DOCUMENT ME!
3630         * 
3631         * @return DOCUMENT ME!
3632         */
3633        public TimeZone getServerTimezoneTZ() {
3634                return this.serverTimezoneTZ;
3635        }
3636 
3637        String getServerVariable(String variableName) {
3638                if (this.serverVariables != null) {
3639                        return (String) this.serverVariables.get(variableName);
3640                }
3641 
3642                return null;
3643        }
3644 
3645        String getServerVersion() {
3646                return this.io.getServerVersion();
3647        }
3648 
3649        protected Calendar getSessionLockedCalendar() {
3650        
3651                return this.sessionCalendar;
3652        }
3653        
3654        
3655        /**
3656         * Get this Connection's current transaction isolation mode.
3657         * 
3658         * @return the current TRANSACTION_ mode value
3659         * @exception SQLException
3660         *                if a database access error occurs
3661         */
3662        public int getTransactionIsolation() throws SQLException {
3663 
3664                if (this.hasIsolationLevels && !getUseLocalSessionState()) {
3665                        java.sql.Statement stmt = null;
3666                        java.sql.ResultSet rs = null;
3667 
3668                        try {
3669                                stmt = getMetadataSafeStatement();
3670 
3671                                String query = null;
3672 
3673                                if (versionMeetsMinimum(4, 0, 3)) {
3674                                        query = "SHOW VARIABLES LIKE 'tx_isolation'";
3675                                } else {
3676                                        query = "SHOW VARIABLES LIKE 'transaction_isolation'";
3677                                }
3678 
3679                                rs = stmt.executeQuery(query);
3680 
3681                                if (rs.next()) {
3682                                        String s = rs.getString(2);
3683 
3684                                        if (s != null) {
3685                                                Integer intTI = (Integer) mapTransIsolationNameToValue
3686                                                                .get(s);
3687 
3688                                                if (intTI != null) {
3689                                                        return intTI.intValue();
3690                                                }
3691                                        }
3692 
3693                                        throw SQLError.createSQLException(
3694                                                        "Could not map transaction isolation '" + s
3695                                                                        + " to a valid JDBC level.",
3696                                                        SQLError.SQL_STATE_GENERAL_ERROR);
3697                                }
3698 
3699                                throw SQLError.createSQLException(
3700                                                "Could not retrieve transaction isolation level from server",
3701                                                SQLError.SQL_STATE_GENERAL_ERROR);
3702 
3703                        } finally {
3704                                if (rs != null) {
3705                                        try {
3706                                                rs.close();
3707                                        } catch (Exception ex) {
3708                                                // ignore
3709                                                ;
3710                                        }
3711 
3712                                        rs = null;
3713                                }
3714 
3715                                if (stmt != null) {
3716                                        try {
3717                                                stmt.close();
3718                                        } catch (Exception ex) {
3719                                                // ignore
3720                                                ;
3721                                        }
3722 
3723                                        stmt = null;
3724                                }
3725                        }
3726                }
3727 
3728                synchronized (this) {
3729                        return this.isolationLevel;
3730                }
3731        }
3732 
3733        /**
3734         * JDBC 2.0 Get the type-map object associated with this connection. By
3735         * default, the map returned is empty.
3736         * 
3737         * @return the type map
3738         * @throws SQLException
3739         *             if a database error occurs
3740         */
3741        public synchronized java.util.Map getTypeMap() throws SQLException {
3742                if (this.typeMap == null) {
3743                        this.typeMap = new HashMap();
3744                }
3745 
3746                return this.typeMap;
3747        }
3748 
3749        String getURL() {
3750                return this.myURL;
3751        }
3752 
3753        String getUser() {
3754                return this.user;
3755        }
3756 
3757        protected Calendar getUtcCalendar() {
3758                return this.utcCalendar;
3759        }
3760 
3761        /**
3762         * The first warning reported by calls on this Connection is returned.
3763         * <B>Note:</B> Sebsequent warnings will be changed to this
3764         * java.sql.SQLWarning
3765         * 
3766         * @return the first java.sql.SQLWarning or null
3767         * @exception SQLException
3768         *                if a database access error occurs
3769         */
3770        public SQLWarning getWarnings() throws SQLException {
3771                return null;
3772        }
3773 
3774        public boolean hasSameProperties(Connection c) {
3775                return this.props.equals(c.props);
3776        }
3777 
3778        protected void incrementNumberOfPreparedExecutes() {
3779                if (getGatherPerformanceMetrics()) {
3780                        this.numberOfPreparedExecutes++;
3781 
3782                        // We need to increment this, because
3783                        // server-side prepared statements bypass
3784                        // any execution by the connection itself...
3785                        this.numberOfQueriesIssued++;
3786                }
3787        }
3788        
3789        protected void incrementNumberOfPrepares() {
3790                if (getGatherPerformanceMetrics()) {
3791                        this.numberOfPrepares++;
3792                }
3793        }
3794 
3795        protected void incrementNumberOfResultSetsCreated() {
3796                if (getGatherPerformanceMetrics()) {
3797                        this.numberOfResultSetsCreated++;
3798                }
3799        }
3800 
3801        /**
3802         * Initializes driver properties that come from URL or properties passed to
3803         * the driver manager.
3804         * 
3805         * @param info
3806         *            DOCUMENT ME!
3807         * @throws SQLException
3808         *             DOCUMENT ME!
3809         */
3810        private void initializeDriverProperties(Properties info)
3811                        throws SQLException {
3812                initializeProperties(info);
3813                
3814                this.usePlatformCharsetConverters = getUseJvmCharsetConverters();
3815 
3816                this.log = LogFactory.getLogger(getLogger(), LOGGER_INSTANCE_NAME);
3817 
3818                if (getProfileSql() || getUseUsageAdvisor()) {
3819                        this.eventSink = ProfileEventSink.getInstance(this);
3820                }
3821 
3822                if (getCachePreparedStatements()) {
3823                        createPreparedStatementCaches();                
3824                }
3825 
3826                if (getNoDatetimeStringSync() && getUseTimezone()) {
3827                        throw SQLError.createSQLException(
3828                                        "Can't enable noDatetimeSync and useTimezone configuration "
3829                                                        + "properties at the same time",
3830                                        SQLError.SQL_STATE_INVALID_CONNECTION_ATTRIBUTE);
3831                }
3832                
3833                if (getCacheCallableStatements()) {
3834                        this.parsedCallableStatementCache = new LRUCache(
3835                                        getCallableStatementCacheSize());
3836                }
3837        }
3838 
3839        /**
3840         * Sets varying properties that depend on server information. Called once we
3841         * have connected to the server.
3842         * 
3843         * @param info
3844         *            DOCUMENT ME!
3845         * @throws SQLException
3846         *             DOCUMENT ME!
3847         */
3848        private void initializePropsFromServer() throws SQLException {
3849                setSessionVariables();
3850 
3851                //
3852                // the "boolean" type didn't come along until MySQL-4.1
3853                //
3854 
3855                if (!versionMeetsMinimum(4, 1, 0)) {
3856                        setTransformedBitIsBoolean(false);
3857                }
3858 
3859                // We need to do this before any further data gets
3860                // sent to the server....
3861                boolean clientCharsetIsConfigured = configureClientCharacterSet();
3862 
3863                this.parserKnowsUnicode = versionMeetsMinimum(4, 1, 0);
3864 
3865                //
3866                // Users can turn off detection of server-side prepared statements
3867                //
3868                if (getUseServerPreparedStmts() && versionMeetsMinimum(4, 1, 0)) {
3869                        this.useServerPreparedStmts = true;
3870 
3871                        if (versionMeetsMinimum(5, 0, 0) && !versionMeetsMinimum(5, 0, 3)) {
3872                                this.useServerPreparedStmts = false; // 4.1.2+ style prepared
3873                                // statements
3874                                // don't work on these versions
3875                        }
3876                }
3877 
3878                this.serverVariables.clear();
3879 
3880                //
3881                // If version is greater than 3.21.22 get the server
3882                // variables.
3883                if (versionMeetsMinimum(3, 21, 22)) {
3884                        loadServerVariables();
3885 
3886                        buildCollationMapping();
3887 
3888                        LicenseConfiguration.checkLicenseType(this.serverVariables);
3889 
3890                        String lowerCaseTables = (String) this.serverVariables
3891                                        .get("lower_case_table_names");
3892 
3893                        this.lowerCaseTableNames = "on".equalsIgnoreCase(lowerCaseTables)
3894                                        || "1".equalsIgnoreCase(lowerCaseTables)
3895                                        || "2".equalsIgnoreCase(lowerCaseTables);
3896 
3897                        configureTimezone();
3898 
3899                        if (this.serverVariables.containsKey("max_allowed_packet")) {
3900                                this.maxAllowedPacket = Integer
3901                                                .parseInt((String) this.serverVariables
3902                                                                .get("max_allowed_packet"));
3903                                
3904                                int preferredBlobSendChunkSize = getBlobSendChunkSize();
3905                                
3906                                int allowedBlobSendChunkSize = Math.min(preferredBlobSendChunkSize, 
3907                                                this.maxAllowedPacket) - 
3908                                                ServerPreparedStatement.BLOB_STREAM_READ_BUF_SIZE 
3909                                                - 11 /* LONG_DATA and MySQLIO packet header size */;
3910                                
3911                                setBlobSendChunkSize(String.valueOf(allowedBlobSendChunkSize));
3912                        }
3913 
3914                        if (this.serverVariables.containsKey("net_buffer_length")) {
3915                                this.netBufferLength = Integer
3916                                                .parseInt((String) this.serverVariables
3917                                                                .get("net_buffer_length"));
3918                        }
3919 
3920                        checkTransactionIsolationLevel();
3921 
3922                        //
3923                        // We only do this for servers older than 4.1.0, because
3924                        // 4.1.0 and newer actually send the server charset
3925                        // during the handshake, and that's handled at the
3926                        // top of this method...
3927                        //
3928                        if (!clientCharsetIsConfigured) {
3929                                checkServerEncoding();
3930                        }
3931 
3932                        this.io.checkForCharsetMismatch();
3933 
3934                        if (this.serverVariables.containsKey("sql_mode")) {
3935                                int sqlMode = 0;
3936 
3937                                String sqlModeAsString = (String) this.serverVariables
3938                                                .get("sql_mode");
3939                                try {
3940                                        sqlMode = Integer.parseInt(sqlModeAsString);
3941                                } catch (NumberFormatException nfe) {
3942                                        // newer versions of the server has this as a string-y
3943                                        // list...
3944                                        sqlMode = 0;
3945 
3946                                        if (sqlModeAsString != null) {
3947                                                if (sqlModeAsString.indexOf("ANSI_QUOTES") != -1) {
3948                                                        sqlMode |= 4;
3949                                                }
3950 
3951                                                if (sqlModeAsString.indexOf("NO_BACKSLASH_ESCAPES") != -1) {
3952                                                        this.noBackslashEscapes = true;
3953                                                }
3954                                        }
3955                                }
3956 
3957                                if ((sqlMode & 4) > 0) {
3958                                        this.useAnsiQuotes = true;
3959                                } else {
3960                                        this.useAnsiQuotes = false;
3961                                }
3962                        }
3963                }
3964                
3965                this.errorMessageEncoding = 
3966                        CharsetMapping.getCharacterEncodingForErrorMessages(this);
3967                
3968                boolean overrideDefaultAutocommit = false;
3969                
3970                String initConnectValue = (String) this.serverVariables
3971                .get("init_connect");
3972 
3973                if (versionMeetsMinimum(4, 1, 2) && initConnectValue != null
3974                                && initConnectValue.length() > 0) {
3975                        // auto-commit might have changed
3976                        java.sql.ResultSet rs = null;
3977                        java.sql.Statement stmt = null;
3978                        
3979                        try {
3980                                stmt = getMetadataSafeStatement();
3981                                
3982                                rs = stmt.executeQuery("SELECT @@session.autocommit");
3983                                
3984                                if (rs.next()) {
3985                                        this.autoCommit = rs.getBoolean(1);
3986                                        if (this.autoCommit != true) {
3987                                                overrideDefaultAutocommit = true;
3988                                        }
3989                                }
3990                                
3991                        } finally {
3992                                if (rs != null) {
3993                                        try {
3994                                                rs.close();
3995                                        } catch (SQLException sqlEx) {
3996                                                // do nothing
3997                                        }
3998                                }
3999                                
4000                                if (stmt != null) {
4001                                        try {
4002                                                stmt.close();
4003                                        } catch (SQLException sqlEx) {
4004                                                // do nothing
4005                                        }
4006                                }
4007                        }
4008                }
4009        
4010                if (versionMeetsMinimum(3, 23, 15)) {
4011                        this.transactionsSupported = true;
4012                        
4013                        if (!overrideDefaultAutocommit) {
4014                                setAutoCommit(true); // to override anything
4015                                // the server is set to...reqd
4016                                // by JDBC spec.
4017                        }
4018                } else {
4019                        this.transactionsSupported = false;
4020                }
4021                
4022 
4023                if (versionMeetsMinimum(3, 23, 36)) {
4024                        this.hasIsolationLevels = true;
4025                } else {
4026                        this.hasIsolationLevels = false;
4027                }
4028 
4029                this.hasQuotedIdentifiers = versionMeetsMinimum(3, 23, 6);
4030 
4031                this.io.resetMaxBuf();
4032 
4033                //
4034                // If we're using MySQL 4.1.0 or newer, we need to figure
4035                // out what character set metadata will be returned in,
4036                // and then map that to a Java encoding name.
4037                //
4038                if (this.io.versionMeetsMinimum(4, 1, 0)) {
4039                        String characterSetResultsOnServerMysql = (String) this.serverVariables
4040                                        .get("character_set_results");
4041 
4042                        if (characterSetResultsOnServerMysql == null
4043                                        || StringUtils.startsWithIgnoreCaseAndWs(
4044                                                        characterSetResultsOnServerMysql, "NULL")) {
4045                                String defaultMetadataCharsetMysql = (String) this.serverVariables
4046                                                .get("character_set_system");
4047                                String defaultMetadataCharset = null;
4048 
4049                                if (defaultMetadataCharsetMysql != null) {
4050                                        defaultMetadataCharset = CharsetMapping
4051                                                        .getJavaEncodingForMysqlEncoding(
4052                                                                        defaultMetadataCharsetMysql, this);
4053                                } else {
4054                                        defaultMetadataCharset = "UTF-8";
4055                                }
4056 
4057                                this.characterSetMetadata = defaultMetadataCharset;
4058                        } else {
4059                                this.characterSetResultsOnServer = CharsetMapping
4060                                                .getJavaEncodingForMysqlEncoding(
4061                                                                characterSetResultsOnServerMysql, this);
4062                                this.characterSetMetadata = this.characterSetResultsOnServer;
4063                        }
4064                }
4065 
4066                //
4067                // Query cache is broken wrt. multi-statements before MySQL-4.1.10
4068                //
4069 
4070                if (this.versionMeetsMinimum(4, 1, 0)
4071                                && !this.versionMeetsMinimum(4, 1, 10)
4072                                && getAllowMultiQueries()) {
4073                        if ("ON".equalsIgnoreCase((String) this.serverVariables
4074                                        .get("query_cache_type"))
4075                                        && !"0".equalsIgnoreCase((String) this.serverVariables
4076                                                        .get("query_cache_size"))) {
4077                                setAllowMultiQueries(false);
4078                        }
4079                }
4080                
4081                //
4082                // Server can do this more efficiently for us
4083                //
4084                
4085                setupServerForTruncationChecks();
4086        }
4087 
4088        private void setupServerForTruncationChecks() throws SQLException {
4089                if (getJdbcCompliantTruncation()) {
4090                        if (versionMeetsMinimum(5, 0, 2)) {
4091                                String currentSqlMode = 
4092                                        (String)this.serverVariables.get("sql_mode");
4093                                
4094                                if (currentSqlMode == null ||
4095                                                currentSqlMode.length() == 0 ||
4096                                                StringUtils.indexOfIgnoreCase(currentSqlMode, "STRICT_TRANS_TABLES") == -1) {
4097                                        StringBuffer commandBuf = new StringBuffer("SET sql_mode='");
4098                                        
4099                                        if (currentSqlMode != null && currentSqlMode.length() > 0) {
4100                                                commandBuf.append(currentSqlMode);
4101                                                commandBuf.append(",");
4102                                        }
4103                                        
4104                                        commandBuf.append("STRICT_TRANS_TABLES'");
4105                                        
4106                                        execSQL(null,  commandBuf.toString(), -1, null,
4107                                                        java.sql.ResultSet.TYPE_FORWARD_ONLY,
4108                                                        java.sql.ResultSet.CONCUR_READ_ONLY, false,
4109                                                        this.database, true, false);
4110                                        
4111                                        setJdbcCompliantTruncation(false); // server's handling this for us now
4112                                }
4113                                
4114                        }
4115                }
4116        }
4117 
4118        protected boolean isClientTzUTC() {
4119                return this.isClientTzUTC;
4120        }
4121 
4122        /**
4123         * DOCUMENT ME!
4124         * 
4125         * @return DOCUMENT ME!
4126         */
4127        public boolean isClosed() {
4128                return this.isClosed;
4129        }
4130 
4131        protected boolean isCursorFetchEnabled() throws SQLException {
4132                return (versionMeetsMinimum(5, 0, 2) && getUseCursorFetch());
4133        }
4134 
4135        public boolean isInGlobalTx() {
4136                return this.isInGlobalTx;
4137        }
4138 
4139        /**
4140         * Is this connection connected to the first host in the list if
4141         * there is a list of servers in the URL?
4142         * 
4143         * @return true if this connection is connected to the first in 
4144         * the list.
4145         */
4146        public synchronized boolean isMasterConnection() {
4147                return !this.failedOver;
4148        }
4149 
4150        /**
4151         * Is the server in a sql_mode that doesn't allow us to use \\ to escape
4152         * things?
4153         * 
4154         * @return Returns the noBackslashEscapes.
4155         */
4156        public boolean isNoBackslashEscapesSet() {
4157                return this.noBackslashEscapes;
4158        }
4159 
4160        boolean isReadInfoMsgEnabled() {
4161                return this.readInfoMsg;
4162        }
4163 
4164        /**
4165         * Tests to see if the connection is in Read Only Mode. Note that we cannot
4166         * really put the database in read only mode, but we pretend we can by
4167         * returning the value of the readOnly flag
4168         * 
4169         * @return true if the connection is read only
4170         * @exception SQLException
4171         *                if a database access error occurs
4172         */
4173        public boolean isReadOnly() throws SQLException {
4174                return this.readOnly;
4175        }
4176 
4177        protected boolean isRunningOnJDK13() {
4178                return this.isRunningOnJDK13;
4179        }
4180 
4181        public synchronized boolean isSameResource(Connection otherConnection) {
4182                if (otherConnection == null) {
4183                        return false;
4184                }
4185                
4186                boolean directCompare = true;
4187                
4188                String otherHost = otherConnection.origHostToConnectTo;
4189                String otherOrigDatabase = otherConnection.origDatabaseToConnectTo;
4190                String otherCurrentCatalog = otherConnection.database;
4191                
4192                if (!nullSafeCompare(otherHost, this.origHostToConnectTo)) {
4193                        directCompare = false;
4194                } else if (otherHost != null & otherHost.indexOf(",") == -1 && 
4195                                otherHost.indexOf(":") == -1) {
4196                        // need to check port numbers
4197                        directCompare = (otherConnection.origPortToConnectTo == 
4198                                this.origPortToConnectTo);
4199                }
4200                
4201                if (directCompare) {
4202                        if (!nullSafeCompare(otherOrigDatabase, this.origDatabaseToConnectTo)) {                        directCompare = false;
4203                                directCompare = false;
4204                        } else if (!nullSafeCompare(otherCurrentCatalog, this.database)) {
4205                                directCompare = false;
4206                        }
4207                }
4208 
4209                if (directCompare) {
4210                        return true;
4211                }
4212                
4213                // Has the user explicitly set a resourceId?
4214                String otherResourceId = otherConnection.getResourceId();
4215                String myResourceId = getResourceId();
4216                
4217                if (otherResourceId != null || myResourceId != null) {
4218                        directCompare = nullSafeCompare(otherResourceId, myResourceId);
4219                        
4220                        if (directCompare) {
4221                                return true;
4222                        }
4223                }
4224                
4225                return false;        
4226        }
4227 
4228        protected boolean isServerTzUTC() {
4229                return this.isServerTzUTC;
4230        }
4231 
4232        /**
4233         * Loads the result of 'SHOW VARIABLES' into the serverVariables field so
4234         * that the driver can configure itself.
4235         * 
4236         * @throws SQLException
4237         *             if the 'SHOW VARIABLES' query fails for any reason.
4238         */
4239        private void loadServerVariables() throws SQLException {
4240 
4241                if (getCacheServerConfiguration()) {
4242                        synchronized (serverConfigByUrl) {
4243                                Map cachedVariableMap = (Map) serverConfigByUrl.get(getURL());
4244 
4245                                if (cachedVariableMap != null) {
4246                                        this.serverVariables = cachedVariableMap;
4247 
4248                                        return;
4249                                }
4250                        }
4251                }
4252 
4253                com.mysql.jdbc.Statement stmt = null;
4254                com.mysql.jdbc.ResultSet results = null;
4255 
4256                try {
4257                        stmt = (com.mysql.jdbc.Statement) createStatement();
4258                        stmt.setEscapeProcessing(false);
4259 
4260                        results = (com.mysql.jdbc.ResultSet) stmt
4261                                        .executeQuery("SHOW VARIABLES");
4262 
4263                        while (results.next()) {
4264                                this.serverVariables.put(results.getString(1), results
4265                                                .getString(2));
4266                        }
4267 
4268                        if (getCacheServerConfiguration()) {
4269                                synchronized (serverConfigByUrl) {
4270                                        serverConfigByUrl.put(getURL(), this.serverVariables);
4271                                }
4272                        }
4273                } catch (SQLException e) {
4274                        throw e;
4275                } finally {
4276                        if (results != null) {
4277                                try {
4278                                        results.close();
4279                                } catch (SQLException sqlE) {
4280                                        ;
4281                                }
4282                        }
4283 
4284                        if (stmt != null) {
4285                                try {
4286                                        stmt.close();
4287                                } catch (SQLException sqlE) {
4288                                        ;
4289                                }
4290                        }
4291                }
4292        }
4293 
4294        /**
4295         * Is the server configured to use lower-case table names only?
4296         * 
4297         * @return true if lower_case_table_names is 'on'
4298         */
4299        public boolean lowerCaseTableNames() {
4300                return this.lowerCaseTableNames;
4301        }
4302 
4303        /**
4304         * Has the maxRows value changed?
4305         * 
4306         * @param stmt
4307         *            DOCUMENT ME!
4308         */
4309        void maxRowsChanged(Statement stmt) {
4310                synchronized (this.mutex) {
4311                        if (this.statementsUsingMaxRows == null) {
4312                                this.statementsUsingMaxRows = new HashMap();
4313                        }
4314 
4315                        this.statementsUsingMaxRows.put(stmt, stmt);
4316 
4317                        this.maxRowsChanged = true;
4318                }
4319        }
4320 
4321        /**
4322         * A driver may convert the JDBC sql grammar into its system's native SQL
4323         * grammar prior to sending it; nativeSQL returns the native form of the
4324         * statement that the driver would have sent.
4325         * 
4326         * @param sql
4327         *            a SQL statement that may contain one or more '?' parameter
4328         *            placeholders
4329         * @return the native form of this statement
4330         * @exception SQLException
4331         *                if a database access error occurs
4332         */
4333        public String nativeSQL(String sql) throws SQLException {
4334                if (sql == null) {
4335                        return null;
4336                }
4337 
4338                Object escapedSqlResult = EscapeProcessor.escapeSQL(sql,
4339                                serverSupportsConvertFn(),
4340                                this);
4341 
4342                if (escapedSqlResult instanceof String) {
4343                        return (String) escapedSqlResult;
4344                }
4345 
4346                return ((EscapeProcessorResult) escapedSqlResult).escapedSql;
4347        }
4348 
4349        private CallableStatement parseCallableStatement(String sql)
4350                        throws SQLException {
4351                Object escapedSqlResult = EscapeProcessor.escapeSQL(sql,
4352                                serverSupportsConvertFn(), this);
4353 
4354                boolean isFunctionCall = false;
4355                String parsedSql = null;
4356 
4357                if (escapedSqlResult instanceof EscapeProcessorResult) {
4358                        parsedSql = ((EscapeProcessorResult) escapedSqlResult).escapedSql;
4359                        isFunctionCall = ((EscapeProcessorResult) escapedSqlResult).callingStoredFunction;
4360                } else {
4361                        parsedSql = (String) escapedSqlResult;
4362                        isFunctionCall = false;
4363                }
4364 
4365                return new CallableStatement(this, parsedSql, this.database,
4366                                isFunctionCall);
4367        }
4368 
4369        /**
4370         * DOCUMENT ME!
4371         * 
4372         * @return DOCUMENT ME!
4373         */
4374        public boolean parserKnowsUnicode() {
4375                return this.parserKnowsUnicode;
4376        }
4377 
4378        /**
4379         * Detect if the connection is still good
4380         * 
4381         * @throws SQLException
4382         *             if the ping fails
4383         */
4384        public void ping() throws SQLException {
4385                pingInternal(true);
4386        }
4387 
4388        private void pingInternal(boolean checkForClosedConnection)
4389                        throws SQLException {
4390                if (checkForClosedConnection) {
4391                        checkClosed();
4392                }
4393 
4394                // Need MySQL-3.22.1, but who uses anything older!?
4395                this.io.sendCommand(MysqlDefs.PING, null, null, false, null);
4396        }
4397 
4398        /**
4399         * DOCUMENT ME!
4400         * 
4401         * @param sql
4402         *            DOCUMENT ME!
4403         * @return DOCUMENT ME!
4404         * @throws SQLException
4405         *             DOCUMENT ME!
4406         */
4407        public java.sql.CallableStatement prepareCall(String sql)
4408                        throws SQLException {
4409                if (this.getUseUltraDevWorkAround()) {
4410                        return new UltraDevWorkAround(prepareStatement(sql));
4411                }
4412 
4413                return prepareCall(sql, java.sql.ResultSet.TYPE_FORWARD_ONLY,
4414                                java.sql.ResultSet.CONCUR_READ_ONLY);
4415        }
4416 
4417        /**
4418         * JDBC 2.0 Same as prepareCall() above, but allows the default result set
4419         * type and result set concurrency type to be overridden.
4420         * 
4421         * @param sql
4422         *            the SQL representing the callable statement
4423         * @param resultSetType
4424         *            a result set type, see ResultSet.TYPE_XXX
4425         * @param resultSetConcurrency
4426         *            a concurrency type, see ResultSet.CONCUR_XXX
4427         * @return a new CallableStatement object containing the pre-compiled SQL
4428         *         statement
4429         * @exception SQLException
4430         *                if a database-access error occurs.
4431         */
4432        public java.sql.CallableStatement prepareCall(String sql,
4433                        int resultSetType, int resultSetConcurrency) throws SQLException {
4434                if (versionMeetsMinimum(5, 0, 0)) {
4435                        CallableStatement cStmt = null;
4436 
4437                        if (!getCacheCallableStatements()) {
4438 
4439                                cStmt = parseCallableStatement(sql);
4440                        } else {
4441                                synchronized (this.parsedCallableStatementCache) {
4442                                        CompoundCacheKey key = new CompoundCacheKey(getCatalog(), sql);
4443        
4444                                        CallableStatement.CallableStatementParamInfo cachedParamInfo = (CallableStatement.CallableStatementParamInfo) this.parsedCallableStatementCache
4445                                                        .get(key);
4446        
4447                                        if (cachedParamInfo != null) {
4448                                                cStmt = new CallableStatement(this, cachedParamInfo);
4449                                        } else {
4450                                                cStmt = parseCallableStatement(sql);
4451        
4452                                                cachedParamInfo = cStmt.paramInfo;
4453        
4454                                                this.parsedCallableStatementCache.put(key, cachedParamInfo);
4455                                        }
4456                                }
4457                        }
4458 
4459                        cStmt.setResultSetType(resultSetType);
4460                        cStmt.setResultSetConcurrency(resultSetConcurrency);
4461 
4462                        return cStmt;
4463                }
4464 
4465                throw SQLError.createSQLException("Callable statements not " + "supported.",
4466                                SQLError.SQL_STATE_DRIVER_NOT_CAPABLE);
4467        }
4468 
4469        /**
4470         * @see Connection#prepareCall(String, int, int, int)
4471         */
4472        public java.sql.CallableStatement prepareCall(String sql,
4473                        int resultSetType, int resultSetConcurrency,
4474                        int resultSetHoldability) throws SQLException {
4475                if (getPedantic()) {
4476                        if (resultSetHoldability != java.sql.ResultSet.HOLD_CURSORS_OVER_COMMIT) {
4477                                throw SQLError.createSQLException(
4478                                                "HOLD_CUSRORS_OVER_COMMIT is only supported holdability level",
4479                                                SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
4480                        }
4481                }
4482 
4483                CallableStatement cStmt = (com.mysql.jdbc.CallableStatement) prepareCall(
4484                                sql, resultSetType, resultSetConcurrency);
4485 
4486                return cStmt;
4487        }
4488 
4489        /**
4490         * A SQL statement with or without IN parameters can be pre-compiled and
4491         * stored in a PreparedStatement object. This object can then be used to
4492         * efficiently execute this statement multiple times.
4493         * <p>
4494         * <B>Note:</B> This method is optimized for handling parametric SQL
4495         * statements that benefit from precompilation if the driver supports
4496         * precompilation. In this case, the statement is not sent to the database
4497         * until the PreparedStatement is executed. This has no direct effect on
4498         * users; however it does affect which method throws certain
4499         * java.sql.SQLExceptions
4500         * </p>
4501         * <p>
4502         * MySQL does not support precompilation of statements, so they are handled
4503         * by the driver.
4504         * </p>
4505         * 
4506         * @param sql
4507         *            a SQL statement that may contain one or more '?' IN parameter
4508         *            placeholders
4509         * @return a new PreparedStatement object containing the pre-compiled
4510         *         statement.
4511         * @exception SQLException
4512         *                if a database access error occurs.
4513         */
4514        public java.sql.PreparedStatement prepareStatement(String sql)
4515                        throws SQLException {
4516                return prepareStatement(sql, java.sql.ResultSet.TYPE_FORWARD_ONLY,
4517                                java.sql.ResultSet.CONCUR_READ_ONLY);
4518        }
4519 
4520        /**
4521         * @see Connection#prepareStatement(String, int)
4522         */
4523        public java.sql.PreparedStatement prepareStatement(String sql,
4524                        int autoGenKeyIndex) throws SQLException {
4525                java.sql.PreparedStatement pStmt = prepareStatement(sql);
4526 
4527                ((com.mysql.jdbc.PreparedStatement) pStmt)
4528                                .setRetrieveGeneratedKeys(autoGenKeyIndex == java.sql.Statement.RETURN_GENERATED_KEYS);
4529 
4530                return pStmt;
4531        }
4532 
4533        /**
4534         * JDBC 2.0 Same as prepareStatement() above, but allows the default result
4535         * set type and result set concurrency type to be overridden.
4536         * 
4537         * @param sql
4538         *            the SQL query containing place holders
4539         * @param resultSetType
4540         *            a result set type, see ResultSet.TYPE_XXX
4541         * @param resultSetConcurrency
4542         *            a concurrency type, see ResultSet.CONCUR_XXX
4543         * @return a new PreparedStatement object containing the pre-compiled SQL
4544         *         statement
4545         * @exception SQLException
4546         *                if a database-access error occurs.
4547         */
4548        public java.sql.PreparedStatement prepareStatement(String sql,
4549                        int resultSetType, int resultSetConcurrency) throws SQLException {
4550                checkClosed();
4551 
4552                //
4553                // FIXME: Create warnings if can't create results of the given
4554                // type or concurrency
4555                //
4556                PreparedStatement pStmt = null;
4557                
4558                boolean canServerPrepare = true;
4559                
4560                String nativeSql = getProcessEscapeCodesForPrepStmts() ? nativeSQL(sql): sql;
4561                
4562                if (getEmulateUnsupportedPstmts()) {
4563                        canServerPrepare = canHandleAsServerPreparedStatement(nativeSql);
4564                }
4565                
4566                if (this.useServerPreparedStmts && canServerPrepare) {
4567                        if (this.getCachePreparedStatements()) {
4568                                synchronized (this.serverSideStatementCache) {
4569                                        pStmt = (com.mysql.jdbc.ServerPreparedStatement)this.serverSideStatementCache.remove(sql);
4570                                        
4571                                        if (pStmt != null) {
4572                                                ((com.mysql.jdbc.ServerPreparedStatement)pStmt).setClosed(false);
4573                                                pStmt.clearParameters();
4574                                        }
4575 
4576                                        if (pStmt == null) {
4577                                                try {
4578                                                        pStmt = new com.mysql.jdbc.ServerPreparedStatement(this, nativeSql,
4579                                                                        this.database);
4580                                                        if (sql.length() < getPreparedStatementCacheSqlLimit()) {
4581                                                                ((com.mysql.jdbc.ServerPreparedStatement)pStmt).isCached = true;
4582                                                        }
4583                                                } catch (SQLException sqlEx) {
4584                                                        // Punt, if necessary
4585                                                        if (getEmulateUnsupportedPstmts()) {
4586                                                                pStmt = clientPrepareStatement(nativeSql);
4587                                                                
4588                                                                if (sql.length() < getPreparedStatementCacheSqlLimit()) {
4589                                                                        this.serverSideStatementCheckCache.put(sql, Boolean.FALSE);
4590                                                                }
4591                                                        } else {
4592                                                                throw sqlEx;
4593                                                        }
4594                                                }
4595                                        }
4596                                }
4597                        } else {
4598                                try {
4599                                        pStmt = new com.mysql.jdbc.ServerPreparedStatement(this, nativeSql,
4600                                                        this.database);
4601                                } catch (SQLException sqlEx) {
4602                                        // Punt, if necessary
4603                                        if (getEmulateUnsupportedPstmts()) {
4604                                                pStmt = clientPrepareStatement(nativeSql);
4605                                        } else {
4606                                                throw sqlEx;
4607                                        }
4608                                }
4609                        }
4610                } else {
4611                        pStmt = clientPrepareStatement(nativeSql);
4612                }
4613 
4614 
4615                pStmt.setResultSetType(resultSetType);
4616                pStmt.setResultSetConcurrency(resultSetConcurrency);
4617 
4618                return pStmt;
4619        }
4620 
4621        /**
4622         * @see Connection#prepareStatement(String, int, int, int)
4623         */
4624        public java.sql.PreparedStatement prepareStatement(String sql,
4625                        int resultSetType, int resultSetConcurrency,
4626                        int resultSetHoldability) throws SQLException {
4627                if (getPedantic()) {
4628                        if (resultSetHoldability != java.sql.ResultSet.HOLD_CURSORS_OVER_COMMIT) {
4629                                throw SQLError.createSQLException(
4630                                                "HOLD_CUSRORS_OVER_COMMIT is only supported holdability level",
4631                                                SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
4632                        }
4633                }
4634 
4635                return prepareStatement(sql, resultSetType, resultSetConcurrency);
4636        }
4637 
4638        /**
4639         * @see Connection#prepareStatement(String, int[])
4640         */
4641        public java.sql.PreparedStatement prepareStatement(String sql,
4642                        int[] autoGenKeyIndexes) throws SQLException {
4643                java.sql.PreparedStatement pStmt = prepareStatement(sql);
4644 
4645                ((com.mysql.jdbc.PreparedStatement) pStmt)
4646                                .setRetrieveGeneratedKeys((autoGenKeyIndexes != null)
4647                                                && (autoGenKeyIndexes.length > 0));
4648 
4649                return pStmt;
4650        }
4651 
4652        /**
4653         * @see Connection#prepareStatement(String, String[])
4654         */
4655        public java.sql.PreparedStatement prepareStatement(String sql,
4656                        String[] autoGenKeyColNames) throws SQLException {
4657                java.sql.PreparedStatement pStmt = prepareStatement(sql);
4658 
4659                ((com.mysql.jdbc.PreparedStatement) pStmt)
4660                                .setRetrieveGeneratedKeys((autoGenKeyColNames != null)
4661                                                && (autoGenKeyColNames.length > 0));
4662 
4663                return pStmt;
4664        }
4665 
4666        /**
4667         * Closes connection and frees resources.
4668         * 
4669         * @param calledExplicitly
4670         *            is this being called from close()
4671         * @param issueRollback
4672         *            should a rollback() be issued?
4673         * @throws SQLException
4674         *             if an error occurs
4675         */
4676        protected void realClose(boolean calledExplicitly, boolean issueRollback,
4677                        boolean skipLocalTeardown, Throwable reason) throws SQLException {
4678                SQLException sqlEx = null;
4679 
4680                if (this.isClosed()) {
4681                        return;
4682                }
4683                
4684                this.forceClosedReason = reason;
4685                
4686                try {
4687                        if (!skipLocalTeardown) {
4688                                if (!getAutoCommit() && issueRollback) {
4689                                        try {
4690                                                rollback();
4691                                        } catch (SQLException ex) {
4692                                                sqlEx = ex;
4693                                        }
4694                                }
4695 
4696                                reportMetrics();
4697 
4698                                if (getUseUsageAdvisor()) {
4699                                        if (!calledExplicitly) {
4700                                                String message = "Connection implicitly closed by Driver. You should call Connection.close() from your code to free resources more efficiently and avoid resource leaks.";
4701 
4702                                                this.eventSink.consumeEvent(new ProfilerEvent(
4703                                                                ProfilerEvent.TYPE_WARN, "", //$NON-NLS-1$
4704                                                                this.getCatalog(), this.getId(), -1, -1, System
4705                                                                                .currentTimeMillis(), 0, null,
4706                                                                this.pointOfOrigin, message));
4707                                        }
4708 
4709                                        long connectionLifeTime = System.currentTimeMillis()
4710                                                        - this.connectionCreationTimeMillis;
4711 
4712                                        if (connectionLifeTime < 500) {
4713                                                String message = "Connection lifetime of < .5 seconds. You might be un-necessarily creating short-lived connections and should investigate connection pooling to be more efficient.";
4714 
4715                                                this.eventSink.consumeEvent(new ProfilerEvent(
4716                                                                ProfilerEvent.TYPE_WARN, "", //$NON-NLS-1$
4717                                                                this.getCatalog(), this.getId(), -1, -1, System
4718                                                                                .currentTimeMillis(), 0, null,
4719                                                                this.pointOfOrigin, message));
4720                                        }
4721                                }
4722 
4723                                try {
4724                                        closeAllOpenStatements();
4725                                } catch (SQLException ex) {
4726                                        sqlEx = ex;
4727                                }
4728 
4729                                if (this.io != null) {
4730                                        try {
4731                                                this.io.quit();
4732                                        } catch (Exception e) {
4733                                                ;
4734                                        }
4735 
4736                                }
4737                        } else {
4738                                this.io.forceClose();
4739                        }
4740                } finally {
4741                        this.openStatements = null;
4742                        this.io = null;
4743                        ProfileEventSink.removeInstance(this);
4744                        this.isClosed = true;
4745                }
4746 
4747                if (sqlEx != null) {
4748                        throw sqlEx;
4749                }
4750 
4751        }
4752 
4753        protected void recachePreparedStatement(ServerPreparedStatement pstmt) {
4754                synchronized (this.serverSideStatementCache) {
4755                        this.serverSideStatementCache.put(pstmt.originalSql, pstmt);
4756                }
4757        }
4758 
4759        /**
4760         * DOCUMENT ME!
4761         * 
4762         * @param queryTimeMs
4763         */
4764        protected void registerQueryExecutionTime(long queryTimeMs) {
4765                if (queryTimeMs > this.longestQueryTimeMs) {
4766                        this.longestQueryTimeMs = queryTimeMs;
4767 
4768                        repartitionPerformanceHistogram();
4769                }
4770 
4771                addToPerformanceHistogram(queryTimeMs, 1);
4772 
4773                if (queryTimeMs < this.shortestQueryTimeMs) {
4774                        this.shortestQueryTimeMs = (queryTimeMs == 0) ? 1 : queryTimeMs;
4775                }
4776 
4777                this.numberOfQueriesIssued++;
4778 
4779                this.totalQueryTimeMs += queryTimeMs;
4780        }
4781 
4782        /**
4783         * Register a Statement instance as open.
4784         * 
4785         * @param stmt
4786         *            the Statement instance to remove
4787         */
4788        void registerStatement(Statement stmt) {
4789                synchronized (this.openStatements) {
4790                        this.openStatements.put(stmt, stmt);
4791                }
4792        }
4793 
4794        /**
4795         * @see Connection#releaseSavepoint(Savepoint)
4796         */
4797        public void releaseSavepoint(Savepoint arg0) throws SQLException {
4798                // this is a no-op
4799        }
4800 
4801        private void repartitionHistogram(int[] histCounts, long[] histBreakpoints,
4802                        long currentLowerBound, long currentUpperBound) {
4803 
4804                if (oldHistCounts == null) {
4805                        oldHistCounts = new int[histCounts.length];
4806                        oldHistBreakpoints = new long[histBreakpoints.length];
4807                }
4808 
4809                for (int i = 0; i < histCounts.length; i++) {
4810                        oldHistCounts[i] = histCounts[i];
4811                }
4812 
4813                for (int i = 0; i < oldHistBreakpoints.length; i++) {
4814                        oldHistBreakpoints[i] = histBreakpoints[i];
4815                }
4816 
4817                createInitialHistogram(histBreakpoints, currentLowerBound,
4818                                currentUpperBound);
4819 
4820                for (int i = 0; i < HISTOGRAM_BUCKETS; i++) {
4821                        addToHistogram(histCounts, histBreakpoints, oldHistBreakpoints[i],
4822                                        oldHistCounts[i], currentLowerBound, currentUpperBound);
4823                }
4824        }
4825 
4826        private void repartitionPerformanceHistogram() {
4827                checkAndCreatePerformanceHistogram();
4828 
4829                repartitionHistogram(this.perfMetricsHistCounts,
4830                                this.perfMetricsHistBreakpoints,
4831                                this.shortestQueryTimeMs == Long.MAX_VALUE ? 0
4832                                                : this.shortestQueryTimeMs, this.longestQueryTimeMs);
4833        }
4834 
4835        private void repartitionTablesAccessedHistogram() {
4836                checkAndCreateTablesAccessedHistogram();
4837 
4838                repartitionHistogram(this.numTablesMetricsHistCounts,
4839                                this.numTablesMetricsHistBreakpoints,
4840                                this.minimumNumberTablesAccessed == Long.MAX_VALUE ? 0
4841                                                : this.minimumNumberTablesAccessed,
4842                                this.maximumNumberTablesAccessed);
4843        }
4844 
4845        private void reportMetrics() {
4846                if (getGatherPerformanceMetrics()) {
4847                        StringBuffer logMessage = new StringBuffer(256);
4848 
4849                        logMessage.append("** Performance Metrics Report **\n");
4850                        logMessage.append("\nLongest reported query: "
4851                                        + this.longestQueryTimeMs + " ms");
4852                        logMessage.append("\nShortest reported query: "
4853                                        + this.shortestQueryTimeMs + " ms");
4854                        logMessage
4855                                        .append("\nAverage query execution time: "
4856                                                        + (this.totalQueryTimeMs / this.numberOfQueriesIssued)
4857                                                        + " ms");
4858                        logMessage.append("\nNumber of statements executed: "
4859                                        + this.numberOfQueriesIssued);
4860                        logMessage.append("\nNumber of result sets created: "
4861                                        + this.numberOfResultSetsCreated);
4862                        logMessage.append("\nNumber of statements prepared: "
4863                                        + this.numberOfPrepares);
4864                        logMessage.append("\nNumber of prepared statement executions: "
4865                                        + this.numberOfPreparedExecutes);
4866 
4867                        if (this.perfMetricsHistBreakpoints != null) {
4868                                logMessage.append("\n\n\tTiming Histogram:\n");
4869                                int maxNumPoints = 20;
4870                                int highestCount = Integer.MIN_VALUE;
4871 
4872                                for (int i = 0; i < (HISTOGRAM_BUCKETS); i++) {
4873                                        if (this.perfMetricsHistCounts[i] > highestCount) {
4874                                                highestCount = this.perfMetricsHistCounts[i];
4875                                        }
4876                                }
4877 
4878                                if (highestCount == 0) {
4879                                        highestCount = 1; // avoid DIV/0
4880                                }
4881 
4882                                for (int i = 0; i < (HISTOGRAM_BUCKETS - 1); i++) {
4883 
4884                                        if (i == 0) {
4885                                                logMessage.append("\n\tless than "
4886                                                                + this.perfMetricsHistBreakpoints[i + 1]
4887                                                                + " ms: \t" + this.perfMetricsHistCounts[i]);
4888                                        } else {
4889                                                logMessage.append("\n\tbetween "
4890                                                                + this.perfMetricsHistBreakpoints[i] + " and "
4891                                                                + this.perfMetricsHistBreakpoints[i + 1]
4892                                                                + " ms: \t" + this.perfMetricsHistCounts[i]);
4893                                        }
4894 
4895                                        logMessage.append("\t");
4896 
4897                                        int numPointsToGraph = (int) (maxNumPoints * ((double) this.perfMetricsHistCounts[i] / (double) highestCount));
4898 
4899                                        for (int j = 0; j < numPointsToGraph; j++) {
4900                                                logMessage.append("*");
4901                                        }
4902 
4903                                        if (this.longestQueryTimeMs < this.perfMetricsHistCounts[i + 1]) {
4904                                                break;
4905                                        }
4906                                }
4907 
4908                                if (this.perfMetricsHistBreakpoints[HISTOGRAM_BUCKETS - 2] < this.longestQueryTimeMs) {
4909                                        logMessage.append("\n\tbetween ");
4910                                        logMessage
4911                                                        .append(this.perfMetricsHistBreakpoints[HISTOGRAM_BUCKETS - 2]);
4912                                        logMessage.append(" and ");
4913                                        logMessage
4914                                                        .append(this.perfMetricsHistBreakpoints[HISTOGRAM_BUCKETS - 1]);
4915                                        logMessage.append(" ms: \t");
4916                                        logMessage
4917                                                        .append(this.perfMetricsHistCounts[HISTOGRAM_BUCKETS - 1]);
4918                                }
4919                        }
4920 
4921                        if (this.numTablesMetricsHistBreakpoints != null) {
4922                                logMessage.append("\n\n\tTable Join Histogram:\n");
4923                                int maxNumPoints = 20;
4924                                int highestCount = Integer.MIN_VALUE;
4925 
4926                                for (int i = 0; i < (HISTOGRAM_BUCKETS); i++) {
4927                                        if (this.numTablesMetricsHistCounts[i] > highestCount) {
4928                                                highestCount = this.numTablesMetricsHistCounts[i];
4929                                        }
4930                                }
4931 
4932                                if (highestCount == 0) {
4933                                        highestCount = 1; // avoid DIV/0
4934                                }
4935 
4936                                for (int i = 0; i < (HISTOGRAM_BUCKETS - 1); i++) {
4937 
4938                                        if (i == 0) {
4939                                                logMessage.append("\n\t"
4940                                                                + this.numTablesMetricsHistBreakpoints[i + 1]
4941                                                                + " tables or less: \t\t"
4942                                                                + this.numTablesMetricsHistCounts[i]);
4943                                        } else {
4944                                                logMessage.append("\n\tbetween "
4945                                                                + this.numTablesMetricsHistBreakpoints[i]
4946                                                                + " and "
4947                                                                + this.numTablesMetricsHistBreakpoints[i + 1]
4948                                                                + " tables: \t"
4949                                                                + this.numTablesMetricsHistCounts[i]);
4950                                        }
4951 
4952                                        logMessage.append("\t");
4953 
4954                                        int numPointsToGraph = (int) (maxNumPoints * ((double) this.numTablesMetricsHistCounts[i] / (double) highestCount));
4955 
4956                                        for (int j = 0; j < numPointsToGraph; j++) {
4957                                                logMessage.append("*");
4958                                        }
4959 
4960                                        if (this.maximumNumberTablesAccessed < this.numTablesMetricsHistBreakpoints[i + 1]) {
4961                                                break;
4962                                        }
4963                                }
4964 
4965                                if (this.numTablesMetricsHistBreakpoints[HISTOGRAM_BUCKETS - 2] < this.maximumNumberTablesAccessed) {
4966                                        logMessage.append("\n\tbetween ");
4967                                        logMessage
4968                                                        .append(this.numTablesMetricsHistBreakpoints[HISTOGRAM_BUCKETS - 2]);
4969                                        logMessage.append(" and ");
4970                                        logMessage
4971                                                        .append(this.numTablesMetricsHistBreakpoints[HISTOGRAM_BUCKETS - 1]);
4972                                        logMessage.append(" tables: ");
4973                                        logMessage
4974                                                        .append(this.numTablesMetricsHistCounts[HISTOGRAM_BUCKETS - 1]);
4975                                }
4976                        }
4977 
4978                        this.log.logInfo(logMessage);
4979 
4980                        this.metricsLastReportedMs = System.currentTimeMillis();
4981                }
4982        }
4983 
4984        /**
4985         * Reports currently collected metrics if this feature is enabled and the
4986         * timeout has passed.
4987         */
4988        private void reportMetricsIfNeeded() {
4989                if (getGatherPerformanceMetrics()) {
4990                        if ((System.currentTimeMillis() - this.metricsLastReportedMs) > getReportMetricsIntervalMillis()) {
4991                                reportMetrics();
4992                        }
4993                }
4994        }
4995 
4996        protected void reportNumberOfTablesAccessed(int numTablesAccessed) {
4997                if (numTablesAccessed < this.minimumNumberTablesAccessed) {
4998                        this.minimumNumberTablesAccessed = numTablesAccessed;
4999                }
5000 
5001                if (numTablesAccessed > this.maximumNumberTablesAccessed) {
5002                        this.maximumNumberTablesAccessed = numTablesAccessed;
5003 
5004                        repartitionTablesAccessedHistogram();
5005                }
5006 
5007                addToTablesAccessedHistogram(numTablesAccessed, 1);
5008        }
5009 
5010        /**
5011         * Resets the server-side state of this connection. Doesn't work for MySQL
5012         * versions older than 4.0.6 or if isParanoid() is set (it will become a
5013         * no-op in these cases). Usually only used from connection pooling code.
5014         * 
5015         * @throws SQLException
5016         *             if the operation fails while resetting server state.
5017         */
5018        public void resetServerState() throws SQLException {
5019                if (!getParanoid()
5020                                && ((this.io != null) & versionMeetsMinimum(4, 0, 6))) {
5021                        changeUser(this.user, this.password);
5022                }
5023        }
5024 
5025        /**
5026         * The method rollback() drops all changes made since the previous
5027         * commit/rollback and releases any database locks currently held by the
5028         * Connection.
5029         * 
5030         * @exception SQLException
5031         *                if a database access error occurs
5032         * @see commit
5033         */
5034        public void rollback() throws SQLException {
5035                synchronized (getMutex()) {
5036                        checkClosed();
5037        
5038                        try {
5039                                // no-op if _relaxAutoCommit == true
5040                                if (this.autoCommit && !getRelaxAutoCommit()) {
5041                                        throw SQLError.createSQLException(
5042                                                        "Can't call rollback when autocommit=true",
5043                                                        SQLError.SQL_STATE_CONNECTION_NOT_OPEN);
5044                                } else if (this.transactionsSupported) {
5045                                        try {
5046                                                rollbackNoChecks();
5047                                        } catch (SQLException sqlEx) {
5048                                                // We ignore non-transactional tables if told to do so
5049                                                if (getIgnoreNonTxTables()
5050                                                                && (sqlEx.getErrorCode() != SQLError.ER_WARNING_NOT_COMPLETE_ROLLBACK)) {
5051                                                        throw sqlEx;
5052                                                }
5053                                        }
5054                                }
5055                        } catch (SQLException sqlException) {
5056                                if (SQLError.SQL_STATE_COMMUNICATION_LINK_FAILURE
5057                                                .equals(sqlException.getSQLState())) {
5058                                        throw SQLError.createSQLException(
5059                                                        "Communications link failure during rollback(). Transaction resolution unknown.",
5060                                                        SQLError.SQL_STATE_TRANSACTION_RESOLUTION_UNKNOWN);
5061                                }
5062        
5063                                throw sqlException;
5064                        } finally {
5065                                this.needsPing = this.getReconnectAtTxEnd();
5066                        }
5067                }
5068        }
5069 
5070        /**
5071         * @see Connection#rollback(Savepoint)
5072         */
5073        public void rollback(Savepoint savepoint) throws SQLException {
5074 
5075                if (versionMeetsMinimum(4, 0, 14) || versionMeetsMinimum(4, 1, 1)) {
5076                        synchronized (getMutex()) {
5077                                checkClosed();
5078        
5079                                try {
5080                                        StringBuffer rollbackQuery = new StringBuffer(
5081                                                        "ROLLBACK TO SAVEPOINT ");
5082                                        rollbackQuery.append('`');
5083                                        rollbackQuery.append(savepoint.getSavepointName());
5084                                        rollbackQuery.append('`');
5085        
5086                                        java.sql.Statement stmt = null;
5087        
5088                                        try {
5089                                                stmt = createStatement();
5090        
5091                                                stmt.executeUpdate(rollbackQuery.toString());
5092                                        } catch (SQLException sqlEx) {
5093                                                int errno = sqlEx.getErrorCode();
5094        
5095                                                if (errno == 1181) {
5096                                                        String msg = sqlEx.getMessage();
5097        
5098                                                        if (msg != null) {
5099                                                                int indexOfError153 = msg.indexOf("153");
5100        
5101                                                                if (indexOfError153 != -1) {
5102                                                                        throw SQLError.createSQLException("Savepoint '"
5103                                                                                        + savepoint.getSavepointName()
5104                                                                                        + "' does not exist",
5105                                                                                        SQLError.SQL_STATE_ILLEGAL_ARGUMENT,
5106                                                                                        errno);
5107                                                                }
5108                                                        }
5109                                                }
5110        
5111                                                // We ignore non-transactional tables if told to do so
5112                                                if (getIgnoreNonTxTables()
5113                                                                && (sqlEx.getErrorCode() != SQLError.ER_WARNING_NOT_COMPLETE_ROLLBACK)) {
5114                                                        throw sqlEx;
5115                                                }
5116        
5117                                                if (SQLError.SQL_STATE_COMMUNICATION_LINK_FAILURE
5118                                                                .equals(sqlEx.getSQLState())) {
5119                                                        throw SQLError.createSQLException(
5120                                                                        "Communications link failure during rollback(). Transaction resolution unknown.",
5121                                                                        SQLError.SQL_STATE_TRANSACTION_RESOLUTION_UNKNOWN);
5122                                                }
5123        
5124                                                throw sqlEx;
5125                                        } finally {
5126                                                closeStatement(stmt);
5127                                        }
5128                                } finally {
5129                                        this.needsPing = this.getReconnectAtTxEnd();
5130                                }
5131                        }
5132                } else {
5133                        throw new NotImplemented();
5134                }
5135        }
5136 
5137        private void rollbackNoChecks() throws SQLException {
5138                execSQL(null, "rollback", -1, null,
5139                                java.sql.ResultSet.TYPE_FORWARD_ONLY,
5140                                java.sql.ResultSet.CONCUR_READ_ONLY, false,
5141                                this.database, true, false);
5142        }
5143 
5144        /**
5145         * DOCUMENT ME!
5146         * 
5147         * @param sql
5148         *            DOCUMENT ME!
5149         * @return DOCUMENT ME!
5150         * @throws SQLException
5151         *             DOCUMENT ME!
5152         */
5153        public ServerPreparedStatement serverPrepare(String sql)
5154                        throws SQLException {
5155                return new ServerPreparedStatement(this, sql, this.getCatalog());
5156        }
5157 
5158        protected boolean serverSupportsConvertFn() throws SQLException {
5159                return versionMeetsMinimum(4, 0, 2);
5160        }
5161 
5162        /**
5163         * If a connection is in auto-commit mode, than all its SQL statements will
5164         * be executed and committed as individual transactions. Otherwise, its SQL
5165         * statements are grouped into transactions that are terminated by either
5166         * commit() or rollback(). By default, new connections are in auto- commit
5167         * mode. The commit occurs when the statement completes or the next execute
5168         * occurs, whichever comes first. In the case of statements returning a
5169         * ResultSet, the statement completes when the last row of the ResultSet has
5170         * been retrieved or the ResultSet has been closed. In advanced cases, a
5171         * single statement may return multiple results as well as output parameter
5172         * values. Here the commit occurs when all results and output param values
5173         * have been retrieved.
5174         * <p>
5175         * <b>Note:</b> MySQL does not support transactions, so this method is a
5176         * no-op.
5177         * </p>
5178         * 
5179         * @param autoCommitFlag -
5180         *            true enables auto-commit; false disables it
5181         * @exception SQLException
5182         *                if a database access error occurs
5183         */
5184        public void setAutoCommit(boolean autoCommitFlag) throws SQLException {
5185                synchronized (getMutex()) {
5186                        checkClosed();
5187        
5188                        if (getAutoReconnectForPools()) {
5189                                setHighAvailability(true);
5190                        }
5191        
5192                        try {
5193                                if (this.transactionsSupported) {
5194        
5195                                        boolean needsSetOnServer = true;
5196        
5197                                        if (this.getUseLocalSessionState()
5198                                                        && this.autoCommit == autoCommitFlag) {
5199                                                needsSetOnServer = false;
5200                                        } else if (!this.getHighAvailability()) {
5201                                                needsSetOnServer = this.getIO()
5202                                                                .isSetNeededForAutoCommitMode(autoCommitFlag);
5203                                        }
5204        
5205                                        // this internal value must be set first as failover depends on
5206                                        // it
5207                                        // being set to true to fail over (which is done by most
5208                                        // app servers and connection pools at the end of
5209                                        // a transaction), and the driver issues an implicit set
5210                                        // based on this value when it (re)-connects to a server
5211                                        // so the value holds across connections
5212                                        this.autoCommit = autoCommitFlag;
5213        
5214                                        if (needsSetOnServer) {
5215                                                execSQL(null, autoCommitFlag ? "SET autocommit=1"
5216                                                                : "SET autocommit=0", -1, null,
5217                                                                java.sql.ResultSet.TYPE_FORWARD_ONLY,
5218                                                                java.sql.ResultSet.CONCUR_READ_ONLY, false,
5219                                                                this.database, true, false);
5220                                        }
5221        
5222                                } else {
5223                                        if ((autoCommitFlag == false) && !getRelaxAutoCommit()) {
5224                                                throw SQLError.createSQLException("MySQL Versions Older than 3.23.15 "
5225                                                                + "do not support transactions",
5226                                                                SQLError.SQL_STATE_CONNECTION_NOT_OPEN);
5227                                        }
5228        
5229                                        this.autoCommit = autoCommitFlag;
5230                                }
5231                        } finally {
5232                                if (this.getAutoReconnectForPools()) {
5233                                        setHighAvailability(false);
5234                                }
5235                        }
5236        
5237                        return;
5238                }
5239        }
5240 
5241        /**
5242         * A sub-space of this Connection's database may be selected by setting a
5243         * catalog name. If the driver does not support catalogs, it will silently
5244         * ignore this request
5245         * <p>
5246         * <b>Note:</b> MySQL's notion of catalogs are individual databases.
5247         * </p>
5248         * 
5249         * @param catalog
5250         *            the database for this connection to use
5251         * @throws SQLException
5252         *             if a database access error occurs
5253         */
5254        public void setCatalog(String catalog) throws SQLException {
5255                synchronized (getMutex()) {
5256                        checkClosed();
5257        
5258                        if (catalog == null) {
5259                                throw SQLError.createSQLException("Catalog can not be null",
5260                                                SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
5261                        }
5262                        
5263                        if (getUseLocalSessionState()) {
5264                                if (this.lowerCaseTableNames) {
5265                                        if (this.database.equalsIgnoreCase(catalog)) {
5266                                                return;
5267                                        }
5268                                } else {
5269                                        if (this.database.equals(catalog)) {
5270                                                return;
5271                                        }
5272                                }
5273                        }
5274                        
5275                        String quotedId = this.dbmd.getIdentifierQuoteString();
5276        
5277                        if ((quotedId == null) || quotedId.equals(" ")) {
5278                                quotedId = "";
5279                        }
5280        
5281                        StringBuffer query = new StringBuffer("USE ");
5282                        query.append(quotedId);
5283                        query.append(catalog);
5284                        query.append(quotedId);
5285        
5286                        execSQL(null, query.toString(), -1, null,
5287                                        java.sql.ResultSet.TYPE_FORWARD_ONLY,
5288                                        java.sql.ResultSet.CONCUR_READ_ONLY, false,
5289                                        this.database, true, false);
5290                        
5291                        this.database = catalog;
5292                }
5293        }
5294 
5295        /**
5296         * @param failedOver
5297         *            The failedOver to set.
5298         */
5299        public synchronized void setFailedOver(boolean flag) {
5300                this.failedOver = flag;
5301        }
5302 
5303        /**
5304         * Sets state for a failed-over connection
5305         * 
5306         * @throws SQLException
5307         *             DOCUMENT ME!
5308         */
5309        private void setFailedOverState() throws SQLException {
5310                if (getFailOverReadOnly()) {
5311                        setReadOnly(true);
5312                }
5313 
5314                this.queriesIssuedFailedOver = 0;
5315                this.failedOver = true;
5316                this.masterFailTimeMillis = System.currentTimeMillis();
5317        }
5318 
5319        /**
5320         * @see Connection#setHoldability(int)
5321         */
5322        public void setHoldability(int arg0) throws SQLException {
5323                // do nothing
5324        }
5325 
5326        public void setInGlobalTx(boolean flag) {
5327                this.isInGlobalTx = flag;
5328        }
5329 
5330        // exposed for testing
5331        /**
5332         * @param preferSlaveDuringFailover
5333         *            The preferSlaveDuringFailover to set.
5334         */
5335        public void setPreferSlaveDuringFailover(boolean flag) {
5336                this.preferSlaveDuringFailover = flag;
5337        }
5338 
5339        void setReadInfoMsgEnabled(boolean flag) {
5340                this.readInfoMsg = flag;
5341        }
5342 
5343        /**
5344         * You can put a connection in read-only mode as a hint to enable database
5345         * optimizations <B>Note:</B> setReadOnly cannot be called while in the
5346         * middle of a transaction
5347         * 
5348         * @param readOnlyFlag -
5349         *            true enables read-only mode; false disables it
5350         * @exception SQLException
5351         *                if a database access error occurs
5352         */
5353        public void setReadOnly(boolean readOnlyFlag) throws SQLException {
5354                checkClosed();
5355                this.readOnly = readOnlyFlag;
5356        }
5357 
5358        /**
5359         * @see Connection#setSavepoint()
5360         */
5361        public java.sql.Savepoint setSavepoint() throws SQLException {
5362                MysqlSavepoint savepoint = new MysqlSavepoint();
5363 
5364                setSavepoint(savepoint);
5365 
5366                return savepoint;
5367        }
5368 
5369        private void setSavepoint(MysqlSavepoint savepoint) throws SQLException {
5370 
5371                if (versionMeetsMinimum(4, 0, 14) || versionMeetsMinimum(4, 1, 1)) {
5372                        synchronized (getMutex()) {
5373                                checkClosed();
5374        
5375                                StringBuffer savePointQuery = new StringBuffer("SAVEPOINT ");
5376                                savePointQuery.append('`');
5377                                savePointQuery.append(savepoint.getSavepointName());
5378                                savePointQuery.append('`');
5379        
5380                                java.sql.Statement stmt = null;
5381        
5382                                try {
5383                                        stmt = createStatement();
5384        
5385                                        stmt.executeUpdate(savePointQuery.toString());
5386                                } finally {
5387                                        closeStatement(stmt);
5388                                }
5389                        }
5390                } else {
5391                        throw new NotImplemented();
5392                }
5393        }
5394 
5395        /**
5396         * @see Connection#setSavepoint(String)
5397         */
5398        public synchronized java.sql.Savepoint setSavepoint(String name) throws SQLException {
5399                MysqlSavepoint savepoint = new MysqlSavepoint(name);
5400 
5401                setSavepoint(savepoint);
5402 
5403                return savepoint;
5404        }
5405 
5406        /**
5407         * 
5408         */
5409        private void setSessionVariables() throws SQLException {
5410                if (this.versionMeetsMinimum(4, 0, 0) && getSessionVariables() != null) {
5411                        List variablesToSet = StringUtils.split(getSessionVariables(), ",", "\"'", "\"'",
5412                                        false);
5413 
5414                        int numVariablesToSet = variablesToSet.size();
5415 
5416                        java.sql.Statement stmt = null;
5417 
5418                        try {
5419                                stmt = getMetadataSafeStatement();
5420 
5421                                for (int i = 0; i < numVariablesToSet; i++) {
5422                                        String variableValuePair = (String) variablesToSet.get(i);
5423 
5424                                        if (variableValuePair.startsWith("@")) {
5425                                                stmt.executeUpdate("SET " + variableValuePair);
5426                                        } else {
5427                                                stmt.executeUpdate("SET SESSION " + variableValuePair);
5428                                        }
5429                                }
5430                        } finally {
5431                                if (stmt != null) {
5432                                        stmt.close();
5433                                }
5434                        }
5435                }
5436 
5437        }
5438 
5439        /**
5440         * DOCUMENT ME!
5441         * 
5442         * @param level
5443         *            DOCUMENT ME!
5444         * @throws SQLException
5445         *             DOCUMENT ME!
5446         */
5447        public synchronized void setTransactionIsolation(int level) throws SQLException {
5448                checkClosed();
5449 
5450                if (this.hasIsolationLevels) {
5451                        String sql = null;
5452 
5453                        boolean shouldSendSet = false;
5454 
5455                        if (getAlwaysSendSetIsolation()) {
5456                                shouldSendSet = true;
5457                        } else {
5458                                if (level != this.isolationLevel) {
5459                                        shouldSendSet = true;
5460                                }
5461                        }
5462 
5463                        if (getUseLocalSessionState()) {
5464                                shouldSendSet = this.isolationLevel != level;
5465                        }
5466 
5467                        if (shouldSendSet) {
5468                                switch (level) {
5469                                case java.sql.Connection.TRANSACTION_NONE:
5470                                        throw SQLError.createSQLException("Transaction isolation level "
5471                                                        + "NONE not supported by MySQL");
5472 
5473                                case java.sql.Connection.TRANSACTION_READ_COMMITTED:
5474                                        sql = "SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED";
5475 
5476                                        break;
5477 
5478                                case java.sql.Connection.TRANSACTION_READ_UNCOMMITTED:
5479                                        sql = "SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED";
5480 
5481                                        break;
5482 
5483                                case java.sql.Connection.TRANSACTION_REPEATABLE_READ:
5484                                        sql = "SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ";
5485 
5486                                        break;
5487 
5488                                case java.sql.Connection.TRANSACTION_SERIALIZABLE:
5489                                        sql = "SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE";
5490 
5491                                        break;
5492 
5493                                default:
5494                                        throw SQLError.createSQLException("Unsupported transaction "
5495                                                        + "isolation level '" + level + "'",
5496                                                        SQLError.SQL_STATE_DRIVER_NOT_CAPABLE);
5497                                }
5498 
5499                                execSQL(null, sql, -1, null,
5500                                                java.sql.ResultSet.TYPE_FORWARD_ONLY,
5501                                                java.sql.ResultSet.CONCUR_READ_ONLY,false,
5502                                                this.database, true, false);
5503 
5504                                this.isolationLevel = level;
5505                        }
5506                } else {
5507                        throw SQLError.createSQLException("Transaction Isolation Levels are "
5508                                        + "not supported on MySQL versions older than 3.23.36.",
5509                                        SQLError.SQL_STATE_DRIVER_NOT_CAPABLE);
5510                }
5511        }
5512        
5513        /**
5514         * JDBC 2.0 Install a type-map object as the default type-map for this
5515         * connection
5516         * 
5517         * @param map
5518         *            the type mapping
5519         * @throws SQLException
5520         *             if a database error occurs.
5521         */
5522        public synchronized void setTypeMap(java.util.Map map) throws SQLException {
5523                this.typeMap = map;
5524        }
5525        
5526        /**
5527         * Should we try to connect back to the master? We try when we've been
5528         * failed over >= this.secondsBeforeRetryMaster _or_ we've issued >
5529         * this.queriesIssuedFailedOver
5530         * 
5531         * @return DOCUMENT ME!
5532         */
5533        private boolean shouldFallBack() {
5534                long secondsSinceFailedOver = (System.currentTimeMillis() - this.masterFailTimeMillis) / 1000;
5535 
5536                // Done this way so we can set a condition in the debugger
5537                boolean tryFallback = ((secondsSinceFailedOver >= getSecondsBeforeRetryMaster()) || (this.queriesIssuedFailedOver >= getQueriesBeforeRetryMaster()));
5538 
5539                return tryFallback;
5540        }
5541        
5542        /**
5543         * Used by MiniAdmin to shutdown a MySQL server
5544         * 
5545         * @throws SQLException
5546         *             if the command can not be issued.
5547         */
5548        public void shutdownServer() throws SQLException {
5549                try {
5550                        this.io.sendCommand(MysqlDefs.SHUTDOWN, null, null, false, null);
5551                } catch (Exception ex) {
5552                        throw SQLError.createSQLException("Unhandled exception '" + ex.toString()
5553                                        + "'", SQLError.SQL_STATE_GENERAL_ERROR);
5554                }
5555        }
5556        
5557        /**
5558         * DOCUMENT ME!
5559         * 
5560         * @return DOCUMENT ME!
5561         */
5562        public boolean supportsIsolationLevel() {
5563                return this.hasIsolationLevels;
5564        }
5565        
5566        /**
5567         * DOCUMENT ME!
5568         * 
5569         * @return DOCUMENT ME!
5570         */
5571        public boolean supportsQuotedIdentifiers() {
5572                return this.hasQuotedIdentifiers;
5573        }
5574        
5575        /**
5576         * DOCUMENT ME!
5577         * 
5578         * @return DOCUMENT ME!
5579         */
5580        public boolean supportsTransactions() {
5581                return this.transactionsSupported;
5582        }
5583        
5584        /**
5585         * Remove the given statement from the list of open statements
5586         * 
5587         * @param stmt
5588         *            the Statement instance to remove
5589         */
5590        void unregisterStatement(Statement stmt) {
5591                if (this.openStatements != null) {
5592                        synchronized (this.openStatements) {
5593                                this.openStatements.remove(stmt);
5594                        }
5595                }
5596        }
5597 
5598        /**
5599         * Called by statements on their .close() to let the connection know when it
5600         * is safe to set the connection back to 'default' row limits.
5601         * 
5602         * @param stmt
5603         *            the statement releasing it's max-rows requirement
5604         * @throws SQLException
5605         *             if a database error occurs issuing the statement that sets
5606         *             the limit default.
5607         */
5608        void unsetMaxRows(Statement stmt) throws SQLException {
5609                synchronized (this.mutex) {
5610                        if (this.statementsUsingMaxRows != null) {
5611                                Object found = this.statementsUsingMaxRows.remove(stmt);
5612 
5613                                if ((found != null)
5614                                                && (this.statementsUsingMaxRows.size() == 0)) {
5615                                        execSQL(null, "SET OPTION SQL_SELECT_LIMIT=DEFAULT", -1,
5616                                                        null, java.sql.ResultSet.TYPE_FORWARD_ONLY,
5617                                                        java.sql.ResultSet.CONCUR_READ_ONLY, false, 
5618                                                        this.database, true, false);
5619 
5620                                        this.maxRowsChanged = false;
5621                                }
5622                        }
5623                }
5624        }
5625        
5626        boolean useAnsiQuotedIdentifiers() {
5627                return this.useAnsiQuotes;
5628        }
5629 
5630        /**
5631         * Has maxRows() been set?
5632         * 
5633         * @return DOCUMENT ME!
5634         */
5635        boolean useMaxRows() {
5636                synchronized (this.mutex) {
5637                        return this.maxRowsChanged;
5638                }
5639        }
5640 
5641        public boolean versionMeetsMinimum(int major, int minor, int subminor)
5642                        throws SQLException {
5643                checkClosed();
5644 
5645                return this.io.versionMeetsMinimum(major, minor, subminor);
5646        }
5647 
5648        protected String getErrorMessageEncoding() {
5649                return errorMessageEncoding;
5650        }
5651        
5652        /*
5653         * For testing failover scenarios
5654         */
5655        private boolean hasTriedMasterFlag = false;
5656        
5657        public void clearHasTriedMaster() {
5658                this.hasTriedMasterFlag = false;
5659        }
5660        
5661        public boolean hasTriedMaster() {
5662                return this.hasTriedMasterFlag;
5663        }
5664}

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