package bo.gotthardt.ebean;
import com.avaje.ebean.EbeanServer;
import com.avaje.ebean.EbeanServerFactory;
import com.avaje.ebean.config.ServerConfig;
import com.codahale.metrics.MetricRegistry;
import io.dropwizard.Configuration;
import io.dropwizard.cli.ConfiguredCommand;
import io.dropwizard.db.DataSourceFactory;
import io.dropwizard.db.ManagedDataSource;
import io.dropwizard.migrations.CloseableLiquibase;
import io.dropwizard.setup.Bootstrap;
import liquibase.diff.DiffResult;
import liquibase.diff.compare.CompareControl;
import liquibase.diff.output.DiffOutputControl;
import liquibase.diff.output.changelog.DiffToChangeLog;
import liquibase.exception.LiquibaseException;
import net.sourceforge.argparse4j.inf.Namespace;
import java.sql.SQLException;
/**
* Dropwizard command for creating Liquibase database changelogs.
* @param <T>
*/
public class DbDiffCommand<T extends Configuration & HasDatabaseConfiguration> extends ConfiguredCommand<T> {
public DbDiffCommand() {
super("dbdiff", "Creates a Liquibase changelog that migrates from the current database to one created freshly by Ebean.\nAn empty database named 'migrationdiff' must exist.");
}
@Override
protected void run(Bootstrap<T> bootstrap, Namespace namespace, T configuration) throws Exception {
// The existing database with migrations managed by Liquibase.
DataSourceFactory outdatedDb = configuration.getDatabaseConfig();
try (CloseableLiquibase outdatedLiquibase = createLiquibase(outdatedDb)) {
// A temporary database that starts out empty and then gets the autogenerated Ebean table definitions applied.
DataSourceFactory freshDb = EbeanConfigUtils.clone(outdatedDb);
String url = outdatedDb.getUrl();
freshDb.setUrl(url.substring(0, url.lastIndexOf("/")) + "/migrationdiff");
// Creating the Ebean server makes it apply its table definitions to the database immediately.
ServerConfig serverConfig = EbeanConfigUtils.createServerConfig(freshDb);
serverConfig.setDdlGenerate(true);
serverConfig.setDdlRun(true);
EbeanServer ebeanServer = EbeanServerFactory.create(serverConfig);
try (CloseableLiquibase freshLiquibase = createLiquibase(freshDb)) {
// Create and print the differences between the two databases, i.e. a migration that should be applied to update to the newest Ebean definitions.
DiffResult diff = outdatedLiquibase.diff(freshLiquibase.getDatabase(), outdatedLiquibase.getDatabase(), CompareControl.STANDARD);
DiffToChangeLog diffToChangeLog = new DiffToChangeLog(diff, new DiffOutputControl(false, false, true));
diffToChangeLog.print(System.out);
}
}
}
private static CloseableLiquibase createLiquibase(DataSourceFactory dbConfig) throws SQLException, LiquibaseException {
ManagedDataSource dataSource = dbConfig.build(new MetricRegistry(), "liquibase");
return new CloseableLiquibase(dataSource);
}
}