use of liquibase.precondition.core.PreconditionContainer in project liquibase by liquibase.
the class DatabaseChangeLog method handleChildNode.
protected void handleChildNode(ParsedNode node, ResourceAccessor resourceAccessor) throws ParsedNodeException, SetupException {
expandExpressions(node);
String nodeName = node.getName();
if (nodeName.equals("changeSet")) {
this.addChangeSet(createChangeSet(node, resourceAccessor));
} else if (nodeName.equals("include")) {
String path = node.getChildValue(null, "file", String.class);
if (path == null) {
throw new UnexpectedLiquibaseException("No 'file' attribute on 'include'");
}
path = path.replace('\\', '/');
ContextExpression includeContexts = new ContextExpression(node.getChildValue(null, "context", String.class));
try {
include(path, node.getChildValue(null, "relativeToChangelogFile", false), resourceAccessor, includeContexts);
} catch (LiquibaseException e) {
throw new SetupException(e);
}
} else if (nodeName.equals("includeAll")) {
String path = node.getChildValue(null, "path", String.class);
String resourceFilterDef = node.getChildValue(null, "filter", String.class);
if (resourceFilterDef == null) {
resourceFilterDef = node.getChildValue(null, "resourceFilter", String.class);
}
IncludeAllFilter resourceFilter = null;
if (resourceFilterDef != null) {
try {
resourceFilter = (IncludeAllFilter) Class.forName(resourceFilterDef).newInstance();
} catch (Exception e) {
throw new SetupException(e);
}
}
String resourceComparatorDef = node.getChildValue(null, "resourceComparator", String.class);
Comparator<?> resourceComparator = null;
if (resourceComparatorDef != null) {
try {
resourceComparator = (Comparator<?>) Class.forName(resourceComparatorDef).newInstance();
} catch (Exception e) {
//take default comparator
LogFactory.getInstance().getLog().info("no resourceComparator defined - taking default implementation");
resourceComparator = getStandardChangeLogComparator();
}
}
ContextExpression includeContexts = new ContextExpression(node.getChildValue(null, "context", String.class));
includeAll(path, node.getChildValue(null, "relativeToChangelogFile", false), resourceFilter, node.getChildValue(null, "errorIfMissingOrEmpty", true), getStandardChangeLogComparator(), resourceAccessor, includeContexts);
} else if (nodeName.equals("preConditions")) {
this.preconditionContainer = new PreconditionContainer();
try {
this.preconditionContainer.load(node, resourceAccessor);
} catch (ParsedNodeException e) {
e.printStackTrace();
}
} else if (nodeName.equals("property")) {
try {
String context = node.getChildValue(null, "context", String.class);
String dbms = node.getChildValue(null, "dbms", String.class);
String labels = node.getChildValue(null, "labels", String.class);
Boolean global = node.getChildValue(null, "global", Boolean.class);
if (global == null) {
// okay behave like liquibase < 3.4 and set global == true
global = true;
}
String file = node.getChildValue(null, "file", String.class);
if (file == null) {
// direct referenced property, no file
String name = node.getChildValue(null, "name", String.class);
String value = node.getChildValue(null, "value", String.class);
this.changeLogParameters.set(name, value, context, labels, dbms, global, this);
} else {
// read properties from the file
Properties props = new Properties();
InputStream propertiesStream = StreamUtil.singleInputStream(file, resourceAccessor);
if (propertiesStream == null) {
LogFactory.getInstance().getLog().info("Could not open properties file " + file);
} else {
props.load(propertiesStream);
for (Map.Entry entry : props.entrySet()) {
this.changeLogParameters.set(entry.getKey().toString(), entry.getValue().toString(), context, labels, dbms, global, this);
}
}
}
} catch (IOException e) {
throw new ParsedNodeException(e);
}
}
}
use of liquibase.precondition.core.PreconditionContainer 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;
}
use of liquibase.precondition.core.PreconditionContainer in project liquibase by liquibase.
the class ValidatingVisitorPreConditionsTest method testPreconditionForOracleOnOracleWithChangeLog.
/**
* Test against oracle, but I don't know for sure if the precondition is really
* validated because oracle supports creating sequences.
*/
@Test
public void testPreconditionForOracleOnOracleWithChangeLog() {
// create the pre condition
PreconditionContainer preCondition = new PreconditionContainer();
preCondition.setOnFail(PreconditionContainer.FailOption.MARK_RAN.toString());
DBMSPrecondition dbmsPrecondition = new DBMSPrecondition();
dbmsPrecondition.setType("oracle");
preCondition.addNestedPrecondition(dbmsPrecondition);
changeSet1.setPreconditions(preCondition);
OracleDatabase oracleDb = new OracleDatabase() {
@Override
public List<RanChangeSet> getRanChangeSetList() throws DatabaseException {
return new ArrayList<RanChangeSet>();
}
@Override
public void rollback() throws DatabaseException {
//super.rollback();
}
};
String[] empty = {};
boolean exceptionThrown = false;
try {
changeLog.validate(oracleDb, empty);
} catch (LiquibaseException ex) {
exceptionThrown = true;
}
assertFalse(exceptionThrown);
}
use of liquibase.precondition.core.PreconditionContainer in project liquibase by liquibase.
the class ValidatingVisitor method validate.
public void validate(Database database, DatabaseChangeLog changeLog) {
this.database = database;
PreconditionContainer preconditions = changeLog.getPreconditions();
try {
if (preconditions == null) {
return;
}
preconditions.check(database, changeLog, null);
} catch (PreconditionFailedException e) {
LogFactory.getLogger().debug("Precondition Failed: " + e.getMessage(), e);
failedPreconditions.addAll(e.getFailedPreconditions());
} catch (PreconditionErrorException e) {
LogFactory.getLogger().debug("Precondition Error: " + e.getMessage(), e);
errorPreconditions.addAll(e.getErrorPreconditions());
} finally {
try {
if (database.getConnection() != null) {
database.rollback();
}
} catch (DatabaseException e) {
LogFactory.getLogger().warning("Error rolling back after precondition check", e);
}
}
}
use of liquibase.precondition.core.PreconditionContainer in project liquibase by liquibase.
the class ChangeSet method handleChildNode.
protected void handleChildNode(ParsedNode child, ResourceAccessor resourceAccessor) throws ParsedNodeException {
if (child.getName().equals("rollback")) {
handleRollbackNode(child, resourceAccessor);
} else if (child.getName().equals("validCheckSum") || child.getName().equals("validCheckSums")) {
if (child.getValue() == null) {
return;
}
if (child.getValue() instanceof Collection) {
for (Object checksum : (Collection) child.getValue()) {
addValidCheckSum((String) checksum);
}
} else {
addValidCheckSum(child.getValue(String.class));
}
} else if (child.getName().equals("modifySql")) {
String dbmsString = StringUtils.trimToNull(child.getChildValue(null, "dbms", String.class));
String contextString = StringUtils.trimToNull(child.getChildValue(null, "context", String.class));
String labelsString = StringUtils.trimToNull(child.getChildValue(null, "labels", String.class));
boolean applyToRollback = child.getChildValue(null, "applyToRollback", false);
Set<String> dbms = new HashSet<String>();
if (dbmsString != null) {
dbms.addAll(StringUtils.splitAndTrim(dbmsString, ","));
}
ContextExpression context = null;
if (contextString != null) {
context = new ContextExpression(contextString);
}
Labels labels = null;
if (labelsString != null) {
labels = new Labels(labelsString);
}
List<ParsedNode> potentialVisitors = child.getChildren();
for (ParsedNode node : potentialVisitors) {
SqlVisitor sqlVisitor = SqlVisitorFactory.getInstance().create(node.getName());
if (sqlVisitor != null) {
sqlVisitor.setApplyToRollback(applyToRollback);
if (dbms.size() > 0) {
sqlVisitor.setApplicableDbms(dbms);
}
sqlVisitor.setContexts(context);
sqlVisitor.setLabels(labels);
sqlVisitor.load(node, resourceAccessor);
addSqlVisitor(sqlVisitor);
}
}
} else if (child.getName().equals("preConditions")) {
this.preconditions = new PreconditionContainer();
try {
this.preconditions.load(child, resourceAccessor);
} catch (ParsedNodeException e) {
e.printStackTrace();
}
} else if (child.getName().equals("changes")) {
for (ParsedNode changeNode : child.getChildren()) {
handleChildNode(changeNode, resourceAccessor);
}
} else {
Change change = toChange(child, resourceAccessor);
if (change == null && child.getValue() instanceof String) {
this.setAttribute(child.getName(), child.getValue());
} else {
addChange(change);
}
}
}
Aggregations