Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,7 @@
target
.idea
*~
.project
.classpath
.settings
classes
11 changes: 3 additions & 8 deletions dbdeploy-ant/src/main/java/com/dbdeploy/AntTarget.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,7 @@ public class AntTarget extends Task {
+ "\n\t\ttemplatedir=\"[DIRECTORY FOR DBMS TEMPLATE SCRIPTS, IF NOT USING BUILT-IN]\""
+ "\n\t\tdir=\"[YOUR SCRIPT FOLDER]\" *"
+ "\n\t\toutputfile=\"[OUTPUT SCRIPT PATH + NAME]\""
+ "\n\t\tlastChangeToApply=\"[NUMBER OF THE LAST SCRIPT TO APPLY]\""
+ "\n\t\tundoOutputfile=\"[UNDO SCRIPT PATH + NAME]\""
+ "\n\t\ttargetVersion=\"[TARGET VERSION OF DATABASE]\""
+ "\n\t\tchangeLogTableName=\"[CHANGE LOG TABLE NAME]\""
+ "\n\t\tdelimiter=\"[STATEMENT DELIMITER - default ;]\""
+ "\n\t\tdelimitertype=\"[STATEMENT DELIMITER TYPE - row or normal, default normal]\""
Expand Down Expand Up @@ -69,12 +68,8 @@ public void setDbms(String dbms) {
dbDeploy.setDbms(dbms);
}

public void setLastChangeToApply(Integer lastChangeToApply) {
dbDeploy.setLastChangeToApply(lastChangeToApply);
}

public void setUndoOutputfile(File undoOutputfile) {
dbDeploy.setUndoOutputfile(undoOutputfile);
public void setTargetVersion(Integer targetVersion) {
dbDeploy.setTargetVersion(targetVersion);
}

public void setChangeLogTableName(String changeLogTableName) {
Expand Down
98 changes: 61 additions & 37 deletions dbdeploy-core/src/main/java/com/dbdeploy/Controller.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.dbdeploy;

import com.dbdeploy.appliers.ApplyMode;
import com.dbdeploy.appliers.ChangeScriptApplier;
import com.dbdeploy.exceptions.DbDeployException;
import com.dbdeploy.scripts.ChangeScript;

Expand All @@ -13,59 +15,81 @@ public class Controller {
private final AvailableChangeScriptsProvider availableChangeScriptsProvider;
private final AppliedChangesProvider appliedChangesProvider;
private final ChangeScriptApplier changeScriptApplier;
private final ChangeScriptApplier undoScriptApplier;

private final PrettyPrinter prettyPrinter = new PrettyPrinter();

public Controller(AvailableChangeScriptsProvider availableChangeScriptsProvider,
AppliedChangesProvider appliedChangesProvider,
ChangeScriptApplier changeScriptApplier, ChangeScriptApplier undoScriptApplier) {
ChangeScriptApplier changeScriptApplier) {
this.availableChangeScriptsProvider = availableChangeScriptsProvider;
this.appliedChangesProvider = appliedChangesProvider;
this.changeScriptApplier = changeScriptApplier;
this.undoScriptApplier = undoScriptApplier;
}

public void processChangeScripts(Integer lastChangeToApply) throws DbDeployException, IOException {
if (lastChangeToApply != Integer.MAX_VALUE) {
info("Only applying changes up and including change script #" + lastChangeToApply);
}

List<ChangeScript> scripts = availableChangeScriptsProvider.getAvailableChangeScripts();
List<Integer> applied = appliedChangesProvider.getAppliedChanges();
List<ChangeScript> toApply = identifyChangesToApply(lastChangeToApply, scripts, applied);

logStatus(scripts, applied, toApply);

changeScriptApplier.apply(Collections.unmodifiableList(toApply));

if (undoScriptApplier != null) {
info("Generating undo scripts...");
Collections.reverse(toApply);
undoScriptApplier.apply(Collections.unmodifiableList(toApply));
}
}

private void logStatus(List<ChangeScript> scripts, List<Integer> applied, List<ChangeScript> toApply) {
info("Changes currently applied to database:\n " + prettyPrinter.format(applied));
info("Scripts available:\n " + prettyPrinter.formatChangeScriptList(scripts));
info("To be applied:\n " + prettyPrinter.formatChangeScriptList(toApply));
public void processChangeScripts(int targetVersion) throws DbDeployException, IOException {
if (targetVersion == Integer.MAX_VALUE)
info("Upgrading database to the latest and greatest");
else
info("Target version of database: " + targetVersion);


List<ChangeScript> availableScripts = availableChangeScriptsProvider.getAvailableChangeScripts();
List<Integer> appliedScripts = appliedChangesProvider.getAppliedChanges();

int latestScriptApplied = getLatestScriptApplied(appliedScripts);
ApplyMode applyMode = getApplyMode(latestScriptApplied, targetVersion);
List<ChangeScript> toApply = identifyChangesToApply(targetVersion, appliedScripts, availableScripts, applyMode);

if (applyMode == ApplyMode.UNDO) Collections.reverse(toApply);
logStatus(availableScripts, appliedScripts, toApply, applyMode);
changeScriptApplier.apply(Collections.unmodifiableList(toApply), applyMode);
}

private List<ChangeScript> identifyChangesToApply(Integer lastChangeToApply, List<ChangeScript> scripts, List<Integer> applied) {
List<ChangeScript> result = new ArrayList<ChangeScript>();
/**
* returns the current version of the database
*/
private int getLatestScriptApplied(List<Integer> applied) {
int latestScriptApplied = 0;

for (ChangeScript script : scripts) {
if (script.getId() > lastChangeToApply)
break;

if (!applied.contains(script.getId())) {
result.add(script);
}
for (Integer i : applied) {
if (i > latestScriptApplied)
latestScriptApplied = i;
}

return latestScriptApplied;
}

private List<ChangeScript> identifyChangesToApply(int targetVersion, List<Integer> appliedScripts
, List<ChangeScript> availableScripts, ApplyMode applyMode) {
List<ChangeScript> changesToApply = new ArrayList<ChangeScript>();

for (ChangeScript script : availableScripts) {
if (applyMode == ApplyMode.DO) {
if (script.getId() <= targetVersion && !appliedScripts.contains(script.getId()))
changesToApply.add(script);
}
else if (applyMode == ApplyMode.UNDO) {
if (script.getId() > targetVersion && appliedScripts.contains(script.getId()))
changesToApply.add(script);
}
}

return result;
return changesToApply;
}

private ApplyMode getApplyMode(int currentVersion, int targetVersion) {
if (currentVersion <= targetVersion)
return ApplyMode.DO;
else
return ApplyMode.UNDO;
}

private void logStatus(List<ChangeScript> scripts, List<Integer> applied, List<ChangeScript> toApply, ApplyMode applyMode) {
info("Changes currently applied to database:\n " + prettyPrinter.format(applied));
info("Scripts available:\n " + prettyPrinter.formatChangeScriptList(scripts));
info("To be applied:\n " + prettyPrinter.formatChangeScriptList(toApply));
info("Apply mode: " + applyMode);
}

private void info(String string) {
System.err.println(string);
Expand Down
45 changes: 11 additions & 34 deletions dbdeploy-core/src/main/java/com/dbdeploy/DbDeploy.java
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package com.dbdeploy;

import java.io.File;

import com.dbdeploy.appliers.ChangeScriptApplier;
import com.dbdeploy.appliers.DirectToDbApplier;
import com.dbdeploy.appliers.TemplateBasedApplier;
import com.dbdeploy.appliers.UndoTemplateBasedApplier;
import com.dbdeploy.database.DelimiterType;
import com.dbdeploy.database.QueryStatementSplitter;
import com.dbdeploy.database.changelog.DatabaseSchemaVersionManager;
Expand All @@ -11,18 +13,14 @@
import com.dbdeploy.scripts.ChangeScriptRepository;
import com.dbdeploy.scripts.DirectoryScanner;

import java.io.File;
import java.io.PrintStream;

public class DbDeploy {
private String url;
private String userid;
private String password;
private File scriptdirectory;
private File outputfile;
private File undoOutputfile;
private String dbms;
private Integer lastChangeToApply = Integer.MAX_VALUE;
private Integer targetVersion = Integer.MAX_VALUE; // based on the target version we decide if we need to upgrade or downgrade the database
private String driver;
private String changeLogTableName = "changelog";
private String delimiter = ";";
Expand Down Expand Up @@ -57,12 +55,8 @@ public void setDbms(String dbms) {
this.dbms = dbms;
}

public void setLastChangeToApply(Integer lastChangeToApply) {
this.lastChangeToApply = lastChangeToApply;
}

public void setUndoOutputfile(File undoOutputfile) {
this.undoOutputfile = undoOutputfile;
public void setTargetVersion(Integer targetVersion) {
this.targetVersion = targetVersion;
}

public void setChangeLogTableName(String changeLogTableName) {
Expand All @@ -71,9 +65,7 @@ public void setChangeLogTableName(String changeLogTableName) {

public void go() throws Exception {
System.err.println(getWelcomeString());

validate();

Class.forName(driver);

QueryExecuter queryExecuter = new QueryExecuter(url, userid, password);
Expand All @@ -87,28 +79,17 @@ public void go() throws Exception {
ChangeScriptApplier doScriptApplier;

if (outputfile != null) {
doScriptApplier = new TemplateBasedApplier(
new PrintStream(outputfile), dbms,
changeLogTableName, getTemplatedir());
doScriptApplier = new TemplateBasedApplier(outputfile, dbms, changeLogTableName, getTemplatedir());
} else {
QueryStatementSplitter splitter = new QueryStatementSplitter();
splitter.setDelimiter(getDelimiter());
splitter.setDelimiterType(getDelimiterType());
doScriptApplier = new DirectToDbApplier(queryExecuter, databaseSchemaVersionManager, splitter);
}

ChangeScriptApplier undoScriptApplier = null;

if (undoOutputfile != null) {
undoScriptApplier =
new UndoTemplateBasedApplier(
new PrintStream(undoOutputfile), dbms, changeLogTableName, getTemplatedir());

}
Controller controller = new Controller(changeScriptRepository, databaseSchemaVersionManager, doScriptApplier);

Controller controller = new Controller(changeScriptRepository, databaseSchemaVersionManager, doScriptApplier, undoScriptApplier);

controller.processChangeScripts(lastChangeToApply);
controller.processChangeScripts(targetVersion);

queryExecuter.close();
}
Expand Down Expand Up @@ -156,16 +137,12 @@ public File getOutputfile() {
return outputfile;
}

public File getUndoOutputfile() {
return undoOutputfile;
}

public String getDbms() {
return dbms;
}

public Integer getLastChangeToApply() {
return lastChangeToApply;
public Integer getTargetVersion() {
return targetVersion;
}

public String getDriver() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
package com.dbdeploy;
package com.dbdeploy.appliers;

import com.dbdeploy.scripts.ChangeScript;

import java.util.List;

public interface ChangeScriptApplier {
void apply(List<ChangeScript> changeScript);
void apply(List<ChangeScript> changeScript, ApplyMode applyMode);
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.dbdeploy.appliers;

import com.dbdeploy.ChangeScriptApplier;
import com.dbdeploy.database.QueryStatementSplitter;
import com.dbdeploy.database.changelog.DatabaseSchemaVersionManager;
import com.dbdeploy.database.changelog.QueryExecuter;
Expand All @@ -20,15 +19,18 @@ public DirectToDbApplier(QueryExecuter queryExecuter, DatabaseSchemaVersionManag
this.splitter = splitter;
}

public void apply(List<ChangeScript> changeScript) {
public void apply(List<ChangeScript> changeScript, ApplyMode applyMode) {
begin();

for (ChangeScript script : changeScript) {
System.err.println("Applying " + script + "...");

applyChangeScriptContent(script.getContent());
insertToSchemaVersionTable(script);

if (applyMode == ApplyMode.DO)
applyChangeScriptContent(script.getContent());
else if (applyMode == ApplyMode.UNDO)
applyChangeScriptContent(script.getUndoContent());

insertToSchemaVersionTable(script, applyMode);
commitTransaction();
}
}
Expand All @@ -51,8 +53,11 @@ protected void applyChangeScriptContent(String scriptContent) {
}
}

protected void insertToSchemaVersionTable(ChangeScript changeScript) {
schemaVersionManager.recordScriptApplied(changeScript);
protected void insertToSchemaVersionTable(ChangeScript changeScript, ApplyMode applyMode) {
if (applyMode == ApplyMode.DO)
schemaVersionManager.recordScriptApplied(changeScript);
else if (applyMode == ApplyMode.UNDO)
schemaVersionManager.recordUndoScriptApplied(changeScript);
}

protected void commitTransaction() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.dbdeploy.appliers;

import com.dbdeploy.ChangeScriptApplier;
import com.dbdeploy.exceptions.UsageException;
import com.dbdeploy.scripts.ChangeScript;
import freemarker.cache.ClassTemplateLoader;
Expand All @@ -18,14 +17,14 @@

public class TemplateBasedApplier implements ChangeScriptApplier {
private Configuration configuration;
private Writer writer;
private Writer outputFileWriter;
private String syntax;
private String changeLogTableName;

public TemplateBasedApplier(OutputStream outputStream, String syntax, String changeLogTableName, File templateDirectory) throws IOException {
public TemplateBasedApplier(File outputfile, String syntax, String changeLogTableName, File templateDirectory) throws IOException {
this.syntax = syntax;
this.changeLogTableName = changeLogTableName;
this.writer = new PrintWriter(outputStream);
this.outputFileWriter = new PrintWriter(new PrintStream(outputfile));
this.configuration = new Configuration();

FileTemplateLoader fileTemplateLoader = createFileTemplateLoader(templateDirectory);
Expand All @@ -36,24 +35,24 @@ public TemplateBasedApplier(OutputStream outputStream, String syntax, String cha
}));
}

private FileTemplateLoader createFileTemplateLoader(File templateDirectory) throws IOException {
private FileTemplateLoader createFileTemplateLoader(File templateDirectory) throws IOException {
if (templateDirectory == null) {
return new FileTemplateLoader();
} else {
return new FileTemplateLoader(templateDirectory, true);
}
}

public void apply(List<ChangeScript> changeScripts) {
String filename = syntax + "_" + getTemplateQualifier() + ".ftl";
public void apply(List<ChangeScript> changeScripts, ApplyMode applyMode) {
String filename = syntax + "_" + getTemplateQualifier(applyMode) + ".ftl";

try {
Map<String, Object> model = new HashMap<String, Object>();
model.put("scripts", changeScripts);
model.put("changeLogTableName", changeLogTableName);

Template template = configuration.getTemplate(filename);
template.process(model, writer);
template.process(model, outputFileWriter);
} catch (FileNotFoundException ex) {
throw new UsageException("Could not find template named " + filename + "\n" +
"Check that you have got the name of the database syntax correct.", ex);
Expand All @@ -62,8 +61,11 @@ public void apply(List<ChangeScript> changeScripts) {
}
}

protected String getTemplateQualifier() {
return "apply";
protected String getTemplateQualifier(ApplyMode applyMode) {
if (applyMode == ApplyMode.UNDO)
return "undo";
else
return "apply";
}

}
Loading