Skip to content

Instantly share code, notes, and snippets.

@simonwoo
Created March 10, 2015 16:31
Show Gist options
  • Save simonwoo/aae51852b2125ea8194a to your computer and use it in GitHub Desktop.
Save simonwoo/aae51852b2125ea8194a to your computer and use it in GitHub Desktop.
automatic migration for cassandra
package com.apispark.db;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Iterator;
import java.io.File;
import java.io.IOException;
import com.datastax.driver.core.ResultSet;
import com.datastax.driver.core.Row;
public class migration extends CassandraMigrator{
//the location of scripts
private String cqlsh = "/Applications/dse-4.6.1/bin/cqlsh";
private String location = "/Users/mac/simon/restlet/apispark/modules/com.apispark.db/resources/cassandra/migrations/";
private String table = "Version"; //the version table
private String cqlMigrationPrefix = "M";
private String cqlMigrationSeparator = "_";
public void run(String[] args){
//set VM params
System.getProperties().setProperty("cassandra.properties.file", "/Users/mac/simon/restlet/apispark.properties");
System.getProperties().setProperty("log4j.configuration", "/Users/mac/simon/restlet/log4j.properties");
super.run(args);
}
@Override
public void migrate() {
ArrayList<String> scriptsJava = new ArrayList<String>(); //script file java
ArrayList<String> scriptsCql = new ArrayList<String>(); //script file cql
//create table Version if it does not exist
//String createVersionStatement = "CREATE TABLE IF NOT EXISTS \"Version\"( \"id\" uuid,\"filename\" varchar,\"timestamp\" varchar,PRIMARY KEY(\"id\"));?";
//executeUpdate(createVersionStatement,"");
//get all the scripts with a timestamp greater than current database timestamp
getScripts(scriptsJava, scriptsCql);
//execute all the scripts java
executeScriptJavas(scriptsJava);
//execute all the scripts cql
executeScriptCqls(scriptsCql);
}
//get all the script file in the cassandra.migrations
private void getScripts(ArrayList<String> scriptsJava, ArrayList<String> scriptsCql){
String biggestTimestamp = biggestTimestamp(); //current db timestamp in the table Version
ArrayList<File> files = listf(location); //get all the files under cassandra.migrations
Iterator iterator = files.iterator();
while(iterator.hasNext()){
File file = (File)iterator.next();
String filename = file.getName();
if(filename.startsWith(cqlMigrationPrefix)){
String timestamp = filename.split(cqlMigrationSeparator)[0];
timestamp = timestamp.substring(1, timestamp.length());
//add the script with the timestamp greater than current db timestamp
if(compareTimestamp(timestamp,biggestTimestamp)){
if(filename.indexOf(".java") >= 0)
scriptsJava.add(filename);
else if(filename.indexOf(".cqlsh.txt") >= 0)
scriptsCql.add(filename);
}
}
}
}
//get the biggest timestamp in the table Version
private String biggestTimestamp(){
//get the biggest timestamp
String biggestTimestamp = "000000000000";
ResultSet rs = query("select * from \"Version\"" + DEFAULT_QUERY_LIMIT);
for(Row row : rs){
String timestamp = row.getString("timestamp");
if(compareTimestamp(timestamp, biggestTimestamp))
biggestTimestamp = timestamp;
}
return biggestTimestamp;
}
//a method to compare two timestamp
private boolean compareTimestamp(String timestamp1, String timestamp2){
//
if(timestamp1.length() != timestamp2.length())
return false;
if(timestamp1.length() == 0)
return true;
else if(timestamp1.length() == 1)
return timestamp1.charAt(0) >= timestamp2.charAt(0);
else if(timestamp1.charAt(0) > timestamp2.charAt(0))
return true;
else if(timestamp1.charAt(0) == timestamp2.charAt(0))
return compareTimestamp(timestamp1.substring(1,timestamp1.length()),timestamp2.substring(1,timestamp2.length()));
return false;
}
//get the all the files under a directory
private ArrayList<File> listf(String directoryName) {
ArrayList<File> files = new ArrayList<File>();
File directory = new File(directoryName);
//test whether the directory exists
if(!directory.exists()){
System.out.println("the script file path is not correct!!");
return files;
}
// get all the files from a directory
File[] fList = directory.listFiles();
for (File file : fList) {
if (file.isFile())
files.add(file);
}
return files;
}
//execute all the script cql
private void executeScriptCqls(ArrayList<String> scriptsCql){
Iterator iterator = scriptsCql.iterator();
while(iterator.hasNext()){
String scriptCql = (String)iterator.next();
executeScriptCql(scriptCql);
insertVersion(scriptCql);
}
}
//execute a script cql
private void executeScriptCql(String scriptCql){
try {
Runtime.getRuntime().exec(cqlsh + " < " + scriptCql);
} catch (IOException e) {
e.printStackTrace();
}
}
//execute all script java
private void executeScriptJavas(ArrayList<String> scriptsJava){
Iterator iterator = scriptsJava.iterator();
while(iterator.hasNext()){
String scriptJava = (String)iterator.next();
String className = scriptJava.substring(0, scriptJava.length() - 5);
executeScriptJava(className);
insertVersion(scriptJava);
}
}
//execute a script java
private void executeScriptJava(String scriptJava){
ClassLoader classLoder = migration.class.getClassLoader();
//add the url for searching the class
try{
URLClassLoader urls = URLClassLoader.newInstance(new URL[]{
new URL("file:///Users/mac/simon/restlet/apispark/modules/com.apispark.db/src/"),
new URL("file:///Users/mac/simon/restlet/apispark/modules/com.apispark.db/resource/")
});
}catch(MalformedURLException e){
e.printStackTrace();
}
try{
//load class
Class update = classLoder.loadClass("cassandra.migrations." + scriptJava);
System.out.println(update.getName());
//execute the main method
Method method = update.getMethod("main", String[].class);
String[] params = {"--dry"};
method.invoke(null, (Object) params);
}catch(ClassNotFoundException e){
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
private void insertVersion(String filename){
String insertStatement = "insert into \"Version\"(\"id\",\"filename\",\"timestamp\") values(now(),'" + filename + "'," + "?);";
String timestamp = filename.split(cqlMigrationSeparator)[0];
timestamp = timestamp.substring(1, timestamp.length());
executeUpdate(insertStatement,timestamp);
}
public static void main(String[] args){
new migration().run(args);
}
}
@simonwoo
Copy link
Author

There are still problems:
1.I have no way to create table "Version" by java.
2.executeCql() does not work.

@boillodmanuel
Copy link

//execute all the scripts java
executeScriptJavas(scriptsJava);
//execute all the scripts cql
executeScriptCqls(scriptsCql);

Cql and java scripts should be sorted together, and execute scripts in the correct order (could be cql or a java)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment