Search in sources :

Example 1 with DbmsTargetedChange

use of liquibase.change.DbmsTargetedChange in project liquibase by liquibase.

the class ChangeSet method execute.

/**
     * This method will actually execute each of the changes in the list against the
     * specified database.
     *
     * @return should change set be marked as ran
     */
public ExecType execute(DatabaseChangeLog databaseChangeLog, ChangeExecListener listener, Database database) throws MigrationFailedException {
    if (validationFailed) {
        return ExecType.MARK_RAN;
    }
    long startTime = new Date().getTime();
    ExecType execType = null;
    boolean skipChange = false;
    Executor executor = ExecutorService.getInstance().getExecutor(database);
    try {
        // set object quoting strategy
        database.setObjectQuotingStrategy(objectQuotingStrategy);
        // set auto-commit based on runInTransaction if database supports DDL in transactions
        if (database.supportsDDLInTransaction()) {
            database.setAutoCommit(!runInTransaction);
        }
        executor.comment("Changeset " + toString(false));
        if (StringUtils.trimToNull(getComments()) != null) {
            String comments = getComments();
            String[] lines = comments.split("\\n");
            for (int i = 0; i < lines.length; i++) {
                if (i > 0) {
                    lines[i] = database.getLineComment() + " " + lines[i];
                }
            }
            executor.comment(StringUtils.join(Arrays.asList(lines), "\n"));
        }
        try {
            if (preconditions != null) {
                preconditions.check(database, databaseChangeLog, this);
            }
        } catch (PreconditionFailedException e) {
            if (listener != null) {
                listener.preconditionFailed(e, preconditions.getOnFail());
            }
            StringBuffer message = new StringBuffer();
            message.append(StreamUtil.getLineSeparator());
            for (FailedPrecondition invalid : e.getFailedPreconditions()) {
                message.append("          ").append(invalid.toString());
                message.append(StreamUtil.getLineSeparator());
            }
            if (preconditions.getOnFail().equals(PreconditionContainer.FailOption.HALT)) {
                throw new MigrationFailedException(this, message.toString(), e);
            } else if (preconditions.getOnFail().equals(PreconditionContainer.FailOption.CONTINUE)) {
                skipChange = true;
                execType = ExecType.SKIPPED;
                LogFactory.getLogger().info("Continuing past: " + toString() + " despite precondition failure due to onFail='CONTINUE': " + message);
            } else if (preconditions.getOnFail().equals(PreconditionContainer.FailOption.MARK_RAN)) {
                execType = ExecType.MARK_RAN;
                skipChange = true;
                log.info("Marking ChangeSet: " + toString() + " ran despite precondition failure due to onFail='MARK_RAN': " + message);
            } else if (preconditions.getOnFail().equals(PreconditionContainer.FailOption.WARN)) {
                //already warned
                execType = null;
            } else {
                throw new UnexpectedLiquibaseException("Unexpected precondition onFail attribute: " + preconditions.getOnFail(), e);
            }
        } catch (PreconditionErrorException e) {
            if (listener != null) {
                listener.preconditionErrored(e, preconditions.getOnError());
            }
            StringBuffer message = new StringBuffer();
            message.append(StreamUtil.getLineSeparator());
            for (ErrorPrecondition invalid : e.getErrorPreconditions()) {
                message.append("          ").append(invalid.toString());
                message.append(StreamUtil.getLineSeparator());
            }
            if (preconditions.getOnError().equals(PreconditionContainer.ErrorOption.HALT)) {
                throw new MigrationFailedException(this, message.toString(), e);
            } else if (preconditions.getOnError().equals(PreconditionContainer.ErrorOption.CONTINUE)) {
                skipChange = true;
                execType = ExecType.SKIPPED;
            } else if (preconditions.getOnError().equals(PreconditionContainer.ErrorOption.MARK_RAN)) {
                execType = ExecType.MARK_RAN;
                skipChange = true;
                log.info("Marking ChangeSet: " + toString() + " ran despite precondition error: " + message);
            } else if (preconditions.getOnError().equals(PreconditionContainer.ErrorOption.WARN)) {
                //already logged
                execType = null;
            } else {
                throw new UnexpectedLiquibaseException("Unexpected precondition onError attribute: " + preconditions.getOnError(), e);
            }
            database.rollback();
        } finally {
            database.rollback();
        }
        if (!skipChange) {
            for (Change change : changes) {
                try {
                    change.finishInitialization();
                } catch (SetupException se) {
                    throw new MigrationFailedException(this, se);
                }
            }
            log.debug("Reading ChangeSet: " + toString());
            for (Change change : getChanges()) {
                if ((!(change instanceof DbmsTargetedChange)) || DatabaseList.definitionMatches(((DbmsTargetedChange) change).getDbms(), database, true)) {
                    if (listener != null) {
                        listener.willRun(change, this, changeLog, database);
                    }
                    if (change.generateStatementsVolatile(database)) {
                        executor.comment("WARNING The following SQL may change each run and therefore is possibly incorrect and/or invalid:");
                    }
                    database.executeStatements(change, databaseChangeLog, sqlVisitors);
                    log.info(change.getConfirmationMessage());
                    if (listener != null) {
                        listener.ran(change, this, changeLog, database);
                    }
                } else {
                    log.debug("Change " + change.getSerializedObjectName() + " not included for database " + database.getShortName());
                }
            }
            if (runInTransaction) {
                database.commit();
            }
            log.info("ChangeSet " + toString(false) + " ran successfully in " + (new Date().getTime() - startTime + "ms"));
            if (execType == null) {
                execType = ExecType.EXECUTED;
            }
        } else {
            log.debug("Skipping ChangeSet: " + toString());
        }
    } catch (Exception e) {
        try {
            database.rollback();
        } catch (Exception e1) {
            throw new MigrationFailedException(this, e);
        }
        if (getFailOnError() != null && !getFailOnError()) {
            log.info("Change set " + toString(false) + " failed, but failOnError was false.  Error: " + e.getMessage());
            log.debug("Failure Stacktrace", e);
            execType = ExecType.FAILED;
        } else {
            // just log the message, dont log the stacktrace by appending exception. Its logged anyway to stdout
            log.severe("Change Set " + toString(false) + " failed.  Error: " + e.getMessage());
            if (e instanceof MigrationFailedException) {
                throw ((MigrationFailedException) e);
            } else {
                throw new MigrationFailedException(this, e);
            }
        }
    } finally {
        // but only if the database supports DDL in transactions
        if (!runInTransaction && database.supportsDDLInTransaction()) {
            try {
                database.setAutoCommit(false);
            } catch (DatabaseException e) {
                throw new MigrationFailedException(this, "Could not resetInternalState autocommit", e);
            }
        }
    }
    return execType;
}
Also used : FailedPrecondition(liquibase.precondition.FailedPrecondition) Change(liquibase.change.Change) EmptyChange(liquibase.change.core.EmptyChange) RawSQLChange(liquibase.change.core.RawSQLChange) DbmsTargetedChange(liquibase.change.DbmsTargetedChange) ParsedNodeException(liquibase.parser.core.ParsedNodeException) Executor(liquibase.executor.Executor) ErrorPrecondition(liquibase.precondition.ErrorPrecondition) DbmsTargetedChange(liquibase.change.DbmsTargetedChange)

