Search in sources :

Example 46 with Executor

use of liquibase.executor.Executor in project liquibase by liquibase.

the class StandardChangeLogHistoryService method init.

public void init() throws DatabaseException {
    if (serviceInitialized) {
        return;
    }
    Database database = getDatabase();
    Table changeLogTable = null;
    try {
        changeLogTable = SnapshotGeneratorFactory.getInstance().getDatabaseChangeLogTable(new SnapshotControl(database, false, Table.class, Column.class), database);
    } catch (LiquibaseException e) {
        throw new UnexpectedLiquibaseException(e);
    }
    List<SqlStatement> statementsToExecute = new ArrayList<>();
    boolean changeLogCreateAttempted = false;
    Executor executor = Scope.getCurrentScope().getSingleton(ExecutorService.class).getExecutor("jdbc", database);
    if (changeLogTable != null) {
        boolean hasDescription = changeLogTable.getColumn("DESCRIPTION") != null;
        boolean hasComments = changeLogTable.getColumn("COMMENTS") != null;
        boolean hasTag = changeLogTable.getColumn("TAG") != null;
        boolean hasLiquibase = changeLogTable.getColumn("LIQUIBASE") != null;
        boolean hasContexts = changeLogTable.getColumn("CONTEXTS") != null;
        boolean hasLabels = changeLogTable.getColumn("LABELS") != null;
        boolean liquibaseColumnNotRightSize = false;
        if (!(this.getDatabase() instanceof SQLiteDatabase)) {
            DataType type = changeLogTable.getColumn("LIQUIBASE").getType();
            if (type.getTypeName().toLowerCase().startsWith("varchar")) {
                Integer columnSize = type.getColumnSize();
                liquibaseColumnNotRightSize = (columnSize != null) && (columnSize < 20);
            } else {
                liquibaseColumnNotRightSize = false;
            }
        }
        boolean hasOrderExecuted = changeLogTable.getColumn("ORDEREXECUTED") != null;
        boolean checksumNotRightSize = false;
        if (!(this.getDatabase() instanceof SQLiteDatabase)) {
            DataType type = changeLogTable.getColumn("MD5SUM").getType();
            if (type.getTypeName().toLowerCase().startsWith("varchar") || type.getTypeName().toLowerCase().startsWith("character varying")) {
                Integer columnSize = type.getColumnSize();
                checksumNotRightSize = (columnSize != null) && (columnSize < 35);
            } else {
                liquibaseColumnNotRightSize = false;
            }
        }
        boolean hasExecTypeColumn = changeLogTable.getColumn("EXECTYPE") != null;
        String charTypeName = getCharTypeName();
        boolean hasDeploymentIdColumn = changeLogTable.getColumn("DEPLOYMENT_ID") != null;
        if (!hasDescription) {
            executor.comment("Adding missing databasechangelog.description column");
            statementsToExecute.add(new AddColumnStatement(getLiquibaseCatalogName(), getLiquibaseSchemaName(), getDatabaseChangeLogTableName(), "DESCRIPTION", charTypeName + "(255)", null));
        }
        if (!hasTag) {
            executor.comment("Adding missing databasechangelog.tag column");
            statementsToExecute.add(new AddColumnStatement(getLiquibaseCatalogName(), getLiquibaseSchemaName(), getDatabaseChangeLogTableName(), "TAG", charTypeName + "(255)", null));
        }
        if (!hasComments) {
            executor.comment("Adding missing databasechangelog.comments column");
            statementsToExecute.add(new AddColumnStatement(getLiquibaseCatalogName(), getLiquibaseSchemaName(), getDatabaseChangeLogTableName(), "COMMENTS", charTypeName + "(255)", null));
        }
        if (!hasLiquibase) {
            executor.comment("Adding missing databasechangelog.liquibase column");
            statementsToExecute.add(new AddColumnStatement(getLiquibaseCatalogName(), getLiquibaseSchemaName(), getDatabaseChangeLogTableName(), "LIQUIBASE", charTypeName + "(20)", null));
        }
        if (!hasOrderExecuted) {
            executor.comment("Adding missing databasechangelog.orderexecuted column");
            statementsToExecute.add(new AddColumnStatement(getLiquibaseCatalogName(), getLiquibaseSchemaName(), getDatabaseChangeLogTableName(), "ORDEREXECUTED", "int", null));
            statementsToExecute.add(new UpdateStatement(getLiquibaseCatalogName(), getLiquibaseSchemaName(), getDatabaseChangeLogTableName()).addNewColumnValue("ORDEREXECUTED", -1));
            statementsToExecute.add(new SetNullableStatement(getLiquibaseCatalogName(), getLiquibaseSchemaName(), getDatabaseChangeLogTableName(), "ORDEREXECUTED", "int", false));
        }
        if (checksumNotRightSize) {
            executor.comment("Modifying size of databasechangelog.md5sum column");
            statementsToExecute.add(new ModifyDataTypeStatement(getLiquibaseCatalogName(), getLiquibaseSchemaName(), getDatabaseChangeLogTableName(), "MD5SUM", charTypeName + "(35)"));
        }
        if (liquibaseColumnNotRightSize) {
            executor.comment("Modifying size of databasechangelog.liquibase column");
            statementsToExecute.add(new ModifyDataTypeStatement(getLiquibaseCatalogName(), getLiquibaseSchemaName(), getDatabaseChangeLogTableName(), "LIQUIBASE", charTypeName + "(20)"));
        }
        if (!hasExecTypeColumn) {
            executor.comment("Adding missing databasechangelog.exectype column");
            statementsToExecute.add(new AddColumnStatement(getLiquibaseCatalogName(), getLiquibaseSchemaName(), getDatabaseChangeLogTableName(), "EXECTYPE", charTypeName + "(10)", null));
            statementsToExecute.add(new UpdateStatement(getLiquibaseCatalogName(), getLiquibaseSchemaName(), getDatabaseChangeLogTableName()).addNewColumnValue("EXECTYPE", "EXECUTED"));
            statementsToExecute.add(new SetNullableStatement(getLiquibaseCatalogName(), getLiquibaseSchemaName(), getDatabaseChangeLogTableName(), "EXECTYPE", charTypeName + "(10)", false));
        }
        if (hasContexts) {
            Integer columnSize = changeLogTable.getColumn("CONTEXTS").getType().getColumnSize();
            if ((columnSize != null) && (columnSize < Integer.parseInt(getContextsSize()))) {
                executor.comment("Modifying size of databasechangelog.contexts column");
                statementsToExecute.add(new ModifyDataTypeStatement(getLiquibaseCatalogName(), getLiquibaseSchemaName(), getDatabaseChangeLogTableName(), "CONTEXTS", charTypeName + "(" + getContextsSize() + ")"));
            }
        } else {
            executor.comment("Adding missing databasechangelog.contexts column");
            statementsToExecute.add(new AddColumnStatement(getLiquibaseCatalogName(), getLiquibaseSchemaName(), getDatabaseChangeLogTableName(), "CONTEXTS", charTypeName + "(" + getContextsSize() + ")", null));
        }
        if (hasLabels) {
            Integer columnSize = changeLogTable.getColumn("LABELS").getType().getColumnSize();
            if ((columnSize != null) && (columnSize < Integer.parseInt(getLabelsSize()))) {
                executor.comment("Modifying size of databasechangelog.labels column");
                statementsToExecute.add(new ModifyDataTypeStatement(getLiquibaseCatalogName(), getLiquibaseSchemaName(), getDatabaseChangeLogTableName(), "LABELS", charTypeName + "(" + getLabelsSize() + ")"));
            }
        } else {
            executor.comment("Adding missing databasechangelog.labels column");
            statementsToExecute.add(new AddColumnStatement(getLiquibaseCatalogName(), getLiquibaseSchemaName(), getDatabaseChangeLogTableName(), "LABELS", charTypeName + "(" + getLabelsSize() + ")", null));
        }
        if (!hasDeploymentIdColumn) {
            executor.comment("Adding missing databasechangelog.deployment_id column");
            statementsToExecute.add(new AddColumnStatement(getLiquibaseCatalogName(), getLiquibaseSchemaName(), getDatabaseChangeLogTableName(), "DEPLOYMENT_ID", "VARCHAR(10)", null));
            if (database instanceof DB2Database) {
                statementsToExecute.add(new ReorganizeTableStatement(getLiquibaseCatalogName(), getLiquibaseSchemaName(), getDatabaseChangeLogTableName()));
            }
        }
        List<Map<String, ?>> md5sumRS = Scope.getCurrentScope().getSingleton(ExecutorService.class).getExecutor("jdbc", database).queryForList(new SelectFromDatabaseChangeLogStatement(new SelectFromDatabaseChangeLogStatement.ByNotNullCheckSum(), new ColumnConfig().setName("MD5SUM")).setLimit(1));
        if (!md5sumRS.isEmpty()) {
            String md5sum = md5sumRS.get(0).get("MD5SUM").toString();
            if (!md5sum.startsWith(CheckSum.getCurrentVersion() + ":")) {
                executor.comment("DatabaseChangeLog checksums are an incompatible version.  Setting them to null " + "so they will be updated on next database update");
                databaseChecksumsCompatible = false;
                UpdateStatement updateStatement = new UpdateStatement(database.getLiquibaseCatalogName(), database.getLiquibaseSchemaName(), database.getDatabaseChangeLogTableName()).addNewColumnValue("MD5SUM", null);
                statementsToExecute.add(updateStatement);
            }
        }
    } else if (!changeLogCreateAttempted) {
        executor.comment("Create Database Change Log Table");
        SqlStatement createTableStatement = new CreateDatabaseChangeLogTableStatement();
        if (!canCreateChangeLogTable()) {
            throw new DatabaseException("Cannot create " + getDatabase().escapeTableName(getLiquibaseCatalogName(), getLiquibaseSchemaName(), getDatabaseChangeLogTableName()) + " table for your getDatabase()" + ".\n\n" + "Please construct it manually using the following SQL as a base and re-run Liquibase:\n\n" + createTableStatement);
        }
        // If there is no table in the database for recording change history create one.
        statementsToExecute.add(createTableStatement);
        Scope.getCurrentScope().getLog(getClass()).info("Creating database history table with name: " + getDatabase().escapeTableName(getLiquibaseCatalogName(), getLiquibaseSchemaName(), getDatabaseChangeLogTableName()));
    }
    for (SqlStatement sql : statementsToExecute) {
        if (SqlGeneratorFactory.getInstance().supports(sql, database)) {
            executor.execute(sql);
            getDatabase().commit();
        } else {
            Scope.getCurrentScope().getLog(getClass()).info("Cannot run " + sql.getClass().getSimpleName() + " on" + " " + getDatabase().getShortName() + " when checking databasechangelog table");
        }
    }
    serviceInitialized = true;
}
Also used : DB2Database(liquibase.database.core.DB2Database) ColumnConfig(liquibase.change.ColumnConfig) SqlStatement(liquibase.statement.SqlStatement) Executor(liquibase.executor.Executor) SQLiteDatabase(liquibase.database.core.SQLiteDatabase) DB2Database(liquibase.database.core.DB2Database) MSSQLDatabase(liquibase.database.core.MSSQLDatabase) Database(liquibase.database.Database) DataType(liquibase.structure.core.DataType) SnapshotControl(liquibase.snapshot.SnapshotControl) Table(liquibase.structure.core.Table) SQLiteDatabase(liquibase.database.core.SQLiteDatabase) ExecutorService(liquibase.executor.ExecutorService) UnexpectedLiquibaseException(liquibase.exception.UnexpectedLiquibaseException) LiquibaseException(liquibase.exception.LiquibaseException) UnexpectedLiquibaseException(liquibase.exception.UnexpectedLiquibaseException) DatabaseException(liquibase.exception.DatabaseException)

