diff --git a/model/jpa/src/main/java/org/keycloak/connections/jpa/DefaultJpaConnectionProviderFactory.java b/model/jpa/src/main/java/org/keycloak/connections/jpa/DefaultJpaConnectionProviderFactory.java
index 33a4745227..c7ecf0e4ed 100755
--- a/model/jpa/src/main/java/org/keycloak/connections/jpa/DefaultJpaConnectionProviderFactory.java
+++ b/model/jpa/src/main/java/org/keycloak/connections/jpa/DefaultJpaConnectionProviderFactory.java
@@ -59,6 +59,7 @@ import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
+import liquibase.GlobalConfiguration;
/**
* @author Stian Thorgersen
@@ -434,7 +435,12 @@ public class DefaultJpaConnectionProviderFactory implements JpaConnectionProvide
@Override
public String getSchema() {
- return config.get("schema");
+ String schema = config.get("schema");
+ if (schema != null && schema.contains("-") && ! Boolean.parseBoolean(System.getProperty(GlobalConfiguration.PRESERVE_SCHEMA_CASE.getKey()))) {
+ System.setProperty(GlobalConfiguration.PRESERVE_SCHEMA_CASE.getKey(), "true");
+ logger.warnf("The passed schema '%s' contains a dash. Setting liquibase config option PRESERVE_SCHEMA_CASE to true. See https://github.com/keycloak/keycloak/issues/20870 for more information.", schema);
+ }
+ return schema;
}
@Override
diff --git a/model/jpa/src/main/java/org/keycloak/connections/jpa/util/JpaUtils.java b/model/jpa/src/main/java/org/keycloak/connections/jpa/util/JpaUtils.java
index 11d7f00aff..4db97b08fd 100644
--- a/model/jpa/src/main/java/org/keycloak/connections/jpa/util/JpaUtils.java
+++ b/model/jpa/src/main/java/org/keycloak/connections/jpa/util/JpaUtils.java
@@ -34,7 +34,6 @@ import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
-import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Properties;
@@ -52,7 +51,7 @@ public class JpaUtils {
public static String getTableNameForNativeQuery(String tableName, EntityManager em) {
String schema = (String) em.getEntityManagerFactory().getProperties().get(HIBERNATE_DEFAULT_SCHEMA);
- return (schema==null) ? tableName : schema + "." + tableName;
+ return (schema==null) ? tableName : "\"" + schema + "\"." + tableName;
}
public static EntityManagerFactory createEntityManagerFactory(KeycloakSession session, String unitName, Map properties, boolean jta) {
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 9aa8b47d87..9901e271a3 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
@@ -46,6 +46,7 @@ import jakarta.transaction.NotSupportedException;
import jakarta.transaction.RollbackException;
import jakarta.transaction.SystemException;
import jakarta.transaction.Transaction;
+import liquibase.GlobalConfiguration;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.internal.SessionImpl;
@@ -401,7 +402,7 @@ public class JpaMapStorageProviderFactory implements
}
}
- String schema = config.get("schema");
+ String schema = getSchema();
if (schema != null) {
properties.put(HIBERNATE_DEFAULT_SCHEMA, schema);
}
@@ -430,6 +431,15 @@ public class JpaMapStorageProviderFactory implements
return emf;
}
+ private String getSchema() {
+ String schema = config.get("schema");
+ if (schema != null && schema.contains("-") && ! Boolean.parseBoolean(System.getProperty(GlobalConfiguration.PRESERVE_SCHEMA_CASE.getKey()))) {
+ System.setProperty(GlobalConfiguration.PRESERVE_SCHEMA_CASE.getKey(), "true");
+ logger.warnf("The passed schema '%s' contains a dash. Setting liquibase config option PRESERVE_SCHEMA_CASE to true. See https://github.com/keycloak/keycloak/issues/20870 for more information.", schema);
+ }
+ return schema;
+ }
+
protected EntityManagerFactory getEntityManagerFactory() {
return emf;
}
@@ -464,7 +474,7 @@ public class JpaMapStorageProviderFactory implements
if (logger.isDebugEnabled()) printOperationalInfo(connection);
MapJpaUpdaterProvider updater = session.getProvider(MapJpaUpdaterProvider.class);
- MapJpaUpdaterProvider.Status status = updater.validate(modelType, connection, config.get("schema"));
+ MapJpaUpdaterProvider.Status status = updater.validate(modelType, connection, getSchema());
databaseShortName = updater.getDatabaseShortName();
if (!status.equals(VALID)) {
@@ -544,10 +554,10 @@ public class JpaMapStorageProviderFactory implements
private void update(Class> modelType, Connection connection, KeycloakSession session) {
if (modelType == MapLockEntity.class) {
// as the MapLockEntity is used by the MapGlobalLockProvider itself, don't create a global lock for creating that schema
- session.getProvider(MapJpaUpdaterProvider.class).update(modelType, connection, config.get("schema"));
+ session.getProvider(MapJpaUpdaterProvider.class).update(modelType, connection, getSchema());
} else {
session.getProvider(GlobalLockProvider.class).withLock(modelType.getName(), lockedSession -> {
- lockedSession.getProvider(MapJpaUpdaterProvider.class).update(modelType, connection, config.get("schema"));
+ lockedSession.getProvider(MapJpaUpdaterProvider.class).update(modelType, connection, getSchema());
return null;
});
}
diff --git a/model/map-jpa/src/main/java/org/keycloak/models/map/storage/jpa/JpaMapUtils.java b/model/map-jpa/src/main/java/org/keycloak/models/map/storage/jpa/JpaMapUtils.java
index 818bd5a1e0..b788d3856c 100644
--- a/model/map-jpa/src/main/java/org/keycloak/models/map/storage/jpa/JpaMapUtils.java
+++ b/model/map-jpa/src/main/java/org/keycloak/models/map/storage/jpa/JpaMapUtils.java
@@ -26,7 +26,6 @@ import jakarta.persistence.EntityManagerFactory;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
-import java.util.Collections;
import java.util.Map;
import java.util.Properties;
import java.util.regex.Pattern;
@@ -44,7 +43,7 @@ public class JpaMapUtils {
public static String getSchemaForNativeQuery(EntityManager em) {
String schema = (String) em.getEntityManagerFactory().getProperties().get(HIBERNATE_DEFAULT_SCHEMA);
- return (schema == null) ? "" : schema + ".";
+ return (schema == null) ? "" : "\"" + schema + "\".";
}
/**
diff --git a/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/storage/database/jpa/AbstractJpaConnectionProviderFactory.java b/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/storage/database/jpa/AbstractJpaConnectionProviderFactory.java
index dcf14f4609..6166689b6a 100644
--- a/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/storage/database/jpa/AbstractJpaConnectionProviderFactory.java
+++ b/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/storage/database/jpa/AbstractJpaConnectionProviderFactory.java
@@ -36,9 +36,13 @@ import org.keycloak.quarkus.runtime.configuration.Configuration;
import io.quarkus.arc.Arc;
import io.quarkus.hibernate.orm.PersistenceUnit;
+import liquibase.GlobalConfiguration;
+import org.jboss.logging.Logger;
public abstract class AbstractJpaConnectionProviderFactory implements JpaConnectionProviderFactory {
+ private final Logger logger = Logger.getLogger(getClass());
+
protected Config.Scope config;
protected EntityManagerFactory entityManagerFactory;
@@ -55,7 +59,12 @@ public abstract class AbstractJpaConnectionProviderFactory implements JpaConnect
@Override
public String getSchema() {
- return Configuration.getRawValue("kc.db-schema");
+ String schema = Configuration.getRawValue("kc.db-schema");
+ if (schema != null && schema.contains("-") && ! Boolean.parseBoolean(System.getProperty(GlobalConfiguration.PRESERVE_SCHEMA_CASE.getKey()))) {
+ System.setProperty(GlobalConfiguration.PRESERVE_SCHEMA_CASE.getKey(), "true");
+ logger.warnf("The passed schema '%s' contains a dash. Setting liquibase config option PRESERVE_SCHEMA_CASE to true. See https://github.com/keycloak/keycloak/issues/20870 for more information.", schema);
+ }
+ return schema;
}
@Override