?? connectionimpl.java
字號:
/* Copyright (C) 2002-2007 MySQL AB This program is free software; you can redistribute it and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. There are special exceptions to the terms and conditions of the GPL as it is applied to this software. View the full text of the exception in file EXCEPTIONS-CONNECTOR-J in the directory of this software distribution. 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.UnsupportedEncodingException;import java.lang.reflect.Array;import java.lang.reflect.Constructor;import java.lang.reflect.Method;import java.sql.Blob;import java.sql.DatabaseMetaData;import java.sql.SQLException;import java.sql.SQLWarning;import java.sql.Savepoint;import java.util.ArrayList;import java.util.Calendar;import java.util.GregorianCalendar;import java.util.HashMap;import java.util.Iterator;import java.util.LinkedList;import java.util.List;import java.util.Locale;import java.util.Map;import java.util.Properties;import java.util.Stack;import java.util.StringTokenizer;import java.util.TimeZone;import java.util.Timer;import java.util.TreeMap;import com.mysql.jdbc.log.Log;import com.mysql.jdbc.log.LogFactory;import com.mysql.jdbc.log.NullLogger;import com.mysql.jdbc.profiler.ProfileEventSink;import com.mysql.jdbc.profiler.ProfilerEvent;import com.mysql.jdbc.util.LRUCache;/** * 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: ConnectionImpl.java 6613 2007-10-04 16:56:05Z mmatthews $ * @see java.sql.Connection */public class ConnectionImpl extends ConnectionPropertiesImpl implements Connection { private static final String JDBC_LOCAL_CHARACTER_SET_RESULTS = "jdbc.local.character_set_results"; /** * Used as a key for caching callable statements which (may) depend on * current catalog...In 5.0.x, they don't (currently), but stored procedure * names soon will, so current catalog is a (hidden) component of the name. */ class CompoundCacheKey { String componentOne; String componentTwo; int hashCode; CompoundCacheKey(String partOne, String partTwo) { this.componentOne = partOne; this.componentTwo = partTwo; // Handle first component (in most cases, currentCatalog) // being NULL.... this.hashCode = (((this.componentOne != null) ? this.componentOne : "") + this.componentTwo).hashCode(); } /* * (non-Javadoc) * * @see java.lang.Object#equals(java.lang.Object) */ public boolean equals(Object obj) { if (obj instanceof CompoundCacheKey) { CompoundCacheKey another = (CompoundCacheKey) obj; boolean firstPartEqual = false; if (this.componentOne == null) { firstPartEqual = (another.componentOne == null); } else { firstPartEqual = this.componentOne .equals(another.componentOne); } return (firstPartEqual && this.componentTwo .equals(another.componentTwo)); } return false; } /* * (non-Javadoc) * * @see java.lang.Object#hashCode() */ public int hashCode() { return this.hashCode; } } /** * Marker for character set converter not being available (not written, * multibyte, etc) Used to prevent multiple instantiation requests. */ private static final Object CHARSET_CONVERTER_NOT_AVAILABLE_MARKER = new Object(); /** * The mapping between MySQL charset names and Java charset names. * Initialized by loadCharacterSetMapping() */ public static Map charsetMap; /** Default logger class name */ protected static final String DEFAULT_LOGGER_CLASS = "com.mysql.jdbc.log.StandardLogger"; private final static int HISTOGRAM_BUCKETS = 20; /** Logger instance name */ private static final String LOGGER_INSTANCE_NAME = "MySQL"; /** * Map mysql transaction isolation level name to * java.sql.Connection.TRANSACTION_XXX */ private static Map mapTransIsolationNameToValue = null; /** Null logger shared by all connections at startup */ private static final Log NULL_LOGGER = new NullLogger(LOGGER_INSTANCE_NAME); private static Map roundRobinStatsMap; private static final Map serverCollationByUrl = new HashMap(); private static final Map serverConfigByUrl = new HashMap(); private long queryTimeCount; private double queryTimeSum; private double queryTimeSumSquares; private double queryTimeMean; private static Timer cancelTimer; private List connectionLifecycleInterceptors; private static final Constructor JDBC_4_CONNECTION_CTOR; static { mapTransIsolationNameToValue = new HashMap(8); mapTransIsolationNameToValue.put("READ-UNCOMMITED", Constants.integerValueOf( TRANSACTION_READ_UNCOMMITTED)); mapTransIsolationNameToValue.put("READ-UNCOMMITTED", Constants.integerValueOf( TRANSACTION_READ_UNCOMMITTED)); mapTransIsolationNameToValue.put("READ-COMMITTED", Constants.integerValueOf( TRANSACTION_READ_COMMITTED)); mapTransIsolationNameToValue.put("REPEATABLE-READ", Constants.integerValueOf( TRANSACTION_REPEATABLE_READ)); mapTransIsolationNameToValue.put("SERIALIZABLE", Constants.integerValueOf( TRANSACTION_SERIALIZABLE)); boolean createdNamedTimer = false; // Use reflection magic to try this on JDK's 1.5 and newer, fallback to non-named // timer on older VMs. try { Constructor ctr = Timer.class.getConstructor(new Class[] {String.class, Boolean.TYPE}); cancelTimer = (Timer)ctr.newInstance(new Object[] { "MySQL Statement Cancellation Timer", Boolean.TRUE}); createdNamedTimer = true; } catch (Throwable t) { createdNamedTimer = false; } if (!createdNamedTimer) { cancelTimer = new Timer(true); } if (Util.isJdbc4()) { try { JDBC_4_CONNECTION_CTOR = Class.forName( "com.mysql.jdbc.JDBC4Connection").getConstructor( new Class[] { String.class, Integer.TYPE, Properties.class, String.class, String.class }); } catch (SecurityException e) { throw new RuntimeException(e); } catch (NoSuchMethodException e) { throw new RuntimeException(e); } catch (ClassNotFoundException e) { throw new RuntimeException(e); } } else { JDBC_4_CONNECTION_CTOR = null; } } protected static SQLException appendMessageToException(SQLException sqlEx, String messageToAppend) { String origMessage = sqlEx.getMessage(); String sqlState = sqlEx.getSQLState(); int vendorErrorCode = sqlEx.getErrorCode(); StringBuffer messageBuf = new StringBuffer(origMessage.length() + messageToAppend.length()); messageBuf.append(origMessage); messageBuf.append(messageToAppend); SQLException sqlExceptionWithNewMessage = SQLError.createSQLException(messageBuf .toString(), sqlState, vendorErrorCode); // // Try and maintain the original stack trace, // only works on JDK-1.4 and newer // try { // Have to do this with reflection, otherwise older JVMs croak Method getStackTraceMethod = null; Method setStackTraceMethod = null; Object theStackTraceAsObject = null; Class stackTraceElementClass = Class .forName("java.lang.StackTraceElement"); Class stackTraceElementArrayClass = Array.newInstance( stackTraceElementClass, new int[] { 0 }).getClass(); getStackTraceMethod = Throwable.class.getMethod("getStackTrace", new Class[] {}); setStackTraceMethod = Throwable.class.getMethod("setStackTrace", new Class[] { stackTraceElementArrayClass }); if (getStackTraceMethod != null && setStackTraceMethod != null) { theStackTraceAsObject = getStackTraceMethod.invoke(sqlEx, new Object[0]); setStackTraceMethod.invoke(sqlExceptionWithNewMessage, new Object[] { theStackTraceAsObject }); } } catch (NoClassDefFoundError noClassDefFound) { } catch (NoSuchMethodException noSuchMethodEx) { } catch (Throwable catchAll) { } return sqlExceptionWithNewMessage; } protected static Timer getCancelTimer() { return cancelTimer; } /** * Creates a connection instance -- We need to provide factory-style methods * so we can support both JDBC3 (and older) and JDBC4 runtimes, otherwise * the class verifier complains when it tries to load JDBC4-only interface * classes that are present in JDBC4 method signatures. */ protected static Connection getInstance(String hostToConnectTo, int portToConnectTo, Properties info, String databaseToConnectTo, String url) throws SQLException { if (!Util.isJdbc4()) { return new ConnectionImpl(hostToConnectTo, portToConnectTo, info, databaseToConnectTo, url); } return (Connection) Util.handleNewInstance(JDBC_4_CONNECTION_CTOR, new Object[] { hostToConnectTo, Constants.integerValueOf(portToConnectTo), info, databaseToConnectTo, url }); } private static synchronized int getNextRoundRobinHostIndex(String url, List hostList) { if (roundRobinStatsMap == null) { roundRobinStatsMap = new HashMap(); } int[] index = (int[]) roundRobinStatsMap.get(url); if (index == null) { index = new int[1]; index[0] = -1; roundRobinStatsMap.put(url, index); } index[0]++; if (index[0] >= hostList.size()) { index[0] = 0; } return index[0]; } private static boolean nullSafeCompare(String s1, String s2) { if (s1 == null && s2 == null) { return true; } if (s1 == null && s2 != null) { return false; } return s1.equals(s2); } /** Are we in autoCommit mode? */ private boolean autoCommit = true; /** A map of SQL to parsed prepared statement parameters. */ private Map cachedPreparedStatementParams; /** * For servers > 4.1.0, what character set is the metadata returned in? */ private String characterSetMetadata = null; /** * The character set we want results and result metadata returned in (null == * results in any charset, metadata in UTF-8). */ private String characterSetResultsOnServer = null; /** * 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 .getNumberOfCharsetsConfigured()); /** * The mapping between MySQL charset names and the max number of chars in * them. Lazily instantiated via getMaxBytesPerChar(). */ private Map charsetToNumBytesMap; /** The point in time when this connection was created */ private long connectionCreationTimeMillis = 0; /** ID used when profiling */ private long connectionId; /** The database we're currently using (called Catalog in JDBC terms). */ private String database = null; /** Internal DBMD to use for various database-version specific features */ private DatabaseMetaData dbmd = null; private TimeZone defaultTimeZone; /** The event sink to use for profiling */ private ProfileEventSink eventSink; private boolean executingFailoverReconnect = false; /** Are we failed-over to a non-master host */ private boolean failedOver = false; /** Why was this connection implicitly closed, if known? (for diagnostics) */ private Throwable forceClosedReason; /** Where was this connection implicitly closed? (for diagnostics) */ private Throwable forcedClosedLocation; /** Does the server suuport isolation levels? */ private boolean hasIsolationLevels = false; /** Does this version of MySQL support quoted identifiers? */ private boolean hasQuotedIdentifiers = false; /** The hostname we're connected to */ private String host = null; /** The list of host(s) to try and connect to */ private List hostList = null; /** How many hosts are in the host list? */ private int hostListSize = 0; /** * We need this 'bootstrapped', because 4.1 and newer will send fields back * with this even before we fill this dynamically from the server. */ private String[] indexToCharsetMapping = CharsetMapping.INDEX_TO_CHARSET; /** The I/O abstraction interface (network conn to MySQL server */ private MysqlIO io = null; private boolean isClientTzUTC = false; /** Has this connection been closed? */ private boolean isClosed = true; /** Is this connection associated with a global tx? */ private boolean isInGlobalTx = false; /** Is this connection running inside a JDK-1.3 VM? */ private boolean isRunningOnJDK13 = false; /** isolation level */ private int isolationLevel = java.sql.Connection.TRANSACTION_READ_COMMITTED; private boolean isServerTzUTC = false; /** When did the last query finish? */ private long lastQueryFinishedTime = 0;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -