Search in sources :

Example 1 with EmptyChange

use of liquibase.change.core.EmptyChange in project liquibase by liquibase.

the class ChangeSet method handleRollbackNode.

protected void handleRollbackNode(ParsedNode rollbackNode, ResourceAccessor resourceAccessor) throws ParsedNodeException {
    String changeSetId = rollbackNode.getChildValue(null, "changeSetId", String.class);
    if (changeSetId != null) {
        String changeSetAuthor = rollbackNode.getChildValue(null, "changeSetAuthor", String.class);
        String changeSetPath = rollbackNode.getChildValue(null, "changeSetPath", getFilePath());
        DatabaseChangeLog changeLog = this.getChangeLog();
        ChangeSet changeSet = changeLog.getChangeSet(changeSetPath, changeSetAuthor, changeSetId);
        while (changeSet == null && changeLog != null) {
            changeLog = changeLog.getParentChangeLog();
            if (changeLog != null) {
                changeSet = changeLog.getChangeSet(changeSetPath, changeSetAuthor, changeSetId);
            }
        }
        if (changeSet == null) {
            throw new ParsedNodeException("Change set " + new ChangeSet(changeSetId, changeSetAuthor, false, false, changeSetPath, null, null, null).toString(false) + " does not exist");
        }
        for (Change change : changeSet.getChanges()) {
            rollback.getChanges().add(change);
        }
        return;
    }
    boolean foundValue = false;
    for (ParsedNode childNode : rollbackNode.getChildren()) {
        Change rollbackChange = toChange(childNode, resourceAccessor);
        if (rollbackChange != null) {
            addRollbackChange(rollbackChange);
            foundValue = true;
        }
    }
    Object value = rollbackNode.getValue();
    if (value != null) {
        if (value instanceof String) {
            String finalValue = StringUtils.trimToNull((String) value);
            if (finalValue != null) {
                String[] strings = StringUtils.processMutliLineSQL(finalValue, true, true, ";");
                for (String string : strings) {
                    addRollbackChange(new RawSQLChange(string));
                    foundValue = true;
                }
            }
        } else {
            throw new ParsedNodeException("Unexpected object: " + value.getClass().getName() + " '" + value.toString() + "'");
        }
    }
    if (!foundValue) {
        addRollbackChange(new EmptyChange());
    }
}
Also used : ParsedNode(liquibase.parser.core.ParsedNode) RawSQLChange(liquibase.change.core.RawSQLChange) ParsedNodeException(liquibase.parser.core.ParsedNodeException) Change(liquibase.change.Change) EmptyChange(liquibase.change.core.EmptyChange) RawSQLChange(liquibase.change.core.RawSQLChange) DbmsTargetedChange(liquibase.change.DbmsTargetedChange) EmptyChange(liquibase.change.core.EmptyChange)

Example 2 with EmptyChange

use of liquibase.change.core.EmptyChange in project liquibase by liquibase.

the class FormattedSqlChangeLogParser method parse.