Example 47 with Executor

use of liquibase.executor.Executor in project liquibase by liquibase.

the class StandardChangeLogHistoryService method tag.

/**
 * Tags the database changelog with the given string.
 */
@Override
public void tag(final String tagString) throws DatabaseException {
    Database database = getDatabase();
    Executor executor = Scope.getCurrentScope().getSingleton(ExecutorService.class).getExecutor("jdbc", database);
    int totalRows = Scope.getCurrentScope().getSingleton(ExecutorService.class).getExecutor("jdbc", database).queryForInt(new SelectFromDatabaseChangeLogStatement(new ColumnConfig().setName("COUNT(*)", true)));
    if (totalRows == 0) {
        ChangeSet emptyChangeSet = new ChangeSet(String.valueOf(new Date().getTime()), "liquibase", false, false, "liquibase-internal", null, null, getDatabase().getObjectQuotingStrategy(), null);
        this.setExecType(emptyChangeSet, ChangeSet.ExecType.EXECUTED);
    }
    executor.execute(new TagDatabaseStatement(tagString));
    getDatabase().commit();
    if (this.ranChangeSetList != null) {
        ranChangeSetList.get(ranChangeSetList.size() - 1).setTag(tagString);
    }
}
Also used : Executor(liquibase.executor.Executor) ColumnConfig(liquibase.change.ColumnConfig) SQLiteDatabase(liquibase.database.core.SQLiteDatabase) DB2Database(liquibase.database.core.DB2Database) MSSQLDatabase(liquibase.database.core.MSSQLDatabase) Database(liquibase.database.Database) ExecutorService(liquibase.executor.ExecutorService)

