KEYCLOAK-19104 Add custom ForeignKeySnapshotGenerator
This commit is contained in:
parent
e1a4f7f485
commit
d216f8f748
3 changed files with 131 additions and 0 deletions
|
@ -0,0 +1,121 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2021 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;
|
||||||
|
|
||||||
|
import java.sql.DatabaseMetaData;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import liquibase.database.Database;
|
||||||
|
import liquibase.database.DatabaseConnection;
|
||||||
|
import liquibase.database.core.MSSQLDatabase;
|
||||||
|
import liquibase.database.jvm.JdbcConnection;
|
||||||
|
import liquibase.exception.DatabaseException;
|
||||||
|
import liquibase.snapshot.jvm.ForeignKeySnapshotGenerator;
|
||||||
|
import liquibase.structure.DatabaseObject;
|
||||||
|
import liquibase.structure.core.ForeignKeyConstraintType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class overrides original ForeignKeySnapshotGenerator from liquibase 3.5.5.
|
||||||
|
* It contains fix https://liquibase.jira.com/browse/CORE-3141
|
||||||
|
*/
|
||||||
|
public class CustomForeignKeySnapshotGenerator extends ForeignKeySnapshotGenerator {
|
||||||
|
|
||||||
|
public CustomForeignKeySnapshotGenerator() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getPriority(Class<? extends DatabaseObject> objectType, Database database) {
|
||||||
|
return super.getPriority(objectType, database) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected ForeignKeyConstraintType convertToForeignKeyConstraintType(Integer jdbcType, Database database) throws DatabaseException {
|
||||||
|
if (jdbcType == null) {
|
||||||
|
return ForeignKeyConstraintType.importedKeyRestrict;
|
||||||
|
}
|
||||||
|
if (driverUsesSpFkeys(database)) {
|
||||||
|
switch (jdbcType) {
|
||||||
|
case 0:
|
||||||
|
return ForeignKeyConstraintType.importedKeyCascade;
|
||||||
|
case 1:
|
||||||
|
return ForeignKeyConstraintType.importedKeyNoAction;
|
||||||
|
case 2:
|
||||||
|
return ForeignKeyConstraintType.importedKeySetNull;
|
||||||
|
case 3:
|
||||||
|
return ForeignKeyConstraintType.importedKeySetDefault;
|
||||||
|
default:
|
||||||
|
throw new DatabaseException("Unknown constraint type: " + jdbcType);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
switch (jdbcType) {
|
||||||
|
case DatabaseMetaData.importedKeyCascade:
|
||||||
|
return ForeignKeyConstraintType.importedKeyCascade;
|
||||||
|
case DatabaseMetaData.importedKeyNoAction:
|
||||||
|
return ForeignKeyConstraintType.importedKeyNoAction;
|
||||||
|
case DatabaseMetaData.importedKeyRestrict:
|
||||||
|
if (database instanceof MSSQLDatabase) {
|
||||||
|
//mssql doesn't support restrict. Not sure why it comes back with this type sometimes
|
||||||
|
return ForeignKeyConstraintType.importedKeyNoAction;
|
||||||
|
} else {
|
||||||
|
return ForeignKeyConstraintType.importedKeyRestrict;
|
||||||
|
}
|
||||||
|
case DatabaseMetaData.importedKeySetDefault:
|
||||||
|
return ForeignKeyConstraintType.importedKeySetDefault;
|
||||||
|
case DatabaseMetaData.importedKeySetNull:
|
||||||
|
return ForeignKeyConstraintType.importedKeySetNull;
|
||||||
|
default:
|
||||||
|
throw new DatabaseException("Unknown constraint type: " + jdbcType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Sql server JDBC drivers prior to 6.3.3 used sp_fkeys to determine the delete/cascade metadata.
|
||||||
|
* The sp_fkeys stored procedure spec says that returned integer values of 0, 1, 2, or 4
|
||||||
|
* translate to cascade, noAction, SetNull, or SetDefault which are not the values in the JDBC
|
||||||
|
* standard.
|
||||||
|
*
|
||||||
|
* If this method returns true, the sp_fkeys values should be used. Otherwise use the standard jdbc logic
|
||||||
|
*
|
||||||
|
* The change in logic went in with https://github.com/Microsoft/mssql-jdbc/pull/490
|
||||||
|
*/
|
||||||
|
private boolean driverUsesSpFkeys(Database database) throws DatabaseException {
|
||||||
|
if (!(database instanceof MSSQLDatabase)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
DatabaseConnection connection = database.getConnection();
|
||||||
|
if (!(connection instanceof JdbcConnection)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
DatabaseMetaData metaData = ((JdbcConnection) connection).getMetaData();
|
||||||
|
int driverMajorVersion = metaData.getDriverMajorVersion();
|
||||||
|
int driverMinorVersion= metaData.getDriverMinorVersion();
|
||||||
|
String driverName = metaData.getDriverName();
|
||||||
|
|
||||||
|
if (!driverName.startsWith("Microsoft")) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return !(driverMajorVersion > 6 || (driverMajorVersion == 6 && driverMinorVersion >= 3));
|
||||||
|
} catch (SQLException e) {
|
||||||
|
throw new DatabaseException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -35,6 +35,7 @@ import liquibase.servicelocator.ServiceLocator;
|
||||||
import liquibase.sqlgenerator.SqlGeneratorFactory;
|
import liquibase.sqlgenerator.SqlGeneratorFactory;
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
import org.keycloak.Config;
|
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.LiquibaseJpaUpdaterProvider;
|
||||||
import org.keycloak.connections.jpa.updater.liquibase.PostgresPlusDatabase;
|
import org.keycloak.connections.jpa.updater.liquibase.PostgresPlusDatabase;
|
||||||
import org.keycloak.connections.jpa.updater.liquibase.MySQL8VarcharType;
|
import org.keycloak.connections.jpa.updater.liquibase.MySQL8VarcharType;
|
||||||
|
@ -50,6 +51,7 @@ import org.keycloak.models.KeycloakSessionFactory;
|
||||||
import java.sql.Connection;
|
import java.sql.Connection;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
import liquibase.changelog.ChangeLogHistoryServiceFactory;
|
import liquibase.changelog.ChangeLogHistoryServiceFactory;
|
||||||
|
import liquibase.snapshot.SnapshotGeneratorFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||||
|
@ -126,6 +128,9 @@ public class DefaultLiquibaseConnectionProvider implements LiquibaseConnectionPr
|
||||||
|
|
||||||
// Adding CustomCreateIndexChange for handling conditional indices creation
|
// Adding CustomCreateIndexChange for handling conditional indices creation
|
||||||
ChangeFactory.getInstance().register(CustomCreateIndexChange.class);
|
ChangeFactory.getInstance().register(CustomCreateIndexChange.class);
|
||||||
|
|
||||||
|
// Contains fix for https://liquibase.jira.com/browse/CORE-3141
|
||||||
|
SnapshotGeneratorFactory.getInstance().register(new CustomForeignKeySnapshotGenerator());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -249,6 +249,11 @@
|
||||||
<artifactId>mariadb-java-client</artifactId>
|
<artifactId>mariadb-java-client</artifactId>
|
||||||
<version>${mariadb.driver.version}</version>
|
<version>${mariadb.driver.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.microsoft.sqlserver</groupId>
|
||||||
|
<artifactId>mssql-jdbc</artifactId>
|
||||||
|
<version>${mssql.driver.version}</version>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue