All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.moznion.mysql.diff.DiffExtractor Maven / Gradle / Ivy

Go to download

Detect and extract diff between two table declarations from schema of MySQL

There is a newer version: 1.1.0
Show newest version
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; } }