io.datarouter.client.mysql.ddl.generate.SqlTableDiffGenerator Maven / Gradle / Ivy
The newest version!
/*
* Copyright © 2009 HotPads ([email protected])
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.datarouter.client.mysql.ddl.generate;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import io.datarouter.bytes.KvString;
import io.datarouter.client.mysql.ddl.domain.SqlColumn;
import io.datarouter.client.mysql.ddl.domain.SqlColumn.SqlColumnByName;
import io.datarouter.client.mysql.ddl.domain.SqlIndex;
import io.datarouter.client.mysql.ddl.domain.SqlTable;
import io.datarouter.scanner.Scanner;
public class SqlTableDiffGenerator{
private final SqlTable current;
private final SqlTable requested;
public SqlTableDiffGenerator(SqlTable current, SqlTable requested){
this.current = current;
this.requested = requested;
}
public List getColumnsToAdd(){
return findDifferentColumnsByName(requested, current);
}
public List getColumnsToRemove(){
return findDifferentColumnsByName(current, requested);
}
private static List findDifferentColumnsByName(SqlTable first, SqlTable second){
Set differentColumns = SqlColumnByName.wrap(first.getColumns());
differentColumns.removeAll(SqlColumnByName.wrap(second.getColumns()));
return Scanner.of(differentColumns)
.map(SqlColumnByName::sqlColumn)
.list();
}
private static Map findSameColumnsByName(List columns1, List columns2){
Map nameToColumns2 = Scanner.of(columns2)
.toMapSupplied(SqlColumn::getName, LinkedHashMap::new);
Map intersectionMap = Scanner.of(columns1)
.toMap(col1 -> col1, col1 -> nameToColumns2.get(col1.getName()));
intersectionMap.values().removeIf(Objects::isNull);
return intersectionMap;
}
public List getColumnsToModify(){
Set modifiedColumns = new HashSet<>(makeMysql8Compatible(requested.getColumns()));
// remove current columns that don't need changes
modifiedColumns.removeAll(makeMysql8Compatible(current.getColumns()));
modifiedColumns.removeAll(getColumnsToAdd());// remove new columns
return new ArrayList<>(modifiedColumns);
}
/*
* DEVOPS-8567 - Temporary method to stop flooding with ddl changes
* as width specification for integer data types was deprecated in MySQL 8.0.17
* Once all environment is upgraded to MySQL8, this temp method usage can be removed.
* */
public List makeMysql8Compatible(List columns){
List modifiedColumns = new ArrayList<>();
for(SqlColumn col : columns){
if(col.isIntegerFieldType()){
col.setMaxLength(null);
}
modifiedColumns.add(col);
}
return modifiedColumns;
}
public Set getIndexesToAdd(){
return findDifferentIndexes(requested.getIndexes(), current.getIndexes());
}
public Set getIndexesToRemove(){
return findDifferentIndexes(current.getIndexes(), requested.getIndexes());
}
public Set getUniqueIndexesToAdd(){
return findDifferentIndexes(requested.getUniqueIndexes(), current.getUniqueIndexes());
}
public Set getUniqueIndexesToRemove(){
return findDifferentIndexes(current.getUniqueIndexes(), requested.getUniqueIndexes());
}
private static Set findDifferentIndexes(Set first, Set second){
Set differentIndexes = new HashSet<>(first);
differentIndexes.removeAll(second);
return differentIndexes;
}
/*------------------------------ helper ---------------------------------*/
public boolean isTableModified(){
return isPrimaryKeyModified()
|| areColumnsModified()
|| isIndexesModified()
|| isUniqueIndexesModified()
|| isEngineModified()
|| isCharacterSetModified()
|| isCollationModified()
|| isRowFormatModified();
}
public boolean isPrimaryKeyModified(){
return !current.hasPrimaryKey() || !current.getPrimaryKey().equals(requested.getPrimaryKey());
}
public boolean areColumnsModified(){
return !new HashSet<>(current.getColumns()).equals(new HashSet<>(requested.getColumns()));
}
public void throwIfColumnTypesModified(){
Map columnsToCompareTypes = findSameColumnsByName(
current.getColumns(),
requested.getColumns());
columnsToCompareTypes.forEach((currCol, newCol) -> {
if(!currCol.getType().equals(newCol.getType())){
throw new RuntimeException("Do not change the type of a MySQL column, instead add a new column and "
+ "migrate the data. "
+ new KvString()
.add("TableName", current.getName())
.add("ColumnName", currCol.getName())
.add("CurrentColumnType", currCol.getType().toString())
.add("NewColumnType", newCol.getType().toString()));
}
});
}
public boolean isIndexesModified(){
return !current.getIndexes().equals(requested.getIndexes());
}
public boolean isUniqueIndexesModified(){
return !current.getUniqueIndexes().equals(requested.getUniqueIndexes());
}
public boolean isEngineModified(){
return current.getEngine() != requested.getEngine();
}
public boolean isCharacterSetModified(){
return current.getCharacterSet() != requested.getCharacterSet();
}
public boolean isCollationModified(){
return current.getCollation() != requested.getCollation();
}
public boolean isRowFormatModified(){
return current.getRowFormat() != requested.getRowFormat();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy