📄 connection.java
字号:
private String origDatabaseToConnectTo; private String errorMessageEncoding = "Cp1252"; // to begin with, changes after we talk to the server private boolean usePlatformCharsetConverters; /** * Creates a connection to a MySQL Server. * * @param hostToConnectTo * the hostname of the database server * @param portToConnectTo * the port number the server is listening on * @param info * a Properties[] list holding the user and password * @param databaseToConnectTo * the database to connect to * @param url * the URL of the connection * @param d * the Driver instantation of the connection * @exception SQLException * if a database access error occurs */ Connection(String hostToConnectTo, int portToConnectTo, Properties info, String databaseToConnectTo, String url) throws SQLException { this.charsetToNumBytesMap = new HashMap(); this.connectionCreationTimeMillis = System.currentTimeMillis(); this.pointOfOrigin = new Throwable(); // Stash away for later, used to clone this connection for Statement.cancel // and Statement.setQueryTimeout(). // this.origHostToConnectTo = hostToConnectTo; this.origPortToConnectTo = portToConnectTo; this.origDatabaseToConnectTo = databaseToConnectTo; try { Blob.class.getMethod("truncate", new Class[] {Long.TYPE}); this.isRunningOnJDK13 = false; } catch (NoSuchMethodException nsme) { this.isRunningOnJDK13 = true; } this.sessionCalendar = new GregorianCalendar(); this.utcCalendar = new GregorianCalendar(); this.utcCalendar.setTimeZone(TimeZone.getTimeZone("GMT")); // // Normally, this code would be in initializeDriverProperties, // but we need to do this as early as possible, so we can start // logging to the 'correct' place as early as possible...this.log // points to 'NullLogger' for every connection at startup to avoid // NPEs and the overhead of checking for NULL at every logging call. // // We will reset this to the configured logger during properties // initialization. // this.log = LogFactory.getLogger(getLogger(), LOGGER_INSTANCE_NAME); // We store this per-connection, due to static synchronization // issues in Java's built-in TimeZone class... this.defaultTimeZone = Util.getDefaultTimeZone(); if ("GMT".equalsIgnoreCase(this.defaultTimeZone.getID())) { this.isClientTzUTC = true; } else { this.isClientTzUTC = false; } this.openStatements = new HashMap(); this.serverVariables = new HashMap(); this.hostList = new ArrayList(); if (hostToConnectTo == null) { this.host = "localhost"; this.hostList.add(this.host); } else if (hostToConnectTo.indexOf(",") != -1) { // multiple hosts separated by commas (failover) StringTokenizer hostTokenizer = new StringTokenizer( hostToConnectTo, ",", false); while (hostTokenizer.hasMoreTokens()) { this.hostList.add(hostTokenizer.nextToken().trim()); } } else { this.host = hostToConnectTo; this.hostList.add(this.host); } this.hostListSize = this.hostList.size(); this.port = portToConnectTo; if (databaseToConnectTo == null) { databaseToConnectTo = ""; } this.database = databaseToConnectTo; this.myURL = url; this.user = info.getProperty(NonRegisteringDriver.USER_PROPERTY_KEY); this.password = info .getProperty(NonRegisteringDriver.PASSWORD_PROPERTY_KEY); if ((this.user == null) || this.user.equals("")) { this.user = ""; } if (this.password == null) { this.password = ""; } this.props = info; initializeDriverProperties(info); try { createNewIO(false); this.dbmd = new DatabaseMetaData(this, this.database); } catch (SQLException ex) { cleanup(ex); // don't clobber SQL exceptions throw ex; } catch (Exception ex) { cleanup(ex); StringBuffer mesg = new StringBuffer(); if (getParanoid()) { 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()); if (!getParanoid()) { mesg.append(Util.stackTraceToString(ex)); } throw SQLError.createSQLException(mesg.toString(), SQLError.SQL_STATE_COMMUNICATION_LINK_FAILURE); } } private void addToHistogram(int[] histogramCounts, long[] histogramBreakpoints, long value, int numberOfTimes, long currentLowerBound, long currentUpperBound) { if (histogramCounts == null) { createInitialHistogram(histogramBreakpoints, currentLowerBound, currentUpperBound); } for (int i = 0; i < HISTOGRAM_BUCKETS; i++) { if (histogramBreakpoints[i] >= value) { histogramCounts[i] += numberOfTimes; break; } } } private void addToPerformanceHistogram(long value, int numberOfTimes) { checkAndCreatePerformanceHistogram(); addToHistogram(this.perfMetricsHistCounts, this.perfMetricsHistBreakpoints, value, numberOfTimes, this.shortestQueryTimeMs == Long.MAX_VALUE ? 0 : this.shortestQueryTimeMs, this.longestQueryTimeMs); } private void addToTablesAccessedHistogram(long value, int numberOfTimes) { checkAndCreateTablesAccessedHistogram(); addToHistogram(this.numTablesMetricsHistCounts, this.numTablesMetricsHistBreakpoints, value, numberOfTimes, this.minimumNumberTablesAccessed == Long.MAX_VALUE ? 0 : this.minimumNumberTablesAccessed, this.maximumNumberTablesAccessed); } /** * Builds the map needed for 4.1.0 and newer servers that maps field-level * charset/collation info to a java character encoding name. * * @throws SQLException * DOCUMENT ME! */ private void buildCollationMapping() throws SQLException { if (versionMeetsMinimum(4, 1, 0)) { TreeMap sortedCollationMap = null; if (getCacheServerConfiguration()) { synchronized (serverConfigByUrl) { sortedCollationMap = (TreeMap) serverCollationByUrl .get(getURL()); } } com.mysql.jdbc.Statement stmt = null; com.mysql.jdbc.ResultSet results = null; try { if (sortedCollationMap == null) { sortedCollationMap = new TreeMap(); stmt = (com.mysql.jdbc.Statement) createStatement(); if (stmt.getMaxRows() != 0) { stmt.setMaxRows(0); } results = (com.mysql.jdbc.ResultSet) stmt .executeQuery("SHOW COLLATION"); while (results.next()) { String charsetName = results.getString(2); Integer charsetIndex = new Integer(results.getInt(3)); sortedCollationMap.put(charsetIndex, charsetName); } if (getCacheServerConfiguration()) { synchronized (serverConfigByUrl) { serverCollationByUrl.put(getURL(), sortedCollationMap); } } } // Now, merge with what we already know int highestIndex = ((Integer) sortedCollationMap.lastKey()) .intValue(); if (CharsetMapping.INDEX_TO_CHARSET.length > highestIndex) { highestIndex = CharsetMapping.INDEX_TO_CHARSET.length; } this.indexToCharsetMapping = new String[highestIndex + 1]; for (int i = 0; i < CharsetMapping.INDEX_TO_CHARSET.length; i++) { this.indexToCharsetMapping[i] = CharsetMapping.INDEX_TO_CHARSET[i]; } for (Iterator indexIter = sortedCollationMap.entrySet() .iterator(); indexIter.hasNext();) { Map.Entry indexEntry = (Map.Entry) indexIter.next(); String mysqlCharsetName = (String) indexEntry.getValue(); this.indexToCharsetMapping[((Integer) indexEntry.getKey()) .intValue()] = CharsetMapping .getJavaEncodingForMysqlEncoding(mysqlCharsetName, this); } } 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) { ; } } } } else { // Safety, we already do this as an initializer, but this makes // the intent more clear this.indexToCharsetMapping = CharsetMapping.INDEX_TO_CHARSET; } } private boolean canHandleAsServerPreparedStatement(String sql) throws SQLException { if (sql == null || sql.length() == 0) { return true; } if (getCachePreparedStatements()) { synchronized (this.serverSideStatementCheckCache) { Boolean flag = (Boolean)this.serverSideStatementCheckCache.get(sql); if (flag != null) { return flag.booleanValue(); } boolean canHandle = canHandleAsServerPreparedStatementNoCache(sql); if (sql.length() < getPreparedStatementCacheSqlLimit()) { this.serverSideStatementCheckCache.put(sql, canHandle ? Boolean.TRUE : Boolean.FALSE); } return canHandle; } } return canHandleAsServerPreparedStatementNoCache(sql); } private boolean canHandleAsServerPreparedStatementNoCache(String sql) throws SQLException { // Can't use server-side prepare for CALL if (StringUtils.startsWithIgnoreCaseAndNonAlphaNumeric(sql, "CALL")) { return false; } boolean canHandleAsStatement = true; if (!versionMeetsMinimum(5, 0, 7) && (StringUtils.startsWithIgnoreCaseAndNonAlphaNumeric(sql, "SELECT") || StringUtils.startsWithIgnoreCaseAndNonAlphaNumeric(sql, "DELETE") || StringUtils.startsWithIgnoreCaseAndNonAlphaNumeric(sql, "INSERT") || StringUtils.startsWithIgnoreCaseAndNonAlphaNumeric(sql, "UPDATE") || StringUtils.startsWithIgnoreCaseAndNonAlphaNumeric(sql, "REPLACE"))) { // check for limit ?[,?] /* * The grammar for this (from the server) is: ULONG_NUM | ULONG_NUM * ',' ULONG_NUM | ULONG_NUM OFFSET_SYM ULONG_NUM */ int currentPos = 0; int statementLength = sql.length(); int lastPosToLook = statementLength - 7; // "LIMIT ".length() boolean allowBackslashEscapes = !this.noBackslashEscapes; char quoteChar = this.useAnsiQuotes ? '"' : '\''; boolean foundLimitWithPlaceholder = false; while (currentPos < lastPosToLook) { int limitStart = StringUtils.indexOfIgnoreCaseRespectQuotes( currentPos, sql, "LIMIT ", quoteChar, allowBackslashEscapes); if (limitStart == -1) { break; } currentPos = limitStart + 7; while (currentPos < statementLength) { char c = sql.charAt(currentPos); // // Have we reached the end // of what can be in a LIMIT clause? // if (!Character.isDigit(c) && !Character.isWhitespace(c) && c != ',' && c != '?') { break; } if (c == '?') { foundLimitWithPlaceholder = true; break; } currentPos++; } } canHandleAsStatement = !foundLimitWithPlaceholder; } else if (StringUtils.startsWithIgnoreCaseAndWs(sql, "CREATE TABLE")) { canHandleAsStatement = false; } else if (StringUtils.startsWithIgnoreCaseAndWs(sql, "DO")) { canHandleAsStatement = false; } else if (StringUtils.startsWithIgnoreCaseAndWs(sql, "SET")) { canHandleAsStatement = false; } return canHandleAsStatement; } /** * Changes the user on this connection by performing a re-authentication. If * authentication fails, the connection will remain under the context of the * current user. * * @param userName * the username to authenticate with * @param newPassword * the password to authenticate with * @throws SQLException * if authentication fails, or some other error occurs while * performing the command. */ public void changeUser(String userName, String newPassword) throws SQLException { if ((userName == null) || userName.equals("")) { userName = ""; } if (newPassword == null) { newPassword = ""; } this.io.changeUser(userName, newPassword, this.database); this.user = userName; this.password = newPassword; if (versionMeetsMinimum(4, 1, 0)) { configureClientCharacterSet(); } setupServerForTruncationChecks(); } private void checkAndCreatePerformanceHistogram() { if (this.perfMetricsHistCounts == null) { this.perfMetricsHistCounts = new int[HISTOGRAM_BUCKETS]; } if (this.perfMetricsHistBreakpoints == null) { this.perfMetricsHistBreakpoints = new long[HISTOGRAM_BUCKETS]; } } private void checkAndCreateTablesAccessedHistogram() { if (this.numTablesMetricsHistCounts == null) { this.numTablesMetricsHistCounts = new int[HISTOGRAM_BUCKETS]; } if (this.numTablesMetricsHistBreakpoints == null) { this.numTablesMetricsHistBreakpoints = new long[HISTOGRAM_BUCKETS]; } } private void checkClosed() throws SQLException { if (this.isClosed) { StringBuffer messageBuf = new StringBuffer( "No operations allowed after connection closed."); if (this.forcedClosedLocation != null || this.forceClosedReason != null) { messageBuf .append("Connection was implicitly closed "); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -