use of liquibase.executor.LoggingExecutor in project liquibase by liquibase.
the class StandardLockService method init.
@Override
public void init() throws DatabaseException {
boolean createdTable = false;
Executor executor = Scope.getCurrentScope().getSingleton(ExecutorService.class).getExecutor("jdbc", database);
int maxIterations = 10;
if (executor instanceof LoggingExecutor) {
// can't / don't have to re-check
if (hasDatabaseChangeLogLockTable()) {
maxIterations = 0;
} else {
maxIterations = 1;
}
}
for (int i = 0; i < maxIterations; i++) {
try {
if (!hasDatabaseChangeLogLockTable(true)) {
executor.comment("Create Database Lock Table");
executor.execute(new CreateDatabaseChangeLogLockTableStatement());
database.commit();
Scope.getCurrentScope().getLog(getClass()).fine("Created database lock table with name: " + database.escapeTableName(database.getLiquibaseCatalogName(), database.getLiquibaseSchemaName(), database.getDatabaseChangeLogLockTableName()));
this.hasDatabaseChangeLogLockTable = true;
createdTable = true;
hasDatabaseChangeLogLockTable = true;
}
if (!isDatabaseChangeLogLockTableInitialized(createdTable, true)) {
executor.comment("Initialize Database Lock Table");
executor.execute(new InitializeDatabaseChangeLogLockTableStatement());
database.commit();
}
if (executor.updatesDatabase() && (database instanceof DerbyDatabase) && ((DerbyDatabase) database).supportsBooleanDataType() || database.getClass().isAssignableFrom(DB2Database.class) && ((DB2Database) database).supportsBooleanDataType()) {
// check if the changelog table is of an old smallint vs. boolean format
String lockTable = database.escapeTableName(database.getLiquibaseCatalogName(), database.getLiquibaseSchemaName(), database.getDatabaseChangeLogLockTableName());
Object obj = executor.queryForObject(new RawSqlStatement("SELECT MIN(locked) AS test FROM " + lockTable + " FETCH FIRST ROW ONLY"), Object.class);
if (!(obj instanceof Boolean)) {
// wrong type, need to recreate table
executor.execute(new DropTableStatement(database.getLiquibaseCatalogName(), database.getLiquibaseSchemaName(), database.getDatabaseChangeLogLockTableName(), false));
executor.execute(new CreateDatabaseChangeLogLockTableStatement());
executor.execute(new InitializeDatabaseChangeLogLockTableStatement());
}
}
} catch (Exception e) {
if (i == maxIterations - 1) {
throw e;
} else {
Scope.getCurrentScope().getLog(getClass()).fine("Failed to create or initialize the lock table, trying again, iteration " + (i + 1) + " of " + maxIterations, e);
// If another node already created the table, then we need to rollback this current transaction,
// otherwise servers like Postgres will not allow continued use of the same connection, failing with
// a message like "current transaction is aborted, commands ignored until end of transaction block"
database.rollback();
try {
Thread.sleep(random.nextInt(1000));
} catch (InterruptedException ex) {
Scope.getCurrentScope().getLog(getClass()).warning("Lock table retry loop thread sleep interrupted", ex);
}
}
}
}
}
use of liquibase.executor.LoggingExecutor in project liquibase by liquibase.
the class ChangeSet method setupCustomExecutorIfNecessary.
//
// Get the custom Executor ready if necessary
// We do not do anything if we have a LoggingExecutor.
//
private Executor setupCustomExecutorIfNecessary(Database database) {
Executor originalExecutor = Scope.getCurrentScope().getSingleton(ExecutorService.class).getExecutor("jdbc", database);
if (getRunWith() == null || originalExecutor instanceof LoggingExecutor) {
return originalExecutor;
}
String executorName = ChangeSet.lookupExecutor(getRunWith());
Executor customExecutor = Scope.getCurrentScope().getSingleton(ExecutorService.class).getExecutor(executorName, database);
Scope.getCurrentScope().getSingleton(ExecutorService.class).setExecutor("jdbc", database, customExecutor);
List<Change> changes = getChanges();
for (Change change : changes) {
if (!(change instanceof AbstractChange)) {
continue;
}
final ResourceAccessor resourceAccessor = ((AbstractChange) change).getResourceAccessor();
if (resourceAccessor != null) {
customExecutor.setResourceAccessor(resourceAccessor);
break;
}
}
return originalExecutor;
}
use of liquibase.executor.LoggingExecutor in project keycloak by keycloak.
the class CustomCreateIndexChange method generateStatements.
@Override
public SqlStatement[] generateStatements(Database database) {
// This check is for manual migration
if (Scope.getCurrentScope().getSingleton(ExecutorService.class).getExecutor(LiquibaseConstants.JDBC_EXECUTOR, database) instanceof LoggingExecutor)
return super.generateStatements(database);
Object indexCreationThreshold = ((AbstractJdbcDatabase) database).get(DefaultLiquibaseConnectionProvider.INDEX_CREATION_THRESHOLD_PARAM);
if (indexCreationThreshold instanceof Integer) {
this.indexCreationThreshold = (Integer) indexCreationThreshold;
if (this.indexCreationThreshold <= 0)
return super.generateStatements(database);
} else {
return super.generateStatements(database);
}
try {
// To check that the table already exists or not on which the index will be created.
if (!SnapshotGeneratorFactory.getInstance().has(new Table().setName(getTableName()).setSchema(new Schema(getCatalogName(), getSchemaName())), database))
return super.generateStatements(database);
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);
logger.warnv("Following index should be created: {0}", loggingString);
getChangeSet().setComments(loggingString);
return new SqlStatement[] {};
}
} catch (DatabaseException | InvalidExampleException e) {
throw new UnexpectedLiquibaseException("Database error while index threshold validation.", e);
}
return super.generateStatements(database);
}
use of liquibase.executor.LoggingExecutor in project keycloak by keycloak.
the class QuarkusJpaUpdaterProvider method outputChangeLogTableCreationScript.
private void outputChangeLogTableCreationScript(Liquibase liquibase, final Writer exportWriter) throws DatabaseException {
Database database = liquibase.getDatabase();
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);
loggingExecutor.comment("*********************************************************************");
loggingExecutor.comment("* Keycloak database creation script - apply this script to empty DB *");
loggingExecutor.comment("*********************************************************************" + StreamUtil.getLineSeparator());
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.
loggingExecutor.comment("*********************************************************************" + StreamUtil.getLineSeparator());
executorService.setExecutor(LiquibaseConstants.JDBC_EXECUTOR, database, oldTemplate);
}
Aggregations