use of liquibase.diff.output.changelog.DiffToChangeLog in project minijax by minijax.
the class LiquibaseHelper method generateMigrations.
private File generateMigrations(final Database referenceDatabase, final Database targetDatabase) throws LiquibaseException, IOException {
if (!resourcesDir.exists()) {
resourcesDir.mkdirs();
}
if (!migrationsDir.exists()) {
migrationsDir.mkdirs();
}
if (masterChangeLogFile.exists()) {
LOG.info("Checking current database state");
validateDatabaseState(targetDatabase);
} else {
LOG.info("Creating new master changelog");
writeChangeSets(masterChangeLogFile, emptyList());
}
@SuppressWarnings("unchecked") final SnapshotControl snapshotControl = new SnapshotControl(referenceDatabase, liquibase.structure.core.Schema.class, liquibase.structure.core.Table.class, liquibase.structure.core.Column.class, liquibase.structure.core.PrimaryKey.class, liquibase.structure.core.Index.class);
LOG.info("Executing diff");
final CompareControl compareControl = new CompareControl(snapshotControl.getTypesToInclude());
final DiffResult diffResult = DiffGeneratorFactory.getInstance().compare(referenceDatabase, targetDatabase, compareControl);
LOG.info("Converting diff to changelog");
final DiffOutputControl diffOutputControl = new DiffOutputControl(false, false, true, null);
final DiffToChangeLog diffToChangeLog = new DiffToChangeLog(diffResult, diffOutputControl);
diffToChangeLog.setChangeSetAuthor(System.getProperty("user.name"));
final List<ChangeSet> changeSets = filterChangeSets(diffToChangeLog.generateChangeSets());
LOG.info("Found {} changes", changeSets.size());
if (changeSets.isEmpty()) {
return null;
}
final File generatedChangeLogFile = new File(migrationsDir, generateFileName(masterChangeLogFile));
LOG.info("Writing new changelog: {}", generatedChangeLogFile);
writeChangeSets(generatedChangeLogFile, changeSets);
LOG.info("Add migration to master changelog: {}", masterChangeLogFile);
addIncludeFile(generatedChangeLogFile);
LOG.info("Cleaning changelog");
cleanXmlFile(masterChangeLogFile);
cleanXmlFile(generatedChangeLogFile);
LOG.info("Diff complete");
return generatedChangeLogFile;
}
use of liquibase.diff.output.changelog.DiffToChangeLog in project stdlib by petergeneric.
the class LiquibaseCore method executeAction.
/**
* Executes the Liquibase update.
*/
private static void executeAction(InitialContext jndi, GuiceApplicationValueContainer config, Map<String, String> parameters, LiquibaseAction action) throws NamingException, SQLException, LiquibaseException, IOException, ParserConfigurationException {
// N.B. liquibase may create a databasechangeloglock / databasechangelog table if one does not already exist
if (action.isWriteAction() && StringUtils.equalsIgnoreCase("true", config.getValue(HIBERNATE_IS_READONLY))) {
log.info("Changing liquibase action from " + action + " to ASSERT_UPDATED because hibernate is set to read only mode");
action = LiquibaseAction.ASSERT_UPDATED;
}
// Fail if hbm2ddl is enabled (Hibernate should not be involved in schema management)
if (StringUtils.isNotEmpty(config.getValue(HIBERNATE_SCHEMA_MANAGEMENT)) && action != LiquibaseAction.GENERATE_CHANGELOG) {
throw new RuntimeException("Liquibase is enabled but so is " + HIBERNATE_SCHEMA_MANAGEMENT + ". Only one of these schema management methods may be used at a time.");
}
final String dataSourceName = config.getDataSource();
final String changeLogFile = config.getValue(GuiceProperties.LIQUIBASE_CHANGELOG);
final String contexts = config.getValue(GuiceProperties.LIQUIBASE_CONTEXTS);
final String labels = config.getValue(GuiceProperties.LIQUIBASE_LABELS);
final String defaultSchema = config.getDefaultSchema();
final String jdbcUrl = config.getValue(AvailableSettings.URL);
final String jdbcUsername = config.getValue(AvailableSettings.USER);
final String jdbcPassword = config.getValue(AvailableSettings.PASS);
if (StringUtils.isEmpty(dataSourceName) && StringUtils.isEmpty(jdbcUrl))
throw new RuntimeException("Cannot run Liquibase: no JNDI datasource or JDBC URL set");
else if (changeLogFile == null)
throw new RuntimeException("Cannot run Liquibase: " + GuiceProperties.LIQUIBASE_CHANGELOG + " is not set");
int storedTransactionIsolation = Integer.MIN_VALUE;
Connection connection = null;
Database database = null;
try {
// Set up the resource accessor
final ResourceAccessor resourceAccessor;
{
final CompositeResourceAccessor composite;
{
ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
ResourceAccessor threadClFO = new ClassLoaderResourceAccessor(contextClassLoader);
ResourceAccessor clFO = new ClassLoaderResourceAccessor();
ResourceAccessor fsFO = new FileSystemResourceAccessor();
composite = new CompositeResourceAccessor(clFO, fsFO, threadClFO);
}
// If loading a resource with an absolute path fails, re-try it as a path relative to /
// This is for unit tests where /liquibase/changelog.xml needs to be accessed as liquibase/changelog.xml
final ResourceAccessor fallback = new RetryAbsoluteAsRelativeResourceAccessor(composite);
// Wrap the resource accessor in a filter that interprets ./ as the changeLogFile folder
resourceAccessor = new RelativePathFilteringResourceAccessor(fallback, changeLogFile);
}
// Set up the database
{
if (StringUtils.isNotEmpty(dataSourceName)) {
if (log.isDebugEnabled())
log.debug("Look up datasource for liquibase: " + dataSourceName);
final DataSource dataSource = (DataSource) jndi.lookup(dataSourceName);
connection = dataSource.getConnection();
} else {
if (log.isDebugEnabled())
log.debug("Create JDBC Connection directly: " + jdbcUrl);
// N.B. do we need to call Class.forName on the JDBC Driver URL?
// JDBC drivers should expose themselves using the service provider interface nowadays so this shouldn't be necessary
connection = DriverManager.getConnection(jdbcUrl, jdbcUsername, jdbcPassword);
}
// Allow changing the transaction isolation away from the default for liquibase
// This is a hack inserted for SQL Server where the SNAPSHOT isolation is being used
// because in this mode it refuses to execute certain DDL statements because of metadata not being versioned
{
storedTransactionIsolation = connection.getTransactionIsolation();
// In this case we change to READ UNCOMMITTED for the duration of the liquibase run
if (storedTransactionIsolation == 4096) {
connection.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);
}
}
database = DatabaseFactory.getInstance().findCorrectDatabaseImplementation(new JdbcConnection(connection));
database.setDefaultSchemaName(defaultSchema);
}
Liquibase liquibase = new Liquibase(changeLogFile, resourceAccessor, database);
for (Map.Entry<String, String> param : parameters.entrySet()) {
liquibase.setChangeLogParameter(param.getKey(), param.getValue());
}
if (log.isDebugEnabled())
log.debug("Execute liquibase action: " + action);
switch(action) {
case ASSERT_UPDATED:
// Figure out which changesets need to be run
List<ChangeSet> unrun = liquibase.listUnrunChangeSets(new Contexts(contexts), new LabelExpression(labels));
if (log.isDebugEnabled())
log.debug("Pending changesets: " + unrun);
// If any need to be run, fail
if (unrun.size() > 0)
throw new LiquibaseChangesetsPending(unrun);
else
return;
case UPDATE:
// Perform a schema update
liquibase.update(new Contexts(contexts), new LabelExpression(labels));
return;
case MARK_UPDATED:
// Mark all pending changesets as run
liquibase.changeLogSync(new Contexts(contexts), new LabelExpression(labels));
return;
case GENERATE_CHANGELOG:
CatalogAndSchema catalogueAndSchema = CatalogAndSchema.DEFAULT;
DiffToChangeLog writer = new DiffToChangeLog(new DiffOutputControl(false, false, false, new CompareControl.SchemaComparison[0]));
ByteArrayOutputStream bos = new ByteArrayOutputStream();
PrintStream pw = new PrintStream(bos);
liquibase.generateChangeLog(catalogueAndSchema, writer, pw);
System.out.println("********** GENERATED CHANGELOG START **********");
System.out.println(new String(bos.toByteArray()));
System.out.println("********** GENERATED CHANGELOG END **********");
break;
default:
throw new RuntimeException("Unknown liquibase action: " + action);
}
} finally {
// N.B. we don't return to isolations < 0 (isolation at db defaults)
if (connection != null && connection.getTransactionIsolation() != storedTransactionIsolation && storedTransactionIsolation >= 0) {
connection.setTransactionIsolation(storedTransactionIsolation);
}
if (database != null)
database.close();
else if (connection != null)
connection.close();
}
}
use of liquibase.diff.output.changelog.DiffToChangeLog in project dropwizard by dropwizard.
the class DbDumpCommand method run.
@Override
@SuppressWarnings("UseOfSystemOutOrSystemErr")
public void run(Namespace namespace, Liquibase liquibase) throws Exception {
final Set<Class<? extends DatabaseObject>> compareTypes = new HashSet<>();
if (isTrue(namespace.getBoolean("columns"))) {
compareTypes.add(Column.class);
}
if (isTrue(namespace.getBoolean("data"))) {
compareTypes.add(Data.class);
}
if (isTrue(namespace.getBoolean("foreign-keys"))) {
compareTypes.add(ForeignKey.class);
}
if (isTrue(namespace.getBoolean("indexes"))) {
compareTypes.add(Index.class);
}
if (isTrue(namespace.getBoolean("primary-keys"))) {
compareTypes.add(PrimaryKey.class);
}
if (isTrue(namespace.getBoolean("sequences"))) {
compareTypes.add(Sequence.class);
}
if (isTrue(namespace.getBoolean("tables"))) {
compareTypes.add(Table.class);
}
if (isTrue(namespace.getBoolean("unique-constraints"))) {
compareTypes.add(UniqueConstraint.class);
}
if (isTrue(namespace.getBoolean("views"))) {
compareTypes.add(View.class);
}
final DiffToChangeLog diffToChangeLog = new DiffToChangeLog(new DiffOutputControl());
final Database database = liquibase.getDatabase();
final String filename = namespace.getString("output");
if (filename != null) {
try (PrintStream file = new PrintStream(filename, StandardCharsets.UTF_8.name())) {
generateChangeLog(database, database.getDefaultSchema(), diffToChangeLog, file, compareTypes);
}
} else {
generateChangeLog(database, database.getDefaultSchema(), diffToChangeLog, outputStream, compareTypes);
}
}
use of liquibase.diff.output.changelog.DiffToChangeLog in project liquibase by liquibase.
the class PostgreSQLIntegrationTest method testMissingDataGenerator.
@Test
public void testMissingDataGenerator() throws Exception {
Scope.getCurrentScope().getSingleton(ExecutorService.class).getExecutor("jdbc", getDatabase()).execute(new RawSqlStatement("CREATE TABLE \"FIRST_TABLE\" (\"ID\" INT, \"NAME\" VARCHAR(20), \"LAST_NAME\" VARCHAR(20) DEFAULT 'Snow', " + "\"AGE\" INT DEFAULT 25, \"REGISTRATION_DATE\" date DEFAULT TO_DATE('2014-08-11', 'YYYY-MM-DD'), " + "\"COMPVALCOL\" INT DEFAULT 1*22)"));
Scope.getCurrentScope().getSingleton(ExecutorService.class).getExecutor("jdbc", getDatabase()).execute(new RawSqlStatement("CREATE TABLE \"SECOND_TABLE\" (\"ID\" INT, \"NAME\" VARCHAR(20))"));
Scope.getCurrentScope().getSingleton(ExecutorService.class).getExecutor("jdbc", getDatabase()).execute(new RawSqlStatement("ALTER TABLE \"FIRST_TABLE\" ADD CONSTRAINT \"FIRST_TABLE_PK\" PRIMARY KEY (\"ID\")"));
Scope.getCurrentScope().getSingleton(ExecutorService.class).getExecutor("jdbc", getDatabase()).execute(new RawSqlStatement("ALTER TABLE \"SECOND_TABLE\" ADD CONSTRAINT \"FIRST_TABLE_FK\" FOREIGN KEY (\"ID\") REFERENCES \"FIRST_TABLE\"(\"ID\")"));
Scope.getCurrentScope().getSingleton(ExecutorService.class).getExecutor("jdbc", getDatabase()).execute(new RawSqlStatement("CREATE INDEX \"IDX_FIRST_TABLE\" ON \"FIRST_TABLE\"(\"NAME\")"));
Scope.getCurrentScope().getSingleton(ExecutorService.class).getExecutor("jdbc", getDatabase()).execute(new RawSqlStatement("INSERT INTO \"FIRST_TABLE\"(\"ID\", \"NAME\") VALUES (1, 'JOHN')"));
Scope.getCurrentScope().getSingleton(ExecutorService.class).getExecutor("jdbc", getDatabase()).execute(new RawSqlStatement("INSERT INTO \"FIRST_TABLE\"(\"ID\", \"NAME\", \"LAST_NAME\", \"AGE\", \"REGISTRATION_DATE\", \"COMPVALCOL\") VALUES (2, 'JEREMY', 'IRONS', 71, TO_DATE('2020-04-01', 'YYYY-MM-DD'), 2*11 )"));
Scope.getCurrentScope().getSingleton(ExecutorService.class).getExecutor("jdbc", getDatabase()).execute(new RawSqlStatement("INSERT INTO \"SECOND_TABLE\"(\"ID\", \"NAME\") VALUES (1, 'JOHN')"));
Scope.getCurrentScope().getSingleton(ExecutorService.class).getExecutor("jdbc", getDatabase()).execute(new RawSqlStatement("INSERT INTO \"SECOND_TABLE\"(\"ID\", \"NAME\") VALUES (2, 'JEREMY')"));
DiffResult diffResult = DiffGeneratorFactory.getInstance().compare(getDatabase(), null, new CompareControl());
DiffToChangeLog changeLogWriter = new DiffToChangeLog(diffResult, new DiffOutputControl(false, false, false, null));
List<ChangeSet> changeSets = changeLogWriter.generateChangeSets();
boolean found = false;
for (ChangeSet changeSet : changeSets) {
List<Change> changes = changeSet.getChanges();
for (Change change : changes) {
if (!(change instanceof CreateTableChange)) {
continue;
}
found = ((CreateTableChange) change).getTableName().equals("FIRST_TABLE");
if (found) {
break;
}
}
if (found) {
break;
}
}
Assert.assertTrue("There should be a table named \"FIRST_TABLE\"", found);
}
use of liquibase.diff.output.changelog.DiffToChangeLog in project liquibase by liquibase.
the class PostgreSQLIntegrationTest method testDependenciesInGenerateChangeLog.
@Test
public void testDependenciesInGenerateChangeLog() throws Exception {
assumeNotNull(this.getDatabase());
Liquibase liquibase = createLiquibase(this.dependenciesChangeLog);
clearDatabase();
try {
liquibase.update(new Contexts());
Database database = liquibase.getDatabase();
DiffResult diffResult = DiffGeneratorFactory.getInstance().compare(database, null, new CompareControl());
DiffToChangeLog changeLogWriter = new DiffToChangeLog(diffResult, new DiffOutputControl(false, false, false, null));
List<ChangeSet> changeSets = changeLogWriter.generateChangeSets();
Assert.assertTrue(changeSets.size() > 0);
ChangeSet addPrimaryKeyChangeSet = changeSets.stream().filter(changeSet -> changeSet.getChanges().get(0) instanceof AddPrimaryKeyChange).findFirst().orElse(null);
Assert.assertNull(addPrimaryKeyChangeSet);
} catch (ValidationFailedException e) {
e.printDescriptiveError(System.out);
throw e;
}
}
Aggregations