Example 2 with DbmsTargetedChange

use of liquibase.change.DbmsTargetedChange in project liquibase by liquibase.

the class ChangeSet method rollback.

public void rollback(Database database) throws RollbackFailedException {
    try {
        Executor executor = ExecutorService.getInstance().getExecutor(database);
        executor.comment("Rolling Back ChangeSet: " + toString());
        database.setObjectQuotingStrategy(objectQuotingStrategy);
        // set auto-commit based on runInTransaction if database supports DDL in transactions
        if (database.supportsDDLInTransaction()) {
            database.setAutoCommit(!runInTransaction);
        }
        RanChangeSet ranChangeSet = database.getRanChangeSet(this);
        if (hasCustomRollbackChanges()) {
            final List<SqlStatement> statements = new LinkedList<SqlStatement>();
            for (Change change : rollback.getChanges()) {
                if (((change instanceof DbmsTargetedChange)) && !DatabaseList.definitionMatches(((DbmsTargetedChange) change).getDbms(), database, true)) {
                    continue;
                }
                ValidationErrors errors = change.validate(database);
                if (errors.hasErrors()) {
                    throw new RollbackFailedException("Rollback statement failed validation: " + errors.toString());
                }
                SqlStatement[] changeStatements = change.generateStatements(database);
                if (changeStatements != null) {
                    statements.addAll(Arrays.asList(changeStatements));
                }
            }
            if (!statements.isEmpty()) {
                database.executeRollbackStatements(statements.toArray(new SqlStatement[] {}), sqlVisitors);
            }
        } else {
            List<Change> changes = getChanges();
            for (int i = changes.size() - 1; i >= 0; i--) {
                Change change = changes.get(i);
                database.executeRollbackStatements(change, sqlVisitors);
            }
        }
        if (runInTransaction) {
            database.commit();
        }
        log.debug("ChangeSet " + toString() + " has been successfully rolled back.");
    } catch (Exception e) {
        try {
            database.rollback();
        } catch (DatabaseException e1) {
        //ok
        }
        throw new RollbackFailedException(e);
    } finally {
        // but only if the database supports DDL in transactions
        if (!runInTransaction && database.supportsDDLInTransaction()) {
            try {
                database.setAutoCommit(false);
            } catch (DatabaseException e) {
                throw new RollbackFailedException("Could not resetInternalState autocommit", e);
            }
        }
    }
}
Also used : Change(liquibase.change.Change) EmptyChange(liquibase.change.core.EmptyChange) RawSQLChange(liquibase.change.core.RawSQLChange) DbmsTargetedChange(liquibase.change.DbmsTargetedChange) ParsedNodeException(liquibase.parser.core.ParsedNodeException) SqlStatement(liquibase.statement.SqlStatement) Executor(liquibase.executor.Executor) DbmsTargetedChange(liquibase.change.DbmsTargetedChange)

Aggregations

Change (liquibase.change.Change)2 DbmsTargetedChange (liquibase.change.DbmsTargetedChange)2 EmptyChange (liquibase.change.core.EmptyChange)2 RawSQLChange (liquibase.change.core.RawSQLChange)2 Executor (liquibase.executor.Executor)2 ParsedNodeException (liquibase.parser.core.ParsedNodeException)2 ErrorPrecondition (liquibase.precondition.ErrorPrecondition)1 FailedPrecondition (liquibase.precondition.FailedPrecondition)1 SqlStatement (liquibase.statement.SqlStatement)1