Skip to content

Commit

Permalink
Make this work for liquibase 2.0.5
Browse files Browse the repository at this point in the history
  • Loading branch information
jhaber committed Aug 23, 2017
1 parent ae15efa commit 39f1740
Show file tree
Hide file tree
Showing 6 changed files with 310 additions and 20 deletions.
6 changes: 3 additions & 3 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ version '1.0'

apply plugin: 'java'

sourceCompatibility = 1.6
sourceCompatibility = 1.7

repositories {
mavenLocal()
Expand All @@ -22,7 +22,7 @@ shadowJar {

dependencies {
testCompile group: 'junit', name: 'junit', version: '4.11'
compile "org.liquibase:liquibase-core:3.4.0"
compile "org.liquibase:liquibase-core:2.0.5"
compile "org.yaml:snakeyaml:1.13"
}

Expand All @@ -43,4 +43,4 @@ task dist(dependsOn: ['clean', 'prepareDist'], type: Zip) {
from ('build/dist')
into (baseName + '-' + version)

}
}
2 changes: 1 addition & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#Fri Jun 26 01:07:09 CDT 2015
#Tue Aug 22 16:37:33 EDT 2017
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
Expand Down
88 changes: 81 additions & 7 deletions src/main/java/com/refactify/Liquify.java
Original file line number Diff line number Diff line change
@@ -1,40 +1,94 @@
package com.refactify;

import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.lang.reflect.Field;
import java.nio.file.Files;
import java.nio.file.Paths;

import com.refactify.arguments.ConversionArguments;
import com.refactify.arguments.ConversionArgumentsParser;
import com.refactify.arguments.TargetFileNameBuilder;
import com.refactify.printer.SqlFormattingWriter;
import com.refactify.printer.UsagePrinter;

import liquibase.change.Change;
import liquibase.changelog.ChangeLogParameters;
import liquibase.changelog.ChangeSet;
import liquibase.changelog.DatabaseChangeLog;
import liquibase.database.Database;
import liquibase.database.DatabaseFactory;
import liquibase.database.core.MySQLDatabase;
import liquibase.exception.LiquibaseException;
import liquibase.exception.MigrationFailedException;
import liquibase.exception.SetupException;
import liquibase.executor.Executor;
import liquibase.executor.ExecutorService;
import liquibase.executor.LoggingExecutor;
import liquibase.parser.ChangeLogParser;
import liquibase.parser.ChangeLogParserFactory;
import liquibase.resource.FileSystemResourceAccessor;
import liquibase.resource.ResourceAccessor;
import liquibase.serializer.ChangeLogSerializer;
import liquibase.serializer.ChangeLogSerializerFactory;

import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;

public class Liquify {
private final static ConversionArgumentsParser parser = new ConversionArgumentsParser();
private final static UsagePrinter usagePrinter = new UsagePrinter();
private final static TargetFileNameBuilder targetFileNameBuilder = new TargetFileNameBuilder();

public static void main(final String[] args) {
//ChangeLogSerializerFactory.getInstance().register(new FormattedSqlChangeLogSerializer());

ConversionArguments conversionArguments = parser.parseArguments(args);
if(conversionArguments.areValid()) {
convertDatabaseChangeLog(conversionArguments);
String targetFileName = targetFileNameBuilder.buildFilename(conversionArguments);

try (Writer writer = new FileWriter(targetFileName)) {
Executor realExecutor = ExecutorService.getInstance().getExecutor(mysql());
Executor loggingExecutor = new LoggingExecutor(realExecutor, new SqlFormattingWriter(writer), mysql());
ExecutorService.getInstance().setExecutor(mysql(), loggingExecutor);

executeChangeLog(conversionArguments, writer);
} catch (Exception e) {
deleteTargetFile(targetFileName);
throw new RuntimeException(e);
}
}
else {
usagePrinter.printUsage();
}
}

private static void executeChangeLog(final ConversionArguments conversionArguments, Writer writer) throws Exception {
ResourceAccessor resourceAccessor = new FileSystemResourceAccessor(System.getProperty("user.dir"));
ChangeLogParser parser = ChangeLogParserFactory.getInstance().getParser(conversionArguments.getSource(), resourceAccessor);
DatabaseChangeLog changeLog = parser.parse(conversionArguments.getSource(), new ChangeLogParameters(), resourceAccessor);

writer.write("--liquibase formatted sql\n\n");

for (ChangeSet changeSet : changeLog.getChangeSets()) {
String author = changeSet.getAuthor()
.replaceAll("\\s+", "_")
.replace("_(generated)","");

writer.write("--changeset " + author + ":" + changeSet.getId() + "\n");
for (Change change : changeSet.getChanges()) {
try {
change.init();
} catch (SetupException se) {
throw new MigrationFailedException(changeSet, se);
}
}

for (Change change : changeSet.getChanges()) {
mysql().executeStatements(change, changeLog, changeSet.getSqlVisitors());
}
}
}

private static void convertDatabaseChangeLog(final ConversionArguments conversionArguments) {
String targetFileName = targetFileNameBuilder.buildFilename(conversionArguments);
try {
Expand All @@ -43,7 +97,7 @@ private static void convertDatabaseChangeLog(final ConversionArguments conversio
DatabaseChangeLog changeLog = parser.parse(conversionArguments.getSource(), new ChangeLogParameters(), resourceAccessor);
ChangeLogSerializer serializer = ChangeLogSerializerFactory.getInstance().getSerializer(targetFileName);
for (ChangeSet set : changeLog.getChangeSets()) {
set.setFilePath(targetFileName);
setFilePath(set, targetFileName);
}
serializer.write(changeLog.getChangeSets(), new FileOutputStream(targetFileName));
}
Expand All @@ -70,4 +124,24 @@ private static void deleteTargetFile(final String targetFileName) {
ioe.printStackTrace();
}
}

private static void setFilePath(ChangeSet changeSet, String filePath) {
try {
Field f = ChangeSet.class.getDeclaredField("filePath");
f.setAccessible(true);
f.set(changeSet, filePath);
} catch (Exception e) {
throw new RuntimeException(e);
}
}

private static Database mysql() {
for (Database database : DatabaseFactory.getInstance().getImplementedDatabases()) {
if (database instanceof MySQLDatabase) {
return database;
}
}

throw new RuntimeException();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,8 @@

public class TargetFileNameBuilder {
public String buildFilename(final ConversionArguments arguments) {
String fileName;
String source = arguments.getSource();
String baseFileName = source.substring(0, source.lastIndexOf("."));
if(arguments.getConversionType().equals(ConversionArguments.ConversionType.SQL)) {
fileName = String.format("%s.%s.%s", baseFileName, arguments.getDatabase(),
arguments.getConversionType().getExtension());
}
else {
fileName = String.format("%s.%s", baseFileName, arguments.getConversionType().getExtension());
}
return fileName;
return String.format("%s.%s", baseFileName, arguments.getConversionType().getExtension());
}
}
116 changes: 116 additions & 0 deletions src/main/java/com/refactify/printer/SqlFormattingWriter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
package com.refactify.printer;

import java.io.IOException;
import java.io.Writer;
import java.util.ArrayList;
import java.util.List;

public class SqlFormattingWriter extends Writer {
private static final String WHITESPACE = " \n\r\f\t";

private final Writer delegate;
private final StringBuilder buffer;

public SqlFormattingWriter(Writer delegate) {
this.delegate = delegate;
this.buffer = new StringBuilder();
}

@Override
public void write(char[] cbuf, int off, int len) throws IOException {
for (int i = off; i < off + len; i++) {
char c = cbuf[i];

if (buffer.length() == 0 && WHITESPACE.indexOf(c) > -1) {
delegate.write(c);
} else {
buffer.append(c);
if (c == ';') {
flushSql();
}
}

}
}

@Override
public void flush() throws IOException {
delegate.flush();
}

@Override
public void close() throws IOException {
if (buffer.length() > 0) {
delegate.write(buffer.toString());
buffer.setLength(0);
}
delegate.close();
}

private void flushSql() throws IOException {
String unformatted = buffer.toString();
String formatted = formatSql(unformatted);

delegate.write(formatted);
buffer.setLength(0);
}

private String formatSql(String unformatted) {
if (!unformatted.startsWith("CREATE TABLE")) {
return unformatted;
}

StringBuilder formatted = new StringBuilder();
int openParen = unformatted.indexOf('(');
formatted.append(unformatted.substring(0, openParen + 1));

int closeParen = unformatted.lastIndexOf(')');

String tableDef = unformatted.substring(openParen + 1, closeParen);

formatted.append('\n');
for (String line : splitLines(tableDef)) {
formatted.append(" ").append(line).append("\n");
}

formatted.append(')');
// force a space after the close paren
if (unformatted.charAt(closeParen + 1) != ' ') {
formatted.append(' ');
}
formatted.append(unformatted.substring(closeParen + 1));

return formatted.toString();
}

// don't split enum defs onto separate lines
private List<String> splitLines(String tableDef) {
List<String> lines = new ArrayList<>();
StringBuilder currentLine = new StringBuilder();
int openParens = 0;

for (char c : tableDef.toCharArray()) {
if (currentLine.length() == 0 && WHITESPACE.indexOf(c) > -1) {
continue;
}

currentLine.append(c);

if (c == '(') {
openParens++;
} else if (c == ')') {
openParens--;
} else if (c == ',' && openParens == 0) {
lines.add(currentLine.toString());
currentLine = new StringBuilder();
}
}

if (currentLine.length() > 0) {
lines.add(currentLine.toString());
currentLine = null;
}

return lines;
}
}
Loading

0 comments on commit 39f1740

Please sign in to comment.