📄 connection.java
字号:
// We store this per-connection, due to static synchronization // issues in Java's built-in TimeZone class... this.defaultTimeZone = TimeZone.getDefault(); 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(new Throwable(), ex); // don't clobber SQL exceptions throw ex; } catch (Exception ex) { cleanup(new Throwable(), 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 new SQLException(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(histogramCounts, 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 synchronized boolean canHandleAsServerPreparedStatement(String sql) throws SQLException { if (sql == null || sql.length() == 0) { return true; } if (getCachePreparedStatements()) { Boolean flag = (Boolean)this.serverSideStatementCheckCache.get(sql); if (flag != null) { return flag.booleanValue(); } } 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; } if (getCachePreparedStatements() && sql.length() < getPreparedStatementCacheSqlLimit()) { this.serverSideStatementCheckCache.put(sql, canHandleAsStatement ? Boolean.TRUE : Boolean.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(); } } 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 "); } if (this.forcedClosedLocation != null) { messageBuf.append("\n\n"); messageBuf .append(" at (stack trace):\n"); messageBuf.append(Util .stackTraceToString(this.forcedClosedLocation)); } if (this.forceClosedReason != null) { if (this.forcedClosedLocation != null) { messageBuf.append("\n\nDue "); } else { messageBuf.append("due "); } messageBuf.append("to underlying exception/error:\n"); messageBuf.append(Util .stackTraceToString(this.forceClosedReason)); } throw new SQLException(messageBuf.toString(), SQLError.SQL_STATE_CONNECTION_NOT_OPEN); } } /** * 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 (getUseUnicode() && (getEncoding() != null)) { // spec'd by client, don't map return; } String serverEncoding = (String) this.serverVariables .get("character_set"); if (serverEncoding == null) { // must be 4.1.1 or newer? serverEncoding = (String) this.serverVariables .get("character_set_server"); } String mappedServerEncoding = null; if (serverEncoding != null) { mappedServerEncoding = CharsetMapping .getJavaEncodingForMysqlEncoding(serverEncoding .toUpperCase(Locale.ENGLISH), this); } // // First check if we can do the encoding ourselves // if (!getUseUnicode() && (mappedServerEncoding != null)) { SingleByteCharsetConverter converter = getCharsetConverter(mappedServerEncoding); if (converter != null) { // we know how to convert this ourselves setUseUnicode(true); // force the issue setEncoding(mappedServerEncoding); return; } } // // Now, try and find a Java I/O converter that can do // the encoding for us // if (serverEncoding != null) { if (mappedServerEncoding == null) { // We don't have a mapping for it, so try // and canonicalize the name.... if (Character.isLowerCase(serverEncoding.charAt(0))) { char[] ach = serverEncoding.toCharArray(); ach[0] = Character.toUpperCase(serverEncoding.charAt(0)); setEncoding(new String(ach)); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -