Upgrade to Liquibase 4.6.2

* Upgrade to Liquibase 4.6.2
* Add valid checksums to changesets to allow migration to newest liquibase
* Update liquibase licenses

Co-authored-by: Martin Kanis <mkanis@redhat.com>
This commit is contained in:
Stefan Guilhen 2022-02-09 08:56:46 -03:00 committed by GitHub
parent 75c7491b85
commit 7c1d6eae43
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
96 changed files with 718 additions and 525 deletions

View file

@ -81,11 +81,11 @@
<dependency>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-core</artifactId>
<version>3.5.5</version>
<version>4.6.2</version>
<licenses>
<license>
<name>Apache Software License 2.0</name>
<url>https://raw.githubusercontent.com/liquibase/liquibase/liquibase-parent-3.5.5/LICENSE.txt</url>
<url>https://raw.githubusercontent.com/liquibase/liquibase/v4.6.2/LICENSE.txt</url>
</license>
</licenses>
</dependency>

View file

@ -81,11 +81,11 @@
<dependency>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-core</artifactId>
<version>3.5.5.redhat-1</version>
<version>4.6.2.redhat-00001</version>
<licenses>
<license>
<name>Apache Software License 2.0</name>
<url>https://raw.githubusercontent.com/liquibase/liquibase/liquibase-parent-3.5.5/LICENSE.txt</url>
<url>https://raw.githubusercontent.com/liquibase/liquibase/v4.6.2/LICENSE.txt</url>
</license>
</licenses>
</dependency>

View file

@ -32,7 +32,7 @@
<module name="org.keycloak.keycloak-server-spi-private"/>
<module name="javax.persistence.api"/>
<module name="org.jboss.logging"/>
<module name="org.liquibase"/>
<module name="org.liquibase" services="import"/>
<module name="org.javassist"/>
<module name="org.hibernate" services="import"/>
<module name="org.bouncycastle" />

View file

@ -96,11 +96,11 @@
<dependency>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-core</artifactId>
<version>3.5.5</version>
<version>3.6.2</version>
<licenses>
<license>
<name>Apache Software License 2.0</name>
<url>https://raw.githubusercontent.com/liquibase/liquibase/liquibase-parent-3.5.5/LICENSE.txt</url>
<url>https://raw.githubusercontent.com/liquibase/liquibase/v4.6.2/LICENSE.txt</url>
</license>
</licenses>
</dependency>

View file

@ -81,11 +81,11 @@
<dependency>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-core</artifactId>
<version>3.5.5.redhat-1</version>
<version>4.6.2.redhat-00001</version>
<licenses>
<license>
<name>Apache Software License 2.0</name>
<url>https://raw.githubusercontent.com/liquibase/liquibase/liquibase-parent-3.5.5/LICENSE.txt</url>
<url>https://raw.githubusercontent.com/liquibase/liquibase/v4.6.2/LICENSE.txt</url>
</license>
</licenses>
</dependency>

View file

@ -32,7 +32,7 @@
<module name="org.keycloak.keycloak-server-spi-private"/>
<module name="javax.persistence.api"/>
<module name="org.jboss.logging"/>
<module name="org.liquibase"/>
<module name="org.liquibase" services="import"/>
<module name="org.javassist"/>
<module name="org.hibernate" services="import"/>
<module name="org.bouncycastle" />

View file

@ -0,0 +1,22 @@
/*
* Copyright 2022 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.connections.jpa.updater.liquibase;
public class LiquibaseConstants {
public static final String JDBC_EXECUTOR = "jdbc";
}

View file

@ -20,6 +20,7 @@ package org.keycloak.connections.jpa.updater.liquibase;
import liquibase.Contexts;
import liquibase.LabelExpression;
import liquibase.Liquibase;
import liquibase.Scope;
import liquibase.changelog.ChangeLogHistoryService;
import liquibase.changelog.ChangeLogHistoryServiceFactory;
import liquibase.changelog.ChangeSet;
@ -79,15 +80,19 @@ public class LiquibaseJpaUpdaterProvider implements JpaUpdaterProvider {
@Override
public void update(Connection connection, String defaultSchema) {
update(connection, null, defaultSchema);
synchronized (LiquibaseJpaUpdaterProvider.class) {
updateSynch(connection, null, defaultSchema);
}
}
@Override
public void export(Connection connection, String defaultSchema, File file) {
update(connection, file, defaultSchema);
synchronized (LiquibaseJpaUpdaterProvider.class) {
updateSynch(connection, file, defaultSchema);
}
}
private void update(Connection connection, File file, String defaultSchema) {
private void updateSynch(Connection connection, File file, String defaultSchema) {
logger.debug("Starting database update");
// Need ThreadLocal as liquibase doesn't seem to have API to inject custom objects into tasks
@ -100,7 +105,7 @@ public class LiquibaseJpaUpdaterProvider implements JpaUpdaterProvider {
if (file != null) {
exportWriter = new FileWriter(file);
}
updateChangeSet(liquibase, connection, exportWriter);
updateChangeSet(liquibase, exportWriter);
// Run update for each custom JpaEntityProvider
Set<JpaEntityProvider> jpaProviders = session.getAllProviders(JpaEntityProvider.class);
@ -110,7 +115,7 @@ public class LiquibaseJpaUpdaterProvider implements JpaUpdaterProvider {
String factoryId = jpaProvider.getFactoryId();
String changelogTableName = JpaUtils.getCustomChangelogTableName(factoryId);
liquibase = getLiquibaseForCustomProviderUpdate(connection, defaultSchema, customChangelog, jpaProvider.getClass().getClassLoader(), changelogTableName);
updateChangeSet(liquibase, connection, exportWriter);
updateChangeSet(liquibase, exportWriter);
}
}
} catch (LiquibaseException | IOException | SQLException e) {
@ -128,7 +133,7 @@ public class LiquibaseJpaUpdaterProvider implements JpaUpdaterProvider {
}
}
protected void updateChangeSet(Liquibase liquibase, Connection connection, Writer exportWriter) throws LiquibaseException, SQLException {
protected void updateChangeSet(Liquibase liquibase, Writer exportWriter) throws LiquibaseException, SQLException {
String changelog = liquibase.getChangeLogFile();
Database database = liquibase.getDatabase();
Table changelogTable = SnapshotGeneratorFactory.getInstance().getDatabaseChangeLogTable(new SnapshotControl(database, false, Table.class, Column.class), database);
@ -152,8 +157,8 @@ public class LiquibaseJpaUpdaterProvider implements JpaUpdaterProvider {
statementsToExecute.add(new SetNullableStatement(database.getLiquibaseCatalogName(), database.getLiquibaseSchemaName(),
changelogTable.getName(), DEPLOYMENT_ID_COLUMN, "VARCHAR(10)", false));
ExecutorService executorService = ExecutorService.getInstance();
Executor executor = executorService.getExecutor(liquibase.getDatabase());
ExecutorService executorService = Scope.getCurrentScope().getSingleton(ExecutorService.class);
Executor executor = executorService.getExecutor(LiquibaseConstants.JDBC_EXECUTOR, liquibase.getDatabase());
for (SqlStatement sql : statementsToExecute) {
executor.execute(sql);
@ -179,7 +184,7 @@ public class LiquibaseJpaUpdaterProvider implements JpaUpdaterProvider {
if (ranChangeSets.isEmpty()) {
outputChangeLogTableCreationScript(liquibase, exportWriter);
}
liquibase.update((Contexts) null, new LabelExpression(), exportWriter, false);
liquibase.update(null, new LabelExpression(), exportWriter, false);
} else {
liquibase.update((Contexts) null);
}
@ -197,26 +202,34 @@ public class LiquibaseJpaUpdaterProvider implements JpaUpdaterProvider {
private void outputChangeLogTableCreationScript(Liquibase liquibase, final Writer exportWriter) throws DatabaseException {
Database database = liquibase.getDatabase();
Executor oldTemplate = ExecutorService.getInstance().getExecutor(database);
LoggingExecutor executor = new LoggingExecutor(ExecutorService.getInstance().getExecutor(database), exportWriter, database);
ExecutorService.getInstance().setExecutor(database, executor);
ExecutorService executorService = Scope.getCurrentScope().getSingleton(ExecutorService.class);
Executor oldTemplate = executorService.getExecutor(LiquibaseConstants.JDBC_EXECUTOR, database);
LoggingExecutor loggingExecutor = new LoggingExecutor(oldTemplate, exportWriter, database);
executorService.setExecutor(LiquibaseConstants.JDBC_EXECUTOR, database, loggingExecutor);
executor.comment("*********************************************************************");
executor.comment("* Keycloak database creation script - apply this script to empty DB *");
executor.comment("*********************************************************************" + StreamUtil.getLineSeparator());
loggingExecutor.comment("*********************************************************************");
loggingExecutor.comment("* Keycloak database creation script - apply this script to empty DB *");
loggingExecutor.comment("*********************************************************************" + StreamUtil.getLineSeparator());
executor.execute(new CreateDatabaseChangeLogTableStatement());
loggingExecutor.execute(new CreateDatabaseChangeLogTableStatement());
// DatabaseChangeLogLockTable is created before this code is executed and recreated if it does not exist automatically
// in org.keycloak.connections.jpa.updater.liquibase.lock.CustomLockService.init() called indirectly from
// KeycloakApplication constructor (search for waitForLock() call). Hence it is not included in the creation script.
executor.comment("*********************************************************************" + StreamUtil.getLineSeparator());
loggingExecutor.comment("*********************************************************************" + StreamUtil.getLineSeparator());
ExecutorService.getInstance().setExecutor(database, oldTemplate);
executorService.setExecutor(LiquibaseConstants.JDBC_EXECUTOR, database, oldTemplate);
}
@Override
public Status validate(Connection connection, String defaultSchema) {
synchronized (LiquibaseJpaUpdaterProvider.class) {
return this.validateSynch(connection, defaultSchema);
}
}
protected Status validateSynch(final Connection connection, final String defaultSchema) {
logger.debug("Validating if database is updated");
ThreadLocalSessionContext.setCurrentSession(session);
@ -279,13 +292,8 @@ public class LiquibaseJpaUpdaterProvider implements JpaUpdaterProvider {
ChangeLogHistoryServiceFactory.getInstance().register(new CustomChangeLogHistoryService());
}
@SuppressWarnings("unchecked")
private List<ChangeSet> getLiquibaseUnrunChangeSets(Liquibase liquibase) {
// TODO tracked as: https://issues.jboss.org/browse/KEYCLOAK-3730
// TODO: When https://liquibase.jira.com/browse/CORE-2919 is resolved, replace the following two lines with:
// List<ChangeSet> changeSets = liquibase.listUnrunChangeSets((Contexts) null, new LabelExpression(), false);
Method listUnrunChangeSets = Reflections.findDeclaredMethod(Liquibase.class, "listUnrunChangeSets", Contexts.class, LabelExpression.class, boolean.class);
return Reflections.invokeMethod(true, listUnrunChangeSets, List.class, liquibase, (Contexts) null, new LabelExpression(), false);
private List<ChangeSet> getLiquibaseUnrunChangeSets(Liquibase liquibase) throws LiquibaseException {
return liquibase.listUnrunChangeSets(null, new LabelExpression(), false);
}
private Liquibase getLiquibaseForKeycloakUpdate(Connection connection, String defaultSchema) throws LiquibaseException {

View file

@ -17,6 +17,7 @@
package org.keycloak.connections.jpa.updater.liquibase;
import liquibase.Scope;
import liquibase.database.DatabaseConnection;
import liquibase.database.core.PostgresDatabase;
import liquibase.exception.DatabaseException;
@ -61,9 +62,8 @@ public class PostgresPlusDatabase extends PostgresDatabase {
@Override
protected String getConnectionSchemaName() {
try {
String currentSchema = ExecutorService.getInstance().getExecutor(this)
return Scope.getCurrentScope().getSingleton(ExecutorService.class).getExecutor(LiquibaseConstants.JDBC_EXECUTOR, this)
.queryForObject(new RawSqlStatement("select current_schema"), String.class);
return currentSchema;
} catch (Exception e) {
throw new RuntimeException("Failed to get current schema", e);

View file

@ -18,40 +18,24 @@
package org.keycloak.connections.jpa.updater.liquibase.conn;
import liquibase.Liquibase;
import liquibase.change.ChangeFactory;
import liquibase.changelog.ChangeSet;
import liquibase.changelog.DatabaseChangeLog;
import liquibase.Scope;
import liquibase.database.AbstractJdbcDatabase;
import liquibase.database.Database;
import liquibase.database.DatabaseFactory;
import liquibase.database.jvm.JdbcConnection;
import liquibase.datatype.DataTypeFactory;
import liquibase.exception.LiquibaseException;
import liquibase.logging.LogFactory;
import liquibase.logging.LogLevel;
import liquibase.resource.ClassLoaderResourceAccessor;
import liquibase.resource.ResourceAccessor;
import liquibase.servicelocator.ServiceLocator;
import liquibase.sqlgenerator.SqlGeneratorFactory;
import org.jboss.logging.Logger;
import org.keycloak.Config;
import org.keycloak.connections.jpa.updater.liquibase.CustomForeignKeySnapshotGenerator;
import org.keycloak.connections.jpa.updater.liquibase.LiquibaseJpaUpdaterProvider;
import org.keycloak.connections.jpa.updater.liquibase.PostgresPlusDatabase;
import org.keycloak.connections.jpa.updater.liquibase.MySQL8VarcharType;
import org.keycloak.connections.jpa.updater.liquibase.UpdatedMariaDBDatabase;
import org.keycloak.connections.jpa.updater.liquibase.UpdatedMySqlDatabase;
import org.keycloak.connections.jpa.updater.liquibase.custom.CustomCreateIndexChange;
import org.keycloak.connections.jpa.updater.liquibase.lock.CustomInsertLockRecordGenerator;
import org.keycloak.connections.jpa.updater.liquibase.lock.CustomLockDatabaseChangeLogGenerator;
import org.keycloak.connections.jpa.updater.liquibase.lock.DummyLockService;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeycloakSessionFactory;
import java.sql.Connection;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
import liquibase.changelog.ChangeLogHistoryServiceFactory;
import liquibase.snapshot.SnapshotGeneratorFactory;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
@ -83,54 +67,25 @@ public class DefaultLiquibaseConnectionProvider implements LiquibaseConnectionPr
}
protected void baseLiquibaseInitialization() {
ServiceLocator sl = ServiceLocator.getInstance();
sl.setResourceAccessor(new ClassLoaderResourceAccessor(getClass().getClassLoader()));
if (!System.getProperties().containsKey("liquibase.scan.packages")) {
if (sl.getPackages().remove("liquibase.core")) {
sl.addPackageToScan("liquibase.core.xml");
}
if (sl.getPackages().remove("liquibase.parser")) {
sl.addPackageToScan("liquibase.parser.core.xml");
}
if (sl.getPackages().remove("liquibase.serializer")) {
sl.addPackageToScan("liquibase.serializer.core.xml");
}
sl.getPackages().remove("liquibase.ext");
sl.getPackages().remove("liquibase.sdk");
String lockPackageName = DummyLockService.class.getPackage().getName();
logger.debugf("Added package %s to liquibase", lockPackageName);
sl.addPackageToScan(lockPackageName);
// we need to initialize the scope using the right classloader, or else Liquibase won't be able to locate the extensions.
ClassLoader currentClassLoader = Thread.currentThread().getContextClassLoader();
try {
Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader());
Scope.getCurrentScope();
} finally {
Thread.currentThread().setContextClassLoader(currentClassLoader);
}
LogFactory.setInstance(new LogWrapper());
// Adding PostgresPlus support to liquibase
DatabaseFactory.getInstance().register(new PostgresPlusDatabase());
// Adding newer version of MySQL/MariaDB support to liquibase
DatabaseFactory.getInstance().register(new UpdatedMySqlDatabase());
DatabaseFactory.getInstance().register(new UpdatedMariaDBDatabase());
// Adding CustomVarcharType for MySQL 8 and newer
DataTypeFactory.getInstance().register(MySQL8VarcharType.class);
// Change command for creating lock and drop DELETE lock record from it
SqlGeneratorFactory.getInstance().register(new CustomInsertLockRecordGenerator());
// Use "SELECT FOR UPDATE" for locking database
SqlGeneratorFactory.getInstance().register(new CustomLockDatabaseChangeLogGenerator());
ChangeLogHistoryServiceFactory.getInstance().register(new CustomChangeLogHistoryService());
// Adding CustomCreateIndexChange for handling conditional indices creation
ChangeFactory.getInstance().register(CustomCreateIndexChange.class);
// Contains fix for https://liquibase.jira.com/browse/CORE-3141
SnapshotGeneratorFactory.getInstance().register(new CustomForeignKeySnapshotGenerator());
// using the initialized scope, create a child scope that sets the classloader and resource accessor so that any attempt
// by Liquibase to load a class (e.g. custom change) using the scope's classloader uses the correct classloader.
final Map<String, Object> scopeValues = new HashMap<>();
scopeValues.put(Scope.Attr.resourceAccessor.name(), new ClassLoaderResourceAccessor(this.getClass().getClassLoader()));
scopeValues.put(Scope.Attr.classLoader.name(), this.getClass().getClassLoader());
try {
Scope.enter(scopeValues);
} catch (Exception e) {
throw new RuntimeException("Failed to initialize Liquibase: " + e.getMessage(), e);
}
}
@Override
@ -184,109 +139,4 @@ public class DefaultLiquibaseConnectionProvider implements LiquibaseConnectionPr
return new Liquibase(changelogLocation, resourceAccessor, database);
}
private static class LogWrapper extends LogFactory {
private static final liquibase.logging.Logger logger = new liquibase.logging.Logger() {
@Override
public void setName(String name) {
}
@Override
public void setLogLevel(String level) {
}
@Override
public void setLogLevel(LogLevel level) {
}
@Override
public void setLogLevel(String logLevel, String logFile) {
}
@Override
public void severe(String message) {
DefaultLiquibaseConnectionProvider.logger.error(message);
}
@Override
public void severe(String message, Throwable e) {
DefaultLiquibaseConnectionProvider.logger.error(message, e);
}
@Override
public void warning(String message) {
// Ignore this warning as cascaded drops doesn't work anyway with all DBs, which we need to support
if ("Database does not support drop with cascade".equals(message)) {
DefaultLiquibaseConnectionProvider.logger.debug(message);
} else {
DefaultLiquibaseConnectionProvider.logger.warn(message);
}
}
@Override
public void warning(String message, Throwable e) {
DefaultLiquibaseConnectionProvider.logger.warn(message, e);
}
@Override
public void info(String message) {
DefaultLiquibaseConnectionProvider.logger.debug(message);
}
@Override
public void info(String message, Throwable e) {
DefaultLiquibaseConnectionProvider.logger.debug(message, e);
}
@Override
public void debug(String message) {
if (DefaultLiquibaseConnectionProvider.logger.isTraceEnabled()) {
DefaultLiquibaseConnectionProvider.logger.trace(message);
}
}
@Override
public LogLevel getLogLevel() {
if (DefaultLiquibaseConnectionProvider.logger.isTraceEnabled()) {
return LogLevel.DEBUG;
} else if (DefaultLiquibaseConnectionProvider.logger.isDebugEnabled()) {
return LogLevel.INFO;
} else {
return LogLevel.WARNING;
}
}
@Override
public void debug(String message, Throwable e) {
DefaultLiquibaseConnectionProvider.logger.trace(message, e);
}
@Override
public void setChangeLog(DatabaseChangeLog databaseChangeLog) {
}
@Override
public void setChangeSet(ChangeSet changeSet) {
}
@Override
public int getPriority() {
return 0;
}
@Override
public void closeLogFile() {}
};
@Override
public liquibase.logging.Logger getLog(String name) {
return logger;
}
@Override
public liquibase.logging.Logger getLog() {
return logger;
}
}
}

View file

@ -18,7 +18,9 @@ package org.keycloak.connections.jpa.updater.liquibase.custom;
import java.io.StringWriter;
import liquibase.Scope;
import org.jboss.logging.Logger;
import org.keycloak.connections.jpa.updater.liquibase.LiquibaseConstants;
import org.keycloak.connections.jpa.updater.liquibase.LiquibaseJpaUpdaterProvider;
import org.keycloak.connections.jpa.updater.liquibase.conn.DefaultLiquibaseConnectionProvider;
@ -57,7 +59,7 @@ public class CustomCreateIndexChange extends CreateIndexChange {
@Override
public SqlStatement[] generateStatements(Database database) {
// This check is for manual migration
if (ExecutorService.getInstance().getExecutor(database) instanceof LoggingExecutor)
if (Scope.getCurrentScope().getSingleton(ExecutorService.class).getExecutor(LiquibaseConstants.JDBC_EXECUTOR, database) instanceof LoggingExecutor)
return super.generateStatements(database);
Object indexCreationThreshold = ((AbstractJdbcDatabase) database)
@ -76,8 +78,8 @@ public class CustomCreateIndexChange extends CreateIndexChange {
.has(new Table().setName(getTableName()).setSchema(new Schema(getCatalogName(), getSchemaName())), database))
return super.generateStatements(database);
int result = ExecutorService.getInstance().getExecutor(database).queryForInt(
new RawSqlStatement("SELECT COUNT(*) FROM " + getTableNameForSqlSelects(database, getTableName())));
int result = Scope.getCurrentScope().getSingleton(ExecutorService.class).getExecutor(LiquibaseConstants.JDBC_EXECUTOR, database)
.queryForInt(new RawSqlStatement("SELECT COUNT(*) FROM " + getTableNameForSqlSelects(database, getTableName())));
if (result > this.indexCreationThreshold) {
String loggingString = createLoggingString(database);
@ -100,10 +102,10 @@ public class CustomCreateIndexChange extends CreateIndexChange {
private String createLoggingString(Database database) throws DatabaseException {
StringWriter writer = new StringWriter();
LoggingExecutor loggingExecutor = new LoggingExecutor(ExecutorService.getInstance().getExecutor(database), writer,
database);
LoggingExecutor loggingExecutor = new LoggingExecutor(Scope.getCurrentScope().getSingleton(ExecutorService.class)
.getExecutor(LiquibaseConstants.JDBC_EXECUTOR, database), writer, database);
SqlStatement sqlStatement = new CreateIndexStatement(getIndexName(), getCatalogName(), getSchemaName(), getTableName(),
this.isUnique(), getAssociatedWith(), getColumns().toArray(new AddColumnConfig[getColumns().size()]))
this.isUnique(), getAssociatedWith(), getColumns().toArray(new AddColumnConfig[0]))
.setTablespace(getTablespace()).setClustered(getClustered());
loggingExecutor.execute(sqlStatement);
@ -140,8 +142,8 @@ public class CustomCreateIndexChange extends CreateIndexChange {
if (SqlGeneratorFactory.getInstance().supports(statement, database)) {
warnings.addAll(SqlGeneratorFactory.getInstance().warn(statement, database));
} else if (statement.skipOnUnsupported()) {
warnings.addWarning(statement.getClass().getName() + " is not supported on " + database.getShortName()
+ ", but " + ChangeFactory.getInstance().getChangeMetaData(this).getName() + " will still execute");
warnings.addWarning(statement.getClass().getName() + " is not supported on " + database.getShortName() + ", but "
+ Scope.getCurrentScope().getSingleton(ChangeFactory.class).getChangeMetaData(this).getName() + " will still execute");
}
}
@ -152,10 +154,11 @@ public class CustomCreateIndexChange extends CreateIndexChange {
public ValidationErrors validate(Database database) {
ValidationErrors changeValidationErrors = new ValidationErrors();
for (ChangeParameterMetaData param : ChangeFactory.getInstance().getChangeMetaData(this).getParameters().values()) {
ChangeFactory changeFactory = Scope.getCurrentScope().getSingleton(ChangeFactory.class);
for (ChangeParameterMetaData param : changeFactory.getChangeMetaData(this).getParameters().values()) {
if (param.isRequiredFor(database) && param.getCurrentValue(this) == null) {
changeValidationErrors.addError(param.getParameterName() + " is required for "
+ ChangeFactory.getInstance().getChangeMetaData(this).getName() + " on " + database.getShortName());
+ changeFactory.getChangeMetaData(this).getName() + " on " + database.getShortName());
}
}
if (changeValidationErrors.hasErrors()) {
@ -163,7 +166,7 @@ public class CustomCreateIndexChange extends CreateIndexChange {
}
if (!generateStatementsVolatile(database)) {
String unsupportedWarning = ChangeFactory.getInstance().getChangeMetaData(this).getName() + " is not supported on "
String unsupportedWarning = changeFactory.getChangeMetaData(this).getName() + " is not supported on "
+ database.getShortName();
boolean sawUnsupportedError = false;

View file

@ -17,6 +17,7 @@
package org.keycloak.connections.jpa.updater.liquibase.lock;
import liquibase.Scope;
import liquibase.database.core.DerbyDatabase;
import liquibase.exception.DatabaseException;
import liquibase.exception.UnexpectedLiquibaseException;
@ -31,6 +32,7 @@ import liquibase.statement.core.RawSqlStatement;
import org.jboss.logging.Logger;
import org.keycloak.common.util.Time;
import org.keycloak.common.util.reflections.Reflections;
import org.keycloak.connections.jpa.updater.liquibase.LiquibaseConstants;
import org.keycloak.models.dblock.DBLockProvider;
import java.lang.reflect.Field;
@ -52,7 +54,7 @@ public class CustomLockService extends StandardLockService {
@Override
public void init() throws DatabaseException {
Executor executor = ExecutorService.getInstance().getExecutor(database);
Executor executor = Scope.getCurrentScope().getSingleton(ExecutorService.class).getExecutor(LiquibaseConstants.JDBC_EXECUTOR, database);
if (!hasDatabaseChangeLogLockTable()) {
@ -119,7 +121,7 @@ public class CustomLockService extends StandardLockService {
private Set<Integer> currentIdsInDatabaseChangeLogLockTable() throws DatabaseException {
try {
Executor executor = ExecutorService.getInstance().getExecutor(database);
Executor executor = Scope.getCurrentScope().getSingleton(ExecutorService.class).getExecutor(LiquibaseConstants.JDBC_EXECUTOR, database);
String idColumnName = database.escapeColumnName(database.getLiquibaseCatalogName(),
database.getLiquibaseSchemaName(),
database.getDatabaseChangeLogLockTableName(),
@ -143,20 +145,6 @@ public class CustomLockService extends StandardLockService {
}
}
@Override
public boolean isDatabaseChangeLogLockTableInitialized(boolean tableJustCreated) throws DatabaseException {
try {
return super.isDatabaseChangeLogLockTableInitialized(tableJustCreated);
} catch (UnexpectedLiquibaseException ulie) {
// It can happen with MariaDB Galera 10.1 that UnexpectedLiquibaseException is rethrown due the DB lock. It is sufficient to just rollback transaction and retry in that case.
if (ulie.getCause() != null && ulie.getCause() instanceof DatabaseException) {
throw (DatabaseException) ulie.getCause();
} else {
throw ulie;
}
}
}
@Override
public void waitForLock() {
waitForLock(new LockDatabaseChangeLogStatement());
@ -203,7 +191,7 @@ public class CustomLockService extends StandardLockService {
return true;
}
Executor executor = ExecutorService.getInstance().getExecutor(database);
Executor executor = Scope.getCurrentScope().getSingleton(ExecutorService.class).getExecutor(LiquibaseConstants.JDBC_EXECUTOR, database);
try {
database.rollback();
@ -249,8 +237,7 @@ public class CustomLockService extends StandardLockService {
hasChangeLogLock = false;
database.setCanCacheLiquibaseTableInfo(false);
database.rollback();
} catch (DatabaseException e) {
;
} catch (DatabaseException ignored) {
}
}
}

View file

@ -0,0 +1,39 @@
/*
* Copyright 2022 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.connections.jpa.updater.liquibase.log;
import liquibase.logging.Logger;
import liquibase.logging.core.AbstractLogService;
/**
* A {@link liquibase.logging.LogService} implementation that creates instances of {@link KeycloakLogger}.
*
* @author <a href="mailto:sguilhen@redhat.com">Stefan Guilhen</a>
*/
public class KeycloakLogService extends AbstractLogService {
@Override
public int getPriority() {
return PRIORITY_DEFAULT + 1;
}
@Override
public Logger getLog(Class clazz) {
return new KeycloakLogger(clazz);
}
}