Example 48 with Executor

use of liquibase.executor.Executor in project liquibase by liquibase.

the class ChangeLogIterator method validateChangeSetExecutor.

// 
// Make sure that any change set which has a runWith=<executor> setting
// has a valid Executor, and that the changes in the change set
// are eligible for execution by this Executor
// 
private void validateChangeSetExecutor(ChangeSet changeSet, RuntimeEnvironment env) throws LiquibaseException {
    if (changeSet.getRunWith() == null) {
        return;
    }
    String executorName = ChangeSet.lookupExecutor(changeSet.getRunWith());
    Executor executor;
    try {
        executor = Scope.getCurrentScope().getSingleton(ExecutorService.class).getExecutor(executorName, env.getTargetDatabase());
    } catch (UnexpectedLiquibaseException ule) {
        String message = String.format(MSG_COULD_NOT_FIND_EXECUTOR, executorName, changeSet.toString());
        Scope.getCurrentScope().getLog(getClass()).severe(message);
        throw new LiquibaseException(message);
    }
    // 
    // ASSERT: the Executor is valid
    // allow the Executor to make changes to the object model
    // if needed
    // 
    executor.modifyChangeSet(changeSet);
    ValidationErrors errors = executor.validate(changeSet);
    if (errors.hasErrors()) {
        String message = errors.toString();
        Scope.getCurrentScope().getLog(getClass()).severe(message);
        throw new LiquibaseException(message);
    }
}
Also used : Executor(liquibase.executor.Executor) ValidationErrors(liquibase.exception.ValidationErrors) LiquibaseException(liquibase.exception.LiquibaseException) UnexpectedLiquibaseException(liquibase.exception.UnexpectedLiquibaseException) UnexpectedLiquibaseException(liquibase.exception.UnexpectedLiquibaseException)

