use of io.mycat.router.CustomRuleFunction in project Mycat2 by MyCATApache.
the class SQLRBORewriter method pushDownERTable.
private static Optional<RelNode> pushDownERTable(Join join, MycatView left, MycatView right) {
if (left.banPushdown() || right.banPushdown()) {
return Optional.empty();
}
switch(join.getJoinType()) {
case INNER:
case LEFT:
case SEMI:
case ANTI:
case RIGHT:
break;
case FULL:
return Optional.empty();
default:
throw new IllegalStateException("Unexpected value: " + join.getJoinType());
}
JoinInfo joinInfo = join.analyzeCondition();
if (joinInfo.isEqui()) {
List<IntPair> pairs = joinInfo.pairs();
if (pairs.isEmpty())
return Optional.empty();
RexNode conditions = left.getCondition().orElse(null);
RelMetadataQuery metadataQuery = join.getCluster().getMetadataQuery();
IdentityHashMap<TableHandler, Set<String>> keysMap = new IdentityHashMap<>();
IdentityHashMap<RelColumnOrigin, RelColumnOrigin> equals = new IdentityHashMap<>();
for (IntPair pair : pairs) {
RelColumnOrigin leftColumnOrigin = metadataQuery.getColumnOrigin(left.getRelNode(), pair.source);
RelColumnOrigin rightColumnOrigin = metadataQuery.getColumnOrigin(right.getRelNode(), pair.target);
if (leftColumnOrigin == null || rightColumnOrigin == null) {
continue;
}
MycatLogicTable leftLogicTable = leftColumnOrigin.getOriginTable().unwrap(MycatLogicTable.class);
MycatLogicTable rightLogicTable = rightColumnOrigin.getOriginTable().unwrap(MycatLogicTable.class);
if (!leftColumnOrigin.isDerived() && !rightColumnOrigin.isDerived()) {
TableHandler leftTableHandler = leftLogicTable.getTable();
keysMap.computeIfAbsent(leftTableHandler, mycatLogicTable -> new HashSet<>()).add(leftTableHandler.getColumns().get(leftColumnOrigin.getOriginColumnOrdinal()).getColumnName());
TableHandler rightTableHandler = rightLogicTable.getTable();
keysMap.computeIfAbsent(rightTableHandler, mycatLogicTable -> new HashSet<>()).add(rightTableHandler.getColumns().get(rightColumnOrigin.getOriginColumnOrdinal()).getColumnName());
equals.put(leftColumnOrigin, rightColumnOrigin);
}
}
boolean allHitPartition = keysMap.entrySet().stream().allMatch(shardingTableHandlerSetEntry -> {
TableHandler tableHandler = shardingTableHandlerSetEntry.getKey();
switch(tableHandler.getType()) {
case SHARDING:
CustomRuleFunction function = ((ShardingTableHandler) tableHandler).function();
Set<String> columns = shardingTableHandlerSetEntry.getValue();
return function.requireShardingKeys(shardingTableHandlerSetEntry.getValue()) || // 保证命中分区
columns.stream().anyMatch(function::isShardingPartitionKey);
case GLOBAL:
case NORMAL:
return true;
case CUSTOM:
case VISUAL:
case VIEW:
default:
return false;
}
});
if (allHitPartition) {
// erjoin
boolean pushDown = isErJoin(equals);
if (!pushDown) {
pushDown = isSameTargetPartitionJoin(left, equals);
}
if (!pushDown) {
pushDown = isSameTargetPartitionGlobalOrNormalJoin(left, right, equals);
}
if (pushDown) {
return left.getDistribution().join(right.getDistribution()).map(distribution -> MycatView.ofCondition(join.copy(join.getTraitSet(), ImmutableList.of(left.getRelNode(), right.getRelNode())), distribution, conditions));
}
}
}
return Optional.empty();
}
use of io.mycat.router.CustomRuleFunction in project Mycat2 by MyCATApache.
the class SQLRBORewriter method isErJoin.
private static boolean isErJoin(IdentityHashMap<RelColumnOrigin, RelColumnOrigin> equals) {
return equals.entrySet().stream().allMatch(entry -> {
RelColumnOrigin leftColumnOrigin = entry.getKey();
RelColumnOrigin rightColumnOrigin = entry.getValue();
MycatLogicTable leftRelNode = leftColumnOrigin.getOriginTable().unwrap(MycatLogicTable.class);
MycatLogicTable rightRelNode = rightColumnOrigin.getOriginTable().unwrap(MycatLogicTable.class);
LogicTableType leftTableType = leftRelNode.getTable().getType();
LogicTableType rightTableType = rightRelNode.getTable().getType();
if (leftTableType == LogicTableType.SHARDING) {
ShardingTable leftTableHandler = (ShardingTable) leftRelNode.logicTable();
SimpleColumnInfo lColumn = leftTableHandler.getColumns().get(leftColumnOrigin.getOriginColumnOrdinal());
CustomRuleFunction lFunction = leftTableHandler.getShardingFuntion();
if (rightTableType == LogicTableType.SHARDING) {
ShardingTable rightTableHandler = (ShardingTable) rightRelNode.logicTable();
SimpleColumnInfo rColumn = rightTableHandler.getColumns().get(rightColumnOrigin.getOriginColumnOrdinal());
CustomRuleFunction rFunction = rightTableHandler.getShardingFuntion();
if (lFunction.isSameDistribution(rFunction)) {
return lFunction.getColumnInfo(lColumn.getColumnName()).equals(rFunction.getColumnInfo(rColumn.getColumnName()));
}
}
}
return false;
});
}
use of io.mycat.router.CustomRuleFunction in project Mycat2 by MyCATApache.
the class SQLRBORewriter method isSameTargetPartitionJoin.
private static boolean isSameTargetPartitionJoin(MycatView leftView, IdentityHashMap<RelColumnOrigin, RelColumnOrigin> equals) {
return equals.entrySet().stream().anyMatch(entry -> {
RelColumnOrigin leftColumnOrigin = entry.getKey();
RelColumnOrigin rightColumnOrigin = entry.getValue();
MycatLogicTable leftRelNode = leftColumnOrigin.getOriginTable().unwrap(MycatLogicTable.class);
MycatLogicTable rightRelNode = rightColumnOrigin.getOriginTable().unwrap(MycatLogicTable.class);
LogicTableType leftTableType = leftRelNode.getTable().getType();
LogicTableType rightTableType = rightRelNode.getTable().getType();
if (leftTableType == LogicTableType.SHARDING) {
ShardingTable leftTableHandler = (ShardingTable) leftRelNode.logicTable();
SimpleColumnInfo lColumn = leftTableHandler.getColumns().get(leftColumnOrigin.getOriginColumnOrdinal());
CustomRuleFunction lFunction = leftTableHandler.getShardingFuntion();
if (isInPartitionKey(leftView, lFunction)) {
if (rightTableType == LogicTableType.SHARDING) {
ShardingTable rightTableHandler = (ShardingTable) rightRelNode.logicTable();
SimpleColumnInfo rColumn = rightTableHandler.getColumns().get(rightColumnOrigin.getOriginColumnOrdinal());
CustomRuleFunction rFunction = rightTableHandler.getShardingFuntion();
return Distribution.isTargetPartitionJoin(lFunction, rFunction);
}
return false;
} else {
return false;
}
}
return false;
});
}
use of io.mycat.router.CustomRuleFunction in project Mycat2 by MyCATApache.
the class Distribution method join.
public Optional<Distribution> join(Distribution arg) {
switch(arg.type()) {
case PHY:
switch(this.type()) {
case PHY:
NormalTable leftNormalTable = this.normalTables.get(0);
NormalTable rightNormalTable = arg.normalTables.get(0);
if (leftNormalTable.getDataNode().getTargetName().equals(rightNormalTable.getDataNode().getTargetName())) {
return Optional.of(new Distribution(this.shardingTables, this.globalTables, merge(this.normalTables, arg.normalTables)));
}
return Optional.empty();
case BROADCAST:
return Optional.of(new Distribution(merge(this.shardingTables, arg.shardingTables), merge(this.globalTables, arg.globalTables), merge(this.normalTables, arg.normalTables)));
case SHARDING:
ShardingTable shardingTable = this.shardingTables.get(0);
if (shardingTable.function().isAllPartitionInTargetName(arg.normalTables.get(0).getDataNode().getTargetName())) {
return Optional.of(new Distribution(merge(this.shardingTables, arg.shardingTables), merge(this.globalTables, arg.globalTables), merge(this.normalTables, arg.normalTables)));
}
return Optional.empty();
default:
throw new IllegalStateException("Unexpected value: " + this.type());
}
case BROADCAST:
return Optional.of(new Distribution(merge(this.shardingTables, arg.shardingTables), merge(this.globalTables, arg.globalTables), merge(this.normalTables, arg.normalTables)));
case SHARDING:
switch(this.type()) {
case PHY:
ShardingTable shardingTable = arg.shardingTables.get(0);
if (shardingTable.function().isAllPartitionInTargetName(this.normalTables.get(0).getDataNode().getTargetName())) {
return Optional.of(new Distribution(merge(this.shardingTables, arg.shardingTables), merge(this.globalTables, arg.globalTables), merge(this.normalTables, arg.normalTables)));
}
return Optional.empty();
case BROADCAST:
return Optional.of(new Distribution(merge(this.shardingTables, arg.shardingTables), merge(this.globalTables, arg.globalTables), merge(this.normalTables, arg.normalTables)));
case SHARDING:
ShardingTable leftShardingTable = this.shardingTables.get(0);
ShardingTable rightShardingTable = arg.shardingTables.get(0);
CustomRuleFunction leftShardingFuntion = leftShardingTable.getShardingFuntion();
CustomRuleFunction rightShardingFuntion = rightShardingTable.getShardingFuntion();
if (leftShardingFuntion.isSameDistribution(rightShardingFuntion) || isTargetPartitionJoin(leftShardingFuntion, rightShardingFuntion)) {
return Optional.of(new Distribution(merge(this.shardingTables, arg.shardingTables), merge(this.globalTables, arg.globalTables), merge(this.normalTables, arg.normalTables)));
}
return Optional.empty();
default:
throw new IllegalStateException("Unexpected value: " + this.type());
}
default:
throw new IllegalStateException("Unexpected value: " + arg.type());
}
}
use of io.mycat.router.CustomRuleFunction in project Mycat2 by MyCATApache.
the class AsyncMycatDataContextImpl method mapSharding.
public static List<PartitionGroup> mapSharding(MycatView view, List<Partition> partitionList) {
Distribution distribution = view.getDistribution();
List<ShardingTable> shardingTableList = distribution.getShardingTables();
ShardingTable primaryShardingTable = shardingTableList.get(0);
CustomRuleFunction primaryShardingFunction = primaryShardingTable.getShardingFuntion();
HashMap<String, Partition> groupTemplate = new HashMap<>();
for (NormalTable normalTable : distribution.getNormalTables()) {
// 可能存在错误的数据分布,但是错误的数据分布访问不到
groupTemplate.put(normalTable.getUniqueName(), normalTable.getDataNode());
}
for (GlobalTable globalTable : distribution.getGlobalTables()) {
groupTemplate.put(globalTable.getUniqueName(), globalTable.getDataNode());
}
if (distribution.getShardingTables().size() == 1) {
List<PartitionGroup> res = new ArrayList<>(partitionList.size());
for (Partition partition : partitionList) {
HashMap<String, Partition> map = new HashMap<>(groupTemplate);
map.put(primaryShardingTable.getUniqueName(), partition);
res.add(new PartitionGroup(partition.getTargetName(), map));
}
return res;
} else {
List<ShardingTable> joinShardingTables = shardingTableList.subList(1, shardingTableList.size());
List<PartitionGroup> res = new ArrayList<>(partitionList.size());
for (Partition primaryPartition : partitionList) {
HashMap<String, Partition> map = new HashMap<>(groupTemplate);
map.put(primaryShardingTable.getUniqueName(), primaryPartition);
for (ShardingTable joinShardingTable : joinShardingTables) {
CustomRuleFunction joinFunction = joinShardingTable.function();
if (primaryShardingFunction.isSameDistribution(joinFunction)) {
Partition joinPartition = joinFunction.getPartition(primaryShardingFunction.indexOf(primaryPartition));
map.put(joinShardingTable.getUniqueName(), joinPartition);
} else if (primaryShardingFunction.isSameTargetFunctionDistribution(joinFunction)) {
List<Partition> joinPartitions = joinShardingTable.getPartitionsByTargetName(primaryPartition.getTargetName());
if (joinPartitions.size() != 1) {
throw new IllegalArgumentException("wrong partition " + joinPartitions + " in " + view);
}
map.put(joinShardingTable.getUniqueName(), joinPartitions.get(0));
}
}
res.add(new PartitionGroup(primaryPartition.getTargetName(), map));
}
return res;
}
}
Aggregations