You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ibatis.apache.org by cb...@apache.org on 2008/08/22 19:10:32 UTC
svn commit: r688124 - in
/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis:
adhoc/AdHocExecutor.java migration/Change.java migration/CommandLine.java
migration/Migrator.java
Author: cbegin
Date: Fri Aug 22 10:10:31 2008
New Revision: 688124
URL: http://svn.apache.org/viewvc?rev=688124&view=rev
Log:
added changelog command for getting status info about the current migration level.
Added:
ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/migration/Change.java
Modified:
ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/adhoc/AdHocExecutor.java
ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/migration/CommandLine.java
ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/migration/Migrator.java
Modified: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/adhoc/AdHocExecutor.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/adhoc/AdHocExecutor.java?rev=688124&r1=688123&r2=688124&view=diff
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/adhoc/AdHocExecutor.java (original)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/adhoc/AdHocExecutor.java Fri Aug 22 10:10:31 2008
@@ -19,6 +19,19 @@
this.forceGeneratedKeySupport = forceGeneratedKeySupport;
}
+ public AdHocExecutor(String driver, String url, String username, String password, boolean forceGeneratedKeySupport) {
+ try {
+ Class driverType = Class.forName(driver);
+ DriverManager.registerDriver((Driver) driverType.newInstance());
+ connection = DriverManager.getConnection(url, username, password);
+ this.connection = connection;
+ this.typeHandlerRegistry = new TypeHandlerRegistry();
+ this.forceGeneratedKeySupport = forceGeneratedKeySupport;
+ } catch (Exception e) {
+ throw new RuntimeException("Error configuring AdHocExecutor. Cause: " + e, e);
+ }
+ }
+
public AdHocExecutor(Connection connection) {
this(connection, false);
}
Added: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/migration/Change.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/migration/Change.java?rev=688124&view=auto
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/migration/Change.java (added)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/migration/Change.java Fri Aug 22 10:10:31 2008
@@ -0,0 +1,43 @@
+package org.apache.ibatis.migration;
+
+import java.math.BigDecimal;
+
+public class Change {
+
+ private BigDecimal id;
+ private String description;
+
+ public Change() {
+ }
+
+ public Change(BigDecimal id, String description) {
+ this.id = id;
+ this.description = description;
+ }
+
+ public BigDecimal getId() {
+ return id;
+ }
+
+ public void setId(BigDecimal id) {
+ this.id = id;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public void setDescription(String description) {
+ this.description = description;
+ }
+
+ public String toString() {
+ StringBuilder idstring = new StringBuilder(id.toString());
+ idstring.insert(12,":");
+ idstring.insert(10,":");
+ idstring.insert(8," ");
+ idstring.insert(6,"-");
+ idstring.insert(4,"-");
+ return id + " [" + idstring + "] " + description;
+ }
+}
Modified: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/migration/CommandLine.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/migration/CommandLine.java?rev=688124&r1=688123&r2=688124&view=diff
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/migration/CommandLine.java (original)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/migration/CommandLine.java Fri Aug 22 10:10:31 2008
@@ -13,13 +13,14 @@
private static final String PATH_PREFIX = "--path=";
private static final String ENV_PREFIX = "--env=";
private static final String FORCE = "--force";
+ private static final String CHANGELOG = "changelog";
private static final String INIT = "init";
private static final String NEW = "new";
private static final String RUN = "run";
private static final String VERSION = "version";
private static final String UNDO = "undo";
private static final Set<String> KNOWN_COMMANDS = Collections.unmodifiableSet(
- new HashSet<String>(Arrays.asList(INIT, NEW, RUN, VERSION, UNDO)));
+ new HashSet<String>(Arrays.asList(INIT, NEW, RUN, VERSION, UNDO, CHANGELOG)));
private String repository;
private String environment;
@@ -84,6 +85,8 @@
migrator.initialize();
} else if (NEW.equals(command)) {
migrator.newMigration(params);
+ } else if (CHANGELOG.equals(command)) {
+ migrator.printChangelog();
} else if (RUN.equals(command)) {
migrator.runPendingMigrations();
} else if (VERSION.equals(command)) {
@@ -123,6 +126,7 @@
out.println(" init Creates (if necessary) and initializes a migration path.");
out.println(" new <description> Creates a new migration with the provided description.");
out.println(" run Run all unapplied migrations.");
+ out.println(" changelog Prints the changelog from the database.");
out.println(" version <version> Migrates the database up or down to the specified version.");
out.println(" undo Undoes the last migration applied to the database.");
out.println();
Modified: ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/migration/Migrator.java
URL: http://svn.apache.org/viewvc/ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/migration/Migrator.java?rev=688124&r1=688123&r2=688124&view=diff
==============================================================================
--- ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/migration/Migrator.java (original)
+++ ibatis/trunk/java/ibatis-3/ibatis-3-core/src/main/java/org/apache/ibatis/migration/Migrator.java Fri Aug 22 10:10:31 2008
@@ -1,11 +1,14 @@
package org.apache.ibatis.migration;
import org.apache.ibatis.io.Resources;
+import org.apache.ibatis.adhoc.AdHocExecutor;
import java.math.BigInteger;
+import java.math.BigDecimal;
import java.io.*;
import java.text.SimpleDateFormat;
import java.sql.Date;
+import java.sql.SQLException;
import java.util.*;
public class Migrator {
@@ -38,8 +41,8 @@
if (description == null) {
throw new MigrationException("No description specified for new migration.");
}
- Map<String,String> variables = new HashMap<String,String>();
- variables.put("description",description);
+ Map<String, String> variables = new HashMap<String, String>();
+ variables.put("description", description);
ensureEnvironment(environment);
String filename = getTimestamp() + "_" + description.replace(' ', '_') + ".sql";
copyResourceTo("org/apache/ibatis/migration/template_migration.sql", repositoryFile(filename), variables);
@@ -50,11 +53,13 @@
try {
String[] filenames = repository.list();
Arrays.sort(filenames);
- for(String filename : filenames) {
+ for (String filename : filenames) {
if (filename.endsWith(".sql")) {
- System.out.println(horizontalLine("Applying: " + filename,80));
+ System.out.println(horizontalLine("Applying: " + filename, 80));
ScriptRunner runner = getScriptRunner();
- runner.runScript(new MigrationReader(new FileReader(repositoryFile(filename)),false));
+ runner.runScript(new MigrationReader(new FileReader(repositoryFile(filename)), false));
+ Change change = parseChangeFromFilename(filename);
+ insertChangelog(change);
}
}
} catch (Exception e) {
@@ -63,22 +68,33 @@
}
public void migrateToVersion(BigInteger version) {
- System.out.println("Migrating to: " + version);
+ getChangelog();
+ }
+
+ public void printChangelog() {
+ List<Change> changelog = getChangelog();
+ System.out.println("ID TIMESTAMP DESCRIPTION");
+ System.out.println(horizontalLine("",60));
+ for (Change change : changelog) {
+ System.out.println(change);
+ }
}
public void undoLastMigration() {
try {
String[] filenames = repository.list();
- Arrays.sort(filenames,new Comparator(){
+ Arrays.sort(filenames, new Comparator() {
public int compare(Object o1, Object o2) {
- return ((Comparable)o2).compareTo(o1);
+ return ((Comparable) o2).compareTo(o1);
}
});
- for(String filename : filenames) {
+ for (String filename : filenames) {
if (filename.endsWith(".sql")) {
- System.out.println(horizontalLine("Undoing: " + filename,80));
+ System.out.println(horizontalLine("Undoing: " + filename, 80));
ScriptRunner runner = getScriptRunner();
- runner.runScript(new MigrationReader(new FileReader(repositoryFile(filename)),true));
+ runner.runScript(new MigrationReader(new FileReader(repositoryFile(filename)), true));
+ Change change = parseChangeFromFilename(filename);
+ deleteChange(change);
}
}
} catch (Exception e) {
@@ -86,12 +102,69 @@
}
}
+ private void insertChangelog(Change change) {
+ try {
+ AdHocExecutor executor = getAdHocExecutor();
+ executor.insert("insert into CHANGELOG (ID, DESCRIPTION) values (?,?)", change.getId(), change.getDescription());
+ } catch (SQLException e) {
+ throw new MigrationException("Error querying last applied migration. Cause: " + e, e);
+ }
+ }
+
+ private void deleteChange(Change change) {
+ try {
+ AdHocExecutor executor = getAdHocExecutor();
+ executor.delete("delete from CHANGELOG where id = ?", change.getId());
+ } catch (SQLException e) {
+ throw new MigrationException("Error querying last applied migration. Cause: " + e, e);
+ }
+ }
+
+ private Change parseChangeFromFilename(String filename) {
+ Change change = new Change();
+ String[] parts = filename.split("\\.")[0].split("_");
+ change.setId(new BigDecimal(parts[0]));
+ StringBuilder builder = new StringBuilder();
+ for (int i=1; i < parts.length; i++) {
+ if (i > 1) builder.append(" ");
+ builder.append(parts[i]);
+ }
+ change.setDescription(builder.toString());
+ return change;
+ }
+
+ private List<Change>getChangelog() {
+ try {
+ AdHocExecutor executor = getAdHocExecutor();
+ List<Map<String,Object>> changelog = executor.selectAll("select ID, DESCRIPTION from CHANGELOG order by id");
+ List<Change> changes = new ArrayList<Change>();
+ for(Map<String,Object> change : changelog) {
+ changes.add(new Change(new BigDecimal(change.get("ID").toString()),change.get("DESCRIPTION").toString()));
+ }
+ return changes;
+ } catch (SQLException e) {
+ throw new MigrationException("Error querying last applied migration. Cause: " + e, e);
+ }
+ }
+
+ private AdHocExecutor getAdHocExecutor() {
+ Properties props = getEnvironmentProperties();
+ String driver = props.getProperty("driver");
+ String url = props.getProperty("url");
+ String username = props.getProperty("username");
+ String password = props.getProperty("password");
+ AdHocExecutor executor = new AdHocExecutor(driver, url, username, password, false);
+ return executor;
+ }
+
private String horizontalLine(String caption, int length) {
StringBuilder builder = new StringBuilder();
- builder.append("========== ");
- builder.append(caption);
- builder.append(" ");
- for (int i=0; i < length - caption.length() - 2; i++) {
+ builder.append("==========");
+ if (caption.length() > 0) {
+ caption = " "+caption+" ";
+ builder.append(caption);
+ }
+ for (int i = 0; i < length - caption.length(); i++) {
builder.append("=");
}
return builder.toString();
@@ -108,14 +181,14 @@
}
private File repositoryFile(String fileName) {
- return new File(repository.getAbsolutePath()+File.separator+fileName);
+ return new File(repository.getAbsolutePath() + File.separator + fileName);
}
private void copyResourceTo(String resource, File toFile) {
- copyResourceTo(resource,toFile,null);
+ copyResourceTo(resource, toFile, null);
}
- private void copyResourceTo(String resource, File toFile, Map<String,String> variables) {
+ private void copyResourceTo(String resource, File toFile, Map<String, String> variables) {
System.out.println("Creating: " + toFile.getName());
try {
LineNumberReader reader = new LineNumberReader(Resources.getResourceAsReader(this.getClass().getClassLoader(), resource));
@@ -124,7 +197,7 @@
try {
String line;
while ((line = reader.readLine()) != null) {
- line = parsePlaceholders(line,variables);
+ line = parsePlaceholders(line, variables);
writer.println(line);
}
} finally {
@@ -157,7 +230,7 @@
}
private File environmentFile(String environment) {
- return repositoryFile(environment+".properties");
+ return repositoryFile(environment + ".properties");
}
private void createIfNecessary(File path) {
@@ -170,7 +243,7 @@
}
}
- private String parsePlaceholders(String string, Map<String,String> variables) {
+ private String parsePlaceholders(String string, Map<String, String> variables) {
final String OPEN = "${";
final String CLOSE = "}";
String newString = string;
@@ -197,21 +270,29 @@
private ScriptRunner getScriptRunner() {
try {
- Properties props = new Properties();
- String filename = repository + File.separator + environment + ".properties";
- File file = new File(filename);
- if (!file.exists()) {
- throw new MigrationException("Could not find environment properties file: " + filename);
- }
- props.load(new FileInputStream(file));
+ Properties props = getEnvironmentProperties();
String driver = props.getProperty("driver");
String url = props.getProperty("url");
String username = props.getProperty("username");
String password = props.getProperty("password");
- return new ScriptRunner(driver,url,username,password,false,!force);
+ return new ScriptRunner(driver, url, username, password, false, !force);
} catch (Exception e) {
throw new MigrationException("Error creating ScriptRunner. Cause: " + e, e);
}
}
+ private Properties getEnvironmentProperties() {
+ try {
+ Properties props = new Properties();
+ File file = environmentFile(environment);
+ if (!file.exists()) {
+ throw new MigrationException("Could not find environment properties file: " + file.getAbsolutePath());
+ }
+ props.load(new FileInputStream(file));
+ return props;
+ } catch (IOException e) {
+ throw new MigrationException("Error loading environment properties. Cause: " + e, e);
+ }
+ }
+
}