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

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