Example 49 with Executor

use of liquibase.executor.Executor in project keycloak by keycloak.

the class CustomLockService method currentIdsInDatabaseChangeLogLockTable.

private Set<Integer> currentIdsInDatabaseChangeLogLockTable() throws DatabaseException {
    try {
        Executor executor = Scope.getCurrentScope().getSingleton(ExecutorService.class).getExecutor(LiquibaseConstants.JDBC_EXECUTOR, database);
        String idColumnName = database.escapeColumnName(database.getLiquibaseCatalogName(), database.getLiquibaseSchemaName(), database.getDatabaseChangeLogLockTableName(), "ID");
        String lockTableName = database.escapeTableName(database.getLiquibaseCatalogName(), database.getLiquibaseSchemaName(), database.getDatabaseChangeLogLockTableName());
        SqlStatement sqlStatement = new RawSqlStatement("SELECT " + idColumnName + " FROM " + lockTableName);
        List<Map<String, ?>> rows = executor.queryForList(sqlStatement);
        Set<Integer> ids = rows.stream().map(columnMap -> ((Number) columnMap.get("ID")).intValue()).collect(Collectors.toSet());
        database.commit();
        return ids;
    } catch (UnexpectedLiquibaseException ulie) {
        // 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;
        }
    }
}
Also used : RawSqlStatement(liquibase.statement.core.RawSqlStatement) LiquibaseConstants(org.keycloak.connections.jpa.updater.liquibase.LiquibaseConstants) DerbyDatabase(liquibase.database.core.DerbyDatabase) InitializeDatabaseChangeLogLockTableStatement(liquibase.statement.core.InitializeDatabaseChangeLogLockTableStatement) Arrays(java.util.Arrays) CreateDatabaseChangeLogLockTableStatement(liquibase.statement.core.CreateDatabaseChangeLogLockTableStatement) DropTableStatement(liquibase.statement.core.DropTableStatement) Logger(org.jboss.logging.Logger) Set(java.util.Set) DatabaseException(liquibase.exception.DatabaseException) LockDatabaseChangeLogStatement(liquibase.statement.core.LockDatabaseChangeLogStatement) Field(java.lang.reflect.Field) Collectors(java.util.stream.Collectors) ExecutorService(liquibase.executor.ExecutorService) RawSqlStatement(liquibase.statement.core.RawSqlStatement) List(java.util.List) SqlStatement(liquibase.statement.SqlStatement) StandardLockService(liquibase.lockservice.StandardLockService) Map(java.util.Map) UnexpectedLiquibaseException(liquibase.exception.UnexpectedLiquibaseException) Scope(liquibase.Scope) Executor(liquibase.executor.Executor) DBLockProvider(org.keycloak.models.dblock.DBLockProvider) Time(org.keycloak.common.util.Time) Reflections(org.keycloak.common.util.reflections.Reflections) RawSqlStatement(liquibase.statement.core.RawSqlStatement) SqlStatement(liquibase.statement.SqlStatement) Executor(liquibase.executor.Executor) ExecutorService(liquibase.executor.ExecutorService) Map(java.util.Map) UnexpectedLiquibaseException(liquibase.exception.UnexpectedLiquibaseException) DatabaseException(liquibase.exception.DatabaseException)