@Override
public DatabaseChangeLog parse(String physicalChangeLogLocation, ChangeLogParameters changeLogParameters, ResourceAccessor resourceAccessor) throws ChangeLogParseException {
    DatabaseChangeLog changeLog = new DatabaseChangeLog();
    changeLog.setChangeLogParameters(changeLogParameters);
    changeLog.setPhysicalFilePath(physicalChangeLogLocation);
    BufferedReader reader = null;
    try {
        reader = new BufferedReader(new UtfBomAwareReader(openChangeLogFile(physicalChangeLogLocation, resourceAccessor)));
        StringBuffer currentSql = new StringBuffer();
        StringBuffer currentRollbackSql = new StringBuffer();
        ChangeSet changeSet = null;
        RawSQLChange change = null;
        Pattern changeLogPattern = Pattern.compile("\\-\\-\\s*liquibase formatted.*", Pattern.CASE_INSENSITIVE);
        Pattern changeSetPattern = Pattern.compile("\\-\\-[\\s]*changeset\\s+([^:]+):(\\S+).*", Pattern.CASE_INSENSITIVE);
        Pattern rollbackPattern = Pattern.compile("\\s*\\-\\-[\\s]*rollback (.*)", Pattern.CASE_INSENSITIVE);
        Pattern preconditionsPattern = Pattern.compile("\\s*\\-\\-[\\s]*preconditions(.*)", Pattern.CASE_INSENSITIVE);
        Pattern preconditionPattern = Pattern.compile("\\s*\\-\\-[\\s]*precondition\\-([a-zA-Z0-9-]+) (.*)", Pattern.CASE_INSENSITIVE);
        Pattern stripCommentsPattern = Pattern.compile(".*stripComments:(\\w+).*", Pattern.CASE_INSENSITIVE);
        Pattern splitStatementsPattern = Pattern.compile(".*splitStatements:(\\w+).*", Pattern.CASE_INSENSITIVE);
        Pattern rollbackSplitStatementsPattern = Pattern.compile(".*rollbackSplitStatements:(\\w+).*", Pattern.CASE_INSENSITIVE);
        Pattern endDelimiterPattern = Pattern.compile(".*endDelimiter:(\\S*).*", Pattern.CASE_INSENSITIVE);
        Pattern rollbackEndDelimiterPattern = Pattern.compile(".*rollbackEndDelimiter:(\\S*).*", Pattern.CASE_INSENSITIVE);
        Pattern commentPattern = Pattern.compile("\\-\\-[\\s]*comment:? (.*)", Pattern.CASE_INSENSITIVE);
        Pattern validCheckSumPattern = Pattern.compile("\\-\\-[\\s]*validCheckSum:? (.*)", Pattern.CASE_INSENSITIVE);
        Pattern runOnChangePattern = Pattern.compile(".*runOnChange:(\\w+).*", Pattern.CASE_INSENSITIVE);
        Pattern runAlwaysPattern = Pattern.compile(".*runAlways:(\\w+).*", Pattern.CASE_INSENSITIVE);
        Pattern contextPattern = Pattern.compile(".*context:(\".*\"|\\S*).*", Pattern.CASE_INSENSITIVE);
        Pattern logicalFilePathPattern = Pattern.compile(".*logicalFilePath:(\\S*).*", Pattern.CASE_INSENSITIVE);
        Pattern labelsPattern = Pattern.compile(".*labels:(\\S*).*", Pattern.CASE_INSENSITIVE);
        Pattern runInTransactionPattern = Pattern.compile(".*runInTransaction:(\\w+).*", Pattern.CASE_INSENSITIVE);
        Pattern dbmsPattern = Pattern.compile(".*dbms:([^,][\\w!,]+).*", Pattern.CASE_INSENSITIVE);
        Pattern failOnErrorPattern = Pattern.compile(".*failOnError:(\\w+).*", Pattern.CASE_INSENSITIVE);
        Pattern onFailPattern = Pattern.compile(".*onFail:(\\w+).*", Pattern.CASE_INSENSITIVE);
        Pattern onErrorPattern = Pattern.compile(".*onError:(\\w+).*", Pattern.CASE_INSENSITIVE);
        Pattern onUpdateSqlPattern = Pattern.compile(".*onUpdateSQL:(\\w+).*", Pattern.CASE_INSENSITIVE);
        boolean rollbackSplitStatements = true;
        String rollbackEndDelimiter = null;
        String line;
        while ((line = reader.readLine()) != null) {
            Matcher changeLogPatterMatcher = changeLogPattern.matcher(line);
            if (changeLogPatterMatcher.matches()) {
                Matcher logicalFilePathMatcher = logicalFilePathPattern.matcher(line);
                changeLog.setLogicalFilePath(parseString(logicalFilePathMatcher));
            }
            Matcher changeSetPatternMatcher = changeSetPattern.matcher(line);
            if (changeSetPatternMatcher.matches()) {
                String finalCurrentSql = changeLogParameters.expandExpressions(StringUtils.trimToNull(currentSql.toString()), changeLog);
                if (changeSet != null) {
                    if (finalCurrentSql == null) {
                        throw new ChangeLogParseException("No SQL for changeset " + changeSet.toString(false));
                    }
                    change.setSql(finalCurrentSql);
                    if (StringUtils.trimToNull(currentRollbackSql.toString()) != null) {
                        if (currentRollbackSql.toString().trim().toLowerCase().matches("^not required.*")) {
                            changeSet.addRollbackChange(new EmptyChange());
                        } else {
                            RawSQLChange rollbackChange = new RawSQLChange();
                            rollbackChange.setSql(changeLogParameters.expandExpressions(currentRollbackSql.toString(), changeLog));
                            changeSet.addRollbackChange(rollbackChange);
                        }
                    }
                }
                Matcher stripCommentsPatternMatcher = stripCommentsPattern.matcher(line);
                Matcher splitStatementsPatternMatcher = splitStatementsPattern.matcher(line);
                Matcher rollbackSplitStatementsPatternMatcher = rollbackSplitStatementsPattern.matcher(line);
                Matcher endDelimiterPatternMatcher = endDelimiterPattern.matcher(line);
                Matcher rollbackEndDelimiterPatternMatcher = rollbackEndDelimiterPattern.matcher(line);
                Matcher logicalFilePathMatcher = logicalFilePathPattern.matcher(line);
                Matcher runOnChangePatternMatcher = runOnChangePattern.matcher(line);
                Matcher runAlwaysPatternMatcher = runAlwaysPattern.matcher(line);
                Matcher contextPatternMatcher = contextPattern.matcher(line);
                Matcher labelsPatternMatcher = labelsPattern.matcher(line);
                Matcher runInTransactionPatternMatcher = runInTransactionPattern.matcher(line);
                Matcher dbmsPatternMatcher = dbmsPattern.matcher(line);
                Matcher failOnErrorPatternMatcher = failOnErrorPattern.matcher(line);
                boolean stripComments = parseBoolean(stripCommentsPatternMatcher, changeSet, true);
                boolean splitStatements = parseBoolean(splitStatementsPatternMatcher, changeSet, true);
                rollbackSplitStatements = parseBoolean(rollbackSplitStatementsPatternMatcher, changeSet, true);
                boolean runOnChange = parseBoolean(runOnChangePatternMatcher, changeSet, false);
                boolean runAlways = parseBoolean(runAlwaysPatternMatcher, changeSet, false);
                boolean runInTransaction = parseBoolean(runInTransactionPatternMatcher, changeSet, true);
                boolean failOnError = parseBoolean(failOnErrorPatternMatcher, changeSet, true);
                String endDelimiter = parseString(endDelimiterPatternMatcher);
                rollbackEndDelimiter = parseString(rollbackEndDelimiterPatternMatcher);
                String context = StringUtils.trimToNull(//remove surrounding quotes if they're in there
                StringUtils.trimToEmpty(parseString(contextPatternMatcher)).replaceFirst("^\"", "").replaceFirst("\"$", ""));
                String labels = parseString(labelsPatternMatcher);
                String logicalFilePath = parseString(logicalFilePathMatcher);
                if (logicalFilePath == null || "".equals(logicalFilePath)) {
                    logicalFilePath = changeLog.getLogicalFilePath();
                }
                String dbms = parseString(dbmsPatternMatcher);
                changeSet = new ChangeSet(changeSetPatternMatcher.group(2), changeSetPatternMatcher.group(1), runAlways, runOnChange, logicalFilePath, context, dbms, runInTransaction, changeLog.getObjectQuotingStrategy(), changeLog);
                changeSet.setLabels(new Labels(labels));
                changeSet.setFailOnError(failOnError);
                changeLog.addChangeSet(changeSet);
                change = new RawSQLChange();
                change.setSql(finalCurrentSql);
                change.setResourceAccessor(resourceAccessor);
                change.setSplitStatements(splitStatements);
                change.setStripComments(stripComments);
                change.setEndDelimiter(endDelimiter);
                changeSet.addChange(change);
                currentSql = new StringBuffer();
                currentRollbackSql = new StringBuffer();
            } else {
                if (changeSet != null) {
                    Matcher commentMatcher = commentPattern.matcher(line);
                    Matcher rollbackMatcher = rollbackPattern.matcher(line);
                    Matcher preconditionsMatcher = preconditionsPattern.matcher(line);
                    Matcher preconditionMatcher = preconditionPattern.matcher(line);
                    Matcher validCheckSumMatcher = validCheckSumPattern.matcher(line);
                    if (commentMatcher.matches()) {
                        if (commentMatcher.groupCount() == 1) {
                            changeSet.setComments(commentMatcher.group(1));
                        }
                    } else if (validCheckSumMatcher.matches()) {
                        if (validCheckSumMatcher.groupCount() == 1) {
                            changeSet.addValidCheckSum(validCheckSumMatcher.group(1));
                        }
                    } else if (rollbackMatcher.matches()) {
                        if (rollbackMatcher.groupCount() == 1) {
                            currentRollbackSql.append(rollbackMatcher.group(1)).append(SystemUtils.LINE_SEPARATOR);
                        }
                    } else if (preconditionsMatcher.matches()) {
                        if (preconditionsMatcher.groupCount() == 1) {
                            String body = preconditionsMatcher.group(1);
                            Matcher onFailMatcher = onFailPattern.matcher(body);
                            Matcher onErrorMatcher = onErrorPattern.matcher(body);
                            Matcher onUpdateSqlMatcher = onUpdateSqlPattern.matcher(body);
                            PreconditionContainer pc = new PreconditionContainer();
                            pc.setOnFail(StringUtils.trimToNull(parseString(onFailMatcher)));
                            pc.setOnError(StringUtils.trimToNull(parseString(onErrorMatcher)));
                            pc.setOnSqlOutput(StringUtils.trimToNull(parseString(onUpdateSqlMatcher)));
                            changeSet.setPreconditions(pc);
                        }
                    } else if (preconditionMatcher.matches()) {
                        if (changeSet.getPreconditions() == null) {
                            // create the defaults
                            changeSet.setPreconditions(new PreconditionContainer());
                        }
                        if (preconditionMatcher.groupCount() == 2) {
                            String name = StringUtils.trimToNull(preconditionMatcher.group(1));
                            if (name != null) {
                                String body = preconditionMatcher.group(2).trim();
                                if ("sql-check".equals(name)) {
                                    changeSet.getPreconditions().addNestedPrecondition(parseSqlCheckCondition(changeLogParameters.expandExpressions(StringUtils.trimToNull(body), changeSet.getChangeLog())));
                                } else {
                                    throw new ChangeLogParseException("The '" + name + "' precondition type is not supported.");
                                }
                            }
                        }
                    } else {
                        currentSql.append(line).append(SystemUtils.LINE_SEPARATOR);
                    }
                }
            }
        }
        if (changeSet != null) {
            change.setSql(changeLogParameters.expandExpressions(StringUtils.trimToNull(currentSql.toString()), changeSet.getChangeLog()));
            if (change.getEndDelimiter() == null && StringUtils.trimToEmpty(change.getSql()).endsWith("\n/")) {
                change.setEndDelimiter("\n/$");
            }
            if (StringUtils.trimToNull(currentRollbackSql.toString()) != null) {
                if (currentRollbackSql.toString().trim().toLowerCase().matches("^not required.*")) {
                    changeSet.addRollbackChange(new EmptyChange());
                } else {
                    RawSQLChange rollbackChange = new RawSQLChange();
                    rollbackChange.setSql(changeLogParameters.expandExpressions(currentRollbackSql.toString(), changeSet.getChangeLog()));
                    rollbackChange.setSplitStatements(rollbackSplitStatements);
                    if (rollbackEndDelimiter != null) {
                        rollbackChange.setEndDelimiter(rollbackEndDelimiter);
                    }
                    changeSet.addRollbackChange(rollbackChange);
                }
            }
        }
    } catch (IOException e) {
        throw new ChangeLogParseException(e);
    } finally {
        if (reader != null) {
            try {
                reader.close();
            } catch (IOException ignore) {
            }
        }
    }
    return changeLog;
}
Also used : RawSQLChange(liquibase.change.core.RawSQLChange) Pattern(java.util.regex.Pattern) PreconditionContainer(liquibase.precondition.core.PreconditionContainer) Matcher(java.util.regex.Matcher) Labels(liquibase.Labels) IOException(java.io.IOException) EmptyChange(liquibase.change.core.EmptyChange) DatabaseChangeLog(liquibase.changelog.DatabaseChangeLog) ChangeLogParseException(liquibase.exception.ChangeLogParseException) BufferedReader(java.io.BufferedReader) UtfBomAwareReader(liquibase.resource.UtfBomAwareReader) ChangeSet(liquibase.changelog.ChangeSet)

Aggregations

EmptyChange (liquibase.change.core.EmptyChange)2 RawSQLChange (liquibase.change.core.RawSQLChange)2 BufferedReader (java.io.BufferedReader)1 IOException (java.io.IOException)1 Matcher (java.util.regex.Matcher)1 Pattern (java.util.regex.Pattern)1 Labels (liquibase.Labels)1 Change (liquibase.change.Change)1 DbmsTargetedChange (liquibase.change.DbmsTargetedChange)1 ChangeSet (liquibase.changelog.ChangeSet)1 DatabaseChangeLog (liquibase.changelog.DatabaseChangeLog)1 ChangeLogParseException (liquibase.exception.ChangeLogParseException)1 ParsedNode (liquibase.parser.core.ParsedNode)1 ParsedNodeException (liquibase.parser.core.ParsedNodeException)1 PreconditionContainer (liquibase.precondition.core.PreconditionContainer)1 UtfBomAwareReader (liquibase.resource.UtfBomAwareReader)1