package com.taobao.tddl.rule.utils;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import com.taobao.tddl.rule.model.MatcherResult;
import com.taobao.tddl.rule.model.TargetDB;
/**
* 有些乱七八糟的oriDb/oriTable比较,我也没想明白具体的应用场景<br/>
* 猜测应该和动态迁移有关,比如指定某个库/表完成了迁移,就单独开放这个表写入权限
*
* @author <a href="junyu@taobao.com">junyu</a>
* @author <a href="jianghang.loujh@taobao.com">jianghang</a>
* @version 1.0
* @since 1.6
* @date 2011-4-22 12:49:53
*/
public class MatchResultCompare {
/**
* 新旧matcherResult对比
*
* @param resultNew
* @param resultOld
* @return 如果库表完全相同返回true,否则返回false
*/
public static boolean matchResultCompare(MatcherResult resultNew, MatcherResult resultOld) {
return matchResultCompare(resultNew, resultOld, null, null);
}
/**
* 新旧MatchResult对比,如果不同,对比当前库表是否和新规则计算结果一致
*
* @param resultNew
* @param resultOld
* @param oriDb
* @param oriTable
* @return
*/
public static boolean matchResultCompare(MatcherResult resultNew, MatcherResult resultOld, String oriDb,
String oriTable) {
List<TargetDB> targetNew = resultNew.getCalculationResult();
List<TargetDB> targetOld = resultOld.getCalculationResult();
return innerCompare(targetNew, targetOld, oriDb, oriTable);
}
/**
* 确定取数据的库表是否在规则计算的结果之内.
*
* @param resultNew
* @param oriDb
* @param oriTable
* @return false 不存在, true 表示规则计算结果完全包含取数据的库表
*/
public static boolean oriDbTabCompareWithMatchResult(MatcherResult resultNew, String oriDb, String oriTable) {
List<TargetDB> targetNew = resultNew.getCalculationResult();
return oriDbTabCompareWithTargetDb(targetNew, oriDb, oriTable);
}
/**
* 新旧TargetDB对比
*
* @param targetNew
* @param targetOld
* @return 如果库表完全相同返回true,否则返回false
*/
public static boolean targetDbCompare(List<TargetDB> targetNew, List<TargetDB> targetOld) {
return targetDbCompare(targetNew, targetOld, null, null);
}
/**
* 新旧TargetDB对比,如果不同,对比当前库表是否和新规则计算结果一致
*
* @param targetNew
* @param targetOld
* @param oriDb
* @param oriTable
* @return
*/
public static boolean targetDbCompare(List<TargetDB> targetNew, List<TargetDB> targetOld, String oriDb,
String oriTable) {
return innerCompare(targetNew, targetOld, oriDb, oriTable);
}
/**
* 确定取数据的库表是否在规则计算的结果之内.
*
* @param resultNew
* @param oriDb
* @param oriTable
* @return false 不存在, true 表示规则计算结果完全包含取数据的库表
*/
public static boolean oriDbTabCompareWithTargetDb(List<TargetDB> targetNew, String oriDb, String oriTable) {
Map<String, Map<String, String>> dbTabMap = getTargetMap(targetNew);
Map<String, String> tables = dbTabMap.get(oriDb);
if (tables == null) {
return false;
} else if (tables.get(oriTable) == null) {
return false;
} else {
return true;
}
}
// ========================== helper method =====================
/**
* 对比下新旧库
*/
private static boolean innerCompare(List<TargetDB> targetNew, List<TargetDB> targetOld, String oriDb,
String oriTable) {
Map<String, Map<String, String>> newOne = getTargetMap(targetNew);
Map<String, Map<String, String>> oldOne = getTargetMap(targetOld);
boolean dbDiff = false;
boolean tbDiff = false;
// 正向比较
for (Map.Entry<String, Map<String, String>> entry : newOne.entrySet()) {
Map<String, String> oldTables = oldOne.get(entry.getKey());
if (oldTables != null) {
// 正向比较表
for (Map.Entry<String, String> newTbEntry : entry.getValue().entrySet()) {
String tb = oldTables.get(newTbEntry.getKey());
if (tb == null) {
tbDiff = true;
}
}
// 反向比较表
for (Map.Entry<String, String> oldTbEntry : oldTables.entrySet()) {
String tb = entry.getValue().get(oldTbEntry.getKey());
if (tb == null) {
tbDiff = true;
}
}
} else {
dbDiff = true;
}
}
// 反向只检测库计算结果是否相同,因为表计算结果比较正向就可以得到
for (Map.Entry<String, Map<String, String>> entry : oldOne.entrySet()) {
Map<String, String> newTables = newOne.get(entry.getKey());
if (newTables == null) {
dbDiff = true;
}
}
return compareResultAnalyse(newOne, oriDb, oriTable, dbDiff, tbDiff);
}
/**
* 判断oriDb+oriTable是否出现在目标中
*/
private static boolean compareResultAnalyse(Map<String, Map<String, String>> newResult, String oriDb,
String oriTable, boolean dbDiff, boolean tbDiff) {
// 如果表计算结果相同,库计算结果不同
if (dbDiff && oriDb != null) {
Map<String, String> tables = newResult.get(oriDb);
if (tables != null) {
// 如果本库就是目标库
return compareResutlAnalyseTable(tables, oriTable, tbDiff);
} else {
// 如果本库不是目标库,那么说明需要迁移.
return false;
}
} else if (dbDiff && oriDb == null) {
return false;
} else {
// 如果库结果计算也相同,看表计算结果
return compareResutlAnalyseTable(newResult.get(oriDb), oriTable, tbDiff);
}
}
/**
* 判断oriTable是否出现在目标表中
*/
private static boolean compareResutlAnalyseTable(Map<String, String> tables, String oriTable, boolean tbDiff) {
if (tbDiff && oriTable != null) {
if (tables.get(oriTable) != null) {
return true;
} else {
return false;
}
} else if (tbDiff && oriTable == null) {
return false;
} else {
return true;
}
}
/**
* 将数据转化为map结构
*
* @param targetDbs
* @return
*/
private static Map<String, Map<String, String>> getTargetMap(List<TargetDB> targetDbs) {
Map<String, Map<String, String>> reMap = new HashMap<String, Map<String, String>>();
for (TargetDB db : targetDbs) {
Map<String, String> tableMap = new HashMap<String, String>();
Set<String> tables = db.getTableNames();
for (String table : tables) {
tableMap.put(table, table);
}
reMap.put(db.getDbIndex(), tableMap);
}
return reMap;
}
}