View file

@ -0,0 +1,102 @@
/*
* Copyright 2022 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.connections.jpa.updater.liquibase.log;
import java.util.logging.Level;
import liquibase.logging.core.AbstractLogger;
import liquibase.logging.core.DefaultLogMessageFilter;
import org.jboss.logging.Logger;
/**
* A {@link liquibase.logging.Logger} implementation that delegates to a JBoss {@link Logger}.
*
* @author <a href="mailto:sguilhen@redhat.com">Stefan Guilhen</a>
*/
public class KeycloakLogger extends AbstractLogger {
private final Logger delegate;
public KeycloakLogger(final Class clazz) {
super(new DefaultLogMessageFilter());
this.delegate = Logger.getLogger(clazz);
}
@Override
public void severe(String message) {
this.delegate.error(message);
}
@Override
public void severe(String message, Throwable e) {
this.delegate.error(message, e);
}
@Override
public void warning(String message) {
// Ignore this warning as cascaded drops doesn't work anyway with all DBs, which we need to support
if ("Database does not support drop with cascade".equals(message)) {
this.delegate.debug(message);
} else {
this.delegate.warn(message);
}
}
@Override
public void warning(String message, Throwable e) {
this.delegate.warn(message, e);
}
@Override
public void info(String message) {
this.delegate.debug(message);
}
@Override
public void info(String message, Throwable e) {
this.delegate.debug(message, e);
}
@Override
public void debug(String message) {
if (this.delegate.isTraceEnabled()) {
this.delegate.trace(message);
}
}
@Override
public void debug(String message, Throwable e) {
this.delegate.trace(message, e);
}
@Override
public void log(Level level, String message, Throwable e) {
if (level.equals(Level.OFF)) {
return;
} else if (level.equals(Level.SEVERE)) {
this.delegate.error(message, e);
} else if (level.equals(Level.WARNING)) {
this.delegate.warn(message, e);
} else if (level.equals(Level.INFO)) {
this.delegate.debug(message, e);
} else if (level.equals(Level.FINE) | level.equals(Level.FINER) | level.equals(Level.FINEST)) {
if (this.delegate.isTraceEnabled())
this.delegate.trace(message, e);
}
}
}

View file

@ -18,6 +18,7 @@
<databaseChangeLog logicalFilePath="META-INF/db2-jpa-changelog-1.0.0.Final.xml" xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.2.xsd">
<changeSet author="sthorger@redhat.com" id="1.0.0.Final-KEYCLOAK-5461">
<validCheckSum>7:cb16724583e9675711801c6875114f28</validCheckSum>
<preConditions onSqlOutput="TEST" onFail="MARK_RAN">
<dbms type="db2" />

View file

@ -18,6 +18,7 @@
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.2.xsd">
<changeSet author="sthorger@redhat.com" id="1.0.0.Final-KEYCLOAK-5461">
<validCheckSum>7:4e70412f24a3f382c82183742ec79317</validCheckSum>
<preConditions onSqlOutput="TEST" onFail="MARK_RAN">
<not>
<changeSetExecuted id="1.0.0.Final" author="sthorger@redhat.com" changeLogFile="META-INF/jpa-changelog-1.0.0.Final.xml"/>

View file

@ -18,6 +18,7 @@
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.2.xsd">
<changeSet author="sthorger@redhat.com" id="1.1.0.Beta1">
<validCheckSum>7:0310eb8ba07cec616460794d42ade0fa</validCheckSum>
<delete tableName="CLIENT_SESSION_ROLE"/>
<delete tableName="CLIENT_SESSION"/>
<delete tableName="USER_SESSION"/>

View file

@ -18,6 +18,7 @@
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.2.xsd">
<changeSet author="sthorger@redhat.com" id="1.1.0.Final">
<validCheckSum>7:5d25857e708c3233ef4439df1f93f012</validCheckSum>
<renameColumn tableName="EVENT_ENTITY" oldColumnName="TIME" newColumnName="EVENT_TIME" columnDataType="BIGINT"/>
</changeSet>
</databaseChangeLog>

View file

@ -18,6 +18,7 @@
<databaseChangeLog logicalFilePath="META-INF/db2-jpa-changelog-1.2.0.Beta1.xml" xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd">
<changeSet author="psilva@redhat.com" id="1.2.0.Beta1">
<validCheckSum>7:2e01012df20974c1c2a605ef8afe25b7</validCheckSum>
<preConditions onSqlOutput="TEST" onFail="MARK_RAN">
<dbms type="db2" />
</preConditions>

View file

@ -18,6 +18,7 @@
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd">
<changeSet author="psilva@redhat.com" id="1.2.0.Beta1">
<validCheckSum>7:c7a54a1041d58eb3817a4a883b4d4e84</validCheckSum>
<preConditions onSqlOutput="TEST" onFail="MARK_RAN">
<not>
<dbms type="db2" />

View file

@ -18,6 +18,7 @@
<databaseChangeLog logicalFilePath="META-INF/db2-jpa-changelog-1.2.0.CR1.xml" xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd">
<changeSet author="bburke@redhat.com" id="1.2.0.RC1">
<validCheckSum>7:a77ea2ad226b345e7d689d366f185c8c</validCheckSum>
<preConditions onSqlOutput="TEST" onFail="MARK_RAN">
<dbms type="db2" />
</preConditions>

View file

@ -18,6 +18,7 @@
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd">
<changeSet author="bburke@redhat.com" id="1.2.0.RC1">
<validCheckSum>7:0f08df48468428e0f30ee59a8ec01a41</validCheckSum>
<preConditions onSqlOutput="TEST" onFail="MARK_RAN">
<not>
<dbms type="db2" />

View file

@ -18,6 +18,7 @@
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd">
<changeSet author="keycloak" id="1.2.0.Final">
<validCheckSum>7:a3377a2059aefbf3b90ebb4c4cc8e2ab</validCheckSum>
<!-- KEYCLOAK-1277 -->
<update tableName="CLIENT">
<column name="DIRECT_GRANTS_ONLY" valueBoolean="false"/>

View file

@ -18,6 +18,7 @@
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd">
<changeSet author="bburke@redhat.com" id="1.3.0">
<validCheckSum>7:04c1dbedc2aa3e9756d1a1668e003451</validCheckSum>
<delete tableName="CLIENT_SESSION_ROLE"/>
<delete tableName="CLIENT_SESSION_PROT_MAPPER"/>
<delete tableName="CLIENT_SESSION_NOTE"/>

View file

@ -18,6 +18,7 @@
<databaseChangeLog logicalFilePath="META-INF/db2-jpa-changelog-1.4.0.xml" xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd">
<changeSet author="bburke@redhat.com" id="1.4.0">
<validCheckSum>7:d909180b2530479a716d3f9c9eaea3d7</validCheckSum>
<preConditions onSqlOutput="TEST" onFail="MARK_RAN">
<dbms type="db2" />
</preConditions>

View file

@ -18,6 +18,7 @@
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd">
<changeSet author="bburke@redhat.com" id="1.4.0">
<validCheckSum>7:36ef39ed560ad07062d956db861042ba</validCheckSum>
<preConditions onSqlOutput="TEST" onFail="MARK_RAN">
<not>
<dbms type="db2" />

View file

@ -18,6 +18,7 @@
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd">
<changeSet author="bburke@redhat.com" id="1.5.0">
<validCheckSum>7:cf12b04b79bea5152f165eb41f3955f6</validCheckSum>
<delete tableName="CLIENT_SESSION_AUTH_STATUS"/>
<delete tableName="CLIENT_SESSION_ROLE"/>
<delete tableName="CLIENT_SESSION_PROT_MAPPER"/>

View file

@ -18,6 +18,7 @@
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd">
<changeSet author="mposolda@redhat.com" id="1.6.1_from15">
<validCheckSum>7:7e32c8f05c755e8675764e7d5f514509</validCheckSum>
<preConditions onFail="MARK_RAN" onFailMessage="Upgrading from 1.6.0 version. Skipped 1.6.1_from15 changeSet and marked as ran" onSqlOutput="TEST">
<not>
@ -83,6 +84,7 @@
<!-- KEYCLOAK-2404 - just for the update from 1.6.0 BUT not 1.6.1 or newer -->
<changeSet author="mposolda@redhat.com" id="1.6.1_from16-pre">
<validCheckSum>7:980ba23cc0ec39cab731ce903dd01291</validCheckSum>
<preConditions onFail="MARK_RAN" onFailMessage="Skipped 1.6.1_from16-pre changeSet and marked as ran" onSqlOutput="TEST">
<and>
@ -100,6 +102,7 @@
<!-- Just for the update from 1.6.0 -->
<changeSet author="mposolda@redhat.com" id="1.6.1_from16">
<validCheckSum>7:2fa220758991285312eb84f3b4ff5336</validCheckSum>
<preConditions onFail="MARK_RAN" onFailMessage="Upgrading from 1.5.0 or older version. Skipped 1.6.1_from16 changeSet and marked as ran" onSqlOutput="TEST">
<changeSetExecuted id="1.6.0" author="mposolda@redhat.com" changeLogFile="META-INF/jpa-changelog-1.6.0.xml" />
@ -134,6 +137,7 @@
</changeSet>
<changeSet author="mposolda@redhat.com" id="1.6.1">
<validCheckSum>7:d41d8cd98f00b204e9800998ecf8427e</validCheckSum>
</changeSet>
</databaseChangeLog>

View file

@ -18,6 +18,7 @@
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd">
<changeSet author="bburke@redhat.com" id="1.7.0">
<validCheckSum>7:91ace540896df890cc00a0490ee52bbc</validCheckSum>
<createTable tableName="KEYCLOAK_GROUP">
<column name="ID" type="VARCHAR(36)">
<constraints nullable="false"/>

View file

@ -18,6 +18,7 @@
<databaseChangeLog logicalFilePath="META-INF/db2-jpa-changelog-1.8.0.xml" xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd">
<changeSet author="mposolda@redhat.com" id="1.8.0">
<validCheckSum>7:f987971fe6b37d963bc95fee2b27f8df</validCheckSum>
<preConditions onSqlOutput="TEST" onFail="MARK_RAN">
<dbms type="db2" />
</preConditions>
@ -137,6 +138,7 @@
</changeSet>
<changeSet id="1.8.0-2" author="keycloak">
<validCheckSum>7:df8bc21027a4f7cbbb01f6344e89ce07</validCheckSum>
<preConditions onSqlOutput="TEST" onFail="MARK_RAN">
<dbms type="db2" />
</preConditions>

View file

@ -18,6 +18,7 @@
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd">
<changeSet author="mposolda@redhat.com" id="1.8.0">
<validCheckSum>7:c31d1646dfa2618a9335c00e07f89f24</validCheckSum>
<preConditions onSqlOutput="TEST" onFail="MARK_RAN">
<not>
<dbms type="db2" />
@ -135,6 +136,7 @@
</changeSet>
<changeSet id="1.8.0-2" author="keycloak">
<validCheckSum>7:df8bc21027a4f7cbbb01f6344e89ce07</validCheckSum>
<preConditions onSqlOutput="TEST" onFail="MARK_RAN">
<not>
<dbms type="db2" />

View file