Example 50 with Executor

use of liquibase.executor.Executor in project keycloak by keycloak.

the class LiquibaseJpaUpdaterProvider method updateChangeSet.

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);
    if (changelogTable != null) {
        boolean hasDeploymentIdColumn = changelogTable.getColumn(DEPLOYMENT_ID_COLUMN) != null;
        // create DEPLOYMENT_ID column if it doesn't exist
        if (!hasDeploymentIdColumn) {
            ChangeLogHistoryService changelogHistoryService = ChangeLogHistoryServiceFactory.getInstance().getChangeLogService(database);
            changelogHistoryService.generateDeploymentId();
            String deploymentId = changelogHistoryService.getDeploymentId();
            logger.debugv("Adding missing column {0}={1} to {2} table", DEPLOYMENT_ID_COLUMN, deploymentId, changelogTable.getName());
            List<SqlStatement> statementsToExecute = new ArrayList<>();
            statementsToExecute.add(new AddColumnStatement(database.getLiquibaseCatalogName(), database.getLiquibaseSchemaName(), changelogTable.getName(), DEPLOYMENT_ID_COLUMN, "VARCHAR(10)", null));
            statementsToExecute.add(new UpdateStatement(database.getLiquibaseCatalogName(), database.getLiquibaseSchemaName(), changelogTable.getName()).addNewColumnValue(DEPLOYMENT_ID_COLUMN, deploymentId));
            statementsToExecute.add(new SetNullableStatement(database.getLiquibaseCatalogName(), database.getLiquibaseSchemaName(), changelogTable.getName(), DEPLOYMENT_ID_COLUMN, "VARCHAR(10)", false));
            ExecutorService executorService = Scope.getCurrentScope().getSingleton(ExecutorService.class);
            Executor executor = executorService.getExecutor(LiquibaseConstants.JDBC_EXECUTOR, liquibase.getDatabase());
            for (SqlStatement sql : statementsToExecute) {
                executor.execute(sql);
                database.commit();
            }
        }
    }
    List<ChangeSet> changeSets = getLiquibaseUnrunChangeSets(liquibase);
    if (!changeSets.isEmpty()) {
        List<RanChangeSet> ranChangeSets = liquibase.getDatabase().getRanChangeSetList();
        if (ranChangeSets.isEmpty()) {
            logger.infov("Initializing database schema. Using changelog {0}", changelog);
        } else {
            if (logger.isDebugEnabled()) {
                logger.debugv("Updating database from {0} to {1}. Using changelog {2}", ranChangeSets.get(ranChangeSets.size() - 1).getId(), changeSets.get(changeSets.size() - 1).getId(), changelog);
            } else {
                logger.infov("Updating database. Using changelog {0}", changelog);
            }
        }
        if (exportWriter != null) {
            if (ranChangeSets.isEmpty()) {
                outputChangeLogTableCreationScript(liquibase, exportWriter);
            }
            liquibase.update(null, new LabelExpression(), exportWriter, false);
        } else {
            liquibase.update((Contexts) null);
        }
        logger.debugv("Completed database update for changelog {0}", changelog);
    } else {
        logger.debugv("Database is up to date for changelog {0}", changelog);
    }
    // Needs to restart liquibase services to clear ChangeLogHistoryServiceFactory.getInstance().
    // See https://issues.jboss.org/browse/KEYCLOAK-3769 for discussion relevant to why reset needs to be here
    resetLiquibaseServices(liquibase);
}
Also used : UpdateStatement(liquibase.statement.core.UpdateStatement) Table(liquibase.structure.core.Table) ArrayList(java.util.ArrayList) SqlStatement(liquibase.statement.SqlStatement) CustomChangeLogHistoryService(org.keycloak.connections.jpa.updater.liquibase.conn.CustomChangeLogHistoryService) ChangeLogHistoryService(liquibase.changelog.ChangeLogHistoryService) SetNullableStatement(liquibase.statement.core.SetNullableStatement) Executor(liquibase.executor.Executor) LoggingExecutor(liquibase.executor.LoggingExecutor) Column(liquibase.structure.core.Column) Database(liquibase.database.Database) ExecutorService(liquibase.executor.ExecutorService) LabelExpression(liquibase.LabelExpression) SnapshotControl(liquibase.snapshot.SnapshotControl) RanChangeSet(liquibase.changelog.RanChangeSet) ChangeSet(liquibase.changelog.ChangeSet) AddColumnStatement(liquibase.statement.core.AddColumnStatement) RanChangeSet(liquibase.changelog.RanChangeSet)

Aggregations

Executor (liquibase.executor.Executor)52 ExecutorService (liquibase.executor.ExecutorService)40 LoggingExecutor (liquibase.executor.LoggingExecutor)32 LiquibaseException (liquibase.exception.LiquibaseException)18 UnexpectedLiquibaseException (liquibase.exception.UnexpectedLiquibaseException)14 DatabaseException (liquibase.exception.DatabaseException)11 RawSqlStatement (liquibase.statement.core.RawSqlStatement)11 Database (liquibase.database.Database)8 SqlStatement (liquibase.statement.SqlStatement)7 RawSQLChange (liquibase.change.core.RawSQLChange)6 MSSQLDatabase (liquibase.database.core.MSSQLDatabase)6 Map (java.util.Map)4 EmptyChange (liquibase.change.core.EmptyChange)4 ChangeSet (liquibase.changelog.ChangeSet)4 SnapshotControl (liquibase.snapshot.SnapshotControl)4 SQLException (java.sql.SQLException)3 DB2Database (liquibase.database.core.DB2Database)3 ParsedNodeException (liquibase.parser.core.ParsedNodeException)3 ErrorPrecondition (liquibase.precondition.ErrorPrecondition)3 FailedPrecondition (liquibase.precondition.FailedPrecondition)3