/* Copyright (C) 2002 MySQL AB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.mysql.jdbc; import java.io.IOException; import java.io.InputStream; import java.io.Reader; import java.io.UnsupportedEncodingException; import java.math.BigDecimal; import java.net.URL; import java.sql.Clob; import java.sql.Date; import java.sql.ParameterMetaData; import java.sql.Ref; import java.sql.SQLException; import java.sql.Savepoint; import java.sql.Time; import java.sql.Timestamp; import java.util.ArrayList; import java.util.Calendar; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.TimeZone; /** * A Connection represents a session with a specific database. Within the * context of a Connection, SQL statements are executed and results are * returned. * * <P> * A Connection's database is able to provide information describing its * tables, its supported SQL grammar, its stored procedures, the capabilities * of this connection, etc. This information is obtained with the getMetaData * method. * </p> * * @author Mark Matthews * @version $Id: Connection.java,v 1.31.2.49 2004/01/13 21:56:18 mmatthew Exp $ * * @see java.sql.Connection */ public class Connection implements java.sql.Connection { // The command used to "ping" the database. // Newer versions of MySQL server have a ping() command, // but this works for everything private static final String PING_COMMAND = "SELECT 1"; /** * Map mysql transaction isolation level name to * java.sql.Connection.TRANSACTION_XXX */ private static Map mapTransIsolationName2Value = null; /** * The mapping between MySQL charset names and Java charset names. * Initialized by loadCharacterSetMapping() */ private static Map charsetMap; /** Table of multi-byte charsets. Initialized by loadCharacterSetMapping() */ private static Map multibyteCharsetsMap; /** Default socket factory classname */ private static final String DEFAULT_SOCKET_FACTORY = StandardSocketFactory.class .getName(); static { loadCharacterSetMapping(); mapTransIsolationName2Value = new HashMap(8); mapTransIsolationName2Value.put("READ-UNCOMMITED", new Integer(TRANSACTION_READ_UNCOMMITTED)); mapTransIsolationName2Value.put("READ-UNCOMMITTED", new Integer(TRANSACTION_READ_UNCOMMITTED)); mapTransIsolationName2Value.put("READ-COMMITTED", new Integer(TRANSACTION_READ_COMMITTED)); mapTransIsolationName2Value.put("REPEATABLE-READ", new Integer(TRANSACTION_REPEATABLE_READ)); mapTransIsolationName2Value.put("SERIALIZABLE", new Integer(TRANSACTION_SERIALIZABLE)); } /** * Marker for character set converter not being available (not written, * multibyte, etc) Used to prevent multiple instantiation requests. */ private final static Object CHARSET_CONVERTER_NOT_AVAILABLE_MARKER = new Object(); /** Internal DBMD to use for various database-version specific features */ private DatabaseMetaData dbmd = null; /** The list of host(s) to try and connect to */ private List hostList = null; /** A map of SQL to parsed prepared statement parameters. */ private Map cachedPreparedStatementParams; /** * Holds cached mappings to charset converters to avoid static * synchronization and at the same time save memory (each charset * converter takes approx 65K of static data). */ private Map charsetConverterMap = new HashMap(CharsetMapping.JAVA_TO_MYSQL_CHARSET_MAP .size()); /** A map of statements that have had setMaxRows() called on them */ private Map statementsUsingMaxRows; /** * The type map for UDTs (not implemented, but used by some third-party * vendors, most notably IBM WebSphere) */ private Map typeMap; /** The I/O abstraction interface (network conn to MySQL server */ private MysqlIO io = null; /** Mutex */ private final Object mutex = new Object(); /** The map of server variables that we retrieve at connection init. */ private Map serverVariables = null; /** The driver instance that created us */ private NonRegisteringDriver myDriver; /** Properties for this connection specified by user */ private Properties props = null; /** The database we're currently using (called Catalog in JDBC terms). */ private String database = null; /** If we're doing unicode character conversions, what encoding do we use? */ private String encoding = null; /** What does MySQL call this encoding? */ private String mysqlEncodingName = null; /** The hostname we're connected to */ private String host = null; /** The JDBC URL we're using */ private String myURL = null; private String negativeInfinityRep = MysqlDefs.MIN_DOUBLE_VAL_STRING; private String notANumberRep = MysqlDefs.NAN_VAL_STRING; /** The password we used */ private String password = null; private String positiveInfinityRep = MysqlDefs.MAX_DOUBLE_VAL_STRING; /** Classname for socket factory */ private String socketFactoryClassName = null; /** The user we're connected as */ private String user = null; /** Where was the connection _explicitly_ closed by the application? */ private Throwable explicitCloseLocation; /** If the connection was forced closed, why was it forced closed? */ private Throwable forcedCloseReason; /** The timezone of the server */ private TimeZone serverTimezone = null; /** Allow LOAD LOCAL INFILE (defaults to true) */ private boolean allowLoadLocalInfile = true; /** Should we clear the input stream each query? */ private boolean alwaysClearStream = false; /** Are we in autoCommit mode? */ private boolean autoCommit = true; /** SHould we cache the parsing of prepared statements? */ private boolean cachePreparedStatements = false; /** Should we capitalize mysql types */ private boolean capitalizeDBMDTypes = false; /** Should we clobber streaming results on new queries, or issue an error? */ private boolean clobberStreamingResults = false; /** * Should we continue processing batch commands if one fails. The JDBC spec * allows either way, so we let the user choose */ private boolean continueBatchOnError = true; /** Should we do unicode character conversions? */ private boolean doUnicode = false; /** Are we failed-over to a non-master host */ private boolean failedOver = false; /** Does the server suuport isolation levels? */ private boolean hasIsolationLevels = false; /** Does this version of MySQL support quoted identifiers? */ private boolean hasQuotedIdentifiers = false; // // This is for the high availability :) routines // private boolean highAvailability = false; /** Ignore non-transactional table warning for rollback? */ private boolean ignoreNonTxTables = false; /** Has this connection been closed? */ private boolean isClosed = true; /** Should we tell MySQL that we're an interactive client? */ private boolean isInteractiveClient = false; /** Is the server configured to use lower-case table names only? */ private boolean lowerCaseTableNames = false; /** Has the max-rows setting been changed from the default? */ private boolean maxRowsChanged = false; private boolean negativeInfinityRepIsClipped = true; private boolean notANumberRepIsClipped = true; /** Do we expose sensitive information in exception and error messages? */ private boolean paranoid = false; /** Should we do 'extra' sanity checks? */ private boolean pedantic = false; private boolean positiveInfinityRepIsClipped = true; /** Should we retrieve 'info' messages from the server? */ private boolean readInfoMsg = false; /** Are we in read-only mode? */ private boolean readOnly = false; /** * If autoReconnect == true, should we attempt to reconnect at transaction * boundaries? */ private boolean reconnectAtTxEnd = false; /** Do we relax the autoCommit semantics? (For enhydra, for example) */ private boolean relaxAutoCommit = false; /** Do we need to correct endpoint rounding errors */ private boolean strictFloatingPoint = false; /** Do we check all keys for updatable result sets? */ private boolean strictUpdates = true; /** Are transactions supported by the MySQL server we are connected to? */ private boolean transactionsSupported = false; /** Has ANSI_QUOTES been enabled on the server? */ private boolean useAnsiQuotes = false; /** Should we use compression? */ private boolean useCompression = false; /** Can we use the "ping" command rather than a query? */ private boolean useFastPing = false; /** Should we tack on hostname in DBMD.getTable/ColumnPrivileges()? */ private boolean useHostsInPrivileges = true; /** Should we use SSL? */ private boolean useSSL = false; /** * Should we use stream lengths in prepared statements? (true by default == * JDBC compliant) */ private boolean useStreamLengthsInPrepStmts = true; /** Should we use timezone information? */ private boolean useTimezone = false; /** Should we return PreparedStatements for UltraDev's stupid bug? */ private boolean useUltraDevWorkAround = false; private double initialTimeout = 2.0D; /** How many hosts are in the host list? */ private int hostListSize = 0; /** isolation level */ private int isolationLevel = java.sql.Connection.TRANSACTION_READ_COMMITTED; /** * The largest packet we can send (changed once we know what the server * supports, we get this at connection init). */ private int maxAllowedPacket = 65536; private int maxReconnects = 3; /** * The max rows that a result set can contain. Defaults to -1, which * according to the JDBC spec means "all". */ private int maxRows = -1; private int netBufferLength = 16384; /** The port number we're connected to (defaults to 3306) */ private int port = 3306; /** * If prepared statement caching is enabled, what should the threshold * length of the SQL to prepare should be in order to _not_ cache? */ private int preparedStatementCacheMaxSqlSize = 256; /** If prepared statement caching is enabled, how many should we cache? */ private int preparedStatementCacheSize = 25; /** * How many queries should we wait before we try to re-connect to the * master, when we are failing over to replicated hosts Defaults to 50 */ private int queriesBeforeRetryMaster = 50; /** What should we set the socket timeout to? */ private int socketTimeout = 0; // infinite /** When did the last query finish? */ private long lastQueryFinishedTime = 0; /** When did the master fail? */ private long masterFailTimeMillis = 0L; /** Number of queries we've issued since the master failed */ private long queriesIssuedFailedOver = 0; /** * How many seconds should we wait before retrying to connect to the master * if failed over? We fall back when either queriesBeforeRetryMaster or * secondsBeforeRetryMaster is reached. */ private long secondsBeforeRetryMaster = 30L; /** * Creates a connection to a MySQL Server. * * @param host the hostname of the database server * @param port the port number the server is listening on * @param info a Properties[] list holding the user and password * @param database the database to connect to * @param url the URL of the connection * @param d the Driver instantation of the connection * * @exception java.sql.SQLException if a database access error occurs * @throws SQLException DOCUMENT ME! */ Connection(String host, int port, Properties info, String database, String url, NonRegisteringDriver d) throws java.sql.SQLException { if (Driver.TRACE) { Object[] args = { host, new Integer(port), info, database, url, d }; Debug.methodCall(this, "constructor", args); } this.serverVariables = new HashMap(); if (host == null) { this.host = "localhost"; hostList = new ArrayList(); hostList.add(this.host); } else if (host.indexOf(",") != -1) { // multiple hosts separated by commas (failover) hostList = StringUtils.split(host, ",", true); } else { this.host = host; hostList = new ArrayList(); hostList.add(this.host); } hostListSize = hostList.size(); this.port = port; if (database == null) { throw new SQLException("Malformed URL '" + url + "'.", SQLError.SQL_STATE_GENERAL_ERROR); } this.database = database; this.myURL = url; this.myDriver = d; this.user = info.getProperty("user"); this.password = info.getProperty("password"); if ((this.user == null) || this.user.equals("")) { this.user = "nobody"; } if (this.password == null) { this.password = ""; } this.props = info; initializeDriverProperties(info); if (Driver.DEBUG) { System.out.println("Connect: " + this.user + " to " + this.database); } try { createNewIO(false); this.dbmd = new DatabaseMetaData(this, this.database); } catch (java.sql.SQLException ex) { cleanup(ex); // don't clobber SQL exceptions throw ex; } catch (Exception ex) { cleanup(ex); StringBuffer mesg = new StringBuffer(); if (!useParanoidErrorMessages()) { mesg.append("Cannot connect to MySQL server on "); mesg.append(this.host); mesg.append(":"); mesg.append(this.port); mesg.append(".\n\n"); mesg.append("Make sure that there is a MySQL server "); mesg.append("running on the machine/port you are trying "); mesg.append( "to connect to and that the machine this software is " + "running on "); mesg.append("is able to connect to this host/port " + "(i.e. not firewalled). "); mesg.append( "Also make sure that the server has not been started " + "with the --skip-networking "); mesg.append("flag.\n\n"); } else { mesg.append("Unable to connect to database."); } mesg.append("Underlying exception: \n\n"); mesg.append(ex.getClass().getName()); throw new java.sql.SQLException(mesg.toString(), SQLError.SQL_STATE_COMMUNICATION_LINK_FAILURE); } } /** * If a connection is in auto-commit mode, than all its SQL statements will * be executed and committed as individual transactions. Otherwise, its * SQL statements are grouped into transactions that are terminated by * either commit() or rollback(). By default, new connections are in * auto- commit mode. The commit occurs when the statement completes or * the next execute occurs, whichever comes first. In the case of * statements returning a ResultSet, the statement completes when the last * row of the ResultSet has been retrieved or the ResultSet has been * closed. In advanced cases, a single statement may return multiple * results as well as output parameter values. Here the commit occurs * when all results and output param values have been retrieved. * * <p> * <b>Note:</b> MySQL does not support transactions, so this method is a * no-op. * </p> * * @param autoCommit - true enables auto-commit; false disables it * * @exception java.sql.SQLException if a database access error occurs * @throws SQLException DOCUMENT ME! */ public void setAutoCommit(boolean autoCommit) throws java.sql.SQLException { if (Driver.TRACE) { Object[] args = { new Boolean(autoCommit) }; Debug.methodCall(this, "setAutoCommit", args); } checkClosed(); if (this.transactionsSupported) { // this internal value must be set first as failover depends on it // being set to true to fail over (which is done by most // app servers and connection pools at the end of // a transaction), and the driver issues an implicit set // based on this value when it (re)-connects to a server // so the value holds across connections // this.autoCommit = autoCommit; // // This is to catch the 'edge' case of // autoCommit going from true -> false // if ((this.highAvailability || this.failedOver) && !this.autoCommit) { pingAndReconnect(true); } String sql = "SET autocommit=" + (autoCommit ? "1" : "0"); execSQL(sql, -1, this.database); } else { if ((autoCommit == false) && (this.relaxAutoCommit == false)) { throw new SQLException("MySQL Versions Older than 3.23.15 " + "do not support transactions", SQLError.SQL_STATE_DRIVER_NOT_CAPABLE); } else { this.autoCommit = autoCommit; } } return; } /** * gets the current auto-commit state * * @return Current state of the auto-commit mode * * @exception java.sql.SQLException (why?) * * @see setAutoCommit */ public boolean getAutoCommit() throws java.sql.SQLException { if (Driver.TRACE) { Object[] args = new Object[0]; Debug.methodCall(this, "getAutoCommit", args); Debug.returnValue(this, "getAutoCommit", new Boolean(this.autoCommit)); } return this.autoCommit; } /** * A sub-space of this Connection's database may be selected by setting a * catalog name. If the driver does not support catalogs, it will * silently ignore this request * * <p> * <b>Note:</b> MySQL's notion of catalogs are individual databases. * </p> * * @param catalog the database for this connection to use * * @throws java.sql.SQLException if a database access error occurs */ public void setCatalog(String catalog) throws java.sql.SQLException { if (Driver.TRACE) { Object[] args = { catalog }; Debug.methodCall(this, "setCatalog", args); } checkClosed(); String quotedId = this.dbmd.getIdentifierQuoteString(); if ((quotedId == null) || quotedId.equals(" ")) { quotedId = ""; } StringBuffer query = new StringBuffer("USE "); query.append(quotedId); query.append(catalog); query.append(quotedId); execSQL(query.toString(), -1, catalog); this.database = catalog; } /** * Return the connections current catalog name, or null if no catalog name * is set, or we dont support catalogs. * * <p> * <b>Note:</b> MySQL's notion of catalogs are individual databases. * </p> * * @return the current catalog name or null * * @exception java.sql.SQLException if a database access error occurs */ public String getCatalog() throws java.sql.SQLException { if (Driver.TRACE) { Object[] args = new Object[0]; Debug.methodCall(this, "getCatalog", args); Debug.returnValue(this, "getCatalog", this.database); } return this.database; } /** * Returns whether we clobber streaming results on new queries, or issue an * error? * * @return true if we should implicitly close streaming result sets upon * receiving a new query */ public boolean getClobberStreamingResults() { return this.clobberStreamingResults; } /** * DOCUMENT ME! * * @return DOCUMENT ME! */ public boolean isClosed() { if (Driver.TRACE) { Object[] args = new Object[0]; Debug.methodCall(this, "isClosed", args); Debug.returnValue(this, "isClosed", new Boolean(this.isClosed)); } return this.isClosed; } /** * Returns the character encoding for this Connection * * @return the character encoding for this connection. */ public String getEncoding() { return this.encoding; } /** * @see Connection#setHoldability(int) */ public void setHoldability(int arg0) throws SQLException { // do nothing } /** * @see Connection#getHoldability() */ public int getHoldability() throws SQLException { return ResultSet.CLOSE_CURSORS_AT_COMMIT; } /** * NOT JDBC-Compliant, but clients can use this method to determine how * long this connection has been idle. This time (reported in * milliseconds) is updated once a query has completed. * * @return number of ms that this connection has been idle, 0 if the driver * is busy retrieving results. */ public long getIdleFor() { if (this.lastQueryFinishedTime == 0) { return 0; } else { long now = System.currentTimeMillis(); long idleTime = now - this.lastQueryFinishedTime; return idleTime; } } /** * Should we tell MySQL that we're an interactive client * * @return true if isInteractiveClient was set to true. */ public boolean isInteractiveClient() { return isInteractiveClient; } /** * A connection's database is able to provide information describing its * tables, its supported SQL grammar, its stored procedures, the * capabilities of this connection, etc. This information is made * available through a DatabaseMetaData object. * * @return a DatabaseMetaData object for this connection * * @exception java.sql.SQLException if a database access error occurs */ public java.sql.DatabaseMetaData getMetaData() throws java.sql.SQLException { checkClosed(); return new DatabaseMetaData(this, this.database); } /** * DOCUMENT ME! * * @return */ public String getNegativeInfinityRep() { return negativeInfinityRep; } /** * DOCUMENT ME! * * @return */ public boolean isNegativeInfinityRepIsClipped() { return negativeInfinityRepIsClipped; } /** * DOCUMENT ME! * * @return */ public String getNotANumberRep() { return notANumberRep; } /** * DOCUMENT ME! * * @return */ public boolean isNotANumberRepIsClipped() { return notANumberRepIsClipped; } /** * DOCUMENT ME! * * @return */ public String getPositiveInfinityRep() { return positiveInfinityRep; } /** * DOCUMENT ME! * * @return */ public boolean isPositiveInfinityRepIsClipped() { return positiveInfinityRepIsClipped; } /** * Should the driver do profiling? * * @param flag set to true to enable profiling. * * @throws SQLException if the connection is closed. */ public void setProfileSql(boolean flag) throws SQLException { // For re-connection this.props.setProperty("profileSql", String.valueOf(flag)); getIO().setProfileSql(flag); } /** * You can put a connection in read-only mode as a hint to enable database * optimizations <B>Note:</B> setReadOnly cannot be called while in the * middle of a transaction * * @param readOnly - true enables read-only mode; false disables it * * @exception java.sql.SQLException if a database access error occurs */ public void setReadOnly(boolean readOnly) throws java.sql.SQLException { if (Driver.TRACE) { Object[] args = { new Boolean(readOnly) }; Debug.methodCall(this, "setReadOnly", args); Debug.returnValue(this, "setReadOnly", new Boolean(readOnly)); } checkClosed(); this.readOnly = readOnly; } /** * Tests to see if the connection is in Read Only Mode. Note that we * cannot really put the database in read only mode, but we pretend we can * by returning the value of the readOnly flag * * @return true if the connection is read only * * @exception java.sql.SQLException if a database access error occurs */ public boolean isReadOnly() throws java.sql.SQLException { if (Driver.TRACE) { Object[] args = new Object[0]; Debug.methodCall(this, "isReadOnly", args); Debug.returnValue(this, "isReadOnly", new Boolean(this.readOnly)); } return this.readOnly; } /** * @see Connection#setSavepoint() */ public java.sql.Savepoint setSavepoint() throws SQLException { throw new NotImplemented(); } /** * @see Connection#setSavepoint(String) */ public java.sql.Savepoint setSavepoint(String arg0) throws SQLException { throw new NotImplemented(); } /** * DOCUMENT ME! * * @return DOCUMENT ME! */ public TimeZone getServerTimezone() { return this.serverTimezone; } /** * DOCUMENT ME! * * @param level DOCUMENT ME! * * @throws java.sql.SQLException DOCUMENT ME! * @throws SQLException DOCUMENT ME! */ public void setTransactionIsolation(int level) throws java.sql.SQLException { if (Driver.TRACE) { Object[] args = { new Integer(level) }; Debug.methodCall(this, "setTransactionIsolation", args); } checkClosed(); if (this.hasIsolationLevels) { StringBuffer sql = new StringBuffer( "SET SESSION TRANSACTION ISOLATION LEVEL "); switch (level) { case java.sql.Connection.TRANSACTION_NONE: throw new SQLException("Transaction isolation level " + "NONE not supported by MySQL"); case java.sql.Connection.TRANSACTION_READ_COMMITTED: sql.append("READ COMMITTED"); break; case java.sql.Connection.TRANSACTION_READ_UNCOMMITTED: sql.append("READ UNCOMMITTED"); break; case java.sql.Connection.TRANSACTION_REPEATABLE_READ: sql.append("REPEATABLE READ"); break; case java.sql.Connection.TRANSACTION_SERIALIZABLE: sql.append("SERIALIZABLE"); break; default: throw new SQLException("Unsupported transaction " + "isolation level '" + level + "'", "S1C00"); } execSQL(sql.toString(), -1, this.database); isolationLevel = level; } else { throw new java.sql.SQLException("Transaction Isolation Levels are " + "not supported on MySQL versions older than 3.23.36.", "S1C00"); } } /** * Get this Connection's current transaction isolation mode. * * @return the current TRANSACTION_ mode value * * @exception java.sql.SQLException if a database access error occurs * @throws SQLException DOCUMENT ME! */ public int getTransactionIsolation() throws java.sql.SQLException { if (Driver.TRACE) { Object[] args = new Object[0]; Debug.methodCall(this, "getTransactionIsolation", args); Debug.returnValue(this, "getTransactionIsolation", new Integer(isolationLevel)); } if (this.hasIsolationLevels) { java.sql.Statement stmt = null; java.sql.ResultSet rs = null; try { stmt = this.createStatement(); if (stmt.getMaxRows() != 0) { stmt.setMaxRows(0); } String query = null; if (this.io.versionMeetsMinimum(4, 0, 3)) { query = "SHOW VARIABLES LIKE 'tx_isolation'"; } else { query = "SHOW VARIABLES LIKE 'transaction_isolation'"; } rs = stmt.executeQuery(query); if (rs.next()) { String s = rs.getString(2); if (s != null) { Integer intTI = (Integer) mapTransIsolationName2Value .get(s); if (intTI != null) { return intTI.intValue(); } } throw new SQLException( "Could not map transaction isolation '" + s + " to a valid JDBC level.", SQLError.SQL_STATE_GENERAL_ERROR); } else { throw new SQLException("Could not retrieve transaction isolation level from server", SQLError.SQL_STATE_GENERAL_ERROR); } } finally { if (rs != null) { try { rs.close(); } catch (Exception ex) { // ignore } rs = null; } if (stmt != null) { try { stmt.close(); } catch (Exception ex) { // ignore } stmt = null; } } } return isolationLevel; } /** * JDBC 2.0 Install a type-map object as the default type-map for this * connection * * @param map the type mapping * * @throws SQLException if a database error occurs. */ public void setTypeMap(java.util.Map map) throws SQLException { this.typeMap = map; } /** * JDBC 2.0 Get the type-map object associated with this connection. By * default, the map returned is empty. * * @return the type map * * @throws SQLException if a database error occurs */ public synchronized java.util.Map getTypeMap() throws SQLException { if (this.typeMap == null) { this.typeMap = new HashMap(); } return this.typeMap; } /** * The first warning reported by calls on this Connection is returned. * <B>Note:</B> Sebsequent warnings will be changed to this * java.sql.SQLWarning * * @return the first java.sql.SQLWarning or null * * @exception java.sql.SQLException if a database access error occurs */ public java.sql.SQLWarning getWarnings() throws java.sql.SQLException { if (Driver.TRACE) { Object[] args = new Object[0]; Debug.methodCall(this, "getWarnings", args); Debug.returnValue(this, "getWarnings", null); } return null; } /** * Allow use of LOAD LOCAL INFILE? * * @return true if allowLoadLocalInfile was set to true. */ public boolean allowLoadLocalInfile() { return this.allowLoadLocalInfile; } /** * DOCUMENT ME! * * @return DOCUMENT ME! */ public boolean capitalizeDBMDTypes() { return this.capitalizeDBMDTypes; } /** * After this call, getWarnings returns null until a new warning is * reported for this connection. * * @exception java.sql.SQLException if a database access error occurs */ public void clearWarnings() throws java.sql.SQLException { if (Driver.TRACE) { Object[] args = new Object[0]; Debug.methodCall(this, "clearWarnings", args); } // firstWarning = null; } /** * In some cases, it is desirable to immediately release a Connection's * database and JDBC resources instead of waiting for them to be * automatically released (cant think why off the top of my head) * <B>Note:</B> A Connection is automatically closed when it is garbage * collected. Certain fatal errors also result in a closed connection. * * @exception java.sql.SQLException if a database access error occurs */ public void close() throws java.sql.SQLException { if (this.explicitCloseLocation == null) { this.explicitCloseLocation = new Throwable(); } realClose(true, true); } /** * The method commit() makes all changes made since the previous * commit/rollback permanent and releases any database locks currently * held by the Connection. This method should only be used when * auto-commit has been disabled. * * <p> * <b>Note:</b> MySQL does not support transactions, so this method is a * no-op. * </p> * * @exception java.sql.SQLException if a database access error occurs * @throws SQLException DOCUMENT ME! * * @see setAutoCommit */ public void commit() throws java.sql.SQLException { if (Driver.TRACE) { Object[] args = new Object[0]; Debug.methodCall(this, "commit", args); } checkClosed(); try { // no-op if _relaxAutoCommit == true if (this.autoCommit && !this.relaxAutoCommit) { throw new SQLException("Can't call commit when autocommit=true", SQLError.SQL_STATE_GENERAL_ERROR); } else if (this.transactionsSupported) { execSQL("commit", -1, this.database); } } finally { if (this.reconnectAtTxEnd) { pingAndReconnect(true); } } return; } //--------------------------JDBC 2.0----------------------------- /** * JDBC 2.0 Same as createStatement() above, but allows the default result * set type and result set concurrency type to be overridden. * * @param resultSetType a result set type, see ResultSet.TYPE_XXX * @param resultSetConcurrency a concurrency type, see ResultSet.CONCUR_XXX * * @return a new Statement object * * @exception SQLException if a database-access error occurs. */ public java.sql.Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException { checkClosed(); Statement stmt = new com.mysql.jdbc.Statement(this, this.database); stmt.setResultSetType(resultSetType); stmt.setResultSetConcurrency(resultSetConcurrency); return stmt; } /** * SQL statements without parameters are normally executed using Statement * objects. If the same SQL statement is executed many times, it is more * efficient to use a PreparedStatement * * @return a new Statement object * * @throws SQLException passed through from the constructor */ public java.sql.Statement createStatement() throws SQLException { return createStatement(java.sql.ResultSet.TYPE_FORWARD_ONLY, java.sql.ResultSet.CONCUR_READ_ONLY); } /** * @see Connection#createStatement(int, int, int) */ public java.sql.Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException { if (this.pedantic) { if (resultSetHoldability != ResultSet.HOLD_CURSORS_OVER_COMMIT) { throw new SQLException("HOLD_CUSRORS_OVER_COMMIT is only supported holdability level", SQLError.SQL_STATE_ILLEGAL_ARGUMENT); } } return createStatement(resultSetType, resultSetConcurrency); } /** * DOCUMENT ME! * * @throws Throwable DOCUMENT ME! */ public void finalize() throws Throwable { cleanup(null); } /** * Is the server configured to use lower-case table names only? * * @return true if lower_case_table_names is 'on' */ public boolean lowerCaseTableNames() { return this.lowerCaseTableNames; } /** * A driver may convert the JDBC sql grammar into its system's native SQL * grammar prior to sending it; nativeSQL returns the native form of the * statement that the driver would have sent. * * @param sql a SQL statement that may contain one or more '?' parameter * placeholders * * @return the native form of this statement * * @exception java.sql.SQLException if a database access error occurs */ public String nativeSQL(String sql) throws java.sql.SQLException { if (Driver.TRACE) { Object[] args = { sql }; Debug.methodCall(this, "nativeSQL", args); Debug.returnValue(this, "nativeSQL", sql); } return EscapeProcessor.escapeSQL(sql, getIO().versionMeetsMinimum(4, 0, 2)); } /** * DOCUMENT ME! * * @param sql DOCUMENT ME! * * @return DOCUMENT ME! * * @throws java.sql.SQLException DOCUMENT ME! */ public java.sql.CallableStatement prepareCall(String sql) throws java.sql.SQLException { if (this.getUseUltraDevWorkAround()) { return new UltraDevWorkAround(prepareStatement(sql)); } else { throw new java.sql.SQLException("Callable statments not " + "supported.", "S1C00"); } } /** * JDBC 2.0 Same as prepareCall() above, but allows the default result set * type and result set concurrency type to be overridden. * * @param sql the SQL representing the callable statement * @param resultSetType a result set type, see ResultSet.TYPE_XXX * @param resultSetConcurrency a concurrency type, see ResultSet.CONCUR_XXX * * @return a new CallableStatement object containing the pre-compiled SQL * statement * * @exception SQLException if a database-access error occurs. */ public java.sql.CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException { return prepareCall(sql); } /** * @see Connection#prepareCall(String, int, int, int) */ public java.sql.CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException { if (this.pedantic) { if (resultSetHoldability != ResultSet.HOLD_CURSORS_OVER_COMMIT) { throw new SQLException("HOLD_CUSRORS_OVER_COMMIT is only supported holdability level", SQLError.SQL_STATE_ILLEGAL_ARGUMENT); } } throw new NotImplemented(); } /** * A SQL statement with or without IN parameters can be pre-compiled and * stored in a PreparedStatement object. This object can then be used to * efficiently execute this statement multiple times. * * <p> * <B>Note:</B> This method is optimized for handling parametric SQL * statements that benefit from precompilation if the driver supports * precompilation. In this case, the statement is not sent to the database * until the PreparedStatement is executed. This has no direct effect on * users; however it does affect which method throws certain * java.sql.SQLExceptions * </p> * * <p> * MySQL does not support precompilation of statements, so they are handled * by the driver. * </p> * * @param sql a SQL statement that may contain one or more '?' IN parameter * placeholders * * @return a new PreparedStatement object containing the pre-compiled * statement. * * @exception java.sql.SQLException if a database access error occurs. */ public java.sql.PreparedStatement prepareStatement(String sql) throws java.sql.SQLException { return prepareStatement(sql, java.sql.ResultSet.TYPE_FORWARD_ONLY, java.sql.ResultSet.CONCUR_READ_ONLY); } /** * JDBC 2.0 Same as prepareStatement() above, but allows the default result * set type and result set concurrency type to be overridden. * * @param sql the SQL query containing place holders * @param resultSetType a result set type, see ResultSet.TYPE_XXX * @param resultSetConcurrency a concurrency type, see ResultSet.CONCUR_XXX * * @return a new PreparedStatement object containing the pre-compiled SQL * statement * * @exception SQLException if a database-access error occurs. */ public synchronized java.sql.PreparedStatement prepareStatement( String sql, int resultSetType, int resultSetConcurrency) throws SQLException { checkClosed(); PreparedStatement pStmt = null; if (this.cachePreparedStatements) { PreparedStatement.ParseInfo pStmtInfo = (PreparedStatement.ParseInfo) cachedPreparedStatementParams .get(sql); if (pStmtInfo == null) { pStmt = new com.mysql.jdbc.PreparedStatement(this, sql, this.database); PreparedStatement.ParseInfo parseInfo = pStmt.getParseInfo(); if (parseInfo.statementLength < this.preparedStatementCacheMaxSqlSize) { if (this.cachedPreparedStatementParams.size() >= 25) { Iterator oldestIter = this.cachedPreparedStatementParams.keySet() .iterator(); long lruTime = Long.MAX_VALUE; String oldestSql = null; while (oldestIter.hasNext()) { String sqlKey = (String) oldestIter.next(); PreparedStatement.ParseInfo lruInfo = (PreparedStatement.ParseInfo) this.cachedPreparedStatementParams .get(sqlKey); if (lruInfo.lastUsed < lruTime) { lruTime = lruInfo.lastUsed; oldestSql = sqlKey; } } if (oldestSql != null) { this.cachedPreparedStatementParams.remove(oldestSql); } } cachedPreparedStatementParams.put(sql, pStmt.getParseInfo()); } } else { pStmtInfo.lastUsed = System.currentTimeMillis(); pStmt = new com.mysql.jdbc.PreparedStatement(this, sql, this.database, pStmtInfo); } } else { pStmt = new com.mysql.jdbc.PreparedStatement(this, sql, this.database); } // // FIXME: Create warnings if can't create results of the given // type or concurrency // pStmt.setResultSetType(resultSetType); pStmt.setResultSetConcurrency(resultSetConcurrency); return pStmt; } /** * @see Connection#prepareStatement(String, int, int, int) */ public java.sql.PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException { if (this.pedantic) { if (resultSetHoldability != ResultSet.HOLD_CURSORS_OVER_COMMIT) { throw new SQLException("HOLD_CUSRORS_OVER_COMMIT is only supported holdability level", SQLError.SQL_STATE_ILLEGAL_ARGUMENT); } } return prepareStatement(sql, resultSetType, resultSetConcurrency); } /** * @see Connection#prepareStatement(String, int) */ public java.sql.PreparedStatement prepareStatement(String sql, int autoGenKeyIndex) throws SQLException { java.sql.PreparedStatement pStmt = prepareStatement(sql); ((com.mysql.jdbc.PreparedStatement) pStmt).setRetrieveGeneratedKeys(autoGenKeyIndex == Statement.RETURN_GENERATED_KEYS); return pStmt; } /** * @see Connection#prepareStatement(String, int[]) */ public java.sql.PreparedStatement prepareStatement(String sql, int[] autoGenKeyIndexes) throws SQLException { java.sql.PreparedStatement pStmt = prepareStatement(sql); ((com.mysql.jdbc.PreparedStatement) pStmt).setRetrieveGeneratedKeys((autoGenKeyIndexes != null) && (autoGenKeyIndexes.length > 0)); return pStmt; } /** * @see Connection#prepareStatement(String, String[]) */ public java.sql.PreparedStatement prepareStatement(String sql, String[] autoGenKeyColNames) throws SQLException { java.sql.PreparedStatement pStmt = prepareStatement(sql); ((com.mysql.jdbc.PreparedStatement) pStmt).setRetrieveGeneratedKeys((autoGenKeyColNames != null) && (autoGenKeyColNames.length > 0)); return pStmt; } /** * @see Connection#releaseSavepoint(Savepoint) */ public void releaseSavepoint(Savepoint arg0) throws SQLException { throw new NotImplemented(); } /** * The method rollback() drops all changes made since the previous * commit/rollback and releases any database locks currently held by the * Connection. * * @exception java.sql.SQLException if a database access error occurs * @throws SQLException DOCUMENT ME! * * @see commit */ public void rollback() throws java.sql.SQLException { if (Driver.TRACE) { Object[] args = new Object[0]; Debug.methodCall(this, "rollback", args); } checkClosed(); try { // no-op if _relaxAutoCommit == true if (this.autoCommit && !this.relaxAutoCommit) { throw new SQLException("Can't call rollback when autocommit=true", SQLError.SQL_STATE_GENERAL_ERROR); } else if (this.transactionsSupported) { try { rollbackNoChecks(); } catch (SQLException sqlEx) { // We ignore non-transactional tables if told to do so if (this.ignoreNonTxTables && (sqlEx.getErrorCode() != MysqlDefs.ER_WARNING_NOT_COMPLETE_ROLLBACK)) { throw sqlEx; } } } } finally { if (this.reconnectAtTxEnd) { pingAndReconnect(true); } } } /** * @see Connection#rollback(Savepoint) */ public void rollback(Savepoint arg0) throws SQLException { throw new NotImplemented(); } /** * Used by MiniAdmin to shutdown a MySQL server * * @throws SQLException if the command can not be issued. */ public void shutdownServer() throws SQLException { try { this.io.sendCommand(MysqlDefs.SHUTDOWN, null, null); } catch (Exception ex) { throw new SQLException("Unhandled exception '" + ex.toString() + "'", SQLError.SQL_STATE_GENERAL_ERROR); } } /** * DOCUMENT ME! * * @return DOCUMENT ME! */ public boolean supportsIsolationLevel() { return this.hasIsolationLevels; } /** * DOCUMENT ME! * * @return DOCUMENT ME! */ public boolean supportsQuotedIdentifiers() { return this.hasQuotedIdentifiers; } /** * DOCUMENT ME! * * @return DOCUMENT ME! */ public boolean supportsTransactions() { return this.transactionsSupported; } /** * Should we use compression? * * @return should we use compression to communicate with the server? */ public boolean useCompression() { return this.useCompression; } /** * Returns the paranoidErrorMessages. * * @return boolean if we should be paranoid about error messages. */ public boolean useParanoidErrorMessages() { return paranoid; } /** * Should we use SSL? * * @return should we use SSL to communicate with the server? */ public boolean useSSL() { return this.useSSL; } /** * Should we enable work-arounds for floating point rounding errors in the * server? * * @return should we use floating point work-arounds? */ public boolean useStrictFloatingPoint() { return this.strictFloatingPoint; } /** * Returns the strictUpdates value. * * @return boolean */ public boolean useStrictUpdates() { return strictUpdates; } /** * DOCUMENT ME! * * @return DOCUMENT ME! */ public boolean useTimezone() { return this.useTimezone; } /** * Should unicode character mapping be used ? * * @return should we use Unicode character mapping? */ public boolean useUnicode() { return this.doUnicode; } /** * Returns the IO channel to the server * * @return the IO channel to the server * * @throws SQLException if the connection is closed. */ protected MysqlIO getIO() throws SQLException { if ((this.io == null) || this.isClosed) { throw new SQLException("Operation not allowed on closed connection", "08003"); } return this.io; } protected int getNetWriteTimeout() { String netWriteTimeoutStr = (String) this.serverVariables.get( "net_write_timeout"); if (netWriteTimeoutStr != null) { try { return Integer.parseInt(netWriteTimeoutStr); } catch (NumberFormatException nfe) { return Integer.MAX_VALUE; } } else { return Integer.MAX_VALUE; } } /** * Creates an IO channel to the server * * @param isForReconnect is this request for a re-connect * * @return a new MysqlIO instance connected to a server * * @throws SQLException if a database access error occurs */ protected com.mysql.jdbc.MysqlIO createNewIO(boolean isForReconnect) throws SQLException { MysqlIO newIo = null; if (!highAvailability && !this.failedOver) { for (int hostIndex = 0; hostIndex < hostListSize; hostIndex++) { try { this.io = new MysqlIO(this.hostList.get(hostIndex).toString(), this.port, this.socketFactoryClassName, this.props, this, this.socketTimeout); this.io.doHandshake(this.user, this.password, this.database); this.isClosed = false; if (this.database.length() != 0) { this.io.sendCommand(MysqlDefs.INIT_DB, this.database, null); } // save state from old connection boolean autoCommit = getAutoCommit(); int oldIsolationLevel = getTransactionIsolation(); boolean oldReadOnly = isReadOnly(); String oldCatalog = getCatalog(); // Server properties might be different // from previous connection, so initialize // again... initializePropsFromServer(this.props); if (isForReconnect) { // Restore state from old connection setAutoCommit(autoCommit); if (this.hasIsolationLevels) { setTransactionIsolation(oldIsolationLevel); } setCatalog(oldCatalog); } if (hostIndex != 0) { setFailedOverState(); } else { this.failedOver = false; if (hostListSize > 1) { setReadOnly(false); } else { setReadOnly(oldReadOnly); } } break; // low-level connection succeeded } catch (SQLException sqlEx) { if (this.io != null) { this.io.forceClose(); } String sqlState = sqlEx.getSQLState(); if ((sqlState == null) || !sqlState.equals(SQLError.SQL_STATE_COMMUNICATION_LINK_FAILURE)) { throw sqlEx; } if ((hostListSize - 1) == hostIndex) { throw sqlEx; } } catch (Exception unknownException) { if (this.io != null) { this.io.forceClose(); } if ((hostListSize - 1) == hostIndex) { throw new SQLException( "Unable to connect to any hosts due to exception: " + unknownException.toString(), SQLError.SQL_STATE_COMMUNICATION_LINK_FAILURE); } } } } else { double timeout = this.initialTimeout; boolean connectionGood = false; Exception connectionException = null; for (int hostIndex = 0; hostIndex < hostListSize; hostIndex++) { for (int attemptCount = 0; attemptCount < this.maxReconnects; attemptCount++) { try { if (this.io != null) { this.io.forceClose(); } this.io = new MysqlIO(this.hostList.get(hostIndex) .toString(), this.port, this.socketFactoryClassName, this.props, this, this.socketTimeout); this.io.doHandshake(this.user, this.password, this.database); if (this.database.length() != 0) { this.io.sendCommand(MysqlDefs.INIT_DB, this.database, null); } ping(); this.isClosed = false; // save state from old connection boolean autoCommit = getAutoCommit(); int oldIsolationLevel = getTransactionIsolation(); boolean oldReadOnly = isReadOnly(); String oldCatalog = getCatalog(); // Server properties might be different // from previous connection, so initialize // again... initializePropsFromServer(this.props); if (isForReconnect) { // Restore state from old connection setAutoCommit(autoCommit); if (this.hasIsolationLevels) { setTransactionIsolation(oldIsolationLevel); } setCatalog(oldCatalog); } connectionGood = true; if (hostIndex != 0) { setFailedOverState(); } else { this.failedOver = false; if (hostListSize > 1) { setReadOnly(false); } else { setReadOnly(oldReadOnly); } } break; } catch (Exception EEE) { connectionException = EEE; connectionGood = false; } if (connectionGood) { break; } try { Thread.sleep((long) timeout * 1000); timeout = timeout * timeout; } catch (InterruptedException IE) { ; } } if (!connectionGood) { // We've really failed! throw new SQLException( "Server connection failure during transaction. Due to underlying exception: '" + connectionException + "'.\nAttempted reconnect " + this.maxReconnects + " times. Giving up.", SQLError.SQL_STATE_UNABLE_TO_CONNECT_TO_DATASOURCE); } } } if (paranoid && !highAvailability && (hostListSize <= 1)) { password = null; user = null; } return newIo; } /** * Closes connection and frees resources. * * @param calledExplicitly is this being called from close() * @param issueRollback should a rollback() be issued? * * @throws SQLException if an error occurs */ protected void realClose(boolean calledExplicitly, boolean issueRollback) throws SQLException { if (Driver.TRACE) { Object[] args = new Object[] { new Boolean(calledExplicitly), new Boolean(issueRollback) }; Debug.methodCall(this, "realClose", args); } SQLException sqlEx = null; if (!isClosed() && !getAutoCommit() && issueRollback) { try { rollback(); } catch (SQLException ex) { sqlEx = ex; } } if (this.io != null) { try { this.io.quit(); } catch (Exception e) { ; } this.io = null; } if (this.cachedPreparedStatementParams != null) { this.cachedPreparedStatementParams.clear(); this.cachedPreparedStatementParams = null; } this.isClosed = true; if (sqlEx != null) { throw sqlEx; } } /** * Returns the locally mapped instance of a charset converter (to avoid * overhead of static synchronization). * * @param javaEncodingName the encoding name to retrieve * * @return a character converter, or null if one couldn't be mapped. */ synchronized SingleByteCharsetConverter getCharsetConverter( String javaEncodingName) { SingleByteCharsetConverter converter = (SingleByteCharsetConverter) this.charsetConverterMap .get(javaEncodingName); if (converter == CHARSET_CONVERTER_NOT_AVAILABLE_MARKER) { return null; } if (converter == null) { try { converter = SingleByteCharsetConverter.getInstance(javaEncodingName); if (converter == null) { this.charsetConverterMap.put(javaEncodingName, CHARSET_CONVERTER_NOT_AVAILABLE_MARKER); } this.charsetConverterMap.put(javaEncodingName, converter); } catch (UnsupportedEncodingException unsupEncEx) { this.charsetConverterMap.put(javaEncodingName, CHARSET_CONVERTER_NOT_AVAILABLE_MARKER); converter = null; } } return converter; } /** * Returns the maximum packet size the MySQL server will accept * * @return DOCUMENT ME! */ int getMaxAllowedPacket() { return this.maxAllowedPacket; } /** * DOCUMENT ME! * * @return the max rows to return for statements (by default) */ int getMaxRows() { return this.maxRows; } /** * Returns the Mutex all queries are locked against * * @return DOCUMENT ME! * * @throws SQLException DOCUMENT ME! */ Object getMutex() throws SQLException { if (this.io == null) { throw new SQLException("Connection.close() has already been called. Invalid operation in this state.", "08003"); } return this.mutex; } /** * Returns the packet buffer size the MySQL server reported upon connection * * @return DOCUMENT ME! */ int getNetBufferLength() { return this.netBufferLength; } boolean isPedantic() { return this.pedantic; } void setReadInfoMsgEnabled(boolean flag) { this.readInfoMsg = flag; } boolean isReadInfoMsgEnabled() { return this.readInfoMsg; } int getServerMajorVersion() { return this.io.getServerMajorVersion(); } int getServerMinorVersion() { return this.io.getServerMinorVersion(); } int getServerSubMinorVersion() { return this.io.getServerSubMinorVersion(); } String getServerVersion() { return this.io.getServerVersion(); } String getURL() { return this.myURL; } /** * Set whether or not this connection should use SSL * * @param flag DOCUMENT ME! */ void setUseSSL(boolean flag) { this.useSSL = flag; } String getUser() { return this.user; } boolean alwaysClearStream() { return this.alwaysClearStream; } boolean continueBatchOnError() { return this.continueBatchOnError; } /** * Send a query to the server. Returns one of the ResultSet objects. This * is synchronized, so Statement's queries will be serialized. * * @param sql the SQL statement to be executed * @param maxRowsToRetreive DOCUMENT ME! * @param catalog DOCUMENT ME! * * @return a ResultSet holding the results * * @exception java.sql.SQLException if a database error occurs */ ResultSet execSQL(String sql, int maxRowsToRetreive, String catalog) throws java.sql.SQLException { if (Driver.TRACE) { Object[] args = { sql, new Integer(maxRowsToRetreive) }; Debug.methodCall(this, "execSQL", args); } return execSQL(sql, maxRowsToRetreive, null, java.sql.ResultSet.CONCUR_READ_ONLY, catalog); } ResultSet execSQL(String sql, int maxRows, int resultSetType, boolean streamResults, boolean queryIsSelectOnly, String catalog) throws SQLException { return execSQL(sql, maxRows, null, resultSetType, streamResults, queryIsSelectOnly, catalog); } ResultSet execSQL(String sql, int maxRows, Buffer packet, String catalog) throws java.sql.SQLException { return execSQL(sql, maxRows, packet, java.sql.ResultSet.CONCUR_READ_ONLY, catalog); } ResultSet execSQL(String sql, int maxRows, Buffer packet, int resultSetType, String catalog) throws java.sql.SQLException { return execSQL(sql, maxRows, packet, resultSetType, true, false, catalog); } ResultSet execSQL(String sql, int maxRows, Buffer packet, int resultSetType, boolean streamResults, boolean queryIsSelectOnly, String catalog) throws java.sql.SQLException { if (Driver.TRACE) { Object[] args = { sql, new Integer(maxRows), packet }; Debug.methodCall(this, "execSQL", args); } // // Fall-back if the master is back online if we've // issued queriesBeforeRetryMaster queries since // we failed over // synchronized (this.mutex) { this.lastQueryFinishedTime = 0; // we're busy! pingAndReconnect(false); try { int realMaxRows = (maxRows == -1) ? MysqlDefs.MAX_ROWS : maxRows; if (packet == null) { String encoding = null; if (useUnicode()) { encoding = getEncoding(); } return this.io.sqlQuery(sql, realMaxRows, encoding, this, resultSetType, streamResults, catalog); } else { return this.io.sqlQueryDirect(packet, realMaxRows, this, resultSetType, streamResults, catalog); } } catch (java.sql.SQLException sqlE) { // don't clobber SQL exceptions String sqlState = sqlE.getSQLState(); if ((sqlState != null) && sqlState.equals(SQLError.SQL_STATE_COMMUNICATION_LINK_FAILURE)) { cleanup(sqlE); } throw sqlE; } catch (Exception ex) { if (ex instanceof IOException) { cleanup(ex); } String exceptionType = ex.getClass().getName(); String exceptionMessage = ex.getMessage(); if (!this.useParanoidErrorMessages()) { exceptionMessage += "\n\nNested Stack Trace:\n"; exceptionMessage += Util.stackTraceToString(ex); } throw new java.sql.SQLException( "Error during query: Unexpected Exception: " + exceptionType + " message given: " + exceptionMessage, SQLError.SQL_STATE_GENERAL_ERROR); } finally { this.lastQueryFinishedTime = System.currentTimeMillis(); } } } /** * Has the maxRows value changed? * * @param stmt DOCUMENT ME! */ void maxRowsChanged(Statement stmt) { synchronized (this.mutex) { if (this.statementsUsingMaxRows == null) { this.statementsUsingMaxRows = new HashMap(); } this.statementsUsingMaxRows.put(stmt, stmt); this.maxRowsChanged = true; } } /** * Called by statements on their .close() to let the connection know when * it is safe to set the connection back to 'default' row limits. * * @param stmt the statement releasing it's max-rows requirement * * @throws SQLException if a database error occurs issuing the statement * that sets the limit default. */ void unsetMaxRows(Statement stmt) throws SQLException { synchronized (this.mutex) { if (this.statementsUsingMaxRows != null) { Object found = this.statementsUsingMaxRows.remove(stmt); if ((found != null) && (this.statementsUsingMaxRows.size() == 0)) { execSQL("SET OPTION SQL_SELECT_LIMIT=DEFAULT", -1, this.database); this.maxRowsChanged = false; } } } } boolean useAnsiQuotedIdentifiers() { return this.useAnsiQuotes; } boolean useHostsInPrivileges() { return this.useHostsInPrivileges; } /** * Has maxRows() been set? * * @return DOCUMENT ME! */ boolean useMaxRows() { synchronized (this.mutex) { return this.maxRowsChanged; } } boolean useStreamLengthsInPrepStmts() { return this.useStreamLengthsInPrepStmts; } /** * Sets state for a failed-over connection * * @throws SQLException DOCUMENT ME! */ private void setFailedOverState() throws SQLException { // FIXME: User Selectable? setReadOnly(true); this.queriesIssuedFailedOver = 0; this.failedOver = true; this.masterFailTimeMillis = System.currentTimeMillis(); } /** * If useUnicode flag is set and explicit client character encoding isn't * specified then assign encoding from server if any. * * @throws SQLException DOCUMENT ME! */ private void checkServerEncoding() throws SQLException { if (this.doUnicode && (this.encoding != null)) { // spec'd by client, don't map, but check // for character encoding 'overlaps' when using // pre-4.1 servers if (!this.io.versionMeetsMinimum(4, 1, 0)) { if ("ISO8859_2".equals("this.encoding")) { throw new SQLException("Character encoding 'ISO8859_2' specified in JDBC URL which maps to multiple MySQL character encodings:" + "\n\n" + "* 'latin2'\n" + "* 'czech'\n" + "* 'hungarian'\n" + "* 'croat'\n" + "\nSpecify one of the above encodings using the 'mysqlEncoding' connection property.", SQLError.SQL_STATE_INVALID_CONNECTION_ATTRIBUTE); } else if ("ISO8859_13".equals("this.encoding")) { throw new SQLException("Character encoding 'ISO8859_13' specified in JDBC URL which maps to multiple MySQL character encodings:" + "\n\n" + "* 'latvian'\n" + "* 'latvian1'\n" + "* 'estonia'\n" + "\nSpecify one of the above encodings using the 'mysqlEncoding' connection property.", SQLError.SQL_STATE_INVALID_CONNECTION_ATTRIBUTE); } } return; } this.mysqlEncodingName = (String) this.serverVariables.get( "character_set"); if (this.mysqlEncodingName == null) { // must be 4.1.1 or newer? this.mysqlEncodingName = (String) this.serverVariables.get( "character_set_client"); } String javaEncodingName = null; if (this.mysqlEncodingName != null) { javaEncodingName = (String) charsetMap.get(this.mysqlEncodingName .toUpperCase()); } // // First check if we can do the encoding ourselves // if (!this.doUnicode && (javaEncodingName != null)) { SingleByteCharsetConverter converter = getCharsetConverter(javaEncodingName); if (converter != null) { // we know how to convert this ourselves this.doUnicode = true; // force the issue this.encoding = javaEncodingName; return; } } // // Now, try and find a Java I/O converter that can do // the encoding for us // if (this.mysqlEncodingName != null) { if (javaEncodingName == null) { // We don't have a mapping for it, so try // and canonicalize the name.... if (Character.isLowerCase(this.mysqlEncodingName.charAt(0))) { char[] ach = this.mysqlEncodingName.toCharArray(); ach[0] = Character.toUpperCase(this.mysqlEncodingName.charAt(0)); this.encoding = new String(ach); } } // // Attempt to use the encoding, and bail out if it // can't be used // try { "abc".getBytes(javaEncodingName); this.encoding = javaEncodingName; this.doUnicode = true; } catch (UnsupportedEncodingException UE) { throw new SQLException( "The driver can not map the character encoding '" + this.encoding + "' that your server is using " + "to a character encoding your JVM understands. You " + "can specify this mapping manually by adding \"useUnicode=true\" " + "as well as \"characterEncoding=[an_encoding_your_jvm_understands]\" " + "to your JDBC URL.", SQLError.SQL_STATE_INVALID_CONNECTION_ATTRIBUTE); } } } /** * Set transaction isolation level to the value received from server if * any. Is called by connectionInit(...) * * @throws SQLException DOCUMENT ME! */ private void checkTransactionIsolationLevel() throws SQLException { String txIsolationName = null; if (this.io.versionMeetsMinimum(4, 0, 3)) { txIsolationName = "tx_isolation"; } else { txIsolationName = "transaction_isolation"; } String s = (String) this.serverVariables.get(txIsolationName); if (s != null) { Integer intTI = (Integer) mapTransIsolationName2Value.get(s); if (intTI != null) { isolationLevel = intTI.intValue(); } } } /** * Destroys this connection and any underlying resources * * @param cleanupReason DOCUMENT ME! */ private void cleanup(Throwable cleanupReason) { try { if ((this.io != null) && !isClosed()) { realClose(false, false); } else if (this.io != null) { this.io.forceClose(); } } catch (SQLException sqlEx) { // ignore, we're going away. } this.isClosed = true; this.forcedCloseReason = cleanupReason; } private void detectFloatingPointStyle() throws SQLException { java.sql.Statement stmt = null; java.sql.ResultSet rs = null; try { stmt = createStatement(); if (stmt.getMaxRows() != 0) { stmt.setMaxRows(0); } rs = stmt.executeQuery( "select round('inf'), round('-inf'), round('nan')"); if (rs.next()) { String posInf = rs.getString(1); if ("inf".equalsIgnoreCase(posInf)) { this.positiveInfinityRep = "'inf'"; this.positiveInfinityRepIsClipped = false; } String negInf = rs.getString(2); if ("-inf".equalsIgnoreCase(negInf)) { this.negativeInfinityRep = "'-inf'"; this.negativeInfinityRepIsClipped = false; } String nan = rs.getString(3); if ("nan".equalsIgnoreCase(nan)) { this.notANumberRep = "'nan'"; this.notANumberRepIsClipped = false; } } rs.close(); rs = null; stmt.close(); stmt = null; } catch (SQLException sqlEx) { ; // ignore here, we default to lowest-common denominator } finally { if (rs != null) { try { rs.close(); } catch (SQLException sqlEx) { ; // ignore } rs = null; } if (stmt != null) { try { stmt.close(); } catch (SQLException sqlEx) { ; // ignore } stmt = null; } } } /** * Initializes driver properties that come from URL or properties passed to * the driver manager. * * @param info DOCUMENT ME! * * @throws SQLException DOCUMENT ME! */ private void initializeDriverProperties(Properties info) throws SQLException { this.socketFactoryClassName = info.getProperty("socketFactory", DEFAULT_SOCKET_FACTORY); if (info.getProperty("cachePrepStmts") != null) { this.cachePreparedStatements = info.getProperty("cachePrepStmts") .equalsIgnoreCase("TRUE"); if (this.cachePreparedStatements) { if (info.getProperty("prepStmtCacheSize") != null) { try { this.preparedStatementCacheSize = Integer.parseInt(info .getProperty("prepStmtCacheSize")); if (this.preparedStatementCacheSize < 0) { throw new SQLException("Connection property 'prepStmtCacheSize' must be a non-negative integer value.", SQLError.SQL_STATE_ILLEGAL_ARGUMENT); } } catch (NumberFormatException nfe) { throw new SQLException("Connection property 'prepStmtCacheSize' must be a non-negative integer value.", SQLError.SQL_STATE_ILLEGAL_ARGUMENT); } } if (info.getProperty("prepStmtCacheSqlLimit") != null) { try { this.preparedStatementCacheMaxSqlSize = Integer .parseInt(info.getProperty("prepStmtCacheSqlLimit")); if (this.preparedStatementCacheMaxSqlSize < 0) { throw new SQLException("Connection property 'prepStmtCacheSqlLimit' must be a non-negative integer value.", SQLError.SQL_STATE_ILLEGAL_ARGUMENT); } } catch (NumberFormatException nfe) { throw new SQLException("Connection property 'prepStmtCacheSqlLimit' must be a non-negative integer value.", SQLError.SQL_STATE_ILLEGAL_ARGUMENT); } } this.cachedPreparedStatementParams = new HashMap(this.preparedStatementCacheSize); } } if (info.getProperty("alwaysClearStream") != null) { this.alwaysClearStream = info.getProperty("alwaysClearStream") .equalsIgnoreCase("TRUE"); } if (info.getProperty("reconnectAtTxEnd") != null) { this.reconnectAtTxEnd = info.getProperty("reconnectAtTxEnd") .equalsIgnoreCase("TRUE"); } if (info.getProperty("clobberStreamingResults") != null) { this.clobberStreamingResults = info.getProperty( "clobberStreamingResults").equalsIgnoreCase("TRUE"); } if (info.getProperty("strictUpdates") != null) { this.strictUpdates = info.getProperty("strictUpdates") .equalsIgnoreCase("TRUE"); } if (info.getProperty("ignoreNonTxTables") != null) { this.ignoreNonTxTables = info.getProperty("ignoreNonTxTables") .equalsIgnoreCase("TRUE"); } if (info.getProperty("secondsBeforeRetryMaster") != null) { String secondsBeforeRetryStr = info.getProperty( "secondsBeforeRetryMaster"); try { int seconds = Integer.parseInt(secondsBeforeRetryStr); if (seconds < 1) { throw new SQLException("Illegal (< 1) value '" + secondsBeforeRetryStr + "' for 'secondsBeforeRetryMaster'", SQLError.SQL_STATE_ILLEGAL_ARGUMENT); } this.secondsBeforeRetryMaster = seconds; } catch (NumberFormatException nfe) { throw new SQLException("Illegal non-numeric value '" + secondsBeforeRetryStr + "' for 'secondsBeforeRetryMaster'", SQLError.SQL_STATE_ILLEGAL_ARGUMENT); } } if (info.getProperty("queriesBeforeRetryMaster") != null) { String queriesBeforeRetryStr = info.getProperty( "queriesBeforeRetryMaster"); try { this.queriesBeforeRetryMaster = Integer.parseInt(queriesBeforeRetryStr); } catch (NumberFormatException nfe) { throw new SQLException("Illegal non-numeric value '" + queriesBeforeRetryStr + "' for 'queriesBeforeRetryMaster'", SQLError.SQL_STATE_ILLEGAL_ARGUMENT); } } if (info.getProperty("allowLoadLocalInfile") != null) { this.allowLoadLocalInfile = info.getProperty("allowLoadLocalInfile") .equalsIgnoreCase("TRUE"); } if (info.getProperty("continueBatchOnError") != null) { this.continueBatchOnError = info.getProperty("continueBatchOnError") .equalsIgnoreCase("TRUE"); } if (info.getProperty("pedantic") != null) { this.pedantic = info.getProperty("pedantic").equalsIgnoreCase("TRUE"); } if (info.getProperty("useStreamLengthsInPrepStmts") != null) { this.useStreamLengthsInPrepStmts = info.getProperty( "useStreamLengthsInPrepStmts").equalsIgnoreCase("TRUE"); } if (info.getProperty("useTimezone") != null) { this.useTimezone = info.getProperty("useTimezone").equalsIgnoreCase("TRUE"); } if (info.getProperty("relaxAutoCommit") != null) { this.relaxAutoCommit = info.getProperty("relaxAutoCommit") .equalsIgnoreCase("TRUE"); } else if (info.getProperty("relaxAutocommit") != null) { this.relaxAutoCommit = info.getProperty("relaxAutocommit") .equalsIgnoreCase("TRUE"); } if (info.getProperty("paranoid") != null) { this.paranoid = info.getProperty("paranoid").equalsIgnoreCase("TRUE"); } if (info.getProperty("autoReconnect") != null) { this.highAvailability = info.getProperty("autoReconnect") .equalsIgnoreCase("TRUE"); } if (info.getProperty("capitalizeTypeNames") != null) { this.capitalizeDBMDTypes = info.getProperty("capitalizeTypeNames") .equalsIgnoreCase("TRUE"); } if (info.getProperty("ultraDevHack") != null) { this.useUltraDevWorkAround = info.getProperty("ultraDevHack") .equalsIgnoreCase("TRUE"); } if (info.getProperty("strictFloatingPoint") != null) { this.strictFloatingPoint = info.getProperty("strictFloatingPoint") .equalsIgnoreCase("TRUE"); } if (info.getProperty("useSSL") != null) { this.useSSL = info.getProperty("useSSL").equalsIgnoreCase("TRUE"); } if (info.getProperty("useCompression") != null) { this.useCompression = info.getProperty("useCompression") .equalsIgnoreCase("TRUE"); } if (info.getProperty("socketTimeout") != null) { try { int n = Integer.parseInt(info.getProperty("socketTimeout")); if (n < 0) { throw new SQLException("socketTimeout can not " + "be < 0", SQLError.SQL_STATE_INVALID_CONNECTION_ATTRIBUTE); } this.socketTimeout = n; } catch (NumberFormatException NFE) { throw new SQLException("Illegal parameter '" + info.getProperty("socketTimeout") + "' for socketTimeout", SQLError.SQL_STATE_INVALID_CONNECTION_ATTRIBUTE); } } if (this.highAvailability) { if (info.getProperty("maxReconnects") != null) { try { int n = Integer.parseInt(info.getProperty("maxReconnects")); this.maxReconnects = n; } catch (NumberFormatException NFE) { throw new SQLException("Illegal parameter '" + info.getProperty("maxReconnects") + "' for maxReconnects", SQLError.SQL_STATE_INVALID_CONNECTION_ATTRIBUTE); } } if (info.getProperty("initialTimeout") != null) { try { double n = Integer.parseInt(info.getProperty( "initialTimeout")); this.initialTimeout = n; } catch (NumberFormatException NFE) { throw new SQLException("Illegal parameter '" + info.getProperty("initialTimeout") + "' for initialTimeout", SQLError.SQL_STATE_INVALID_CONNECTION_ATTRIBUTE); } } } if (info.getProperty("maxRows") != null) { try { int n = Integer.parseInt(info.getProperty("maxRows")); if (n == 0) { n = -1; } // adjust so that it will become MysqlDefs.MAX_ROWS // in execSQL() this.maxRows = n; this.maxRowsChanged = true; } catch (NumberFormatException NFE) { throw new SQLException("Illegal parameter '" + info.getProperty("maxRows") + "' for maxRows", SQLError.SQL_STATE_INVALID_CONNECTION_ATTRIBUTE); } } if (info.getProperty("useHostsInPrivileges") != null) { this.useHostsInPrivileges = info.getProperty("useHostsInPrivileges") .equalsIgnoreCase("TRUE"); } if (info.getProperty("interactiveClient") != null) { this.isInteractiveClient = info.getProperty("interactiveClient") .equalsIgnoreCase("TRUE"); } if (info.getProperty("useUnicode") != null) { this.doUnicode = info.getProperty("useUnicode").equalsIgnoreCase("TRUE"); } if (this.doUnicode) { if (info.getProperty("mysqlEncoding") != null) { this.mysqlEncodingName = info.getProperty("mysqlEncoding"); } if (info.getProperty("characterEncoding") != null) { this.encoding = info.getProperty("characterEncoding"); // Attempt to use the encoding, and bail out if it // can't be used try { String testString = "abc"; testString.getBytes(this.encoding); } catch (UnsupportedEncodingException UE) { throw new SQLException("Unsupported character " + "encoding '" + this.encoding + "'.", SQLError.SQL_STATE_INVALID_CONNECTION_ATTRIBUTE); } } } } /** * Sets varying properties that depend on server information. Called once * we have connected to the server. * * @param info DOCUMENT ME! * * @throws SQLException DOCUMENT ME! */ private void initializePropsFromServer(Properties info) throws SQLException { if (this.io.versionMeetsMinimum(3, 22, 1)) { this.useFastPing = true; } detectFloatingPointStyle(); this.serverVariables.clear(); // // If version is greater than 3.21.22 get the server // variables. if (this.io.versionMeetsMinimum(3, 21, 22)) { com.mysql.jdbc.Statement stmt = null; com.mysql.jdbc.ResultSet results = null; try { stmt = (com.mysql.jdbc.Statement) createStatement(); if (stmt.getMaxRows() != 0) { stmt.setMaxRows(0); } results = (com.mysql.jdbc.ResultSet) stmt.executeQuery( "SHOW VARIABLES"); while (results.next()) { this.serverVariables.put(results.getString(1), results.getString(2)); } } catch (java.sql.SQLException e) { throw e; } finally { if (results != null) { try { results.close(); } catch (java.sql.SQLException sqlE) { ; } } if (stmt != null) { try { stmt.close(); } catch (java.sql.SQLException sqlE) { ; } } } String lowerCaseTables = (String) serverVariables.get( "lower_case_table_names"); if (lowerCaseTables != null) { this.lowerCaseTableNames = lowerCaseTables.trim() .equalsIgnoreCase("on"); } if (this.useTimezone && this.serverVariables.containsKey("timezone")) { // user can specify/override as property String canoncicalTimezone = this.props.getProperty( "serverTimezone"); if ((canoncicalTimezone == null) || (canoncicalTimezone.length() == 0)) { String serverTimezoneStr = (String) this.serverVariables .get("timezone"); try { canoncicalTimezone = TimeUtil.getCanoncialTimezone(serverTimezoneStr); if (canoncicalTimezone == null) { throw new SQLException("Can't map timezone '" + serverTimezoneStr + "' to " + " canonical timezone.", SQLError.SQL_STATE_ILLEGAL_ARGUMENT); } } catch (IllegalArgumentException iae) { throw new SQLException(iae.getMessage(), SQLError.SQL_STATE_GENERAL_ERROR); } } serverTimezone = TimeZone.getTimeZone(canoncicalTimezone); // // The Calendar class has the behavior of mapping // unknown timezones to 'GMT' instead of throwing an // exception, so we must check for this... // if (!canoncicalTimezone.equalsIgnoreCase("GMT") && serverTimezone.getID().equals("GMT")) { throw new SQLException("No timezone mapping entry for '" + canoncicalTimezone + "'", SQLError.SQL_STATE_ILLEGAL_ARGUMENT); } } if (this.serverVariables.containsKey("max_allowed_packet")) { this.maxAllowedPacket = Integer.parseInt((String) this.serverVariables .get("max_allowed_packet")); } if (this.serverVariables.containsKey("net_buffer_length")) { this.netBufferLength = Integer.parseInt((String) this.serverVariables .get("net_buffer_length")); } checkTransactionIsolationLevel(); checkServerEncoding(); this.io.checkForCharsetMismatch(); } if (this.io.versionMeetsMinimum(3, 23, 15)) { this.transactionsSupported = true; setAutoCommit(true); // to override anything // the server is set to...reqd // by JDBC spec. } else { this.transactionsSupported = false; } if (this.io.versionMeetsMinimum(3, 23, 36)) { this.hasIsolationLevels = true; } else { this.hasIsolationLevels = false; } // Start logging perf/profile data if the user has requested it. String profileSql = info.getProperty("profileSql"); if ((profileSql != null) && profileSql.trim().equalsIgnoreCase("true")) { this.io.setProfileSql(true); } else { this.io.setProfileSql(false); } this.hasQuotedIdentifiers = this.io.versionMeetsMinimum(3, 23, 6); if (this.serverVariables.containsKey("sql_mode")) { int sqlMode = 0; try { sqlMode = Integer.parseInt((String) this.serverVariables.get( "sql_mode")); } catch (NumberFormatException nfe) { sqlMode = 0; } if ((sqlMode & 4) > 0) { this.useAnsiQuotes = true; } else { this.useAnsiQuotes = false; } } // // Setup client character set for MySQL-4.1 and newer // if (this.io.versionMeetsMinimum(4, 1, 0) && useUnicode() && (getEncoding() != null)) { if (getEncoding().equalsIgnoreCase("UTF-8")) { // charset names are case-sensitive execSQL("SET NAMES utf8", -1, this.database); } else { String namesEncoding = this.mysqlEncodingName; if ("koi8_ru".equals(this.mysqlEncodingName)) { // This has a _different_ name in 4.1... namesEncoding = "ko18r"; } if (namesEncoding != null) { execSQL("SET NAMES " + namesEncoding, -1, this.database); } } } this.io.resetMaxBuf(); } /** * Loads the mapping between MySQL character sets and Java character sets */ private static void loadCharacterSetMapping() { multibyteCharsetsMap = new HashMap(); Iterator multibyteCharsets = CharsetMapping.MULTIBYTE_CHARSETS.keySet() .iterator(); while (multibyteCharsets.hasNext()) { String charset = ((String) multibyteCharsets.next()).toUpperCase(); multibyteCharsetsMap.put(charset, charset); } // // Now change all server encodings to upper-case to "future-proof" // this mapping // Iterator keys = CharsetMapping.CHARSETMAP.keySet().iterator(); charsetMap = new HashMap(); while (keys.hasNext()) { String mysqlCharsetName = ((String) keys.next()).trim(); String javaCharsetName = CharsetMapping.CHARSETMAP.get(mysqlCharsetName) .toString().trim(); charsetMap.put(mysqlCharsetName.toUpperCase(), javaCharsetName); charsetMap.put(mysqlCharsetName, javaCharsetName); } } private boolean getUseUltraDevWorkAround() { return useUltraDevWorkAround; } private void checkClosed() throws SQLException { if (this.isClosed) { StringBuffer exceptionMessage = new StringBuffer(); exceptionMessage.append( "No operations allowed after connection closed."); if (!this.paranoid) { if (this.forcedCloseReason != null) { exceptionMessage.append( "\n\nConnection was closed due to the following exception:"); exceptionMessage.append(Util.stackTraceToString( this.forcedCloseReason)); } else if (this.explicitCloseLocation != null) { exceptionMessage.append( "\n\nConnection was closed explicitly by the application at the following location:"); exceptionMessage.append(Util.stackTraceToString( this.explicitCloseLocation)); } } throw new SQLException(exceptionMessage.toString(), "08003"); } } // ********************************************************************* // // END OF PUBLIC INTERFACE // // ********************************************************************* /** * Detect if the connection is still good * * @throws Exception DOCUMENT ME! */ private void ping() throws Exception { if (this.useFastPing) { this.io.sendCommand(MysqlDefs.PING, null, null); } else { this.io.sqlQuery(PING_COMMAND, MysqlDefs.MAX_ROWS, this.encoding, this, java.sql.ResultSet.CONCUR_READ_ONLY, false, this.database); } } private void pingAndReconnect(boolean ignoreAutoCommitSetting) throws SQLException { boolean localAutoCommit = this.autoCommit; // We use this to catch the 'edge' case // of autoReconnect going from true->false // if (ignoreAutoCommitSetting) { localAutoCommit = true; } if (this.failedOver && localAutoCommit) { this.queriesIssuedFailedOver++; if (shouldFallBack()) { createNewIO(true); String connectedHost = this.io.getHost(); if ((connectedHost != null) && this.hostList.get(0).equals(connectedHost)) { this.failedOver = false; this.queriesIssuedFailedOver = 0; setReadOnly(false); } } } if ((this.highAvailability || this.failedOver) && localAutoCommit) { try { ping(); } catch (Exception Ex) { createNewIO(true); } } } private void rollbackNoChecks() throws SQLException { execSQL("rollback", -1, null); } /** * Should we try to connect back to the master? We try when we've been * failed over >= this.secondsBeforeRetryMaster _or_ we've issued > * this.queriesIssuedFailedOver * * @return DOCUMENT ME! */ private boolean shouldFallBack() { long secondsSinceFailedOver = (System.currentTimeMillis() - this.masterFailTimeMillis) / 1000; return ((secondsSinceFailedOver >= this.secondsBeforeRetryMaster) || ((this.queriesIssuedFailedOver % this.queriesBeforeRetryMaster) == 0)); } /** * Wrapper class for UltraDev CallableStatements that are really * PreparedStatments. Nice going, UltraDev developers. */ class UltraDevWorkAround implements java.sql.CallableStatement { private java.sql.PreparedStatement delegate = null; UltraDevWorkAround(java.sql.PreparedStatement pstmt) { delegate = pstmt; } public void setArray(int p1, final java.sql.Array p2) throws java.sql.SQLException { delegate.setArray(p1, p2); } public java.sql.Array getArray(int p1) throws java.sql.SQLException { throw new SQLException("Not supported"); } /** * @see CallableStatement#getArray(String) */ public java.sql.Array getArray(String arg0) throws SQLException { throw new NotImplemented(); } public void setAsciiStream(int p1, final java.io.InputStream p2, int p3) throws java.sql.SQLException { delegate.setAsciiStream(p1, p2, p3); } /** * @see CallableStatement#setAsciiStream(String, InputStream, int) */ public void setAsciiStream(String arg0, InputStream arg1, int arg2) throws SQLException { throw new NotImplemented(); } public void setBigDecimal(int p1, final java.math.BigDecimal p2) throws java.sql.SQLException { delegate.setBigDecimal(p1, p2); } /** * @see CallableStatement#setBigDecimal(String, BigDecimal) */ public void setBigDecimal(String arg0, BigDecimal arg1) throws SQLException { throw new NotImplemented(); } public java.math.BigDecimal getBigDecimal(int p1) throws java.sql.SQLException { throw new SQLException("Not supported"); } public java.math.BigDecimal getBigDecimal(int p1, int p2) throws java.sql.SQLException { throw new SQLException("Not supported"); } /** * @see CallableStatement#getBigDecimal(String) */ public BigDecimal getBigDecimal(String arg0) throws SQLException { return null; } public void setBinaryStream(int p1, final java.io.InputStream p2, int p3) throws java.sql.SQLException { delegate.setBinaryStream(p1, p2, p3); } /** * @see CallableStatement#setBinaryStream(String, InputStream, int) */ public void setBinaryStream(String arg0, InputStream arg1, int arg2) throws SQLException { throw new NotImplemented(); } public void setBlob(int p1, final java.sql.Blob p2) throws java.sql.SQLException { delegate.setBlob(p1, p2); } public java.sql.Blob getBlob(int p1) throws java.sql.SQLException { throw new SQLException("Not supported"); } /** * @see CallableStatement#getBlob(String) */ public java.sql.Blob getBlob(String arg0) throws SQLException { throw new NotImplemented(); } public void setBoolean(int p1, boolean p2) throws java.sql.SQLException { delegate.setBoolean(p1, p2); } /** * @see CallableStatement#setBoolean(String, boolean) */ public void setBoolean(String arg0, boolean arg1) throws SQLException { throw new NotImplemented(); } public boolean getBoolean(int p1) throws java.sql.SQLException { throw new SQLException("Not supported"); } /** * @see CallableStatement#getBoolean(String) */ public boolean getBoolean(String arg0) throws SQLException { throw new NotImplemented(); } public void setByte(int p1, byte p2) throws java.sql.SQLException { delegate.setByte(p1, p2); } /** * @see CallableStatement#setByte(String, byte) */ public void setByte(String arg0, byte arg1) throws SQLException { throw new NotImplemented(); } public byte getByte(int p1) throws java.sql.SQLException { throw new SQLException("Not supported"); } /** * @see CallableStatement#getByte(String) */ public byte getByte(String arg0) throws SQLException { throw new NotImplemented(); } public void setBytes(int p1, byte[] p2) throws java.sql.SQLException { delegate.setBytes(p1, p2); } /** * @see CallableStatement#setBytes(String, byte[]) */ public void setBytes(String arg0, byte[] arg1) throws SQLException { throw new NotImplemented(); } public byte[] getBytes(int p1) throws java.sql.SQLException { throw new SQLException("Not supported"); } /** * @see CallableStatement#getBytes(String) */ public byte[] getBytes(String arg0) throws SQLException { throw new NotImplemented(); } public void setCharacterStream(int p1, final java.io.Reader p2, int p3) throws java.sql.SQLException { delegate.setCharacterStream(p1, p2, p3); } /** * @see CallableStatement#setCharacterStream(String, Reader, int) */ public void setCharacterStream(String arg0, Reader arg1, int arg2) throws SQLException { throw new NotImplemented(); } public void setClob(int p1, final java.sql.Clob p2) throws java.sql.SQLException { delegate.setClob(p1, p2); } public java.sql.Clob getClob(int p1) throws java.sql.SQLException { throw new SQLException("Not supported"); } /** * @see CallableStatement#getClob(String) */ public Clob getClob(String arg0) throws SQLException { throw new NotImplemented(); } public java.sql.Connection getConnection() throws java.sql.SQLException { return delegate.getConnection(); } public void setCursorName(java.lang.String p1) throws java.sql.SQLException { throw new SQLException("Not supported"); } public void setDate(int p1, final java.sql.Date p2) throws java.sql.SQLException { delegate.setDate(p1, p2); } public void setDate(int p1, final java.sql.Date p2, final java.util.Calendar p3) throws java.sql.SQLException { delegate.setDate(p1, p2, p3); } /** * @see CallableStatement#setDate(String, Date, Calendar) */ public void setDate(String arg0, Date arg1, Calendar arg2) throws SQLException { throw new NotImplemented(); } /** * @see CallableStatement#setDate(String, Date) */ public void setDate(String arg0, Date arg1) throws SQLException { throw new NotImplemented(); } public java.sql.Date getDate(int p1) throws java.sql.SQLException { throw new SQLException("Not supported"); } public java.sql.Date getDate(int p1, final java.util.Calendar p2) throws java.sql.SQLException { throw new SQLException("Not supported"); } /** * @see CallableStatement#getDate(String, Calendar) */ public Date getDate(String arg0, Calendar arg1) throws SQLException { throw new NotImplemented(); } /** * @see CallableStatement#getDate(String) */ public Date getDate(String arg0) throws SQLException { throw new NotImplemented(); } public void setDouble(int p1, double p2) throws java.sql.SQLException { delegate.setDouble(p1, p2); } /** * @see CallableStatement#setDouble(String, double) */ public void setDouble(String arg0, double arg1) throws SQLException { throw new NotImplemented(); } public double getDouble(int p1) throws java.sql.SQLException { throw new SQLException("Not supported"); } /** * @see CallableStatement#getDouble(String) */ public double getDouble(String arg0) throws SQLException { throw new NotImplemented(); } public void setEscapeProcessing(boolean p1) throws java.sql.SQLException { delegate.setEscapeProcessing(p1); } public void setFetchDirection(int p1) throws java.sql.SQLException { delegate.setFetchDirection(p1); } public int getFetchDirection() throws java.sql.SQLException { return delegate.getFetchDirection(); } public void setFetchSize(int p1) throws java.sql.SQLException { delegate.setFetchSize(p1); } public int getFetchSize() throws java.sql.SQLException { return delegate.getFetchSize(); } public void setFloat(int p1, float p2) throws java.sql.SQLException { delegate.setFloat(p1, p2); } /** * @see CallableStatement#setFloat(String, float) */ public void setFloat(String arg0, float arg1) throws SQLException { throw new NotImplemented(); } public float getFloat(int p1) throws java.sql.SQLException { throw new SQLException("Not supported"); } /** * @see CallableStatement#getFloat(String) */ public float getFloat(String arg0) throws SQLException { throw new NotImplemented(); } /** * @see Statement#getGeneratedKeys() */ public java.sql.ResultSet getGeneratedKeys() throws SQLException { return delegate.getGeneratedKeys(); } public void setInt(int p1, int p2) throws java.sql.SQLException { delegate.setInt(p1, p2); } /** * @see CallableStatement#setInt(String, int) */ public void setInt(String arg0, int arg1) throws SQLException { throw new NotImplemented(); } public int getInt(int p1) throws java.sql.SQLException { throw new SQLException("Not supported"); } /** * @see CallableStatement#getInt(String) */ public int getInt(String arg0) throws SQLException { throw new NotImplemented(); } public void setLong(int p1, long p2) throws java.sql.SQLException { delegate.setLong(p1, p2); } /** * @see CallableStatement#setLong(String, long) */ public void setLong(String arg0, long arg1) throws SQLException { throw new NotImplemented(); } public long getLong(int p1) throws java.sql.SQLException { throw new SQLException("Not supported"); } /** * @see CallableStatement#getLong(String) */ public long getLong(String arg0) throws SQLException { throw new NotImplemented(); } public void setMaxFieldSize(int p1) throws java.sql.SQLException { delegate.setMaxFieldSize(p1); } public int getMaxFieldSize() throws java.sql.SQLException { return delegate.getMaxFieldSize(); } public void setMaxRows(int p1) throws java.sql.SQLException { delegate.setMaxRows(p1); } public int getMaxRows() throws java.sql.SQLException { return delegate.getMaxRows(); } public java.sql.ResultSetMetaData getMetaData() throws java.sql.SQLException { throw new SQLException("Not supported"); } public boolean getMoreResults() throws java.sql.SQLException { return delegate.getMoreResults(); } /** * @see Statement#getMoreResults(int) */ public boolean getMoreResults(int arg0) throws SQLException { return delegate.getMoreResults(); } public void setNull(int p1, int p2) throws java.sql.SQLException { delegate.setNull(p1, p2); } public void setNull(int p1, int p2, java.lang.String p3) throws java.sql.SQLException { delegate.setNull(p1, p2, p3); } /** * @see CallableStatement#setNull(String, int, String) */ public void setNull(String arg0, int arg1, String arg2) throws SQLException { throw new NotImplemented(); } /** * @see CallableStatement#setNull(String, int) */ public void setNull(String arg0, int arg1) throws SQLException { throw new NotImplemented(); } public void setObject(int p1, final java.lang.Object p2) throws java.sql.SQLException { delegate.setObject(p1, p2); } public void setObject(int p1, final java.lang.Object p2, int p3) throws java.sql.SQLException { delegate.setObject(p1, p2, p3); } public void setObject(int p1, final java.lang.Object p2, int p3, int p4) throws java.sql.SQLException { delegate.setObject(p1, p2, p3, p4); } /** * @see CallableStatement#setObject(String, Object, int, int) */ public void setObject(String arg0, Object arg1, int arg2, int arg3) throws SQLException { throw new NotImplemented(); } /** * @see CallableStatement#setObject(String, Object, int) */ public void setObject(String arg0, Object arg1, int arg2) throws SQLException { throw new NotImplemented(); } /** * @see CallableStatement#setObject(String, Object) */ public void setObject(String arg0, Object arg1) throws SQLException { throw new NotImplemented(); } public java.lang.Object getObject(int p1) throws java.sql.SQLException { throw new SQLException("Not supported"); } public java.lang.Object getObject(int p1, final java.util.Map p2) throws java.sql.SQLException { throw new SQLException("Not supported"); } /** * @see CallableStatement#getObject(String, Map) */ public Object getObject(String arg0, Map arg1) throws SQLException { throw new NotImplemented(); } /** * @see CallableStatement#getObject(String) */ public Object getObject(String arg0) throws SQLException { throw new NotImplemented(); } /** * @see PreparedStatement#getParameterMetaData() */ public ParameterMetaData getParameterMetaData() throws SQLException { return delegate.getParameterMetaData(); } public void setQueryTimeout(int p1) throws java.sql.SQLException { throw new SQLException("Not supported"); } public int getQueryTimeout() throws java.sql.SQLException { return delegate.getQueryTimeout(); } public void setRef(int p1, final java.sql.Ref p2) throws java.sql.SQLException { throw new SQLException("Not supported"); } public java.sql.Ref getRef(int p1) throws java.sql.SQLException { throw new SQLException("Not supported"); } /** * @see CallableStatement#getRef(String) */ public Ref getRef(String arg0) throws SQLException { throw new NotImplemented(); } public java.sql.ResultSet getResultSet() throws java.sql.SQLException { return delegate.getResultSet(); } public int getResultSetConcurrency() throws java.sql.SQLException { return delegate.getResultSetConcurrency(); } /** * @see Statement#getResultSetHoldability() */ public int getResultSetHoldability() throws SQLException { return delegate.getResultSetHoldability(); } public int getResultSetType() throws java.sql.SQLException { return delegate.getResultSetType(); } public void setShort(int p1, short p2) throws java.sql.SQLException { delegate.setShort(p1, p2); } /** * @see CallableStatement#setShort(String, short) */ public void setShort(String arg0, short arg1) throws SQLException { throw new NotImplemented(); } public short getShort(int p1) throws java.sql.SQLException { throw new SQLException("Not supported"); } /** * @see CallableStatement#getShort(String) */ public short getShort(String arg0) throws SQLException { throw new NotImplemented(); } public void setString(int p1, java.lang.String p2) throws java.sql.SQLException { delegate.setString(p1, p2); } /** * @see CallableStatement#setString(String, String) */ public void setString(String arg0, String arg1) throws SQLException { throw new NotImplemented(); } public java.lang.String getString(int p1) throws java.sql.SQLException { throw new SQLException("Not supported"); } /** * @see CallableStatement#getString(String) */ public String getString(String arg0) throws SQLException { throw new NotImplemented(); } public void setTime(int p1, final java.sql.Time p2) throws java.sql.SQLException { delegate.setTime(p1, p2); } public void setTime(int p1, final java.sql.Time p2, final java.util.Calendar p3) throws java.sql.SQLException { delegate.setTime(p1, p2, p3); } /** * @see CallableStatement#setTime(String, Time, Calendar) */ public void setTime(String arg0, Time arg1, Calendar arg2) throws SQLException { throw new NotImplemented(); } /** * @see CallableStatement#setTime(String, Time) */ public void setTime(String arg0, Time arg1) throws SQLException { throw new NotImplemented(); } public java.sql.Time getTime(int p1) throws java.sql.SQLException { throw new SQLException("Not supported"); } public java.sql.Time getTime(int p1, final java.util.Calendar p2) throws java.sql.SQLException { throw new SQLException("Not supported"); } /** * @see CallableStatement#getTime(String, Calendar) */ public Time getTime(String arg0, Calendar arg1) throws SQLException { throw new NotImplemented(); } /** * @see CallableStatement#getTime(String) */ public Time getTime(String arg0) throws SQLException { throw new NotImplemented(); } public void setTimestamp(int p1, final java.sql.Timestamp p2) throws java.sql.SQLException { delegate.setTimestamp(p1, p2); } public void setTimestamp(int p1, final java.sql.Timestamp p2, final java.util.Calendar p3) throws java.sql.SQLException { delegate.setTimestamp(p1, p2, p3); } /** * @see CallableStatement#setTimestamp(String, Timestamp, Calendar) */ public void setTimestamp(String arg0, Timestamp arg1, Calendar arg2) throws SQLException { throw new NotImplemented(); } /** * @see CallableStatement#setTimestamp(String, Timestamp) */ public void setTimestamp(String arg0, Timestamp arg1) throws SQLException { throw new NotImplemented(); } public java.sql.Timestamp getTimestamp(int p1) throws java.sql.SQLException { throw new SQLException("Not supported"); } public java.sql.Timestamp getTimestamp(int p1, final java.util.Calendar p2) throws java.sql.SQLException { throw new SQLException("Not supported"); } /** * @see CallableStatement#getTimestamp(String, Calendar) */ public Timestamp getTimestamp(String arg0, Calendar arg1) throws SQLException { throw new NotImplemented(); } /** * @see CallableStatement#getTimestamp(String) */ public Timestamp getTimestamp(String arg0) throws SQLException { throw new NotImplemented(); } /** * @see CallableStatement#setURL(String, URL) */ public void setURL(String arg0, URL arg1) throws SQLException { throw new NotImplemented(); } /** * @see PreparedStatement#setURL(int, URL) */ public void setURL(int arg0, URL arg1) throws SQLException { delegate.setURL(arg0, arg1); } /** * @see CallableStatement#getURL(int) */ public URL getURL(int arg0) throws SQLException { throw new NotImplemented(); } /** * @see CallableStatement#getURL(String) */ public URL getURL(String arg0) throws SQLException { throw new NotImplemented(); } public void setUnicodeStream(int p1, final java.io.InputStream p2, int p3) throws java.sql.SQLException { delegate.setUnicodeStream(p1, p2, p3); } public int getUpdateCount() throws java.sql.SQLException { return delegate.getUpdateCount(); } public java.sql.SQLWarning getWarnings() throws java.sql.SQLException { return delegate.getWarnings(); } public void addBatch() throws java.sql.SQLException { delegate.addBatch(); } public void addBatch(java.lang.String p1) throws java.sql.SQLException { delegate.addBatch(p1); } public void cancel() throws java.sql.SQLException { delegate.cancel(); } public void clearBatch() throws java.sql.SQLException { delegate.clearBatch(); } public void clearParameters() throws java.sql.SQLException { delegate.clearParameters(); } public void clearWarnings() throws java.sql.SQLException { delegate.clearWarnings(); } public void close() throws java.sql.SQLException { delegate.close(); } public boolean execute() throws java.sql.SQLException { return delegate.execute(); } public boolean execute(java.lang.String p1) throws java.sql.SQLException { return delegate.execute(p1); } /** * @see Statement#execute(String, int) */ public boolean execute(String arg0, int arg1) throws SQLException { return delegate.execute(arg0, arg1); } /** * @see Statement#execute(String, int[]) */ public boolean execute(String arg0, int[] arg1) throws SQLException { return delegate.execute(arg0, arg1); } /** * @see Statement#execute(String, String[]) */ public boolean execute(String arg0, String[] arg1) throws SQLException { return delegate.execute(arg0, arg1); } public int[] executeBatch() throws java.sql.SQLException { return delegate.executeBatch(); } public java.sql.ResultSet executeQuery() throws java.sql.SQLException { return delegate.executeQuery(); } public java.sql.ResultSet executeQuery(java.lang.String p1) throws java.sql.SQLException { return delegate.executeQuery(p1); } public int executeUpdate() throws java.sql.SQLException { return delegate.executeUpdate(); } public int executeUpdate(java.lang.String p1) throws java.sql.SQLException { return delegate.executeUpdate(p1); } /** * @see Statement#executeUpdate(String, int) */ public int executeUpdate(String arg0, int arg1) throws SQLException { return delegate.executeUpdate(arg0, arg1); } /** * @see Statement#executeUpdate(String, int[]) */ public int executeUpdate(String arg0, int[] arg1) throws SQLException { return delegate.executeUpdate(arg0, arg1); } /** * @see Statement#executeUpdate(String, String[]) */ public int executeUpdate(String arg0, String[] arg1) throws SQLException { return delegate.executeUpdate(arg0, arg1); } public void registerOutParameter(int p1, int p2) throws java.sql.SQLException { throw new SQLException("Not supported"); } public void registerOutParameter(int p1, int p2, int p3) throws java.sql.SQLException { throw new SQLException("Not supported"); } public void registerOutParameter(int p1, int p2, java.lang.String p3) throws java.sql.SQLException { throw new SQLException("Not supported"); } /** * @see CallableStatement#registerOutParameter(String, int, int) */ public void registerOutParameter(String arg0, int arg1, int arg2) throws SQLException { throw new NotImplemented(); } /** * @see CallableStatement#registerOutParameter(String, int, String) */ public void registerOutParameter(String arg0, int arg1, String arg2) throws SQLException { throw new NotImplemented(); } /** * @see CallableStatement#registerOutParameter(String, int) */ public void registerOutParameter(String arg0, int arg1) throws SQLException { throw new NotImplemented(); } public boolean wasNull() throws java.sql.SQLException { throw new SQLException("Not supported"); } } }