Skip to content

Commit

Permalink
Fix for Bug#35811592, Missing implementation for Connection.releaseSa…
Browse files Browse the repository at this point in the history
…vepoint().

Change-Id: Ibf392dc4e4a00f8fd04406cbefdd93096995c112
  • Loading branch information
fjssilva committed Sep 18, 2023
1 parent 9df3820 commit 06a1f72
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 75 deletions.
2 changes: 2 additions & 0 deletions CHANGES
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@

Version 8.2.0

- Fix for Bug#35811592, Missing implementation for Connection.releaseSavepoint().

- Fix for Bug#91351 (Bug#28225464), MysqlConnectionPoolDataSource - autocommit status lost if global autocommit = 0.

- WL#15197, Support WebauthN in fido authentication plugin.
Expand Down
43 changes: 18 additions & 25 deletions src/main/user-impl/java/com/mysql/cj/jdbc/ConnectionImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -1741,8 +1741,21 @@ public void registerStatement(JdbcStatement stmt) {
}

@Override
public void releaseSavepoint(Savepoint arg0) throws SQLException {
// this is a no-op
public void releaseSavepoint(Savepoint savepoint) throws SQLException {
synchronized (getConnectionMutex()) {
checkClosed();

StringBuilder releaseSavepointQuery = new StringBuilder("RELEASE SAVEPOINT ");
releaseSavepointQuery
.append(StringUtils.quoteIdentifier(savepoint.getSavepointName(), this.session.getIdentifierQuoteString(), this.pedantic.getValue()));
java.sql.Statement stmt = null;
try {
stmt = getMetadataSafeStatement();
stmt.executeUpdate(releaseSavepointQuery.toString());
} finally {
closeStatement(stmt);
}
}
}

@Override
Expand Down Expand Up @@ -1836,25 +1849,18 @@ void forEach(ConnectionLifecycleInterceptor each) throws SQLException {
}

StringBuilder rollbackQuery = new StringBuilder("ROLLBACK TO SAVEPOINT ");
rollbackQuery.append('`');
rollbackQuery.append(savepoint.getSavepointName());
rollbackQuery.append('`');

rollbackQuery
.append(StringUtils.quoteIdentifier(savepoint.getSavepointName(), this.session.getIdentifierQuoteString(), this.pedantic.getValue()));
java.sql.Statement stmt = null;

try {
stmt = getMetadataSafeStatement();

stmt.executeUpdate(rollbackQuery.toString());
} catch (SQLException sqlEx) {
int errno = sqlEx.getErrorCode();

if (errno == 1181) {
String msg = sqlEx.getMessage();

if (msg != null) {
int indexOfError153 = msg.indexOf("153");

if (indexOfError153 != -1) {
throw SQLError.createSQLException(Messages.getString("Connection.22", new Object[] { savepoint.getSavepointName() }),
MysqlErrorNumbers.SQL_STATE_ILLEGAL_ARGUMENT, errno, getExceptionInterceptor());
Expand Down Expand Up @@ -2064,10 +2070,6 @@ void forEach(ConnectionLifecycleInterceptor each) throws SQLException {

String quotedId = this.session.getIdentifierQuoteString();

if (quotedId == null || quotedId.equals(" ")) {
quotedId = "";
}

StringBuilder query = new StringBuilder("USE ");
query.append(StringUtils.quoteIdentifier(db, quotedId, this.pedantic.getValue()));

Expand Down Expand Up @@ -2122,9 +2124,7 @@ public void setReadOnlyInternal(boolean readOnlyFlag) throws SQLException {
@Override
public java.sql.Savepoint setSavepoint() throws SQLException {
MysqlSavepoint savepoint = new MysqlSavepoint(getExceptionInterceptor());

setSavepoint(savepoint);

return savepoint;
}

Expand All @@ -2133,15 +2133,10 @@ private void setSavepoint(MysqlSavepoint savepoint) throws SQLException {
checkClosed();

StringBuilder savePointQuery = new StringBuilder("SAVEPOINT ");
savePointQuery.append('`');
savePointQuery.append(savepoint.getSavepointName());
savePointQuery.append('`');

savePointQuery.append(StringUtils.quoteIdentifier(savepoint.getSavepointName(), this.session.getIdentifierQuoteString(), this.pedantic.getValue()));
java.sql.Statement stmt = null;

try {
stmt = getMetadataSafeStatement();

stmt.executeUpdate(savePointQuery.toString());
} finally {
closeStatement(stmt);
Expand All @@ -2153,9 +2148,7 @@ private void setSavepoint(MysqlSavepoint savepoint) throws SQLException {
public java.sql.Savepoint setSavepoint(String name) throws SQLException {
synchronized (getConnectionMutex()) {
MysqlSavepoint savepoint = new MysqlSavepoint(name, getExceptionInterceptor());

setSavepoint(savepoint);

return savepoint;
}
}
Expand Down
99 changes: 49 additions & 50 deletions src/test/java/testsuite/simple/ConnectionTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -322,58 +322,57 @@ public void testIsolationLevel() throws Exception {
*/
@Test
public void testSavepoint() throws Exception {
DatabaseMetaData dbmd = this.conn.getMetaData();
assumeTrue(this.conn.getMetaData().supportsSavepoints(), "Savepoints not supported");

if (dbmd.supportsSavepoints()) {
System.out.println("Testing SAVEPOINTs");
try {
this.conn.setAutoCommit(true);

try {
this.conn.setAutoCommit(true);

createTable("testSavepoints", "(field1 int)", "InnoDB");

// Try with named save points
this.conn.setAutoCommit(false);
this.stmt.executeUpdate("INSERT INTO testSavepoints VALUES (1)");

Savepoint afterInsert = this.conn.setSavepoint("afterInsert");
this.stmt.executeUpdate("UPDATE testSavepoints SET field1=2");

Savepoint afterUpdate = this.conn.setSavepoint("afterUpdate");
this.stmt.executeUpdate("DELETE FROM testSavepoints");

assertTrue(getRowCount("testSavepoints") == 0, "Row count should be 0");
this.conn.rollback(afterUpdate);
assertTrue(getRowCount("testSavepoints") == 1, "Row count should be 1");
assertTrue("2".equals(getSingleValue("testSavepoints", "field1", null).toString()), "Value should be 2");
this.conn.rollback(afterInsert);
assertTrue("1".equals(getSingleValue("testSavepoints", "field1", null).toString()), "Value should be 1");
this.conn.rollback();
assertTrue(getRowCount("testSavepoints") == 0, "Row count should be 0");

// Try with 'anonymous' save points
this.conn.rollback();

this.stmt.executeUpdate("INSERT INTO testSavepoints VALUES (1)");
afterInsert = this.conn.setSavepoint();
this.stmt.executeUpdate("UPDATE testSavepoints SET field1=2");
afterUpdate = this.conn.setSavepoint();
this.stmt.executeUpdate("DELETE FROM testSavepoints");

assertTrue(getRowCount("testSavepoints") == 0, "Row count should be 0");
this.conn.rollback(afterUpdate);
assertTrue(getRowCount("testSavepoints") == 1, "Row count should be 1");
assertTrue("2".equals(getSingleValue("testSavepoints", "field1", null).toString()), "Value should be 2");
this.conn.rollback(afterInsert);
assertTrue("1".equals(getSingleValue("testSavepoints", "field1", null).toString()), "Value should be 1");
this.conn.rollback();

this.conn.releaseSavepoint(this.conn.setSavepoint());
} finally {
this.conn.setAutoCommit(true);
}
} else {
System.out.println("MySQL version does not support SAVEPOINTs");
createTable("testSavepoints", "(field1 int)", "InnoDB");

// Try with named save points
this.conn.setAutoCommit(false);
this.stmt.executeUpdate("INSERT INTO testSavepoints VALUES (1)");

Savepoint afterInsert = this.conn.setSavepoint("afterInsert");
this.stmt.executeUpdate("UPDATE testSavepoints SET field1=2");

Savepoint afterUpdate = this.conn.setSavepoint("afterUpdate");
this.stmt.executeUpdate("DELETE FROM testSavepoints");

assertEquals(0, getRowCount("testSavepoints"), "Row count should be 0");
this.conn.rollback(afterUpdate);
assertEquals(1, getRowCount("testSavepoints"), "Row count should be 1");
assertEquals("2", getSingleValue("testSavepoints", "field1", null).toString(), "Value should be 2");
this.conn.rollback(afterInsert);
assertEquals("1", getSingleValue("testSavepoints", "field1", null).toString(), "Value should be 1");
this.conn.rollback();
assertEquals(0, getRowCount("testSavepoints"), "Row count should be 0");

// Try with 'anonymous' save points
this.conn.rollback();

this.stmt.executeUpdate("INSERT INTO testSavepoints VALUES (1)");
afterInsert = this.conn.setSavepoint();
this.stmt.executeUpdate("UPDATE testSavepoints SET field1=2");
afterUpdate = this.conn.setSavepoint();
this.stmt.executeUpdate("DELETE FROM testSavepoints");

assertEquals(0, getRowCount("testSavepoints"), "Row count should be 0");
this.conn.rollback(afterUpdate);
assertEquals(1, getRowCount("testSavepoints"), "Row count should be 1");
assertEquals("2", getSingleValue("testSavepoints", "field1", null).toString(), "Value should be 2");
this.conn.rollback(afterInsert);
assertEquals("1", getSingleValue("testSavepoints", "field1", null).toString(), "Value should be 1");
this.conn.rollback();

Savepoint savepoint = this.conn.setSavepoint();
this.conn.releaseSavepoint(savepoint);
assertThrows(SQLException.class, "SAVEPOINT .* does not exist", () -> {
this.conn.rollback(savepoint);
return null;
});
} finally {
this.conn.setAutoCommit(true);
}
}

Expand Down

0 comments on commit 06a1f72

Please sign in to comment.