diff --git a/model/map-jpa/src/main/java/org/keycloak/models/map/storage/jpa/JpaMapStorageProviderFactory.java b/model/map-jpa/src/main/java/org/keycloak/models/map/storage/jpa/JpaMapStorageProviderFactory.java index d82e12d9b2..039837f3fc 100644 --- a/model/map-jpa/src/main/java/org/keycloak/models/map/storage/jpa/JpaMapStorageProviderFactory.java +++ b/model/map-jpa/src/main/java/org/keycloak/models/map/storage/jpa/JpaMapStorageProviderFactory.java @@ -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, 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) {