@ -18,6 +18,7 @@
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd">
<changeSet author="mposolda@redhat.com" id="1.9.0">
<validCheckSum>7:ed2dc7f799d19ac452cbcda56c929e47</validCheckSum>
<!-- This is needed for MSSQL :( -->
<!-- 1.5 -->

View file

@ -18,6 +18,7 @@
<databaseChangeLog logicalFilePath="META-INF/db2-jpa-changelog-1.9.1.xml" xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd">
<changeSet author="keycloak" id="1.9.1">
<validCheckSum>7:1437310ed1305a9b93f8848f301726ce</validCheckSum>
<preConditions onSqlOutput="TEST" onFail="MARK_RAN">
<dbms type="db2" />
</preConditions>

View file

@ -18,6 +18,7 @@
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd">
<changeSet author="keycloak" id="1.9.1">
<validCheckSum>7:80b5db88a5dda36ece5f235be8757615</validCheckSum>
<preConditions onSqlOutput="TEST" onFail="MARK_RAN">
<not>
<dbms type="db2" />

View file

@ -18,6 +18,7 @@
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd">
<changeSet author="keycloak" id="1.9.2">
<validCheckSum>7:b82ffb34850fa0836be16deefc6a87c4</validCheckSum>
<!-- Optimized as lookup user by email is often operation -->
<createIndex indexName="IDX_USER_EMAIL" tableName="USER_ENTITY">

View file

@ -18,6 +18,7 @@
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd">
<changeSet author="keycloak" id="map-remove-ri">
<validCheckSum>7:3dace6b144c11f53f1ad2c0361279b86</validCheckSum>
<dropForeignKeyConstraint baseTableName="REALM" constraintName="FK_TRAF444KK6QRKMS7N56AIWQ5Y"/>
<dropForeignKeyConstraint baseTableName="KEYCLOAK_ROLE" constraintName="FK_KJHO5LE2C0RAL09FL8CM9WFW9"/>
</changeSet>

View file

@ -18,6 +18,7 @@
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd">
<changeSet author="keycloak" id="map-remove-ri">
<validCheckSum>7:578d0b92077eaf2ab95ad0ec087aa903</validCheckSum>
<dropForeignKeyConstraint baseTableName="REALM_DEFAULT_GROUPS" constraintName="FK_DEF_GROUPS_GROUP"/>
<dropForeignKeyConstraint baseTableName="REALM_DEFAULT_ROLES" constraintName="FK_H4WPD7W4HSOOLNI3H0SW7BTJE"/>
<dropForeignKeyConstraint baseTableName="CLIENT_SCOPE_ROLE_MAPPING" constraintName="FK_CL_SCOPE_RM_ROLE"/>
@ -27,6 +28,7 @@
</changeSet>
<changeSet author="keycloak" id="12.1.0-add-realm-localization-table">
<validCheckSum>7:c95abe90d962c57a09ecaee57972835d</validCheckSum>
<createTable tableName="REALM_LOCALIZATIONS">
<column name="REALM_ID" type="VARCHAR(255)">
<constraints nullable="false"/>

View file

@ -18,6 +18,7 @@
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd">
<changeSet author="keycloak" id="default-roles">
<validCheckSum>7:f1313bcc2994a5c4dc1062ed6d8282d3</validCheckSum>
<addColumn tableName="REALM">
<column name="DEFAULT_ROLE" type="VARCHAR(255)"/>
</addColumn>
@ -26,11 +27,13 @@
</changeSet>
<changeSet author="keycloak" id="default-roles-cleanup">
<validCheckSum>7:90d763b52eaffebefbcbde55f269508b</validCheckSum>
<dropTable tableName="REALM_DEFAULT_ROLES" />
<dropTable tableName="CLIENT_DEFAULT_ROLES" />
</changeSet>
<changeSet author="keycloak" id="13.0.0-KEYCLOAK-16844">
<validCheckSum>7:d554f0cb92b764470dccfa5e0014a7dd</validCheckSum>
<createIndex tableName="OFFLINE_USER_SESSION" indexName="IDX_OFFLINE_USS_PRELOAD">
<column name="OFFLINE_FLAG" type="VARCHAR(4)"/>
<column name="CREATED_ON" type="INT"/>
@ -39,6 +42,7 @@
</changeSet>
<changeSet author="keycloak" id="map-remove-ri-13.0.0">
<validCheckSum>7:73193e3ab3c35cf0f37ccea3bf783764</validCheckSum>
<dropForeignKeyConstraint baseTableName="DEFAULT_CLIENT_SCOPE" constraintName="FK_R_DEF_CLI_SCOPE_SCOPE"/>
<dropForeignKeyConstraint baseTableName="CLIENT_SCOPE_CLIENT" constraintName="FK_C_CLI_SCOPE_SCOPE"/>
<dropForeignKeyConstraint baseTableName="CLIENT_SCOPE_CLIENT" constraintName="FK_C_CLI_SCOPE_CLIENT"/>
@ -48,6 +52,7 @@
</changeSet>
<changeSet author="keycloak" id="13.0.0-KEYCLOAK-17992-drop-constraints">
<validCheckSum>7:90a1e74f92e9cbaa0c5eab80b8a037f3</validCheckSum>
<preConditions onFail="MARK_RAN" onSqlOutput="TEST">
<!-- sql server needs drop and re-create constraints before modifying data type -->
<dbms type="mssql"/>
@ -58,11 +63,13 @@
</changeSet>
<changeSet author="keycloak" id="13.0.0-increase-column-size-federated">
<validCheckSum>7:5b9248f29cd047c200083cc6d8388b16</validCheckSum>
<modifyDataType newDataType="VARCHAR(255)" tableName="CLIENT_SCOPE_CLIENT" columnName="CLIENT_ID"/>
<modifyDataType newDataType="VARCHAR(255)" tableName="CLIENT_SCOPE_CLIENT" columnName="SCOPE_ID"/>
</changeSet>
<changeSet author="keycloak" id="13.0.0-KEYCLOAK-17992-recreate-constraints">
<validCheckSum>7:64db59e44c374f13955489e8990d17a1</validCheckSum>
<preConditions onFail="MARK_RAN" onSqlOutput="TEST">
<!-- sql server needs drop and re-create constraints before modifying data type -->
<dbms type="mssql"/>
@ -79,6 +86,7 @@
</changeSet>
<changeSet author="keycloak" id="json-string-accomodation-fixed">
<validCheckSum>7:329a578cdb43262fff975f0a7f6cda60</validCheckSum>
<preConditions onFail="MARK_RAN" onSqlOutput="TEST">
<not>
<changeSetExecuted id="json-string-accomodation" author="keycloak" changeLogFile="META-INF/jpa-changelog-13.0.0.xml"/>

View file

@ -18,6 +18,7 @@
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd">
<changeSet author="keycloak" id="14.0.0-KEYCLOAK-11019">
<validCheckSum>7:fae0de241ac0fd0bbc2b380b85e4f567</validCheckSum>
<createIndex tableName="OFFLINE_CLIENT_SESSION" indexName="IDX_OFFLINE_CSS_PRELOAD">
<column name="CLIENT_ID" type="VARCHAR(36)"/>
<column name="OFFLINE_FLAG" type="VARCHAR(4)"/>
@ -37,6 +38,7 @@
</changeSet>
<changeSet author="keycloak" id="14.0.0-KEYCLOAK-18286">
<validCheckSum>7:075d54e9180f49bb0c64ca4218936e81</validCheckSum>
<preConditions onSqlOutput="TEST" onFail="MARK_RAN">
<changeSetExecuted id="NONEXISTENT" author="NONEXISTENT" changeLogFile="NONEXISTENT" /> <!-- Effectively disable this changeset -->
</preConditions>
@ -47,6 +49,7 @@
</changeSet>
<changeSet author="keycloak" id="14.0.0-KEYCLOAK-18286-revert">
<validCheckSum>7:06499836520f4f6b3d05e35a59324910</validCheckSum>
<preConditions onSqlOutput="TEST" onFail="MARK_RAN">
<indexExists tableName="CLIENT_ATTRIBUTES" indexName="IDX_CLIENT_ATT_BY_NAME_VALUE" />
<or>
@ -58,6 +61,9 @@
</changeSet>
<changeSet author="keycloak" id="14.0.0-KEYCLOAK-18286-supported-dbs">
<validCheckSum>7:fad08e83c77d0171ec166bc9bc5d390a</validCheckSum>
<validCheckSum>7:72553fac2d2281052acbbbb14aa22ccf</validCheckSum>
<validCheckSum>7:b558ad47ea0e4d3c3514225a49cc0d65</validCheckSum>
<preConditions onSqlOutput="TEST" onFail="MARK_RAN">
<or>
<dbms type="mysql"/>
@ -79,6 +85,7 @@
</changeSet>
<changeSet author="keycloak" id="14.0.0-KEYCLOAK-18286-unsupported-dbs">
<validCheckSum>7:3d2b23076e59c6f70bae703aa01be35b</validCheckSum>
<preConditions onSqlOutput="TEST" onFail="MARK_RAN">
<not>
<or>
@ -96,6 +103,7 @@
</changeSet>
<changeSet author="keycloak" id="KEYCLOAK-17267-add-index-to-user-attributes">
<validCheckSum>7:1a7f28ff8d9e53aeb879d76ea3d9341a</validCheckSum>
<createIndex indexName="IDX_USER_ATTRIBUTE_NAME" tableName="USER_ATTRIBUTE">
<column name="NAME" type="VARCHAR(255)"/>
<column name="VALUE" type="VARCHAR(255)"/>
@ -103,6 +111,7 @@
</changeSet>
<changeSet author="keycloak" id="KEYCLOAK-18146-add-saml-art-binding-identifier">
<validCheckSum>7:2fd554456fed4a82c698c555c5b751b6</validCheckSum>
<customChange class="org.keycloak.connections.jpa.updater.liquibase.custom.JpaUpdate14_0_0_MigrateSamlArtifactAttribute"/>
</changeSet>

View file

@ -19,6 +19,7 @@
<!-- change datatype of field REALM_LOCALIZATIONS.TEXTS to NCLOB (instead of CLOB) -->
<changeSet author="keycloak" id="15.0.0-KEYCLOAK-18467">
<validCheckSum>7:b06356d66c2790ecc2ae54ba0458397a</validCheckSum>
<addColumn tableName="REALM_LOCALIZATIONS">
<column name="TEXTS_NEW" type="NCLOB">
<!-- not-null constraint has to be added at the end, when data has been copied -->

View file

@ -18,6 +18,7 @@
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd">
<changeSet author="keycloak" id="17.0.0-9562">
<validCheckSum>7:467c7f7d35d0697dde968b1be60730a6</validCheckSum>
<createIndex indexName="IDX_USER_SERVICE_ACCOUNT" tableName="USER_ENTITY">
<column name="REALM_ID" type="VARCHAR(255)"/>
<column name="SERVICE_ACCOUNT_CLIENT_LINK" type="VARCHAR(36)"/>

View file

@ -18,6 +18,7 @@
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd">
<changeSet author="bburke@redhat.com" id="2.1.0-KEYCLOAK-5461">
<validCheckSum>7:f1f9fd8710399d725b780f463c6b21cd</validCheckSum>
<preConditions onSqlOutput="TEST" onFail="MARK_RAN">
<not>
<changeSetExecuted id="2.1.0" author="bburke@redhat.com" changeLogFile="META-INF/jpa-changelog-2.1.0.xml"/>

View file

@ -19,6 +19,7 @@
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd">
<changeSet author="bburke@redhat.com" id="2.2.0">
<validCheckSum>7:53188c3eb1107546e6f765835705b6c1</validCheckSum>
<addColumn tableName="ADMIN_EVENT_ENTITY">
<column name="RESOURCE_TYPE" type="VARCHAR(64)"></column>

View file

@ -19,6 +19,7 @@
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd">
<changeSet author="bburke@redhat.com" id="2.3.0">
<validCheckSum>7:d6e6f3bc57a0c5586737d1351725d4d4</validCheckSum>
<createTable tableName="FEDERATED_USER">
<column name="ID" type="VARCHAR(255)">
<constraints nullable="false"/>

View file

@ -19,6 +19,7 @@
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd">
<changeSet author="bburke@redhat.com" id="2.4.0">
<validCheckSum>7:454d604fbd755d9df3fd9c6329043aa5</validCheckSum>
<customChange class="org.keycloak.connections.jpa.updater.liquibase.custom.PortLdapUserFedToComponentModel"/>
</changeSet>

View file

@ -19,12 +19,14 @@
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd">
<changeSet author="bburke@redhat.com" id="2.5.0">
<validCheckSum>7:57e98a3077e29caf562f7dbf80c72600</validCheckSum>
<customChange class="org.keycloak.connections.jpa.updater.liquibase.custom.MigrateUserFedToComponent"/>
<modifyDataType tableName="OFFLINE_USER_SESSION" columnName="USER_ID" newDataType="VARCHAR(255)"/>
</changeSet>
<changeSet author="hmlnarik@redhat.com" id="2.5.0-unicode-oracle">
<validCheckSum>7:e4c7e8f2256210aee71ddc42f538b57a</validCheckSum>
<preConditions onSqlOutput="TEST" onFail="MARK_RAN">
<dbms type="oracle" />
</preConditions>
@ -62,6 +64,7 @@
</changeSet>
<changeSet author="hmlnarik@redhat.com" id="2.5.0-unicode-other-dbs">
<validCheckSum>7:09a43c97e49bc626460480aa1379b522</validCheckSum>
<preConditions onSqlOutput="TEST" onFail="MARK_RAN">
<not>
<dbms type="oracle" />
@ -100,6 +103,7 @@
</changeSet>
<changeSet author="slawomir@dabek.name" id="2.5.0-duplicate-email-support">
<validCheckSum>7:26bfc7c74fefa9126f2ce702fb775553</validCheckSum>
<addColumn tableName="REALM">
<column name="LOGIN_WITH_EMAIL_ALLOWED" type="BOOLEAN" defaultValueBoolean="true">
<constraints nullable="false"/>
@ -111,6 +115,7 @@
</changeSet>
<changeSet author="hmlnarik@redhat.com" id="2.5.0-unique-group-names">
<validCheckSum>7:a161e2ae671a9020fff61e996a207377</validCheckSum>
<preConditions onSqlOutput="TEST" onFail="MARK_RAN">
<not>
<dbms type="db2" /> <!-- exclude DB2 as it requires all fields to be non-NULL for unique constraints -->

View file

@ -19,6 +19,7 @@
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd">
<changeSet author="bburke@redhat.com" id="2.5.1">
<validCheckSum>7:37fc1781855ac5388c494f1442b3f717</validCheckSum>
<addColumn tableName="FED_USER_CONSENT">
<column name="CREATED_DATE" type="BIGINT"/>
<column name="LAST_UPDATED_DATE" type="BIGINT"/>

View file

@ -19,6 +19,7 @@
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd">
<changeSet author="bburke@redhat.com" id="3.0.0">
<validCheckSum>7:13a27db0dae6049541136adad7261d27</validCheckSum>
<addColumn tableName="IDENTITY_PROVIDER">
<column name="LINK_ONLY" type="BOOLEAN" defaultValueBoolean="false">
<constraints nullable="false" />

View file

@ -25,6 +25,7 @@
-->
<changeSet author="keycloak" id="3.2.0-fix">
<validCheckSum>7:550300617e3b59e8af3a6294df8248a3</validCheckSum>
<preConditions onFail="MARK_RAN" onSqlOutput="TEST">
<changeSetExecuted id="3.2.0" author="keycloak" changeLogFile="META-INF/jpa-changelog-3.2.0.xml"/>
<not>
@ -36,6 +37,7 @@
</changeSet>
<changeSet author="keycloak" id="3.2.0-fix-with-keycloak-5416">
<validCheckSum>7:e3a9482b8931481dc2772a5c07c44f17</validCheckSum>
<preConditions onFail="MARK_RAN" onSqlOutput="TEST">
<changeSetExecuted id="3.2.0" author="keycloak" changeLogFile="META-INF/jpa-changelog-3.2.0.xml"/>
<dbms type="mssql"/>
@ -49,6 +51,7 @@
</changeSet>
<changeSet author="hmlnarik" id="3.2.0-fix-offline-sessions">
<validCheckSum>7:72b07d85a2677cb257edb02b408f332d</validCheckSum>
<preConditions onFail="MARK_RAN" onSqlOutput="TEST">
<not>
<changeSetExecuted id="3.2.0-fixed" author="keycloak" changeLogFile="META-INF/jpa-changelog-3.2.0.xml"/>
@ -62,6 +65,7 @@
</changeSet>
<changeSet author="keycloak" id="3.2.0-fixed">
<validCheckSum>7:a72a7858967bd414835d19e04d880312</validCheckSum>
<preConditions onFail="MARK_RAN" onSqlOutput="TEST">
<not>
<changeSetExecuted id="3.2.0" author="keycloak" changeLogFile="META-INF/jpa-changelog-3.2.0.xml"/>

View file

@ -18,6 +18,7 @@
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd">
<changeSet author="keycloak" id="3.3.0">
<validCheckSum>7:94edff7cf9ce179e7e85f0cd78a3cf2c</validCheckSum>
<addColumn tableName="USER_ENTITY">
<column name="NOT_BEFORE" type="INT" defaultValueNumeric="0">
<constraints nullable="false"/>

View file

@ -18,6 +18,7 @@
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd">
<changeSet author="keycloak" id="3.4.0">
<validCheckSum>7:0f88b78b7b46480eb92690cbf5e44900</validCheckSum>
<addPrimaryKey columnNames="REALM_ID,ROLE_ID" constraintName="CONSTRAINT_REALM_DEFAULT_ROLES" tableName="REALM_DEFAULT_ROLES"/>
<addPrimaryKey columnNames="COMPOSITE,CHILD_ROLE" constraintName="CONSTRAINT_COMPOSITE_ROLE" tableName="COMPOSITE_ROLE"/>
<addPrimaryKey columnNames="REALM_ID,GROUP_ID" constraintName="CONSTR_REALM_DEFAULT_GROUPS" tableName="REALM_DEFAULT_GROUPS"/>
@ -48,7 +49,7 @@
</changeSet>
<changeSet author="hmlnarik@redhat.com" id="3.4.0-KEYCLOAK-5230">
<validCheckSum>7:d560e43982611d936457c327f872dd59</validCheckSum>
<createIndex tableName="FED_USER_ATTRIBUTE" indexName="IDX_FU_ATTRIBUTE">
<column name="USER_ID" type="VARCHAR(255)" />
<column name="REALM_ID" type="VARCHAR(36)" />

View file

@ -18,6 +18,7 @@
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd">
<changeSet author="psilva@redhat.com" id="3.4.1">
<validCheckSum>7:c155566c42b4d14ef07059ec3b3bbd8e</validCheckSum>
<!-- KEYCLOAK-4231, changing length to same value used by COMPONENT_CONFIG.VALUE -->
<modifyDataType tableName="CLIENT_ATTRIBUTES" columnName="VALUE" newDataType="VARCHAR(4000)"/>
</changeSet>

View file

@ -18,6 +18,7 @@
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd">
<changeSet author="keycloak" id="3.4.2">
<validCheckSum>7:b40376581f12d70f3c89ba8ddf5b7dea</validCheckSum>
<!-- KEYCLOAK-5868 REFRESH_TOKEN_MAX_REUSE added in 3.4.0.CR1, but value for existing realms is null -->
<update tableName="REALM">
<column name="REFRESH_TOKEN_MAX_REUSE" type="INT" valueNumeric="0"/>
@ -26,6 +27,7 @@
</changeSet>
<changeSet author="mkanis@redhat.com" id="3.4.2-KEYCLOAK-5172">
<validCheckSum>7:a1132cc395f7b95b3646146c2e38f168</validCheckSum>
<update tableName="CLIENT">
<column name="PROTOCOL" type="VARCHAR(255)" value="openid-connect"/>
<where>PROTOCOL IS NULL</where>

View file

@ -18,6 +18,7 @@
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd">
<changeSet author="bburke@redhat.com" id="4.0.0-KEYCLOAK-6335">
<validCheckSum>7:d8dc5d89c789105cfa7ca0e82cba60af</validCheckSum>
<createTable tableName="CLIENT_AUTH_FLOW_BINDINGS">
<column name="CLIENT_ID" type="VARCHAR(36)">
<constraints nullable="false"/>
@ -30,9 +31,11 @@
<addPrimaryKey columnNames="CLIENT_ID, BINDING_NAME" constraintName="C_CLI_FLOW_BIND" tableName="CLIENT_AUTH_FLOW_BINDINGS"/>
</changeSet>
<changeSet author="bburke@redhat.com" id="4.0.0-CLEANUP-UNUSED-TABLE">
<validCheckSum>7:7822e0165097182e8f653c35517656a3</validCheckSum>
<dropTable tableName="CLIENT_IDENTITY_PROV_MAPPING"/>
</changeSet>
<changeSet author="bburke@redhat.com" id="4.0.0-KEYCLOAK-6228">
<validCheckSum>7:c6538c29b9c9a08f9e9ea2de5c2b6375</validCheckSum>
<!-- Modifying some columns so that CLIENT_ID is 255. Drop foreign key constraints too that referenced CLIENT tablename.
This is needed for client storage SPI but only needed for tables that might reference a federated client -->
@ -86,6 +89,7 @@
</changeSet>
<changeSet author="mposolda@redhat.com" id="4.0.0-KEYCLOAK-5579-fixed">
<validCheckSum>7:6d4893e36de22369cf73bcb051ded875</validCheckSum>
<preConditions onFail="MARK_RAN" onSqlOutput="TEST">
<not>
<changeSetExecuted id="4.0.0-KEYCLOAK-5579" author="mposolda@redhat.com" changeLogFile="META-INF/jpa-changelog-4.0.0.xml" />

View file

@ -18,6 +18,7 @@
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd">
<changeSet author="wadahiro@gmail.com" id="4.2.0-KEYCLOAK-6313">
<validCheckSum>7:14d407c35bc4fe1976867756bcea0c36</validCheckSum>
<addColumn tableName="REQUIRED_ACTION_PROVIDER">
<column name="PRIORITY" type="INT"/>
</addColumn>

View file

@ -18,6 +18,7 @@
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd">
<changeSet author="wadahiro@gmail.com" id="4.3.0-KEYCLOAK-7984">
<validCheckSum>7:241a8030c748c8548e346adee548fa93</validCheckSum>
<update tableName="REQUIRED_ACTION_PROVIDER">
<column name="PRIORITY" type="INT" valueNumeric="0"/>
<where>PRIORITY is NULL</where>

View file

@ -18,6 +18,7 @@
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd">
<changeSet author="psilva@redhat.com" id="4.6.0-KEYCLOAK-7950">
<validCheckSum>7:7d3182f65a34fcc61e8d23def037dc3f</validCheckSum>
<update tableName="RESOURCE_SERVER_RESOURCE">
<column name="TYPE" value="Group"/>
<where>NAME LIKE 'group.resource.%'</where>
@ -25,6 +26,7 @@
</changeSet>
<changeSet author="keycloak" id="4.6.0-KEYCLOAK-8377">
<validCheckSum>7:b30039e00a0b9715d430d1b0636728fa</validCheckSum>
<createTable tableName="ROLE_ATTRIBUTE">
<column name="ID" type="VARCHAR(36)">
<constraints nullable="false"/>
@ -45,6 +47,7 @@
</changeSet>
<changeSet author="gideonray@gmail.com" id="4.6.0-KEYCLOAK-8555">
<validCheckSum>7:3797315ca61d531780f8e6f82f258159</validCheckSum>
<createIndex tableName="COMPONENT" indexName="IDX_COMPONENT_PROVIDER_TYPE">
<column name="PROVIDER_TYPE" type="VARCHAR(255)"/>
</createIndex>

View file

@ -18,6 +18,7 @@
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd">
<changeSet author="sguilhen@redhat.com" id="4.7.0-KEYCLOAK-1267">
<validCheckSum>7:c7aa4c8d9573500c2d347c1941ff0301</validCheckSum>
<addColumn tableName="REALM">
<column name="SSO_MAX_LIFESPAN_REMEMBER_ME" type="INT" defaultValueNumeric="0"/>
<column name="SSO_IDLE_TIMEOUT_REMEMBER_ME" type="INT" defaultValueNumeric="0"/>
@ -26,6 +27,7 @@
<changeSet author="keycloak" id="4.7.0-KEYCLOAK-7275">
<validCheckSum>7:b207faee394fc074a442ecd42185a5dd</validCheckSum>
<renameColumn tableName="OFFLINE_USER_SESSION" oldColumnName="LAST_SESSION_REFRESH" newColumnName="CREATED_ON" columnDataType="INT" />
<addNotNullConstraint tableName="OFFLINE_USER_SESSION" columnName="CREATED_ON" columnDataType="INT" defaultNullValue="0" />

View file

@ -18,6 +18,7 @@
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd">
<changeSet author="sguilhen@redhat.com" id="4.8.0-KEYCLOAK-8835">
<validCheckSum>7:ab9a9762faaba4ddfa35514b212c4922</validCheckSum>
<addNotNullConstraint tableName="REALM" columnName="SSO_MAX_LIFESPAN_REMEMBER_ME" columnDataType="INT" defaultNullValue="0"/>
<addNotNullConstraint tableName="REALM" columnName="SSO_IDLE_TIMEOUT_REMEMBER_ME" columnDataType="INT" defaultNullValue="0"/>
</changeSet>

View file

@ -19,6 +19,7 @@
<!--modifies the credentials to the new format, while copying the data as json in the new fields-->
<changeSet author="keycloak" id="8.0.0-adding-credential-columns">
<validCheckSum>7:ec9707ae4d4f0b7452fee20128083879</validCheckSum>
<addColumn tableName="CREDENTIAL">
<column name="USER_LABEL" type="VARCHAR(255)">
@ -53,6 +54,7 @@
<!--Update format of credential to fill secret_data and credential_data - used on all databases beside Oracle DB -->
<changeSet author="keycloak" id="8.0.0-updating-credential-data-not-oracle-fixed">
<validCheckSum>7:3979a0ae07ac465e920ca696532fc736</validCheckSum>
<preConditions onSqlOutput="TEST" onFail="MARK_RAN">
<and>
<not>
@ -117,6 +119,7 @@
<!--Update format of credential to fill secret_data and credential_data - used on Oracle DB. Oracle doesn't support CONCAT with more than 2 arguments -->
<changeSet author="keycloak" id="8.0.0-updating-credential-data-oracle-fixed">
<validCheckSum>7:5abfde4c259119d143bd2fbf49ac2bca</validCheckSum>
<preConditions onSqlOutput="TEST" onFail="MARK_RAN">
<and>
<dbms type="oracle" />
@ -178,6 +181,7 @@
</changeSet>
<changeSet author="keycloak" id="8.0.0-credential-cleanup-fixed">
<validCheckSum>7:b48da8c11a3d83ddd6b7d0c8c2219345</validCheckSum>
<preConditions onFail="MARK_RAN" onSqlOutput="TEST">
<not>
<changeSetExecuted id="8.0.0-credential-cleanup" author="keycloak" changeLogFile="META-INF/jpa-changelog-8.0.0.xml"/>
@ -219,6 +223,7 @@
</changeSet>
<changeSet author="keycloak" id="8.0.0-resource-tag-support">
<validCheckSum>7:a73379915c23bfad3e8f5c6d5c0aa4bd</validCheckSum>
<addColumn tableName="MIGRATION_MODEL">
<column name="UPDATE_TIME" type="BIGINT" defaultValueNumeric="0">
<constraints nullable="false"/>

View file

@ -18,6 +18,7 @@
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd">
<changeSet author="keycloak" id="9.0.0-always-display-client">
<validCheckSum>7:39e0073779aba192646291aa2332493d</validCheckSum>
<addColumn tableName="CLIENT">
<column name="ALWAYS_DISPLAY_IN_CONSOLE" type="BOOLEAN" defaultValueBoolean="false">
<constraints nullable="false"/>
@ -26,6 +27,7 @@
</changeSet>
<changeSet author="keycloak" id="9.0.0-drop-constraints-for-column-increase">
<validCheckSum>7:81f87368f00450799b4bf42ea0b3ec34</validCheckSum>
<preConditions onFail="MARK_RAN" onSqlOutput="TEST">
<dbms type="mssql"/>
</preConditions>
@ -37,6 +39,7 @@
</changeSet>
<changeSet author="keycloak" id="9.0.0-increase-column-size-federated-fk">
<validCheckSum>7:20b37422abb9fb6571c618148f013a15</validCheckSum>
<modifyDataType newDataType="VARCHAR(255)" tableName="FED_USER_CONSENT" columnName="CLIENT_ID"/>
<modifyDataType newDataType="VARCHAR(255)" tableName="KEYCLOAK_ROLE" columnName="CLIENT_REALM_CONSTRAINT"/>
<modifyDataType newDataType="VARCHAR(255)" tableName="RESOURCE_SERVER_POLICY" columnName="OWNER"/>
@ -49,6 +52,7 @@
</changeSet>
<changeSet author="keycloak" id="9.0.0-recreate-constraints-after-column-increase">
<validCheckSum>7:1970bb6cfb5ee800736b95ad3fb3c78a</validCheckSum>
<preConditions onFail="MARK_RAN" onSqlOutput="TEST">
<dbms type="mssql"/>
</preConditions>

View file

@ -18,12 +18,14 @@
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd">
<changeSet author="keycloak" id="9.0.1-add-index-to-client.client_id">
<validCheckSum>7:45d9b25fc3b455d522d8dcc10a0f4c80</validCheckSum>
<createIndex indexName="IDX_CLIENT_ID" tableName="CLIENT">
<column name="CLIENT_ID" type="VARCHAR(255)"/>
</createIndex>
</changeSet>
<changeSet author="keycloak" id="9.0.1-KEYCLOAK-12579-drop-constraints">
<validCheckSum>7:890ae73712bc187a66c2813a724d037f</validCheckSum>
<preConditions onFail="MARK_RAN" onSqlOutput="TEST">
<!-- sql server needs drop and re-create the constraint SIBLING_NAMES -->
<dbms type="mssql"/>
@ -32,12 +34,14 @@
</changeSet>
<changeSet author="keycloak" id="9.0.1-KEYCLOAK-12579-add-not-null-constraint">
<validCheckSum>7:0a211980d27fafe3ff50d19a3a29b538</validCheckSum>
<!-- Now the parent group cannot be NULL to make SIBLING_NAMES unique constraint work -->
<!-- Top level groups are now marked with the " " (one space) string -->
<addNotNullConstraint tableName="KEYCLOAK_GROUP" columnName="PARENT_GROUP" columnDataType="VARCHAR(36)" defaultNullValue=" "/>
</changeSet>
<changeSet author="keycloak" id="9.0.1-KEYCLOAK-12579-recreate-constraints">
<validCheckSum>7:a161e2ae671a9020fff61e996a207377</validCheckSum>
<preConditions onFail="MARK_RAN" onSqlOutput="TEST">
<!-- sql server needs drop and re-create the constraint SIBLING_NAMES -->
<dbms type="mssql"/>
@ -46,6 +50,7 @@
</changeSet>
<changeSet author="keycloak" id="9.0.1-add-index-to-events">
<validCheckSum>7:01c49302201bdf815b0a18d1f98a55dc</validCheckSum>
<createIndex indexName="IDX_EVENT_TIME" tableName="EVENT_ENTITY">
<column name="REALM_ID" type="VARCHAR(255)"/>
<column name="EVENT_TIME" type="BIGINT"/>

View file

@ -19,6 +19,7 @@
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.2.xsd">
<changeSet author="psilva@redhat.com" id="authz-2.0.0">
<validCheckSum>7:9cc98082921330d8d9266decdd4bd658</validCheckSum>
<createTable tableName="RESOURCE_SERVER">
<column name="ID" type="VARCHAR(36)">
<constraints nullable="false"/>

View file

@ -18,6 +18,7 @@
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.2.xsd">
<changeSet author="psilva@redhat.com" id="authz-2.5.1">
<validCheckSum>7:03d64aeed9cb52b969bd30a7ac0db57e</validCheckSum>
<update tableName="RESOURCE_SERVER_POLICY">
<column name="TYPE" value="rules"/>
<where>TYPE = :value</where>

View file

@ -18,6 +18,7 @@
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.2.xsd">
<changeSet author="glavoie@gmail.com" id="authz-3.4.0.CR1-resource-server-pk-change-part1">
<validCheckSum>7:6a48ce645a3525488a90fbf76adf3bb3</validCheckSum>
<!-- Data migration to change the PK of RESOURCE_SERVER to use the CLIENT_ID. -->
<addColumn tableName="RESOURCE_SERVER_POLICY">
<column name="RESOURCE_SERVER_CLIENT_ID" type="VARCHAR(36)"/>
@ -31,6 +32,7 @@
</changeSet>
<changeSet author="hmlnarik@redhat.com" id="authz-3.4.0.CR1-resource-server-pk-change-part2-KEYCLOAK-6095">
<validCheckSum>7:e64b5dcea7db06077c6e57d3b9e5ca14</validCheckSum>
<preConditions onFail="MARK_RAN" onSqlOutput="TEST">
<not>
<changeSetExecuted id="authz-3.4.0.CR1-resource-server-pk-change-part3" author="glavoie@gmail.com" changeLogFile="META-INF/jpa-changelog-authz-3.4.0.CR1.xml" />
@ -41,6 +43,7 @@
</changeSet>
<changeSet author="glavoie@gmail.com" id="authz-3.4.0.CR1-resource-server-pk-change-part3-fixed">
<validCheckSum>7:fd8cf02498f8b1e72496a20afc75178c</validCheckSum>
<preConditions onFail="MARK_RAN" onSqlOutput="TEST">
<dbms type="mssql" />
<not>
@ -54,6 +57,7 @@
</changeSet>
<changeSet author="glavoie@gmail.com" id="authz-3.4.0.CR1-resource-server-pk-change-part3-fixed-nodropindex">
<validCheckSum>7:542794f25aa2b1fbabb7e577d6646319</validCheckSum>
<preConditions onFail="MARK_RAN" onSqlOutput="TEST">
<not>
<changeSetExecuted id="authz-3.4.0.CR1-resource-server-pk-change-part3" author="glavoie@gmail.com" changeLogFile="META-INF/jpa-changelog-authz-3.4.0.CR1.xml" />
@ -117,6 +121,7 @@
</changeSet>
<changeSet author="glavoie@gmail.com" id="authn-3.4.0.CR1-refresh-token-max-reuse">
<validCheckSum>7:edad604c882df12f74941dac3cc6d650</validCheckSum>
<addColumn tableName="REALM">
<column name="REFRESH_TOKEN_MAX_REUSE" type="INT" defaultValueNumeric="0"/>
</addColumn>

View file

@ -18,6 +18,7 @@
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.2.xsd">
<changeSet author="psilva@redhat.com" id="authz-4.0.0.Beta3">
<validCheckSum>7:2b4b8bff39944c7097977cc18dbceb3b</validCheckSum>
<addColumn tableName="RESOURCE_SERVER_POLICY">
<column name="OWNER" type="VARCHAR(36)">
<constraints nullable="true"/>

View file

@ -18,6 +18,7 @@
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.2.xsd">
<changeSet author="psilva@redhat.com" id="authz-4.0.0.CR1">
<validCheckSum>7:57960fc0b0f0dd0563ea6f8b2e4a1707</validCheckSum>
<createTable tableName="RESOURCE_SERVER_PERM_TICKET">
<column name="ID" type="VARCHAR(36)">
<constraints nullable="false"/>

View file

@ -18,6 +18,7 @@
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.2.xsd">
<changeSet author="mhajas@redhat.com" id="authz-4.2.0.Final">
<validCheckSum>7:2aa42a964c59cd5b8ca9822340ba33a8</validCheckSum>
<createTable tableName="RESOURCE_URIS">
<column name="RESOURCE_ID" type="VARCHAR(36)">
<constraints nullable="false"/>
@ -35,6 +36,7 @@
</changeSet>
<changeSet author="hmlnarik@redhat.com" id="authz-4.2.0.Final-KEYCLOAK-9944">
<validCheckSum>7:9ac9e58545479929ba23f4a3087a0346</validCheckSum>
<addPrimaryKey constraintName="CONSTRAINT_RESOUR_URIS_PK" tableName="RESOURCE_URIS" columnNames="RESOURCE_ID,VALUE"/>
</changeSet>
</databaseChangeLog>

View file

@ -18,6 +18,7 @@
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.2.xsd">
<changeSet author="psilva@redhat.com" id="authz-7.0.0-KEYCLOAK-10443">
<validCheckSum>7:b9710f74515a6ccb51b72dc0d19df8c4</validCheckSum>
<addColumn tableName="RESOURCE_SERVER">
<column name="DECISION_STRATEGY" type="TINYINT" defaultValue="1">
<constraints nullable="false"/>

View file

@ -0,0 +1,18 @@
#
# Copyright 2022 Red Hat, Inc. and/or its affiliates
# and other contributors as indicated by the @author tags.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
org.keycloak.connections.jpa.updater.liquibase.custom.CustomCreateIndexChange

View file

@ -0,0 +1,18 @@
#
# Copyright 2022 Red Hat, Inc. and/or its affiliates
# and other contributors as indicated by the @author tags.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
org.keycloak.connections.jpa.updater.liquibase.conn.CustomChangeLogHistoryService

View file

@ -0,0 +1,20 @@
#
# Copyright 2022 Red Hat, Inc. and/or its affiliates
# and other contributors as indicated by the @author tags.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
org.keycloak.connections.jpa.updater.liquibase.PostgresPlusDatabase
org.keycloak.connections.jpa.updater.liquibase.UpdatedMariaDBDatabase
org.keycloak.connections.jpa.updater.liquibase.UpdatedMySqlDatabase

View file

@ -0,0 +1,18 @@
#
# Copyright 2022 Red Hat, Inc. and/or its affiliates
# and other contributors as indicated by the @author tags.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
org.keycloak.connections.jpa.updater.liquibase.MySQL8VarcharType

View file

@ -0,0 +1,18 @@
#
# Copyright 2022 Red Hat, Inc. and/or its affiliates
# and other contributors as indicated by the @author tags.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
org.keycloak.connections.jpa.updater.liquibase.lock.DummyLockService

View file

@ -0,0 +1,18 @@
#
# Copyright 2022 Red Hat, Inc. and/or its affiliates
# and other contributors as indicated by the @author tags.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
org.keycloak.connections.jpa.updater.liquibase.log.KeycloakLogService

View file

@ -0,0 +1,19 @@
#
# Copyright 2022 Red Hat, Inc. and/or its affiliates
# and other contributors as indicated by the @author tags.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
org.keycloak.connections.jpa.updater.liquibase.lock.CustomInsertLockRecordGenerator
org.keycloak.connections.jpa.updater.liquibase.lock.CustomLockDatabaseChangeLogGenerator

View file

@ -18,25 +18,16 @@
package org.keycloak.models.map.storage.jpa.liquibase.connection;
import java.sql.Connection;
import java.util.concurrent.atomic.AtomicBoolean;
import liquibase.Liquibase;
import liquibase.change.ChangeFactory;
import liquibase.database.Database;
import liquibase.database.DatabaseFactory;
import liquibase.database.jvm.JdbcConnection;
import liquibase.datatype.DataTypeFactory;
import liquibase.exception.LiquibaseException;
import liquibase.resource.ClassLoaderResourceAccessor;
import liquibase.resource.ResourceAccessor;
import liquibase.sqlgenerator.SqlGeneratorFactory;
import org.jboss.logging.Logger;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.map.storage.jpa.liquibase.extension.GeneratedColumnSqlGenerator;
import org.keycloak.models.map.storage.jpa.liquibase.extension.CreateJsonIndexChange;
import org.keycloak.models.map.storage.jpa.liquibase.extension.CreateJsonIndexGenerator;
import org.keycloak.models.map.storage.jpa.liquibase.extension.GeneratedColumnChange;
import org.keycloak.models.map.storage.jpa.liquibase.extension.JsonDataType;
/**
* A {@link MapLiquibaseConnectionProvider} implementation for the map-jpa module. This provider registers the custom {@code Liquibase}
@ -53,35 +44,8 @@ public class DefaultLiquibaseConnectionProvider implements MapLiquibaseConnectio
private static final Logger logger = Logger.getLogger(DefaultLiquibaseConnectionProvider.class);
private static final AtomicBoolean INITIALIZED = new AtomicBoolean(false);
@SuppressWarnings("unused")
public DefaultLiquibaseConnectionProvider(final KeycloakSession session) {
if (! INITIALIZED.get()) {
// TODO: all liquibase providers should probably synchronize on the same object.
synchronized (INITIALIZED) {
if (! INITIALIZED.get()) {
initializeLiquibase();
INITIALIZED.set(true);
}
}
}
}
/**
* Registers the custom changes/types so we can work with data stored in JSON format.
*/
protected void initializeLiquibase() {
// Add custom JSON data type
DataTypeFactory.getInstance().register(JsonDataType.class);
// Add custom change to generate columns from properties in JSON files stored in the DB.
ChangeFactory.getInstance().register(GeneratedColumnChange.class);
SqlGeneratorFactory.getInstance().register(new GeneratedColumnSqlGenerator());
// Add custom change to create indexes for properties in JSON files stored in the DB.
ChangeFactory.getInstance().register(CreateJsonIndexChange.class);
SqlGeneratorFactory.getInstance().register(new CreateJsonIndexGenerator());
}
@Override

View file

@ -31,7 +31,7 @@ import liquibase.sqlgenerator.core.AbstractSqlGenerator;
import liquibase.statement.core.CreateIndexStatement;
import liquibase.structure.core.Index;
import liquibase.structure.core.Table;
import liquibase.util.StringUtils;
import liquibase.util.StringUtil;
/**
* A {@link SqlGenerator} implementation that supports {@link CreateJsonIndexStatement}s. It generates the SQL required
@ -88,7 +88,7 @@ public class CreateJsonIndexGenerator extends AbstractSqlGenerator<CreateJsonInd
builder.append("ON ").append(database.escapeTableName(statement.getTableCatalogName(), statement.getTableSchemaName(),
statement.getTableName()));
this.handleJsonIndex(statement, database, builder);
if (StringUtils.trimToNull(statement.getTablespace()) != null && database.supportsTablespaces()) {
if (StringUtil.trimToNull(statement.getTablespace()) != null && database.supportsTablespaces()) {
builder.append(" TABLESPACE ").append(statement.getTablespace());
}

View file

@ -80,7 +80,7 @@ public class GeneratedColumnSqlGenerator extends AddColumnGenerator {
List<Sql> returnSql = new ArrayList<>();
returnSql.add(new UnparsedSql(sqlBuilder.toString(), super.getAffectedColumn(statement)));
super.addUniqueConstrantStatements(statement, database, returnSql);
super.addUniqueConstraintStatements(statement, database, returnSql);
super.addForeignKeyStatements(statement, database, returnSql);
return returnSql.toArray(new Sql[0]);

View file

@ -17,6 +17,7 @@
package org.keycloak.models.map.storage.jpa.liquibase.extension;
import liquibase.change.core.LoadDataChange;
import liquibase.database.Database;
import liquibase.database.core.PostgresDatabase;
import liquibase.datatype.DataTypeInfo;
@ -39,4 +40,9 @@ public class JsonDataType extends LiquibaseDataType {
}
return super.toDatabaseDataType(database);
}
@Override
public LoadDataChange.LOAD_DATA_TYPE getLoadTypeName() {
return LoadDataChange.LOAD_DATA_TYPE.UNKNOWN;
}
}

View file

@ -22,7 +22,6 @@ import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;
@ -33,7 +32,6 @@ import liquibase.changelog.ChangeSet;
import liquibase.changelog.RanChangeSet;
import liquibase.exception.LiquibaseException;
import org.jboss.logging.Logger;
import org.keycloak.common.util.reflections.Reflections;
import org.keycloak.connections.jpa.updater.liquibase.ThreadLocalSessionContext;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.map.storage.ModelEntityUtil;
@ -72,7 +70,7 @@ public class MapJpaLiquibaseUpdaterProvider implements MapJpaUpdaterProvider {
exportWriter = new FileWriter(file);
}
updateChangeSet(liquibase, connection);
updateChangeSet(liquibase);
} catch (LiquibaseException | IOException | SQLException e) {
logger.error("Error has occurred while updating the database", e);
@ -89,9 +87,9 @@ public class MapJpaLiquibaseUpdaterProvider implements MapJpaUpdaterProvider {
}
}
protected void updateChangeSet(Liquibase liquibase, Connection connection) throws LiquibaseException, SQLException {
protected void updateChangeSet(Liquibase liquibase) throws LiquibaseException, SQLException {
String changelog = liquibase.getChangeLogFile();
List<ChangeSet> changeSets = getLiquibaseUnrunChangeSets(liquibase);
List<ChangeSet> changeSets = this.getLiquibaseUnrunChangeSets(liquibase);
if (!changeSets.isEmpty()) {
List<RanChangeSet> ranChangeSets = liquibase.getDatabase().getRanChangeSetList();
if (ranChangeSets.isEmpty()) {
@ -135,7 +133,7 @@ public class MapJpaLiquibaseUpdaterProvider implements MapJpaUpdaterProvider {
protected Status validateChangeSet(Liquibase liquibase, String changelog) throws LiquibaseException {
final Status result;
List<ChangeSet> changeSets = getLiquibaseUnrunChangeSets(liquibase);
List<ChangeSet> changeSets = this.getLiquibaseUnrunChangeSets(liquibase);
if (!changeSets.isEmpty()) {
if (changeSets.size() == liquibase.getDatabaseChangeLog().getChangeSets().size()) {
@ -152,13 +150,8 @@ public class MapJpaLiquibaseUpdaterProvider implements MapJpaUpdaterProvider {
return result;
}
@SuppressWarnings("unchecked")
private List<ChangeSet> getLiquibaseUnrunChangeSets(Liquibase liquibase) {
// TODO tracked as: https://issues.jboss.org/browse/KEYCLOAK-3730
// TODO: When https://liquibase.jira.com/browse/CORE-2919 is resolved, replace the following two lines with:
// List<ChangeSet> changeSets = liquibase.listUnrunChangeSets((Contexts) null, new LabelExpression(), false);
Method listUnrunChangeSets = Reflections.findDeclaredMethod(Liquibase.class, "listUnrunChangeSets", Contexts.class, LabelExpression.class, boolean.class);
return Reflections.invokeMethod(true, listUnrunChangeSets, List.class, liquibase, (Contexts) null, new LabelExpression(), false);
private List<ChangeSet> getLiquibaseUnrunChangeSets(Liquibase liquibase) throws LiquibaseException {
return liquibase.listUnrunChangeSets(null, new LabelExpression(), false);
}
private Liquibase getLiquibase(Class modelType, Connection connection, String defaultSchema) throws LiquibaseException {

View file

@ -0,0 +1,19 @@
#
# Copyright 2022 Red Hat, Inc. and/or its affiliates
# and other contributors as indicated by the @author tags.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
org.keycloak.models.map.storage.jpa.liquibase.extension.CreateJsonIndexChange
org.keycloak.models.map.storage.jpa.liquibase.extension.GeneratedColumnChange

View file

@ -0,0 +1,18 @@
#
# Copyright 2022 Red Hat, Inc. and/or its affiliates
# and other contributors as indicated by the @author tags.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
org.keycloak.models.map.storage.jpa.liquibase.extension.JsonDataType

View file

@ -0,0 +1,19 @@
#
# Copyright 2022 Red Hat, Inc. and/or its affiliates
# and other contributors as indicated by the @author tags.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
org.keycloak.models.map.storage.jpa.liquibase.extension.CreateJsonIndexGenerator
org.keycloak.models.map.storage.jpa.liquibase.extension.GeneratedColumnSqlGenerator

View file

@ -131,7 +131,7 @@
<freemarker.version>2.3.31</freemarker.version>
<jetty9.version>${jetty92.version}</jetty9.version>
<liquibase.version>3.5.5</liquibase.version>
<liquibase.version>4.6.2</liquibase.version>
<osgi.version>4.2.0</osgi.version>
<pax.web.version>7.1.0</pax.web.version>
<servlet.api.30.version>1.0.2.Final</servlet.api.30.version>

View file

@ -15,17 +15,13 @@ import org.jboss.jandex.AnnotationInstance;
import org.jboss.jandex.ClassInfo;
import org.jboss.jandex.DotName;
import org.jboss.jandex.IndexView;
import org.keycloak.connections.jpa.updater.liquibase.lock.CustomInsertLockRecordGenerator;
import org.keycloak.connections.jpa.updater.liquibase.lock.CustomLockDatabaseChangeLogGenerator;
import org.keycloak.connections.jpa.updater.liquibase.lock.DummyLockService;
import org.keycloak.quarkus.runtime.storage.database.liquibase.KeycloakLogger;
import io.quarkus.deployment.annotations.BuildStep;
import io.quarkus.deployment.annotations.ExecutionTime;
import io.quarkus.deployment.annotations.Record;
import liquibase.database.Database;
import liquibase.lockservice.LockService;
import liquibase.logging.Logger;
import liquibase.parser.ChangeLogParser;
import liquibase.parser.core.xml.XMLChangeLogSAXParser;
import liquibase.servicelocator.LiquibaseService;
@ -47,13 +43,11 @@ class LiquibaseProcessor {
liquibase.parser.NamespaceDetails.class,
liquibase.precondition.Precondition.class,
Database.class,
ChangeLogParser.class,
liquibase.change.Change.class,
liquibase.snapshot.SnapshotGenerator.class,
liquibase.changelog.ChangeLogHistoryService.class,
liquibase.datatype.LiquibaseDataType.class,
liquibase.executor.Executor.class,
LockService.class,
SqlGenerator.class)) {
List<String> impls = new ArrayList<>();
services.put(c.getName(), impls);
@ -78,11 +72,8 @@ class LiquibaseProcessor {
}
}
services.put(Logger.class.getName(), Arrays.asList(KeycloakLogger.class.getName()));
services.put(LockService.class.getName(), Arrays.asList(DummyLockService.class.getName()));
services.put(ChangeLogParser.class.getName(), Arrays.asList(XMLChangeLogSAXParser.class.getName()));
services.get(SqlGenerator.class.getName()).add(CustomInsertLockRecordGenerator.class.getName());
services.get(SqlGenerator.class.getName()).add(CustomLockDatabaseChangeLogGenerator.class.getName());
recorder.configureLiquibase(services);
}

View file

@ -20,6 +20,7 @@ package org.keycloak.quarkus.runtime;
import java.util.List;
import java.util.Map;
import liquibase.Scope;
import org.infinispan.configuration.parsing.ConfigurationBuilderHolder;
import org.infinispan.configuration.parsing.ParserRegistry;
import org.infinispan.jboss.marshalling.core.JBossUserMarshaller;
@ -31,7 +32,6 @@ import org.keycloak.common.Profile;
import org.keycloak.quarkus.runtime.configuration.Configuration;
import org.keycloak.quarkus.runtime.integration.QuarkusKeycloakSessionFactory;
import org.keycloak.quarkus.runtime.storage.database.liquibase.FastServiceLocator;
import org.keycloak.quarkus.runtime.storage.database.liquibase.KeycloakLogger;
import org.keycloak.provider.Provider;
import org.keycloak.provider.ProviderFactory;
import org.keycloak.provider.Spi;
@ -40,34 +40,15 @@ import org.keycloak.quarkus.runtime.storage.infinispan.CacheManagerFactory;
import io.quarkus.runtime.RuntimeValue;
import io.quarkus.runtime.ShutdownContext;
import io.quarkus.runtime.annotations.Recorder;
import liquibase.logging.LogFactory;
import liquibase.servicelocator.ServiceLocator;
@Recorder
public class KeycloakRecorder {
public void configureLiquibase(Map<String, List<String>> services) {
LogFactory.setInstance(new LogFactory() {
final KeycloakLogger logger = new KeycloakLogger();
@Override
public liquibase.logging.Logger getLog(String name) {
return logger;
}
@Override
public liquibase.logging.Logger getLog() {
return logger;
}
});
// we set this property to avoid Liquibase to lookup resources from the classpath and access JAR files
// we already index the packages we want so Liquibase will still be able to load these services
// for uber-jar, this is not a problem because everything is inside the JAR, but once we move to fast-jar we'll have performance penalties
// it seems that v4 of liquibase provides a more smart way of initialization the ServiceLocator that may allow us to remove this
System.setProperty("liquibase.scan.packages", "org.liquibase.core");
ServiceLocator.setInstance(new FastServiceLocator(services));
ServiceLocator locator = Scope.getCurrentScope().getServiceLocator();
if (locator instanceof FastServiceLocator)
((FastServiceLocator) locator).initServices(services);
}
public void configSessionFactory(

View file

@ -17,108 +17,48 @@
package org.keycloak.quarkus.runtime.storage.database.liquibase;
import java.util.HashSet;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import liquibase.database.DatabaseFactory;
import liquibase.exception.ServiceNotFoundException;
import liquibase.servicelocator.StandardServiceLocator;
import liquibase.database.Database;
import liquibase.logging.Logger;
import liquibase.servicelocator.DefaultPackageScanClassResolver;
import liquibase.servicelocator.ServiceLocator;
public class FastServiceLocator extends StandardServiceLocator {
public class FastServiceLocator extends ServiceLocator {
private Map<String, List<String>> services = new HashMap<>();
private final Map<String, List<String>> services;
public FastServiceLocator(Map<String, List<String>> services) {
super(new DefaultPackageScanClassResolver() {
@Override
public Set<Class<?>> findImplementations(Class parent, String... packageNames) {
List<String> found = services.get(parent.getName());
if (found == null) {
return super.findImplementations(parent, packageNames);
}
Set<Class<?>> ret = new HashSet<>();
for (String i : found) {
try {
ret.add(Class.forName(i, false, Thread.currentThread().getContextClassLoader()));
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
return ret;
}
});
if (!System.getProperties().containsKey("liquibase.scan.packages")) {
if (getPackages().remove("liquibase.core")) {
addPackageToScan("liquibase.core.xml");
}
if (getPackages().remove("liquibase.parser")) {
addPackageToScan("liquibase.parser.core.xml");
}
if (getPackages().remove("liquibase.serializer")) {
addPackageToScan("liquibase.serializer.core.xml");
}
getPackages().remove("liquibase.ext");
getPackages().remove("liquibase.sdk");
}
// we only need XML parsers
getPackages().remove("liquibase.parser.core.yaml");
getPackages().remove("liquibase.serializer.core.yaml");
getPackages().remove("liquibase.parser.core.json");
getPackages().remove("liquibase.serializer.core.json");
// register only the implementations related to the chosen db
for (String databaseImpl : services.get(Database.class.getName())) {
try {
register((Database) getClass().getClassLoader().loadClass(databaseImpl).getDeclaredConstructor().newInstance());
} catch (Exception cause) {
throw new RuntimeException("Failed to load database implementation", cause);
}
}
this.services = services;
@Override
public int getPriority() {
return super.getPriority() + 1;
}
@Override
public Object newInstance(Class requiredInterface) throws ServiceNotFoundException {
if (Logger.class.equals(requiredInterface)) {
return new KeycloakLogger();
}
return super.newInstance(requiredInterface);
}
@Override
public <T> Class<? extends T>[] findClasses(Class<T> requiredInterface) throws ServiceNotFoundException {
List<String> found = services.get(requiredInterface.getName());
@SuppressWarnings("unchecked")
public <T> List<T> findInstances(Class<T> interfaceType) throws ServiceNotFoundException {
List<String> found = services.get(interfaceType.getName());
if (found == null) {
return super.findClasses(requiredInterface);
return super.findInstances(interfaceType);
}
Set<Class<?>> ret = new HashSet<>();
List<T> ret = new ArrayList<>();
for (String i : found) {
try {
ret.add(Class.forName(i, false, Thread.currentThread().getContextClassLoader()));
} catch (ClassNotFoundException e) {
e.printStackTrace();
ret.add((T) Class.forName(i, false, Thread.currentThread().getContextClassLoader())
.getDeclaredConstructor().newInstance());
} catch (Exception e) {
throw new RuntimeException("Failed to find Liquibase implementation", e);
}
}
return ret.toArray(new Class[ret.size()]);
return ret;
}
public void register(Database database) {
DatabaseFactory.getInstance().register(database);
public FastServiceLocator() {
}
}
public void initServices(final Map<String, List<String>> services) {
this.services = services;
}
}

View file

@ -0,0 +1,39 @@
/*
* Copyright 2022 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.quarkus.runtime.storage.database.liquibase;
import liquibase.logging.Logger;
import liquibase.logging.core.AbstractLogService;
/**
* A {@link liquibase.logging.LogService} implementation that creates instances of {@link org.keycloak.connections.jpa.updater.liquibase.log.KeycloakLogger}.
*
* @author <a href="mailto:sguilhen@redhat.com">Stefan Guilhen</a>
*/
public class KeycloakLogService extends AbstractLogService {
@Override
public int getPriority() {
return PRIORITY_DEFAULT + 1;
}
@Override
public Logger getLog(Class clazz) {
return new KeycloakLogger(clazz);
}
}

View file

@ -17,104 +17,86 @@
package org.keycloak.quarkus.runtime.storage.database.liquibase;
import liquibase.changelog.ChangeSet;
import liquibase.changelog.DatabaseChangeLog;
import liquibase.logging.LogLevel;
import liquibase.logging.Logger;
import java.util.logging.Level;
public class KeycloakLogger implements Logger {
import liquibase.logging.core.AbstractLogger;
import liquibase.logging.core.DefaultLogMessageFilter;
import org.jboss.logging.Logger;
private static final org.jboss.logging.Logger logger = org.jboss.logging.Logger.getLogger(KeycloakLogger.class);
@Override
public void setName(String name) {
}
/**
* A {@link liquibase.logging.Logger} implementation that delegates to a JBoss {@link Logger}.
*
* @author <a href="mailto:sguilhen@redhat.com">Stefan Guilhen</a>
*/
public class KeycloakLogger extends AbstractLogger {
@Override
public void setLogLevel(String logLevel, String logFile) {
private final Logger delegate;
public KeycloakLogger(final Class clazz) {
super(new DefaultLogMessageFilter());
this.delegate = Logger.getLogger(clazz);
}
@Override
public void severe(String message) {
logger.error(message);
this.delegate.error(message);
}
@Override
public void severe(String message, Throwable e) {
logger.error(message, e);
this.delegate.error(message, e);
}
@Override
public void warning(String message) {
// Ignore this warning as cascaded drops doesn't work anyway with all DBs, which we need to support
if ("Database does not support drop with cascade".equals(message)) {
logger.debug(message);
this.delegate.debug(message);
} else {
logger.warn(message);
this.delegate.warn(message);
}
}
@Override
public void warning(String message, Throwable e) {
logger.warn(message, e);
this.delegate.warn(message, e);
}
@Override
public void info(String message) {
logger.debug(message);
this.delegate.debug(message);
}
@Override
public void info(String message, Throwable e) {
logger.debug(message, e);
this.delegate.debug(message, e);
}
@Override
public void debug(String message) {
if (logger.isTraceEnabled()) {
logger.trace(message);
if (this.delegate.isTraceEnabled()) {
this.delegate.trace(message);
}
}
@Override
public LogLevel getLogLevel() {
if (logger.isTraceEnabled()) {
return LogLevel.DEBUG;
} else if (logger.isDebugEnabled()) {
return LogLevel.INFO;
} else {
return LogLevel.WARNING;
}
}
@Override
public void setLogLevel(String level) {
}
@Override
public void setLogLevel(LogLevel level) {
}
@Override
public void debug(String message, Throwable e) {
logger.trace(message, e);
this.delegate.trace(message, e);
}
@Override
public void setChangeLog(DatabaseChangeLog databaseChangeLog) {
public void log(Level level, String message, Throwable e) {
if (level.equals(Level.OFF)) {
return;
} else if (level.equals(Level.SEVERE)) {
this.delegate.error(message, e);
} else if (level.equals(Level.WARNING)) {
this.delegate.warn(message, e);
} else if (level.equals(Level.INFO)) {
this.delegate.debug(message, e);
} else if (level.equals(Level.FINE) | level.equals(Level.FINER) | level.equals(Level.FINEST)) {
if (this.delegate.isTraceEnabled())
this.delegate.trace(message, e);
}
}
@Override
public void setChangeSet(ChangeSet changeSet) {
}
@Override
public int getPriority() {
return 0;
}
@Override
public void closeLogFile() {
}
}

View file

@ -28,12 +28,13 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import liquibase.Scope;
import org.jboss.logging.Logger;
import org.keycloak.common.util.reflections.Reflections;
import org.keycloak.connections.jpa.entityprovider.JpaEntityProvider;
import org.keycloak.connections.jpa.updater.JpaUpdaterProvider;
import org.keycloak.connections.jpa.updater.liquibase.LiquibaseConstants;
import org.keycloak.connections.jpa.updater.liquibase.ThreadLocalSessionContext;
import org.keycloak.connections.jpa.updater.liquibase.conn.CustomChangeLogHistoryService;
import org.keycloak.connections.jpa.updater.liquibase.conn.LiquibaseConnectionProvider;
@ -159,8 +160,8 @@ public class QuarkusJpaUpdaterProvider implements JpaUpdaterProvider {
statementsToExecute.add(new SetNullableStatement(database.getLiquibaseCatalogName(), database.getLiquibaseSchemaName(),
changelogTable.getName(), DEPLOYMENT_ID_COLUMN, "VARCHAR(10)", false));
ExecutorService executorService = ExecutorService.getInstance();
Executor executor = executorService.getExecutor(liquibase.getDatabase());
ExecutorService executorService = Scope.getCurrentScope().getSingleton(ExecutorService.class);
Executor executor = executorService.getExecutor(LiquibaseConstants.JDBC_EXECUTOR, liquibase.getDatabase());
for (SqlStatement sql : statementsToExecute) {
executor.execute(sql);
@ -186,7 +187,7 @@ public class QuarkusJpaUpdaterProvider implements JpaUpdaterProvider {
if (ranChangeSets.isEmpty()) {
outputChangeLogTableCreationScript(liquibase, exportWriter);
}
liquibase.update((Contexts) null, new LabelExpression(), exportWriter, false);
liquibase.update(null, new LabelExpression(), exportWriter, false);
} else {
liquibase.update((Contexts) null);
}
@ -204,22 +205,23 @@ public class QuarkusJpaUpdaterProvider implements JpaUpdaterProvider {
private void outputChangeLogTableCreationScript(Liquibase liquibase, final Writer exportWriter) throws DatabaseException {
Database database = liquibase.getDatabase();
Executor oldTemplate = ExecutorService.getInstance().getExecutor(database);
LoggingExecutor executor = new LoggingExecutor(ExecutorService.getInstance().getExecutor(database), exportWriter, database);
ExecutorService.getInstance().setExecutor(database, executor);
ExecutorService executorService = Scope.getCurrentScope().getSingleton(ExecutorService.class);
Executor oldTemplate = executorService.getExecutor(LiquibaseConstants.JDBC_EXECUTOR, database);
LoggingExecutor loggingExecutor = new LoggingExecutor(executorService.getExecutor(LiquibaseConstants.JDBC_EXECUTOR, database), exportWriter, database);
executorService.setExecutor(LiquibaseConstants.JDBC_EXECUTOR, database, loggingExecutor);
executor.comment("*********************************************************************");
executor.comment("* Keycloak database creation script - apply this script to empty DB *");
executor.comment("*********************************************************************" + StreamUtil.getLineSeparator());
loggingExecutor.comment("*********************************************************************");
loggingExecutor.comment("* Keycloak database creation script - apply this script to empty DB *");
loggingExecutor.comment("*********************************************************************" + StreamUtil.getLineSeparator());
executor.execute(new CreateDatabaseChangeLogTableStatement());
loggingExecutor.execute(new CreateDatabaseChangeLogTableStatement());
// DatabaseChangeLogLockTable is created before this code is executed and recreated if it does not exist automatically
// in org.keycloak.connections.jpa.updater.liquibase.lock.CustomLockService.init() called indirectly from
// KeycloakApplication constructor (search for waitForLock() call). Hence it is not included in the creation script.
executor.comment("*********************************************************************" + StreamUtil.getLineSeparator());
loggingExecutor.comment("*********************************************************************" + StreamUtil.getLineSeparator());
ExecutorService.getInstance().setExecutor(database, oldTemplate);
executorService.setExecutor(LiquibaseConstants.JDBC_EXECUTOR, database, oldTemplate);
}
@Override
@ -288,19 +290,13 @@ public class QuarkusJpaUpdaterProvider implements JpaUpdaterProvider {
ChangeLogHistoryServiceFactory.getInstance().register(new CustomChangeLogHistoryService());
}
@SuppressWarnings("unchecked")
private List<ChangeSet> getLiquibaseUnrunChangeSets(Liquibase liquibase) {
// we don't need to fetch change sets if they were previously obtained
return changeSets.computeIfAbsent(liquibase.getChangeLogFile(), new Function<String, List<ChangeSet>>() {
@Override
public List<ChangeSet> apply(String s) {
// TODO tracked as: https://issues.jboss.org/browse/KEYCLOAK-3730
// TODO: When https://liquibase.jira.com/browse/CORE-2919 is resolved, replace the following two lines with:
// List<ChangeSet> changeSets = liquibase.listUnrunChangeSets((Contexts) null, new LabelExpression(), false);
Method listUnrunChangeSets = Reflections.findDeclaredMethod(Liquibase.class, "listUnrunChangeSets", Contexts.class, LabelExpression.class, boolean.class);
return Reflections
.invokeMethod(true, listUnrunChangeSets, List.class, liquibase, (Contexts) null, new LabelExpression(), false);
return changeSets.computeIfAbsent(liquibase.getChangeLogFile(), s -> {
try {
return liquibase.listUnrunChangeSets(null, new LabelExpression(), false);
} catch (LiquibaseException e) {
throw new RuntimeException(e);
}
});
}
@ -321,8 +317,4 @@ public class QuarkusJpaUpdaterProvider implements JpaUpdaterProvider {
changeSets = null;
}
public static String getTable(String table, String defaultSchema) {
return defaultSchema != null ? defaultSchema + "." + table : table;
}
}

View file

@ -22,32 +22,23 @@ import java.sql.Connection;
import javax.xml.parsers.SAXParserFactory;
import liquibase.database.core.MariaDBDatabase;
import liquibase.database.core.MySQLDatabase;
import org.jboss.logging.Logger;
import org.keycloak.Config;
import org.keycloak.connections.jpa.JpaConnectionProvider;
import org.keycloak.connections.jpa.JpaConnectionProviderFactory;
import org.keycloak.connections.jpa.updater.liquibase.MySQL8VarcharType;
import org.keycloak.connections.jpa.updater.liquibase.conn.CustomChangeLogHistoryService;
import org.keycloak.connections.jpa.updater.liquibase.conn.LiquibaseConnectionProvider;
import org.keycloak.connections.jpa.updater.liquibase.conn.LiquibaseConnectionProviderFactory;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeycloakSessionFactory;
import liquibase.Liquibase;
import liquibase.changelog.ChangeLogHistoryServiceFactory;
import liquibase.database.Database;
import liquibase.database.DatabaseFactory;
import liquibase.database.jvm.JdbcConnection;
import liquibase.datatype.DataTypeFactory;
import liquibase.exception.LiquibaseException;
import liquibase.parser.ChangeLogParser;
import liquibase.parser.ChangeLogParserFactory;
import liquibase.parser.core.xml.XMLChangeLogSAXParser;
import liquibase.resource.ClassLoaderResourceAccessor;
import liquibase.resource.ResourceAccessor;
import liquibase.servicelocator.ServiceLocator;
public class QuarkusLiquibaseConnectionProvider implements LiquibaseConnectionProviderFactory, LiquibaseConnectionProvider {
@ -71,30 +62,6 @@ public class QuarkusLiquibaseConnectionProvider implements LiquibaseConnectionPr
protected void baseLiquibaseInitialization(KeycloakSession session) {
resourceAccessor = new ClassLoaderResourceAccessor(getClass().getClassLoader());
FastServiceLocator locator = (FastServiceLocator) ServiceLocator.getInstance();
JpaConnectionProviderFactory jpaConnectionProvider = (JpaConnectionProviderFactory) session
.getKeycloakSessionFactory().getProviderFactory(JpaConnectionProvider.class);
// registers only the database we are using
try (Connection connection = jpaConnectionProvider.getConnection()) {
Database database = DatabaseFactory.getInstance()
.findCorrectDatabaseImplementation(new JdbcConnection(connection));
if (database.getDatabaseProductName().equals(MySQLDatabase.PRODUCT_NAME)) {
// Adding CustomVarcharType for MySQL 8 and newer
DataTypeFactory.getInstance().register(MySQL8VarcharType.class);
ChangeLogHistoryServiceFactory.getInstance().register(new CustomChangeLogHistoryService());
} else if (database.getDatabaseProductName().equals(MariaDBDatabase.PRODUCT_NAME)) {
// Adding CustomVarcharType for MySQL 8 and newer
DataTypeFactory.getInstance().register(MySQL8VarcharType.class);
}
DatabaseFactory.getInstance().clearRegistry();
locator.register(database);
} catch (Exception cause) {
throw new RuntimeException("Failed to configure Liquibase database", cause);
}
// disables XML validation
for (ChangeLogParser parser : ChangeLogParserFactory.getInstance().getParsers()) {

View file

@ -0,0 +1,18 @@
#
# Copyright 2022 Red Hat, Inc. and/or its affiliates
# and other contributors as indicated by the @author tags.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
org.keycloak.quarkus.runtime.storage.database.liquibase.KeycloakLogService

View file

@ -0,0 +1,18 @@
#
# Copyright 2022 Red Hat, Inc. and/or its affiliates
# and other contributors as indicated by the @author tags.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
org.keycloak.quarkus.runtime.storage.database.liquibase.FastServiceLocator