Close prepared statement used to set the lock timeout

Closes #16801
This commit is contained in:
Alexander Schwartz 2023-02-02 18:45:08 +01:00 committed by Michal Hajas
parent 71d292ff70
commit 48aae83891

View file

@ -22,6 +22,7 @@ import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.LinkedHashMap;
@ -148,7 +149,7 @@ import org.keycloak.provider.EnvironmentDependentProviderFactory;
import org.keycloak.sessions.RootAuthenticationSessionModel;
import org.keycloak.transaction.JtaTransactionManagerLookup;
public class JpaMapStorageProviderFactory implements
public class JpaMapStorageProviderFactory implements
AmphibianProviderFactory<MapStorageProvider>,
MapStorageProviderFactory,
EnvironmentDependentProviderFactory {
@ -288,8 +289,16 @@ public class JpaMapStorageProviderFactory implements
if (lockTimeout != null) {
em.unwrap(SessionImpl.class)
.doWork(connection -> {
PreparedStatement preparedStatement = connection.prepareStatement("SET LOCAL lock_timeout = '" + lockTimeout + "';");
preparedStatement.execute();
// 'SET LOCAL lock_timeout = ...' can't be used with parameters in a prepared statement, leads to an
// 'ERROR: syntax error at or near "$1"'
// on PostgreSQL.
// Using 'set_config()' instead as described here: https://www.postgresql.org/message-id/CAKFQuwbMaoO9%3DVUY1K0Nz5YBDyE6YQ9A_A6ncCxD%2Bt0yK1AxJg%40mail.gmail.com
// See https://www.postgresql.org/docs/13/functions-admin.html for the documentation on this function
try (PreparedStatement preparedStatement = connection.prepareStatement("SELECT set_config('lock_timeout', ?, true)")) {
preparedStatement.setString(1, String.valueOf(lockTimeout));
ResultSet resultSet = preparedStatement.executeQuery();
resultSet.close();
}
});
} else {
logger.warnf("Database %s used without lockTimeout option configured. This can result in deadlock where one connection waits for a pessimistic write lock forever.", databaseShortName);
@ -490,8 +499,8 @@ public class JpaMapStorageProviderFactory implements
} else {
Class.forName(config.get("driver"));
return DriverManager.getConnection(
StringPropertyReplacer.replaceProperties(config.get("url"), System.getProperties()),
config.get("user"),
StringPropertyReplacer.replaceProperties(config.get("url"), System.getProperties()),
config.get("user"),
config.get("password"));
}
} catch (ClassNotFoundException | SQLException | NamingException e) {