From: Date: June 27 2006 10:31pm Subject: Connector/J commit: r5446 - in branches/branch_3_1/connector-j: . src/com/mysql/jdbc src/testsuite/regression List-Archive: http://lists.mysql.com/commits/8351 X-Bug: 20687 Message-Id: <200606272031.k5RKVQ4k031003@bk-internal.mysql.com> Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Modified: branches/branch_3_1/connector-j/CHANGES branches/branch_3_1/connector-j/src/com/mysql/jdbc/Connection.java branches/branch_3_1/connector-j/src/testsuite/regression/StatementRegressionTest.java Log: Fixed BUG#20687 - Can't pool server-side prepared statements, exception raised when re-using them. Merged reliability testsuite fixes from 5.0. Modified: branches/branch_3_1/connector-j/CHANGES =================================================================== --- branches/branch_3_1/connector-j/CHANGES 2006-06-27 20:24:02 UTC (rev 5445) +++ branches/branch_3_1/connector-j/CHANGES 2006-06-27 20:31:24 UTC (rev 5446) @@ -20,6 +20,9 @@ - Fixed BUG#20306 - ResultSet.getShort() for UNSIGNED TINYINT returns incorrect values when using server-side prepared statements. + - Fixed BUG#20687 - Can't pool server-side prepared statements, exception + raised when re-using them. + 05-26-06 - Version 3.1.13 - Fixed BUG#15464 - INOUT parameter does not store IN value. Modified: branches/branch_3_1/connector-j/src/com/mysql/jdbc/Connection.java =================================================================== --- branches/branch_3_1/connector-j/src/com/mysql/jdbc/Connection.java 2006-06-27 20:24:02 UTC (rev 5445) +++ branches/branch_3_1/connector-j/src/com/mysql/jdbc/Connection.java 2006-06-27 20:31:24 UTC (rev 5446) @@ -2536,6 +2536,10 @@ for (; hostIndex < this.hostListSize; hostIndex++) { try { + if (hostIndex == 0) { + this.hasTriedMasterFlag = true; + } + String newHostPortPair = (String) this.hostList .get(hostIndex); @@ -2650,6 +2654,10 @@ for (; (hostIndex < this.hostListSize) && !connectionGood; hostIndex++) { + if (hostIndex == 0) { + this.hasTriedMasterFlag = true; + } + if (this.preferSlaveDuringFailover && hostIndex == 0) { hostIndex++; } @@ -3182,39 +3190,42 @@ * the encoding name to retrieve * @return a character converter, or null if one couldn't be mapped. */ - synchronized SingleByteCharsetConverter getCharsetConverter( + SingleByteCharsetConverter getCharsetConverter( String javaEncodingName) throws SQLException { if (javaEncodingName == null) { return null; } - SingleByteCharsetConverter converter = (SingleByteCharsetConverter) this.charsetConverterMap - .get(javaEncodingName); + synchronized (this.charsetConverterMap) { + Object asObject = this.charsetConverterMap.get(javaEncodingName); + + if (asObject == CHARSET_CONVERTER_NOT_AVAILABLE_MARKER) { + return null; + } + + SingleByteCharsetConverter converter = (SingleByteCharsetConverter)asObject; - if (converter == CHARSET_CONVERTER_NOT_AVAILABLE_MARKER) { - return null; - } - - if (converter == null) { - try { - converter = SingleByteCharsetConverter.getInstance( - javaEncodingName, this); - - if (converter == null) { + if (converter == null) { + try { + converter = SingleByteCharsetConverter.getInstance( + javaEncodingName, this); + + if (converter == null) { + this.charsetConverterMap.put(javaEncodingName, + CHARSET_CONVERTER_NOT_AVAILABLE_MARKER); + } else { + this.charsetConverterMap.put(javaEncodingName, converter); + } + } catch (UnsupportedEncodingException unsupEncEx) { this.charsetConverterMap.put(javaEncodingName, CHARSET_CONVERTER_NOT_AVAILABLE_MARKER); + + converter = null; } - - this.charsetConverterMap.put(javaEncodingName, converter); - } catch (UnsupportedEncodingException unsupEncEx) { - this.charsetConverterMap.put(javaEncodingName, - CHARSET_CONVERTER_NOT_AVAILABLE_MARKER); - - converter = null; } + + return converter; } - - return converter; } /** @@ -4324,8 +4335,8 @@ pStmt = (com.mysql.jdbc.ServerPreparedStatement)this.serverSideStatementCache.remove(sql); if (pStmt != null) { + ((com.mysql.jdbc.ServerPreparedStatement)pStmt).setClosed(false); pStmt.clearParameters(); - ((com.mysql.jdbc.ServerPreparedStatement)pStmt).setClosed(false); } } @@ -5393,4 +5404,17 @@ protected boolean isRunningOnJDK13() { return this.isRunningOnJDK13; } + + /* + * For testing failover scenarios + */ + private boolean hasTriedMasterFlag = false; + + public void clearHasTriedMaster() { + this.hasTriedMasterFlag = false; + } + + public boolean hasTriedMaster() { + return this.hasTriedMasterFlag; + } } Modified: branches/branch_3_1/connector-j/src/testsuite/regression/StatementRegressionTest.java =================================================================== --- branches/branch_3_1/connector-j/src/testsuite/regression/StatementRegressionTest.java 2006-06-27 20:24:02 UTC (rev 5445) +++ branches/branch_3_1/connector-j/src/testsuite/regression/StatementRegressionTest.java 2006-06-27 20:31:24 UTC (rev 5446) @@ -1251,6 +1251,7 @@ * if the test fails. */ public void testBug3620() throws SQLException { + long epsillon = 3000; // 3 seconds time difference try { @@ -3158,4 +3159,136 @@ } } + + public void testBug20029() throws Exception { + createTable("testBug20029", ("(field1 int)")); + + long initialTimeout = 20; // may need to raise this depending on environment + // we try and do this automatically in this testcase + + for (int i = 0; i < 10; i++) { + final Connection toBeKilledConn = getConnectionWithProps(new Properties()); + final long timeout = initialTimeout; + PreparedStatement toBeKilledPstmt = null; + + try { + toBeKilledPstmt = ((com.mysql.jdbc.Connection)toBeKilledConn).clientPrepareStatement("INSERT INTO testBug20029 VALUES (?)"); + + for (int j = 0; j < 1000; j++) { + toBeKilledPstmt.setInt(1, j); + toBeKilledPstmt.addBatch(); + } + + Thread t = new Thread() { + public void run() { + try { + sleep(timeout); + toBeKilledConn.close(); + } catch (Throwable t) { + + } + } + }; + + t.start(); + + try { + if (toBeKilledConn.isClosed()) { + initialTimeout *= 2; + continue; + } + + toBeKilledPstmt.executeBatch(); + fail("Should've caught a SQLException for the statement being closed here"); + } catch (BatchUpdateException batchEx) { + assertEquals("08003", batchEx.getSQLState()); + break; + } + + fail("Connection didn't close while in the middle of PreparedStatement.executeBatch()"); + } finally { + if (toBeKilledPstmt != null) { + toBeKilledPstmt.close(); + } + + if (toBeKilledConn != null) { + toBeKilledConn.close(); + } + } + } + } + + public void testLikeWithBackslashes() throws Exception { + if (!versionMeetsMinimum(5, 0, 0)) { + return; + } + + Connection noBackslashEscapesConn = null; + + try { + Properties props = new Properties(); + props.setProperty("sessionVariables", + "sql_mode=NO_BACKSLASH_ESCAPES"); + + noBackslashEscapesConn = getConnectionWithProps(props); + + createTable( + "X_TEST", + "(userName varchar(32) not null, ivalue integer, CNAME varchar(255), bvalue CHAR(1), svalue varchar(255), ACTIVE CHAR(1), primary key (userName))"); + + String insert_sql = "insert into X_TEST (ivalue, CNAME, bvalue, svalue, ACTIVE, userName) values (?, ?, ?, ?, ?, ?)"; + + this.pstmt = noBackslashEscapesConn.prepareStatement(insert_sql); + this.pstmt.setInt(1, 0); + this.pstmt.setString(2, "c:\\jetson"); + this.pstmt.setInt(3, 1); + this.pstmt.setString(4, "c:\\jetson"); + this.pstmt.setInt(5, 1); + this.pstmt.setString(6, "c:\\jetson"); + this.pstmt.execute(); + + String select_sql = "select user0_.userName as userName0_0_, user0_.ivalue as ivalue0_0_, user0_.CNAME as CNAME0_0_, user0_.bvalue as bvalue0_0_, user0_.svalue as svalue0_0_, user0_.ACTIVE as ACTIVE0_0_ from X_TEST user0_ where user0_.userName like ?"; + this.pstmt = noBackslashEscapesConn.prepareStatement(select_sql); + this.pstmt.setString(1, "c:\\j%"); + // if we comment out the previous line and uncomment the following, the like clause matches + // stmt.setString(1,"c:\\\\j%"); + System.out.println("about to execute query " + select_sql); + this.rs = this.pstmt.executeQuery(); + assertTrue(this.rs.next()); + } finally { + closeMemberJDBCResources(); + + if (noBackslashEscapesConn != null) { + noBackslashEscapesConn.close(); + } + } + } + + /** + * Fixes BUG#20687 - Can't pool server-side prepared statements, exception + * raised when re-using them. + * + * @throws Exception if the test fails. + */ + public void testBug20687() throws Exception { + createTable("testBug20687", "(field1 int)"); + Connection poolingConn = null; + + Properties props = new Properties(); + props.setProperty("cachePrepStmts", "true"); + + try { + poolingConn = getConnectionWithProps(props); + PreparedStatement pstmt1 = poolingConn.prepareStatement("SELECT field1 FROM testBug20687"); + pstmt1.executeQuery(); + pstmt1.close(); + + PreparedStatement pstmt2 = poolingConn.prepareStatement("SELECT field1 FROM testBug20687"); + pstmt2.executeQuery(); + assertSame(pstmt1, pstmt2); + pstmt2.close(); + } finally { + + } + } }