Search in sources :

Example 1 with CustomRuleFunction

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();
}
Also used : io.mycat(io.mycat) RelShuttleImpl(org.apache.calcite.rel.RelShuttleImpl) LoggerFactory(org.slf4j.LoggerFactory) MycatSortMergeJoin(io.mycat.calcite.physical.MycatSortMergeJoin) IntPair(org.apache.calcite.util.mapping.IntPair) ShardingTableHandler(io.mycat.router.ShardingTableHandler) BigDecimal(java.math.BigDecimal) RexUtil(org.apache.calcite.rex.RexUtil) RexNode(org.apache.calcite.rex.RexNode) RelBuilder(org.apache.calcite.tools.RelBuilder) RelHint(org.apache.calcite.rel.hint.RelHint) org.apache.calcite.rel.logical(org.apache.calcite.rel.logical) RelOptCluster(org.apache.calcite.plan.RelOptCluster) ImmutableBitSet(org.apache.calcite.util.ImmutableBitSet) ImmutableIntList(org.apache.calcite.util.ImmutableIntList) MycatView(io.mycat.calcite.logical.MycatView) RexLiteral(org.apache.calcite.rex.RexLiteral) MycatConvention(io.mycat.calcite.MycatConvention) MycatMergeJoinRule(io.mycat.calcite.rules.MycatMergeJoinRule) Collectors(java.util.stream.Collectors) ServerConfig(io.mycat.config.ServerConfig) QueryType(io.mycat.querycondition.QueryType) RelMetadataQuery(org.apache.calcite.rel.metadata.RelMetadataQuery) SqlStdOperatorTable(org.apache.calcite.sql.fun.SqlStdOperatorTable) RelCollation(org.apache.calcite.rel.RelCollation) LocalRules(io.mycat.calcite.localrel.LocalRules) NotNull(org.jetbrains.annotations.NotNull) java.util(java.util) CustomRuleFunction(io.mycat.router.CustomRuleFunction) MycatHashAggregate(io.mycat.calcite.physical.MycatHashAggregate) NumberFormat(java.text.NumberFormat) RelOptTable(org.apache.calcite.plan.RelOptTable) ImmutableList(com.google.common.collect.ImmutableList) Pair(org.apache.calcite.util.Pair) RelColumnOrigin(org.apache.calcite.rel.metadata.RelColumnOrigin) io.mycat.calcite.table(io.mycat.calcite.table) org.apache.calcite.rel.core(org.apache.calcite.rel.core) RelOptListener(org.apache.calcite.plan.RelOptListener) Logger(org.slf4j.Logger) RexBuilder(org.apache.calcite.rex.RexBuilder) MycatProject(io.mycat.calcite.physical.MycatProject) MycatCalciteSupport(io.mycat.calcite.MycatCalciteSupport) HepPlanner(org.apache.calcite.plan.hep.HepPlanner) HepProgramBuilder(org.apache.calcite.plan.hep.HepProgramBuilder) RelNode(org.apache.calcite.rel.RelNode) LocalSort(io.mycat.calcite.localrel.LocalSort) NameMap(io.mycat.util.NameMap) RelOptSchema(org.apache.calcite.plan.RelOptSchema) MycatAggregateUnionTransposeRule(io.mycat.calcite.localrel.MycatAggregateUnionTransposeRule) RelMetadataQuery(org.apache.calcite.rel.metadata.RelMetadataQuery) ShardingTableHandler(io.mycat.router.ShardingTableHandler) ImmutableBitSet(org.apache.calcite.util.ImmutableBitSet) CustomRuleFunction(io.mycat.router.CustomRuleFunction) IntPair(org.apache.calcite.util.mapping.IntPair) ShardingTableHandler(io.mycat.router.ShardingTableHandler) RelColumnOrigin(org.apache.calcite.rel.metadata.RelColumnOrigin) RexNode(org.apache.calcite.rex.RexNode)

Example 2 with CustomRuleFunction

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;
    });
}
Also used : RelColumnOrigin(org.apache.calcite.rel.metadata.RelColumnOrigin) CustomRuleFunction(io.mycat.router.CustomRuleFunction)

Example 3 with CustomRuleFunction

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;
    });
}
Also used : RelColumnOrigin(org.apache.calcite.rel.metadata.RelColumnOrigin) CustomRuleFunction(io.mycat.router.CustomRuleFunction)

Example 4 with CustomRuleFunction

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());
    }
}
Also used : NormalTable(io.mycat.calcite.table.NormalTable) CustomRuleFunction(io.mycat.router.CustomRuleFunction) ShardingTable(io.mycat.calcite.table.ShardingTable)

Example 5 with CustomRuleFunction

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;
    }
}
Also used : ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) SqlString(org.apache.calcite.sql.util.SqlString) CustomRuleFunction(io.mycat.router.CustomRuleFunction) NormalTable(io.mycat.calcite.table.NormalTable) GlobalTable(io.mycat.calcite.table.GlobalTable) Distribution(io.mycat.calcite.rewriter.Distribution) ImmutableList(com.google.common.collect.ImmutableList) ShardingTable(io.mycat.calcite.table.ShardingTable)

Aggregations

CustomRuleFunction (io.mycat.router.CustomRuleFunction)19 ShardingTable (io.mycat.calcite.table.ShardingTable)14 MetadataManager (io.mycat.MetadataManager)12 ShardingTableConfig (io.mycat.config.ShardingTableConfig)12 Test (org.junit.Test)12 Partition (io.mycat.Partition)11 RangeVariable (io.mycat.RangeVariable)11 Map (java.util.Map)10 ImmutableMap (com.google.common.collect.ImmutableMap)5 ImmutableList (com.google.common.collect.ImmutableList)3 RelColumnOrigin (org.apache.calcite.rel.metadata.RelColumnOrigin)3 NormalTable (io.mycat.calcite.table.NormalTable)2 ShardingTableHandler (io.mycat.router.ShardingTableHandler)2 LocalDate (java.time.LocalDate)2 java.util (java.util)2 Collectors (java.util.stream.Collectors)2 SQLUtils (com.alibaba.druid.sql.SQLUtils)1 SQLExpr (com.alibaba.druid.sql.ast.SQLExpr)1 SQLMethodInvokeExpr (com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr)1 SQLExprParser (com.alibaba.druid.sql.parser.SQLExprParser)1