Skip to content

Commit

Permalink
Fix for Bug#74932 (20066806), ConnectionImp Doesn't Close Server Prep…
Browse files Browse the repository at this point in the history
…ared Statement (PreparedStatement Leak).
  • Loading branch information
fjssilva committed Jul 3, 2017
1 parent 109e7a5 commit 05201b0
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 1 deletion.
2 changes: 2 additions & 0 deletions CHANGES
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@

Version 5.1.43

- Fix for Bug#74932 (20066806), ConnectionImp Doesn't Close Server Prepared Statement (PreparedStatement Leak).

- WL#10536, Deprecating COM_SHUTDOWN.

- Fix for Bug#25650305, GETDATE(),GETTIME() AND GETTIMESTAMP() CALL WITH NULL CALENDAR RETURNS NPE.
Expand Down
6 changes: 5 additions & 1 deletion src/com/mysql/jdbc/ConnectionImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -4273,7 +4273,11 @@ public void recachePreparedStatement(ServerPreparedStatement pstmt) throws SQLEx
synchronized (getConnectionMutex()) {
if (getCachePreparedStatements() && pstmt.isPoolable()) {
synchronized (this.serverSideStatementCache) {
this.serverSideStatementCache.put(makePreparedStatementCacheKey(pstmt.currentCatalog, pstmt.originalSql), pstmt);
Object oldServerPrepStmt = this.serverSideStatementCache.put(makePreparedStatementCacheKey(pstmt.currentCatalog, pstmt.originalSql), pstmt);
if (oldServerPrepStmt != null) {
((ServerPreparedStatement) oldServerPrepStmt).isCached = false;
((ServerPreparedStatement) oldServerPrepStmt).realClose(true, true);
}
}
}
}
Expand Down
63 changes: 63 additions & 0 deletions src/testsuite/regression/StatementRegressionTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -8290,4 +8290,67 @@ public Void call() throws Exception {
testConn.close();
} while (useSPS = !useSPS);
}

/**
* Tests fix for Bug#74932 - ConnectionImp Doesn't Close Server Prepared Statement (PreparedStatement Leak).
*/
public void testBug74932() throws Exception {
createTable("testBug74932", "(c1 INT, c2 INT)");
this.stmt.executeUpdate("INSERT INTO testBug74932 VALUES (1, 1), (1, 2), (2, 1), (2, 2)");

String sql1 = "SELECT * FROM testBug74932 WHERE c1 = ?";
String sql2 = "SELECT * FROM testBug74932 WHERE c2 = ?";

// Prepare different statements.
Connection testConn = getConnectionWithProps("prepStmtCacheSize=10,cachePrepStmts=true,useServerPrepStmts=true");
for (int i = 0; i < 10; i++) {
testBug74932ExecuteStmts(testConn, sql1, sql2);

this.rs = testConn.createStatement().executeQuery("SHOW STATUS LIKE 'Prepared_stmt_count'");
assertTrue(this.rs.next());
assertEquals(2, this.rs.getInt(2));
}
testConn.close();

// Prepare same statement.
testConn = getConnectionWithProps("prepStmtCacheSize=10,cachePrepStmts=true,useServerPrepStmts=true");
for (int i = 0; i < 10; i++) {
testBug74932ExecuteStmts(testConn, sql1, sql1);
this.rs = testConn.createStatement().executeQuery("SHOW STATUS LIKE 'Prepared_stmt_count'");
assertTrue(this.rs.next());
assertEquals(1, this.rs.getInt(2));
}
testConn.close();
}

private void testBug74932ExecuteStmts(final Connection testConn, final String sqlOuter, final String sqlInner) throws SQLException {
PreparedStatement psOuter = null;
PreparedStatement psInner = null;
ResultSet rsOuter = null;
ResultSet rsInner = null;

psOuter = testConn.prepareStatement(sqlOuter);
psOuter.setInt(1, 1);
rsOuter = psOuter.executeQuery();
for (int i = 0; i < 2; i++) {
assertTrue(rsOuter.next());
try {
psInner = testConn.prepareStatement(sqlInner);
psInner.setInt(1, 2);
rsInner = psInner.executeQuery();
assertTrue(rsInner.next());
assertTrue(rsInner.next());
assertFalse(rsInner.next());
} finally {
if (rsInner != null) {
rsInner.close();
}
psInner.close();
}
}
assertFalse(rsOuter.next());
rsOuter.close();
rsInner.close();
psOuter.close();
}
}

0 comments on commit 05201b0

Please sign in to comment.