EMMA Coverage Report (generated Fri May 26 15:35:26 CDT 2006)
[all classes][com.mysql.jdbc]

COVERAGE SUMMARY FOR SOURCE FILE [Connection.java]

nameclass, %method, %block, %line, %
Connection.java75%  (3/4)42%  (127/299)67%  (4796/7158)68%  (1141.3/1672)

COVERAGE BREAKDOWN BY CLASS AND METHOD

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

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