.
org.apache.shardingsphere.sharding.route.engine.type.standard.ShardingStandardRoutingEngine
public final class ShardingStandardRoutingEngine implements ShardingRouteEngine {
private final String logicTableName;
private final SQLStatementContext sqlStatementContext;
/**
* <pre>
* // 插入有多少行,有多少条ShardingCondition
* List = List<ShardingCondition> : [
* ShardingCondition { // 插入某一行数据,提取出来的sharding条件
* routeValues : [ // 根据多个列sharding,会有多个值
* ListRouteValue {columnName : "id", tableName : "tb_users", values : ["1"]}
* ListRouteValue {columnName : "city_id", tableName : "tb_users", values : ["2"]}
* ListRouteValue {columnName : "gen_seq_no", tableName : "tb_users", values : ["45678909876545676789"]} // 自动生成,即:用户编写的sql不包含gen_seq_no字段
* ]
* }
* ]
* </pre>
*/
private final ShardingConditions shardingConditions;
private final ConfigurationProperties properties;
private final Collection<Collection<DataNode>> originalDataNodes = new LinkedList<>();
@Override
public RouteResult route(final ShardingRule shardingRule) {
if (isDMLForModify(sqlStatementContext) && 1 != ((TableAvailable) sqlStatementContext).getAllTables().size()) {
throw new ShardingSphereException("Cannot support Multiple-Table for '%s'.", sqlStatementContext.getSqlStatement());
}
return generateRouteResult(
// 数据节点
getDataNodes(shardingRule, shardingRule.getTableRule(logicTableName))
);
}
private boolean isDMLForModify(final SQLStatementContext sqlStatementContext) {
return sqlStatementContext instanceof InsertStatementContext || sqlStatementContext instanceof UpdateStatementContext || sqlStatementContext instanceof DeleteStatementContext;
}
private RouteResult generateRouteResult(final Collection<DataNode> routedDataNodes) {
RouteResult result = new RouteResult();
result.getOriginalDataNodes().addAll(originalDataNodes);
/**
* routedDataNodes = [
* DataNode : { dataSourceName : "dataSource00", tableName : "tb_users_00"}
* DataNode : { dataSourceName : "dataSource00", tableName : "tb_users_01"}
* DataNode : { dataSourceName : "dataSource01", tableName : "tb_users_00"}
* DataNode : { dataSourceName : "dataSource01", tableName : "tb_users_01"}
* ]
*/
for (DataNode each : routedDataNodes) { // 要操作的数据节点列表
result.getRouteUnits().add(
new RouteUnit(new RouteMapper(each.getDataSourceName(), each.getDataSourceName()), Collections.singletonList(new RouteMapper(logicTableName, each.getTableName()))));
}
/**
* <pre>
* RouteResult : {
* routeUnits : [
* RouteUnit : {
* dataSourceMapper : RouteMapper {logicName : "dataSource00", actualName : "dataSource00"},
* tableMappers : [
* RouteMapper : {logicName : "tb_users", actualName : "tb_users_00"}
* ]
* },
* RouteUnit : {
* dataSourceMapper : RouteMapper {logicName : "dataSource00", actualName : "dataSource00"},
* tableMappers : [
* RouteMapper : {logicName : "tb_users", actualName : "tb_users_01"}
* ]
* },
* RouteUnit : {
* dataSourceMapper : RouteMapper {logicName : "dataSource01", actualName : "dataSource00"},
* tableMappers : [
* RouteMapper : {logicName : "tb_users", actualName : "tb_users_00"}
* ]
* },
* RouteUnit : {
* dataSourceMapper : RouteMapper {logicName : "dataSource01", actualName : "dataSource00"},
* tableMappers : [
* RouteMapper : {logicName : "tb_users", actualName : "tb_users_01"}
* ]
* }
* ]
*
* }
* </pre>
*/
return result;
}
private Collection<DataNode> getDataNodes(final ShardingRule shardingRule, final TableRule tableRule) {
// 根据hint分片
if (isRoutingByHint(shardingRule, tableRule)) {
return routeByHint(shardingRule, tableRule);
}
// 根据condition分片
if (isRoutingByShardingConditions(shardingRule, tableRule)) {
return routeByShardingConditions(shardingRule, tableRule); // !!!
}
// 混合条件分片
return routeByMixedConditions(shardingRule, tableRule);
}
private boolean isRoutingByHint(final ShardingRule shardingRule, final TableRule tableRule) {
return shardingRule.getDatabaseShardingStrategy(tableRule) instanceof HintShardingStrategy && shardingRule.getTableShardingStrategy(tableRule) instanceof HintShardingStrategy;
}
private Collection<DataNode> routeByHint(final ShardingRule shardingRule, final TableRule tableRule) {
return route0(shardingRule, tableRule, getDatabaseShardingValuesFromHint(), getTableShardingValuesFromHint());
}
private boolean isRoutingByShardingConditions(final ShardingRule shardingRule, final TableRule tableRule) {
return !(shardingRule.getDatabaseShardingStrategy(tableRule) instanceof HintShardingStrategy || shardingRule.getTableShardingStrategy(tableRule) instanceof HintShardingStrategy);
}
private Collection<DataNode> routeByShardingConditions(final ShardingRule shardingRule, final TableRule tableRule) {
return shardingConditions.getConditions().isEmpty()
? route0(shardingRule, tableRule, Collections.emptyList(), Collections.emptyList())
: routeByShardingConditionsWithCondition(shardingRule, tableRule); // 按condition分片
}
private Collection<DataNode> routeByShardingConditionsWithCondition(final ShardingRule shardingRule, final TableRule tableRule) {
Collection<DataNode> result = new LinkedList<>();
// 遍历分片条件列表,插入多少条数据,shardingConditions.getConditions()的size就等于多少。
for (ShardingCondition each : shardingConditions.getConditions()) {
// 处理要插入的某行数据
Collection<DataNode> dataNodes = route0(shardingRule, tableRule,
getShardingValuesFromShardingConditions( // !!!
shardingRule,
shardingRule.getDatabaseShardingStrategy(tableRule).getShardingColumns(), // 某表格决定《分库》的column列表
each
),
getShardingValuesFromShardingConditions(
shardingRule,
shardingRule.getTableShardingStrategy(tableRule).getShardingColumns(), // 某表格决定《分表》的column列表
each
)
);
result.addAll(dataNodes);
originalDataNodes.add(dataNodes);
}
return result;
}
private Collection<DataNode> routeByMixedConditions(final ShardingRule shardingRule, final TableRule tableRule) {
return shardingConditions.getConditions().isEmpty() ? routeByMixedConditionsWithHint(shardingRule, tableRule) : routeByMixedConditionsWithCondition(shardingRule, tableRule);
}
private Collection<DataNode> routeByMixedConditionsWithCondition(final ShardingRule shardingRule, final TableRule tableRule) {
Collection<DataNode> result = new LinkedList<>();
for (ShardingCondition each : shardingConditions.getConditions()) {
Collection<DataNode> dataNodes = route0(shardingRule, tableRule, getDatabaseShardingValues(shardingRule, tableRule, each), getTableShardingValues(shardingRule, tableRule, each));
result.addAll(dataNodes);
originalDataNodes.add(dataNodes);
}
return result;
}
private Collection<DataNode> routeByMixedConditionsWithHint(final ShardingRule shardingRule, final TableRule tableRule) {
if (shardingRule.getDatabaseShardingStrategy(tableRule) instanceof HintShardingStrategy) {
return route0(shardingRule, tableRule, getDatabaseShardingValuesFromHint(), Collections.emptyList());
}
return route0(shardingRule, tableRule, Collections.emptyList(), getTableShardingValuesFromHint());
}
private List<RouteValue> getDatabaseShardingValues(final ShardingRule shardingRule, final TableRule tableRule, final ShardingCondition shardingCondition) {
ShardingStrategy dataBaseShardingStrategy = shardingRule.getDatabaseShardingStrategy(tableRule);
return isGettingShardingValuesFromHint(dataBaseShardingStrategy)
? getDatabaseShardingValuesFromHint() : getShardingValuesFromShardingConditions(shardingRule, dataBaseShardingStrategy.getShardingColumns(), shardingCondition);
}
private List<RouteValue> getTableShardingValues(final ShardingRule shardingRule, final TableRule tableRule, final ShardingCondition shardingCondition) {
ShardingStrategy tableShardingStrategy = shardingRule.getTableShardingStrategy(tableRule);
return isGettingShardingValuesFromHint(tableShardingStrategy)
? getTableShardingValuesFromHint() : getShardingValuesFromShardingConditions(shardingRule, tableShardingStrategy.getShardingColumns(), shardingCondition);
}
private boolean isGettingShardingValuesFromHint(final ShardingStrategy shardingStrategy) {
return shardingStrategy instanceof HintShardingStrategy;
}
private List<RouteValue> getDatabaseShardingValuesFromHint() {
return getRouteValues(HintManager.isDatabaseShardingOnly() ? HintManager.getDatabaseShardingValues() : HintManager.getDatabaseShardingValues(logicTableName));
}
private List<RouteValue> getTableShardingValuesFromHint() {
return getRouteValues(HintManager.getTableShardingValues(logicTableName));
}
private List<RouteValue> getRouteValues(final Collection<Comparable<?>> shardingValue) {
return shardingValue.isEmpty() ? Collections.emptyList() : Collections.singletonList(new ListRouteValue<>("", logicTableName, shardingValue));
}
private List<RouteValue> getShardingValuesFromShardingConditions(final ShardingRule shardingRule, final Collection<String> shardingColumns, final ShardingCondition shardingCondition) {
List<RouteValue> result = new ArrayList<>(shardingColumns.size());
// shardingCondition === 要插入的某行数据
// shardingCondition.getRouteValues() === 要插入行的《决定分片的值列表》
for (RouteValue each : shardingCondition.getRouteValues()) {
Optional<BindingTableRule> bindingTableRule = shardingRule.findBindingTableRule(logicTableName);
// 表名 && 字段命中
if ((logicTableName.equals(each.getTableName()) || bindingTableRule.isPresent() && bindingTableRule.get().hasLogicTable(logicTableName))
&& shardingColumns.contains(each.getColumnName())) {
result.add(each);
}
}
return result;
}
/**
* 处理要插入的某行数据
*/
private Collection<DataNode> route0(final ShardingRule shardingRule, final TableRule tableRule, final List<RouteValue> databaseShardingValues, final List<RouteValue> tableShardingValues) {
// databaseShardingValues === 影响《分库》的的值列表
// tableShardingValues === 影响《分表》的值列表
// 路由数据源
Collection<String> routedDataSources = routeDataSources(shardingRule, tableRule, databaseShardingValues);
// 路由表
Collection<DataNode> result = new LinkedList<>();
for (String each : routedDataSources) { // 遍历数据源列表
result.addAll(
routeTables(shardingRule, tableRule, each, tableShardingValues) // !!!
);
}
return result;
}
private Collection<String> routeDataSources(final ShardingRule shardingRule, final TableRule tableRule, final List<RouteValue> databaseShardingValues) {
if (databaseShardingValues.isEmpty()) { // 没有值,就使用支持的《所有数据源列表》
return tableRule.getActualDatasourceNames();
}
Collection<String> result = new LinkedHashSet<>(
// 获取《分库策略》执行分库
shardingRule.getDatabaseShardingStrategy(tableRule).doSharding(
tableRule.getActualDatasourceNames(), // 支持的《所有数据源列表》
databaseShardingValues, // 影响分库的值列表
this.properties
)
);
Preconditions.checkState(!result.isEmpty(), "no database route info");
Preconditions.checkState(tableRule.getActualDatasourceNames().containsAll(result),
"Some routed data sources do not belong to configured data sources. routed data sources: `%s`, configured data sources: `%s`", result, tableRule.getActualDatasourceNames());
return result;
}
private Collection<DataNode> routeTables(final ShardingRule shardingRule, final TableRule tableRule, final String routedDataSource, final List<RouteValue> tableShardingValues) {
// routedDataSource === 要分表的数据源
// 获取某个数据源下支持的《所有表列表》
Collection<String> availableTargetTables = tableRule.getActualTableNames(routedDataSource);
Collection<String> routedTables = new LinkedHashSet<>(
tableShardingValues.isEmpty() ?
// 影响《分表》的值列表为空,就路由到《所有表列表》
availableTargetTables
// 获取《分表策略》执行分表
: shardingRule.getTableShardingStrategy(tableRule).doSharding(
availableTargetTables, // 支持的《所有表列表》
tableShardingValues, // 影响《分表》的值列表
this.properties
)
);
Preconditions.checkState(!routedTables.isEmpty(), "no table route info");
Collection<DataNode> result = new LinkedList<>();
for (String each : routedTables) {
// routedDataSource === 数据源名称
// each === 对应的真实表名称
result.add(new DataNode(routedDataSource, each));
}
return result;
}
}
.