Introduce a workaround for liquibase bug to allow use database schema with a dash in its name

Closes #20870
This commit is contained in:
vramik 2023-09-11 14:45:03 +02:00 committed by Alexander Schwartz
parent 0789d3c1cc
commit dc9970f578
5 changed files with 33 additions and 10 deletions

View file

@ -59,6 +59,7 @@ import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import liquibase.GlobalConfiguration;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
@ -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

View file

@ -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<String, Object> properties, boolean jta) {

View file

@ -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;
});
}

View file

@ -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 + "\".";
}
/**

View file

@ -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