net.moznion.mysql.diff.DiffExtractor Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of mysql-diff Show documentation
Show all versions of mysql-diff Show documentation
Detect and extract diff between two table declarations from schema of MySQL
package net.moznion.mysql.diff;
import net.moznion.mysql.diff.model.Column;
import net.moznion.mysql.diff.model.OrdinaryKey;
import net.moznion.mysql.diff.model.Table;
import net.moznion.mysql.diff.model.UniqueKey;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.stream.Collectors;
/**
* Diff extractor for table definition of schema.
*
* @author moznion
*
*/
public class DiffExtractor {
/**
* Extract diff between two schemas.
*
* @param oldTables tables of old schema.
* @param newTables tables of new schema.
* @return Diff string.
*/
public static String extractDiff(List oldTables, List newTables) {
StringBuilder diffStringBuilder = new StringBuilder();
List newTableNames = newTables.stream()
.map(table -> table.getTableName())
.sorted()
.collect(Collectors.toList());
Map oldTableMap = oldTables.stream()
.collect(Collectors.toMap(Table::getTableName, t -> t));
Map newTableMap = newTables.stream()
.collect(Collectors.toMap(Table::getTableName, t -> t));
for (String tableName : newTableNames) {
Table newTable = newTableMap.get(tableName);
if (oldTableMap.containsKey(tableName)) {
Table oldTable = oldTableMap.get(tableName);
diffStringBuilder.append(extractTableDiff(tableName, oldTable, newTable));
} else {
diffStringBuilder.append(newTable.getContent()).append(";\n\n");
}
}
return diffStringBuilder.toString();
}
private static String extractTableDiff(String tableName, Table oldTable, Table newTable) {
List changes = extractColumnDiff(oldTable, newTable);
changes.addAll(extractKeyDiff(oldTable, newTable));
if (changes.isEmpty()) {
return "";
}
return new StringBuilder()
.append("ALTER TABLE `")
.append(tableName)
.append("` ")
.append(String.join(", ", changes))
.append(";\n\n")
.toString();
}
private static List extractColumnDiff(Table oldTable, Table newTable) {
List oldColumns = oldTable.getColumns();
List newColumns = newTable.getColumns();
Map oldColumnMap = oldColumns.stream()
.collect(Collectors.toMap(Column::getName, c -> c));
Map newColumnMap = newColumns.stream()
.collect(Collectors.toMap(Column::getName, c -> c));
Map allColumnMap = new HashMap<>();
allColumnMap.putAll(oldColumnMap);
allColumnMap.putAll(newColumnMap);
List changes = new ArrayList<>();
for (Entry column : allColumnMap.entrySet()) {
String columnName = column.getKey();
if (!oldColumnMap.containsKey(columnName)) {
changes.add(new StringBuilder()
.append("ADD `")
.append(columnName)
.append("` ")
.append(newColumnMap.get(columnName).getDefinition())
.toString());
continue;
}
if (!newColumnMap.containsKey(columnName)) {
changes.add(new StringBuilder()
.append("DROP `")
.append(columnName)
.append("`")
.toString());
continue;
}
String oldDefinition = oldColumnMap.get(columnName).getDefinition();
String newDefinition = newColumnMap.get(columnName).getDefinition();
if (!oldDefinition.equals(newDefinition)) {
changes.add(new StringBuilder()
.append("MODIFY `")
.append(columnName)
.append("` ")
.append(newDefinition)
.toString());
continue;
}
}
return changes;
}
private static List extractKeyDiff(Table oldTable, Table newTable) {
List changes = new ArrayList<>();
// For ordinary key
changes.addAll(extractOrdinaryKeyDiff(oldTable, newTable));
// For unique key
changes.addAll(extractUniqueKeyDiff(oldTable, newTable));
return changes;
}
private static List extractOrdinaryKeyDiff(Table oldTable, Table newTable) {
List changes = new ArrayList<>();
List oldKeys = oldTable.getKeys();
List newKeys = newTable.getKeys();
Set oldKeysAttendance = oldKeys.stream()
.map(OrdinaryKey::getColumn)
.collect(Collectors.toSet());
Set newKeysAttendance = newKeys.stream()
.map(OrdinaryKey::getColumn)
.collect(Collectors.toSet());
// add key
for (OrdinaryKey key : newKeys) {
String column = key.getColumn();
if (oldKeysAttendance.contains(column)) {
continue;
}
String name = String.join("_",
Arrays.stream(column.split(","))
.map(col -> col.replaceAll("[`()]", ""))
.collect(Collectors.toList()));
changes.add(
new StringBuilder()
.append("ADD INDEX `")
.append(name)
.append("` (")
.append(column)
.append(")")
.toString());
}
// drop key
for (OrdinaryKey key : oldKeys) {
String column = key.getColumn();
if (newKeysAttendance.contains(column)) {
continue;
}
changes.add(
new StringBuilder()
.append("DROP INDEX `")
.append(key.getName())
.append("`")
.toString());
}
return changes;
}
private static List extractUniqueKeyDiff(Table oldTable, Table newTable) {
List changes = new ArrayList<>();
List oldKeys = oldTable.getUniqueKeys();
List newKeys = newTable.getUniqueKeys();
Set oldKeysAtendance = oldKeys.stream()
.map(OrdinaryKey::getColumn)
.collect(Collectors.toSet());
Set newKeysAtendance = newKeys.stream()
.map(OrdinaryKey::getColumn)
.collect(Collectors.toSet());
// add key
for (UniqueKey key : newKeys) {
String column = key.getColumn();
if (oldKeysAtendance.contains(column)) {
continue;
}
String name = String.join("_",
Arrays.asList(column.split(",")).stream()
.map(col -> col.replaceAll("[`()]", ""))
.collect(Collectors.toList()));
changes.add(
new StringBuilder()
.append("ADD UNIQUE INDEX `")
.append(name)
.append("` (")
.append(column)
.append(")")
.toString());
}
// drop key
for (OrdinaryKey key : oldKeys) {
String column = key.getColumn();
if (newKeysAtendance.contains(column)) {
continue;
}
changes.add(
new StringBuilder()
.append("DROP INDEX `")
.append(key.getName())
.append("`")
.toString());
}
return changes;
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy