use of liquibase.change.core.RawSQLChange 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 = StringUtil.trimToNull((String) value);
if (finalValue != null) {
String[] strings = StringUtil.processMultiLineSQL(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());
}
}
use of liquibase.change.core.RawSQLChange 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);
try (BufferedReader reader = new BufferedReader(StreamUtil.readStreamWithReader(openChangeLogFile(physicalChangeLogLocation, resourceAccessor), null))) {
StringBuilder currentSql = new StringBuilder();
StringBuilder currentRollbackSql = new StringBuilder();
ChangeSet changeSet = null;
RawSQLChange change = null;
Pattern changeLogPattern = Pattern.compile("\\-\\-\\s*liquibase formatted.*", Pattern.CASE_INSENSITIVE);
Pattern propertyPattern = Pattern.compile("\\s*\\-\\-[\\s]*property\\s+(.*:.*)\\s+(.*:.*).*", Pattern.CASE_INSENSITIVE);
Pattern changeSetPattern = Pattern.compile("\\s*\\-\\-[\\s]*changeset\\s+(\"[^\"]+\"|[^:]+):\\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 ignoreLinesPattern = Pattern.compile("\\-\\-[\\s]*ignoreLines:(\\w+)", Pattern.CASE_INSENSITIVE);
Pattern runWithPattern = Pattern.compile(".*runWith:([\\w\\$\\{\\}]+).*", 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 changeLogIdPattern = Pattern.compile(".*changeLogId:(\\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);
Matcher rollbackSplitStatementsPatternMatcher = null;
boolean rollbackSplitStatements = true;
String rollbackEndDelimiter = null;
String line;
while ((line = reader.readLine()) != null) {
Matcher propertyPatternMatcher = propertyPattern.matcher(line);
if (propertyPatternMatcher.matches()) {
handleProperty(changeLogParameters, changeLog, propertyPatternMatcher);
continue;
}
Matcher changeLogPatterMatcher = changeLogPattern.matcher(line);
if (changeLogPatterMatcher.matches()) {
Matcher logicalFilePathMatcher = logicalFilePathPattern.matcher(line);
changeLog.setLogicalFilePath(parseString(logicalFilePathMatcher));
Matcher changeLogIdMatcher = changeLogIdPattern.matcher(line);
changeLog.setChangeLogId(parseString(changeLogIdMatcher));
}
Matcher ignoreLinesMatcher = ignoreLinesPattern.matcher(line);
if (ignoreLinesMatcher.matches()) {
if ("start".equals(ignoreLinesMatcher.group(1))) {
while ((line = reader.readLine()) != null) {
ignoreLinesMatcher = ignoreLinesPattern.matcher(line);
if (ignoreLinesMatcher.matches()) {
if ("end".equals(ignoreLinesMatcher.group(1))) {
break;
}
}
}
continue;
} else {
try {
long ignoreCount = Long.parseLong(ignoreLinesMatcher.group(1));
while (ignoreCount > 0 && (line = reader.readLine()) != null) {
ignoreCount--;
}
continue;
} catch (NumberFormatException | NullPointerException nfe) {
throw new ChangeLogParseException("Unknown ignoreLines syntax");
}
}
}
Matcher changeSetPatternMatcher = changeSetPattern.matcher(line);
if (changeSetPatternMatcher.matches()) {
String finalCurrentSql = changeLogParameters.expandExpressions(StringUtil.trimToNull(currentSql.toString()), changeLog);
if (changeSet != null) {
if (finalCurrentSql == null) {
throw new ChangeLogParseException("No SQL for changeset " + changeSet.toString(false));
}
change.setSql(finalCurrentSql);
if (StringUtil.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));
if (rollbackSplitStatementsPatternMatcher.matches()) {
rollbackChange.setSplitStatements(rollbackSplitStatements);
}
if (rollbackEndDelimiter != null) {
rollbackChange.setEndDelimiter(rollbackEndDelimiter);
}
changeSet.addRollbackChange(rollbackChange);
}
}
}
Matcher stripCommentsPatternMatcher = stripCommentsPattern.matcher(line);
Matcher splitStatementsPatternMatcher = splitStatementsPattern.matcher(line);
Matcher runWithMatcher = runWithPattern.matcher(line);
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 runWith = parseString(runWithMatcher);
if (runWith != null) {
runWith = changeLogParameters.expandExpressions(runWith, changeLog);
}
String endDelimiter = parseString(endDelimiterPatternMatcher);
rollbackEndDelimiter = parseString(rollbackEndDelimiterPatternMatcher);
String context = StringUtil.trimToNull(// remove surrounding quotes if they're in there
StringUtil.trimToEmpty(parseString(contextPatternMatcher)).replaceFirst("^\"", "").replaceFirst("\"$", ""));
if (context != null) {
context = changeLogParameters.expandExpressions(context, changeLog);
}
String labels = parseString(labelsPatternMatcher);
if (labels != null) {
labels = changeLogParameters.expandExpressions(labels, changeLog);
}
String logicalFilePath = parseString(logicalFilePathMatcher);
if ((logicalFilePath == null) || "".equals(logicalFilePath)) {
logicalFilePath = changeLog.getLogicalFilePath();
}
if (logicalFilePath != null) {
logicalFilePath = changeLogParameters.expandExpressions(logicalFilePath, changeLog);
}
String dbms = parseString(dbmsPatternMatcher);
if (dbms != null) {
dbms = changeLogParameters.expandExpressions(dbms, changeLog);
}
String changeSetId = changeLogParameters.expandExpressions(StringUtil.stripEnclosingQuotes(changeSetPatternMatcher.group(2)), changeLog);
String changeSetAuthor = changeLogParameters.expandExpressions(StringUtil.stripEnclosingQuotes(changeSetPatternMatcher.group(1)), changeLog);
changeSet = new ChangeSet(changeSetId, changeSetAuthor, runAlways, runOnChange, logicalFilePath, context, dbms, runWith, runInTransaction, changeLog.getObjectQuotingStrategy(), changeLog);
changeSet.setLabels(new Labels(labels));
changeSet.setFailOnError(failOnError);
changeLog.addChangeSet(changeSet);
change = new RawSQLChange();
change.setSql(finalCurrentSql);
if (splitStatementsPatternMatcher.matches()) {
change.setSplitStatements(splitStatements);
}
change.setStripComments(stripComments);
change.setEndDelimiter(endDelimiter);
changeSet.addChange(change);
currentSql.setLength(0);
currentRollbackSql.setLength(0);
} 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(System.lineSeparator());
}
} 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(StringUtil.trimToNull(parseString(onFailMatcher)));
pc.setOnError(StringUtil.trimToNull(parseString(onErrorMatcher)));
pc.setOnSqlOutput(StringUtil.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 = StringUtil.trimToNull(preconditionMatcher.group(1));
if (name != null) {
String body = preconditionMatcher.group(2).trim();
if ("sql-check".equals(name)) {
changeSet.getPreconditions().addNestedPrecondition(parseSqlCheckCondition(changeLogParameters.expandExpressions(StringUtil.trimToNull(body), changeSet.getChangeLog())));
} else {
throw new ChangeLogParseException("The '" + name + "' precondition type is not supported.");
}
}
}
} else {
currentSql.append(line).append(System.lineSeparator());
}
}
}
}
if (changeSet != null) {
change.setSql(changeLogParameters.expandExpressions(StringUtil.trimToNull(currentSql.toString()), changeSet.getChangeLog()));
if ((change.getEndDelimiter() == null) && StringUtil.trimToEmpty(change.getSql()).endsWith("\n/")) {
change.setEndDelimiter("\n/$");
}
if (StringUtil.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()));
if (rollbackSplitStatementsPatternMatcher.matches()) {
rollbackChange.setSplitStatements(rollbackSplitStatements);
}
if (rollbackEndDelimiter != null) {
rollbackChange.setEndDelimiter(rollbackEndDelimiter);
}
changeSet.addRollbackChange(rollbackChange);
}
}
}
} catch (IOException e) {
throw new ChangeLogParseException(e);
}
return changeLog;
}
use of liquibase.change.core.RawSQLChange in project liquibase by liquibase.
the class Liquibase method executeRollbackScript.
protected void executeRollbackScript(String rollbackScript, List<ChangeSet> changeSets, Contexts contexts, LabelExpression labelExpression) throws LiquibaseException {
final Executor executor = Scope.getCurrentScope().getSingleton(ExecutorService.class).getExecutor("jdbc", database);
String rollbackScriptContents;
try (InputStreamList streams = resourceAccessor.openStreams(null, rollbackScript)) {
if ((streams == null) || streams.isEmpty()) {
throw new LiquibaseException("WARNING: The rollback script '" + rollbackScript + "' was not located. Please check your parameters. No rollback was performed");
} else if (streams.size() > 1) {
throw new LiquibaseException("Found multiple rollbackScripts named " + rollbackScript);
}
rollbackScriptContents = StreamUtil.readStreamAsString(streams.iterator().next());
} catch (IOException e) {
throw new LiquibaseException("Error reading rollbackScript " + executor + ": " + e.getMessage());
}
//
// Expand changelog properties
//
changeLogParameters.setContexts(contexts);
changeLogParameters.setLabels(labelExpression);
DatabaseChangeLog changelog = getDatabaseChangeLog();
rollbackScriptContents = changeLogParameters.expandExpressions(rollbackScriptContents, changelog);
RawSQLChange rollbackChange = buildRawSQLChange(rollbackScriptContents);
try {
((HubChangeExecListener) changeExecListener).setRollbackScriptContents(rollbackScriptContents);
sendRollbackMessages(changeSets, changelog, RollbackMessageType.WILL_ROLLBACK, contexts, labelExpression, null);
executor.execute(rollbackChange);
sendRollbackMessages(changeSets, changelog, RollbackMessageType.ROLLED_BACK, contexts, labelExpression, null);
} catch (DatabaseException e) {
Scope.getCurrentScope().getLog(getClass()).warning(e.getMessage());
LOG.severe("Error executing rollback script: " + e.getMessage());
if (changeExecListener != null) {
sendRollbackMessages(changeSets, changelog, RollbackMessageType.ROLLBACK_FAILED, contexts, labelExpression, e);
}
throw new DatabaseException("Error executing rollback script", e);
}
database.commit();
}
use of liquibase.change.core.RawSQLChange in project liquibase by liquibase.
the class Liquibase method buildRawSQLChange.
protected RawSQLChange buildRawSQLChange(String rollbackScriptContents) {
RawSQLChange rollbackChange = new RawSQLChange(rollbackScriptContents);
rollbackChange.setSplitStatements(true);
rollbackChange.setStripComments(true);
return rollbackChange;
}
use of liquibase.change.core.RawSQLChange in project liquibase by liquibase.
the class AbstractSQLChange method generateStatements.
/**
* Generates one or more SqlStatements depending on how the SQL should be parsed.
* If split statements is set to true then the SQL is split and each command is made into a separate SqlStatement.
* <p></p>
* If stripping comments is true then any comments are removed before the splitting is executed.
* The set SQL is passed through the {@link java.sql.Connection#nativeSQL} method if a connection is available.
*/
@Override
public SqlStatement[] generateStatements(Database database) {
List<SqlStatement> returnStatements = new ArrayList<>();
String sql = StringUtil.trimToNull(getSql());
if (sql == null) {
return new SqlStatement[0];
}
String processedSQL = normalizeLineEndings(sql);
if (this instanceof RawSQLChange && ((RawSQLChange) this).isRerunnable()) {
returnStatements.add(new RawSqlStatement(processedSQL, getEndDelimiter()));
return returnStatements.toArray(new SqlStatement[returnStatements.size()]);
}
for (String statement : StringUtil.processMultiLineSQL(processedSQL, isStripComments(), isSplitStatements(), getEndDelimiter())) {
if (database instanceof MSSQLDatabase) {
statement = statement.replaceAll("\\n", "\r\n");
}
String escapedStatement = statement;
try {
if (database.getConnection() != null) {
escapedStatement = database.getConnection().nativeSQL(statement);
}
} catch (DatabaseException e) {
escapedStatement = statement;
}
returnStatements.add(new RawSqlStatement(escapedStatement, getEndDelimiter()));
}
return returnStatements.toArray(new SqlStatement[returnStatements.size()]);
}
Aggregations