Search in sources :

Example 1 with ShardingTableHandler

use of io.mycat.router.ShardingTableHandler 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 ShardingTableHandler

use of io.mycat.router.ShardingTableHandler in project Mycat2 by MyCATApache.

the class PartitionByCRC32PreSlotTest method getPartitionByCRC32PreSlot.

private PartitionByCRC32PreSlot getPartitionByCRC32PreSlot(int count) {
    String text = String.valueOf(count);
    PartitionByCRC32PreSlot partition = new PartitionByCRC32PreSlot();
    ShardingTableHandler shardingTableHandler = TableHandlerMocks.mockTableHandlerWithDataNodes(count);
    partition.init(shardingTableHandler, Collections.singletonMap("count", text), Collections.emptyMap());
    return partition;
}
Also used : ShardingTableHandler(io.mycat.router.ShardingTableHandler)

Example 3 with ShardingTableHandler

use of io.mycat.router.ShardingTableHandler in project Mycat2 by MyCATApache.

the class MySQLCheckHandler method onExecute.

@Override
protected Future<Void> onExecute(SQLRequest<MySqlCheckTableStatement> request, MycatDataContext dataContext, Response response) {
    ResultSetBuilder resultSetBuilder = ResultSetBuilder.create();
    resultSetBuilder.addColumnInfo("TABLE", JDBCType.VARCHAR);
    resultSetBuilder.addColumnInfo("OP", JDBCType.VARCHAR);
    resultSetBuilder.addColumnInfo("MSG_TYPE", JDBCType.VARCHAR);
    resultSetBuilder.addColumnInfo("MSG_TEXT", JDBCType.VARCHAR);
    MetadataManager metadataManager = MetaClusterCurrent.wrapper(MetadataManager.class);
    JdbcConnectionManager jdbcConnectionManager = MetaClusterCurrent.wrapper(JdbcConnectionManager.class);
    List<Throwable> throwables = Collections.synchronizedList(new LinkedList<>());
    MySqlCheckTableStatement ast = request.getAst();
    for (SQLExprTableSource table : ast.getTables()) {
        resolveSQLExprTableSource(table, dataContext);
        String schemaName = SQLUtils.normalize(table.getSchema());
        String tableName = SQLUtils.normalize(table.getTableName());
        TableHandler tableHandler = metadataManager.getTable(schemaName, tableName);
        Set<String> errorInfo = new HashSet<>();
        switch(tableHandler.getType()) {
            case SHARDING:
                {
                    ShardingTableHandler shardingTableHandler = (ShardingTableHandler) tableHandler;
                    errorInfo = check(metadataManager, jdbcConnectionManager, throwables, shardingTableHandler.dataNodes().parallelStream());
                    break;
                }
            case GLOBAL:
                {
                    GlobalTableHandler globalTableHandler = (GlobalTableHandler) tableHandler;
                    errorInfo = check(metadataManager, jdbcConnectionManager, throwables, globalTableHandler.getGlobalDataNode().parallelStream());
                    break;
                }
            case NORMAL:
                {
                    break;
                }
            case CUSTOM:
                {
                    break;
                }
            default:
                throw new IllegalStateException("Unexpected value: " + tableHandler.getType());
        }
        resultSetBuilder.addObjectRowPayload(Arrays.asList(table.toString(), "check", errorInfo.isEmpty() ? "Ok" : "Error", String.join(",", errorInfo)));
    }
    return response.sendResultSet(resultSetBuilder.build());
}
Also used : ResultSetBuilder(io.mycat.beans.mycat.ResultSetBuilder) ShardingTableHandler(io.mycat.router.ShardingTableHandler) GlobalTableHandler(io.mycat.calcite.table.GlobalTableHandler) GlobalTableHandler(io.mycat.calcite.table.GlobalTableHandler) ShardingTableHandler(io.mycat.router.ShardingTableHandler) SQLExprTableSource(com.alibaba.druid.sql.ast.statement.SQLExprTableSource) JdbcConnectionManager(io.mycat.datasource.jdbc.datasource.JdbcConnectionManager) MySqlCheckTableStatement(com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCheckTableStatement)

Example 4 with ShardingTableHandler

use of io.mycat.router.ShardingTableHandler in project Mycat2 by MyCATApache.

the class SQLRBORewriter method aggregate.

public static Optional<RelNode> aggregate(RelNode original, Aggregate aggregate) {
    RelNode input = original;
    Distribution dataNodeInfo = null;
    MycatView view = null;
    ImmutableList<RelHint> hints = aggregate.getHints();
    if (input instanceof MycatView) {
        dataNodeInfo = ((MycatView) input).getDistribution();
        view = (MycatView) original;
        if (view.banPushdown()) {
            return Optional.empty();
        }
        input = ((MycatView) input).getRelNode();
    }
    if (dataNodeInfo == null) {
        return Optional.empty();
    }
    if (dataNodeInfo.type() == Distribution.Type.PHY || dataNodeInfo.type() == Distribution.Type.BROADCAST) {
        input = aggregate.copy(aggregate.getTraitSet(), ImmutableList.of(input));
        return Optional.of(view.changeTo(input, dataNodeInfo));
    } else {
        ImmutableBitSet groupSet = aggregate.getGroupSet();
        RelMetadataQuery metadataQuery = aggregate.getCluster().getMetadataQuery();
        IdentityHashMap<MycatLogicTable, Set<String>> shardingKeysMap = new IdentityHashMap<>();
        for (Integer integer : groupSet) {
            RelColumnOrigin columnOrigin = metadataQuery.getColumnOrigin(input, integer);
            if (columnOrigin == null || columnOrigin.isDerived()) {
                continue;
            }
            MycatLogicTable mycatLogicTable = columnOrigin.getOriginTable().unwrap(MycatLogicTable.class);
            if (mycatLogicTable == null || !mycatLogicTable.isSharding()) {
                continue;
            }
            ShardingTableHandler tableHandler = (ShardingTableHandler) mycatLogicTable.getTable();
            SimpleColumnInfo simpleColumnInfo = tableHandler.getColumns().get(columnOrigin.getOriginColumnOrdinal());
            if (simpleColumnInfo.isShardingKey()) {
                Set<String> shardingKeySet = shardingKeysMap.computeIfAbsent(mycatLogicTable, s -> new HashSet<>());
                shardingKeySet.add(simpleColumnInfo.getColumnName());
                if (tableHandler.function().requireShardingKeys(shardingKeySet)) {
                    input = aggregate.copy(aggregate.getTraitSet(), ImmutableList.of(input));
                    return Optional.of(view.changeTo(input, dataNodeInfo));
                }
            }
        }
        RelNode backup = input;
        if (!(input instanceof Union)) {
            input = LogicalUnion.create(ImmutableList.of(input, input), true);
            input = LogicalAggregate.create(input, aggregate.getHints(), aggregate.getGroupSet(), aggregate.getGroupSets(), aggregate.getAggCallList());
        }
        HepProgramBuilder hepProgram = new HepProgramBuilder();
        hepProgram.addMatchLimit(512);
        hepProgram.addRuleInstance(MycatAggregateUnionTransposeRule.Config.DEFAULT.toRule());
        HepPlanner planner = new HepPlanner(hepProgram.build());
        planner.setRoot(input);
        RelNode bestExp = planner.findBestExp();
        if (bestExp instanceof Aggregate) {
            Aggregate mergeAgg = (Aggregate) bestExp;
            if (mergeAgg.getInput() instanceof Union && mergeAgg.getInput(0).getInput(0) instanceof Aggregate) {
                MycatView multiView = view.changeTo(mergeAgg.getInput(0).getInput(0), dataNodeInfo);
                MycatHashAggregate mycatHashAggregate = MycatHashAggregate.create(mergeAgg.getTraitSet(), hints, multiView, mergeAgg.getGroupSet(), mergeAgg.getGroupSets(), mergeAgg.getAggCallList());
                return Optional.of(mycatHashAggregate);
            }
        }
        {
            return splitAggregate(view, aggregate);
        }
    }
}
Also used : RelMetadataQuery(org.apache.calcite.rel.metadata.RelMetadataQuery) ShardingTableHandler(io.mycat.router.ShardingTableHandler) ImmutableBitSet(org.apache.calcite.util.ImmutableBitSet) ImmutableBitSet(org.apache.calcite.util.ImmutableBitSet) HepProgramBuilder(org.apache.calcite.plan.hep.HepProgramBuilder) RelHint(org.apache.calcite.rel.hint.RelHint) HepPlanner(org.apache.calcite.plan.hep.HepPlanner) MycatView(io.mycat.calcite.logical.MycatView) MycatHashAggregate(io.mycat.calcite.physical.MycatHashAggregate) RelNode(org.apache.calcite.rel.RelNode) RelColumnOrigin(org.apache.calcite.rel.metadata.RelColumnOrigin) MycatHashAggregate(io.mycat.calcite.physical.MycatHashAggregate)

Example 5 with ShardingTableHandler

use of io.mycat.router.ShardingTableHandler in project Mycat2 by MyCATApache.

the class AutoFunctionFactory method getTableFunction.

@SneakyThrows
public static final CustomRuleFunction getTableFunction(ShardingTableHandler tableHandler, ShardingFunction shardingFunction) {
    Map<String, Object> properties = shardingFunction.getProperties();
    int dbNum = Integer.parseInt(properties.getOrDefault("dbNum", 1).toString());
    int tableNum = Integer.parseInt(properties.getOrDefault("tableNum", 1).toString());
    int storeNum = Optional.ofNullable(properties.get("storeNum")).map(i -> Integer.parseInt(i.toString())).orElse(0);
    boolean prototype = (storeNum == 0);
    if (prototype) {
        storeNum = 1;
    }
    Integer storeDbNum = Optional.ofNullable(properties.get("storeDbNum")).map(i -> Integer.parseInt(i.toString())).orElse(dbNum * tableNum / storeNum);
    SQLMethodInvokeExpr tableMethod = converyToMethodExpr((String) properties.get("tableMethod"));
    SQLMethodInvokeExpr dbMethod = converyToMethodExpr((String) properties.get("dbMethod"));
    String sep = "/";
    String erUniqueName = Optional.ofNullable(dbMethod).map(i -> i.getMethodName()).orElse("") + Optional.ofNullable(tableMethod).map(i -> i.getMethodName()).orElse("") + " storeNum:" + storeNum + " storeDbNum:" + storeDbNum + " dbNum:" + dbNum + " tableNum:" + tableNum;
    ToIntFunction<Object> tableFunction = (o) -> 0;
    Set<String> dbShardingKeys = new HashSet<>();
    ToIntFunction<Object> dbFunction = (o) -> 0;
    Set<String> tableShardingKeys = new HashSet<>();
    String mappingFormat = (String) properties.computeIfAbsent("mappingFormat", (unused) -> String.join(sep, prototype ? "prototype" : "c${targetIndex}", tableHandler.getSchemaName() + "_${dbIndex}", tableHandler.getTableName() + ((!supportFlattenMapping(tableMethod, dbMethod)) ? "_${tableIndex}" : "_${index}")));
    final boolean flattenMapping = mappingFormat.contains("${index}") && supportFlattenMapping(tableMethod, dbMethod);
    boolean dbEnum = Optional.ofNullable(dbMethod).map(db -> {
        return ENUM_RANGE.contains(SQLUtils.normalize(db.getMethodName().toUpperCase()));
    }).orElse(false);
    boolean tableEnum = Optional.ofNullable(tableMethod).map(tb -> {
        return ENUM_RANGE.contains(SQLUtils.normalize(tb.getMethodName().toUpperCase()));
    }).orElse(false);
    if (dbMethod != null) {
        int num = dbNum;
        SQLMethodInvokeExpr methodInvokeExpr = dbMethod;
        if (SQLUtils.nameEquals("HASH", methodInvokeExpr.getMethodName())) {
            methodInvokeExpr.setMethodName("MOD_HASH");
        }
        if (SQLUtils.nameEquals("MOD_HASH", methodInvokeExpr.getMethodName())) {
            String shardingKey = getShardingKey(methodInvokeExpr);
            dbShardingKeys.add(shardingKey);
            SimpleColumnInfo columnInfo = tableHandler.getColumnByName(shardingKey);
            dbFunction = specilizeSingleModHash(num, columnInfo);
        }
        if (SQLUtils.nameEquals("UNI_HASH", methodInvokeExpr.getMethodName())) {
            String shardingKey = getShardingKey(methodInvokeExpr);
            dbShardingKeys.add(shardingKey);
            SimpleColumnInfo columnInfo = tableHandler.getColumnByName(shardingKey);
            dbFunction = specilizeSingleModHash(num, columnInfo);
        }
        if (SQLUtils.nameEquals("RIGHT_SHIFT", methodInvokeExpr.getMethodName())) {
            String shardingKey = getShardingKey(methodInvokeExpr);
            dbShardingKeys.add(shardingKey);
            int shift = Integer.parseInt(getShardingKey(methodInvokeExpr, 1));
            SimpleColumnInfo columnInfo = tableHandler.getColumnByName(shardingKey);
            dbFunction = specilizeSingleRightShift(num, shift, columnInfo);
        }
        if (SQLUtils.nameEquals("RANGE_HASH", methodInvokeExpr.getMethodName())) {
            String shardingKey1 = getShardingKey(methodInvokeExpr);
            dbShardingKeys.add(shardingKey1);
            String shardingKey2 = getShardingKey(methodInvokeExpr, 1);
            dbShardingKeys.add(shardingKey2);
            SimpleColumnInfo column1 = Objects.requireNonNull(tableHandler.getColumnByName(shardingKey1));
            SimpleColumnInfo column2 = Objects.requireNonNull(tableHandler.getColumnByName(shardingKey2));
            if (!column1.getType().equals(column2.getType())) {
                throw new IllegalArgumentException(column1 + " and " + column2 + " type is different");
            }
            int n;
            if (methodInvokeExpr.getArguments().size() > 2) {
                n = Integer.parseInt(getShardingKey(methodInvokeExpr, 2));
            } else {
                n = 0;
            }
            dbFunction = specilizeSingleRangeHash(num, n, column1);
        }
        if (SQLUtils.nameEquals("YYYYMM", methodInvokeExpr.getMethodName())) {
            String shardingKey = getShardingKey(methodInvokeExpr);
            dbShardingKeys.add(shardingKey);
            SimpleColumnInfo column1 = Objects.requireNonNull(tableHandler.getColumnByName(shardingKey));
            dbFunction = specilizeyyyymm(num, column1);
        }
        if (SQLUtils.nameEquals("YYYYDD", methodInvokeExpr.getMethodName())) {
            String shardingKey = getShardingKey(methodInvokeExpr);
            dbShardingKeys.add(shardingKey);
            SimpleColumnInfo column1 = Objects.requireNonNull(tableHandler.getColumnByName(shardingKey));
            dbFunction = specilizeyyyydd(num, column1);
        }
        if (SQLUtils.nameEquals("YYYYWEEK", methodInvokeExpr.getMethodName())) {
            String shardingKey = getShardingKey(methodInvokeExpr);
            dbShardingKeys.add(shardingKey);
            SimpleColumnInfo column1 = Objects.requireNonNull(tableHandler.getColumnByName(shardingKey));
            dbFunction = specilizeyyyyWeek(num, column1);
        }
        if ("STR_HASH".equalsIgnoreCase(methodInvokeExpr.getMethodName())) {
            String shardingKey = getShardingKey(methodInvokeExpr);
            dbShardingKeys.add(shardingKey);
            List<SQLExpr> arguments = methodInvokeExpr.getArguments();
            int startIndex;
            int endIndex;
            int valType;
            int randSeed;
            if (arguments.size() >= 3) {
                startIndex = Integer.parseInt(Objects.toString(arguments.get(1)));
                endIndex = Integer.parseInt(Objects.toString(arguments.get(2)));
            } else {
                startIndex = -1;
                endIndex = -1;
            }
            if (arguments.size() >= 4) {
                valType = Integer.parseInt(Objects.toString(arguments.get(3)));
            } else {
                valType = 0;
            }
            if (arguments.size() >= 5) {
                randSeed = Integer.parseInt(Objects.toString(arguments.get(4)));
            } else {
                randSeed = 31;
            }
            SimpleColumnInfo column1 = Objects.requireNonNull(tableHandler.getColumnByName(shardingKey));
            dbFunction = specilizeStrHash(num, startIndex, endIndex, valType, randSeed, column1);
        }
    }
    if (tableMethod != null) {
        int num = tableNum;
        SQLMethodInvokeExpr methodInvokeExpr = tableMethod;
        if (SQLUtils.nameEquals("HASH", methodInvokeExpr.getMethodName())) {
            methodInvokeExpr.setMethodName("MOD_HASH");
        }
        if (SQLUtils.nameEquals("MOD_HASH", methodInvokeExpr.getMethodName())) {
            String shardingKey = getShardingKey(methodInvokeExpr);
            tableShardingKeys.add(shardingKey);
            SimpleColumnInfo column1 = Objects.requireNonNull(tableHandler.getColumnByName(shardingKey));
            tableFunction = specilizeSingleModHash(num, column1);
        }
        if (SQLUtils.nameEquals("UNI_HASH", methodInvokeExpr.getMethodName())) {
            String shardingKey = getShardingKey(methodInvokeExpr);
            tableShardingKeys.add(getShardingKey(methodInvokeExpr));
            SimpleColumnInfo column1 = Objects.requireNonNull(tableHandler.getColumnByName(shardingKey));
            tableFunction = specilizeSingleModHash(num, column1);
        }
        if (SQLUtils.nameEquals("RIGHT_SHIFT", methodInvokeExpr.getMethodName())) {
            String shardingKey = getShardingKey(methodInvokeExpr);
            tableShardingKeys.add(shardingKey);
            int shift = Integer.parseInt(getShardingKey(methodInvokeExpr, 1));
            SimpleColumnInfo column1 = Objects.requireNonNull(tableHandler.getColumnByName(shardingKey));
            tableFunction = specilizeSingleRightShift(num, shift, column1);
        }
        if (SQLUtils.nameEquals("RANGE_HASH", methodInvokeExpr.getMethodName())) {
            String shardingKey = getShardingKey(methodInvokeExpr);
            tableShardingKeys.add(shardingKey);
            tableShardingKeys.add(getShardingKey(methodInvokeExpr, 1));
            int n;
            if (methodInvokeExpr.getArguments().size() > 2) {
                n = Integer.parseInt(getShardingKey(methodInvokeExpr, 2));
            } else {
                n = 0;
            }
            SimpleColumnInfo column1 = Objects.requireNonNull(tableHandler.getColumnByName(shardingKey));
            tableFunction = specilizeSingleRangeHash(num, n, column1);
        }
        if (SQLUtils.nameEquals("YYYYMM", methodInvokeExpr.getMethodName())) {
            String shardingKey = getShardingKey(methodInvokeExpr);
            tableShardingKeys.add(shardingKey);
            SimpleColumnInfo column1 = Objects.requireNonNull(tableHandler.getColumnByName(shardingKey));
            tableFunction = specilizeyyyymm(num, column1);
        }
        if (SQLUtils.nameEquals("YYYYDD", methodInvokeExpr.getMethodName())) {
            String shardingKey = getShardingKey(methodInvokeExpr);
            tableShardingKeys.add(shardingKey);
            SimpleColumnInfo column1 = Objects.requireNonNull(tableHandler.getColumnByName(shardingKey));
            tableFunction = specilizeyyyydd(num, column1);
        }
        if (SQLUtils.nameEquals("YYYYWEEK", methodInvokeExpr.getMethodName())) {
            String shardingKey = getShardingKey(methodInvokeExpr);
            tableShardingKeys.add(shardingKey);
            SimpleColumnInfo column1 = Objects.requireNonNull(tableHandler.getColumnByName(shardingKey));
            tableFunction = specilizeyyyyWeek(num, column1);
        }
        if (SQLUtils.nameEquals("WEEK", methodInvokeExpr.getMethodName())) {
            String shardingKey = getShardingKey(methodInvokeExpr);
            SimpleColumnInfo column1 = Objects.requireNonNull(tableHandler.getColumnByName(shardingKey));
            tableShardingKeys.add(shardingKey);
            tableFunction = specilizeWeek(num, column1);
        }
        if (SQLUtils.nameEquals("MMDD", methodInvokeExpr.getMethodName())) {
            String shardingKey = getShardingKey(methodInvokeExpr);
            SimpleColumnInfo column1 = Objects.requireNonNull(tableHandler.getColumnByName(shardingKey));
            tableShardingKeys.add(shardingKey);
            tableFunction = specilizemmdd(num, column1);
        }
        if (SQLUtils.nameEquals("DD", methodInvokeExpr.getMethodName())) {
            String shardingKey = getShardingKey(methodInvokeExpr);
            SimpleColumnInfo column1 = Objects.requireNonNull(tableHandler.getColumnByName(shardingKey));
            tableShardingKeys.add(shardingKey);
            tableFunction = specilizedd(num, column1);
        }
        if (SQLUtils.nameEquals("MM", methodInvokeExpr.getMethodName())) {
            String shardingKey = getShardingKey(methodInvokeExpr);
            SimpleColumnInfo column1 = Objects.requireNonNull(tableHandler.getColumnByName(shardingKey));
            tableShardingKeys.add(shardingKey);
            tableFunction = specilizemm(num, column1);
        }
        if ("STR_HASH".equalsIgnoreCase(methodInvokeExpr.getMethodName())) {
            String shardingKey = getShardingKey(methodInvokeExpr);
            SimpleColumnInfo column1 = Objects.requireNonNull(tableHandler.getColumnByName(shardingKey));
            tableShardingKeys.add(shardingKey);
            List<SQLExpr> arguments = methodInvokeExpr.getArguments();
            int startIndex;
            int endIndex;
            int valType;
            int randSeed;
            if (arguments.size() >= 3) {
                startIndex = Integer.parseInt(Objects.toString(arguments.get(1)));
                endIndex = Integer.parseInt(Objects.toString(arguments.get(2)));
            } else {
                startIndex = -1;
                endIndex = -1;
            }
            if (arguments.size() >= 4) {
                valType = Integer.parseInt(Objects.toString(arguments.get(3)));
            } else {
                valType = 0;
            }
            if (arguments.size() >= 5) {
                randSeed = Integer.parseInt(Objects.toString(arguments.get(4)));
            } else {
                randSeed = 31;
            }
            tableFunction = specilizeStrHash(num, startIndex, endIndex, valType, randSeed, column1);
        }
    }
    if (flattenMapping) {
        String needMethodName = SQLUtils.normalize(dbMethod.getMethodName().toUpperCase());
        String tableShardingKey = Objects.requireNonNull(getShardingKey(tableMethod));
        SimpleColumnInfo tableColumn = tableHandler.getColumnByName(tableShardingKey);
        int total = dbNum * tableNum;
        if (SQLUtils.nameEquals("MOD_HASH", needMethodName)) {
            ToIntFunction<Object> core = specilizeSingleModHash(total, tableColumn);
            tableFunction = core;
            dbFunction = value -> core.applyAsInt(value) / tableNum;
        } else if (SQLUtils.nameEquals("UNI_HASH", needMethodName)) {
            ToIntFunction<Object> core = specilizeSingleModHash(dbNum, tableColumn);
            dbFunction = core;
            tableFunction = value -> {
                int coreIndex = core.applyAsInt(value);
                return coreIndex * tableNum + coreIndex % tableNum;
            };
        } else if (SQLUtils.nameEquals("RIGHT_SHIFT", needMethodName)) {
            int shift = Integer.parseInt(getShardingKey(dbMethod, 1));
            ToIntFunction<Object> core = specilizeSingleRightShift(dbNum, shift, tableColumn);
            dbFunction = core;
            tableFunction = value -> {
                int coreIndex = core.applyAsInt(value);
                return coreIndex * tableNum + coreIndex % tableNum;
            };
        } else if (SQLUtils.nameEquals("YYYYMM", needMethodName)) {
            ToIntFunction<Object> core = specilizeyyyymm(total, tableColumn);
            tableFunction = core;
            dbFunction = value -> core.applyAsInt(value) / tableNum;
        } else if (SQLUtils.nameEquals("YYYYDD", needMethodName)) {
            ToIntFunction<Object> core = specilizeyyyydd(total, tableColumn);
            tableFunction = core;
            dbFunction = value -> core.applyAsInt(value) / tableNum;
        } else if (SQLUtils.nameEquals("YYYYWEEK", needMethodName)) {
            ToIntFunction<Object> core = specilizeyyyyWeek(total, tableColumn);
            tableFunction = core;
            dbFunction = value -> core.applyAsInt(value) / tableNum;
        }
    }
    final boolean finalFlattenMapping = flattenMapping;
    final ToIntFunction<Object> finalDbFunction = dbFunction;
    final ToIntFunction<Object> finalTableFunction = tableFunction;
    List<Partition> indexDataNodes = Optional.ofNullable(tableHandler.dataNodes()).map(i -> new ArrayList<>(i)).orElse(new ArrayList<>());
    if (indexDataNodes.isEmpty()) {
        List<int[]> seq = new ArrayList<>();
        int tableCount = 0;
        for (int dbIndex = 0; dbIndex < dbNum; dbIndex++) {
            for (int tableIndex = 0; tableIndex < tableNum; tableCount++, tableIndex++) {
                seq.add(new int[] { dbIndex, tableIndex, tableCount });
            }
        }
        SimpleTemplateEngine templateEngine = new SimpleTemplateEngine();
        Template template = templateEngine.createTemplate(mappingFormat);
        HashMap<String, Object> context = new HashMap<>(properties);
        for (int i = 0; i < seq.size(); i++) {
            int seqIndex = i / storeDbNum;
            int[] ints = seq.get(i);
            int currentDbIndex = ints[0];
            int currentTableIndex = ints[1];
            int currentTableCount = ints[2];
            context.put("targetIndex", String.valueOf(seqIndex));
            context.put("dbIndex", String.valueOf(currentDbIndex));
            context.put("tableIndex", String.valueOf(currentTableIndex));
            context.put("index", String.valueOf(currentTableCount));
            StringWriter stringWriter = new StringWriter();
            template.make(context).writeTo(stringWriter);
            String[] strings = SplitUtil.split(stringWriter.getBuffer().toString(), sep);
            IndexDataNode backendTableInfo = new IndexDataNode(strings[0], strings[1], strings[2], currentDbIndex, currentTableIndex, currentTableCount);
            indexDataNodes.add(backendTableInfo);
        }
    }
    ShardingTableType shardingTableType = ShardingTableType.computeByName(indexDataNodes);
    if (flattenMapping) {
        Map<Integer, List<Partition>> dbIndexToNode = indexDataNodes.stream().collect(Collectors.groupingBy(k -> k.getDbIndex()));
        return new AutoFunction(dbNum, tableNum, dbMethod, tableMethod, dbShardingKeys, tableShardingKeys, finalDbFunction, finalTableFunction, storeNum) {

            @Override
            public ShardingTableType getShardingTableType() {
                return shardingTableType;
            }

            @Override
            public List<Partition> scanAll() {
                return ImmutableList.copyOf(indexDataNodes);
            }

            @Override
            public List<Partition> scanOnlyTableIndex(int index) {
                return ImmutableList.of(indexDataNodes.get(index));
            }

            @Override
            public List<Partition> scanOnlyDbIndex(int index) {
                return dbIndexToNode.get(index);
            }

            @Override
            public List<Partition> scanOnlyDbTableIndex(int dbIndex, int tableIndex) {
                return scanOnlyTableIndex(tableIndex);
            }

            @Override
            public boolean isFlattenMapping() {
                return true;
            }

            @Override
            public boolean isShardingDbEnum() {
                return dbEnum;
            }

            @Override
            public boolean isShardingTableEnum() {
                return tableEnum;
            }
        };
    } else {
        Map<Integer, List<Partition>> dbIndexToNode = indexDataNodes.stream().collect(Collectors.groupingBy(k -> k.getDbIndex()));
        Map<Integer, List<Partition>> tableIndexToNode = indexDataNodes.stream().collect(Collectors.groupingBy(k -> k.getTableIndex()));
        return new AutoFunction(dbNum, tableNum, dbMethod, tableMethod, dbShardingKeys, tableShardingKeys, finalDbFunction, finalTableFunction, storeNum) {

            @Override
            public ShardingTableType getShardingTableType() {
                return shardingTableType;
            }

            @Override
            public List<Partition> scanAll() {
                return ImmutableList.copyOf(indexDataNodes);
            }

            @Override
            public List<Partition> scanOnlyTableIndex(int index) {
                return ImmutableList.copyOf(tableIndexToNode.get(index));
            }

            @Override
            public List<Partition> scanOnlyDbIndex(int index) {
                return ImmutableList.copyOf(dbIndexToNode.get(index));
            }

            @Override
            public List<Partition> scanOnlyDbTableIndex(int dbIndex, int tableIndex) {
                List<Partition> dataNodes = Objects.requireNonNull(dbIndexToNode.get(dbIndex));
                for (Partition dataNode : dataNodes) {
                    if (dataNode.getTableIndex() == tableIndex) {
                        return ImmutableList.of(dataNode);
                    }
                }
                return dataNodes;
            }

            @Override
            public boolean isFlattenMapping() {
                return false;
            }

            @Override
            public boolean isShardingDbEnum() {
                return dbEnum;
            }

            @Override
            public boolean isShardingTableEnum() {
                return tableEnum;
            }
        };
    }
}
Also used : ShardingTableType(io.mycat.ShardingTableType) java.util(java.util) CustomRuleFunction(io.mycat.router.CustomRuleFunction) LocalDateTime(java.time.LocalDateTime) SimpleColumnInfo(io.mycat.SimpleColumnInfo) ShardingTableHandler(io.mycat.router.ShardingTableHandler) Partition(io.mycat.Partition) ImmutableList(com.google.common.collect.ImmutableList) ShardingFunction(io.mycat.config.ShardingFunction) Duration(java.time.Duration) Template(groovy.text.Template) SplitUtil(io.mycat.util.SplitUtil) WeekFields(java.time.temporal.WeekFields) SQLUtils(com.alibaba.druid.sql.SQLUtils) SQLMethodInvokeExpr(com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr) ImmutableSet(com.google.common.collect.ImmutableSet) StringWriter(java.io.StringWriter) ToIntFunction(java.util.function.ToIntFunction) SQLExpr(com.alibaba.druid.sql.ast.SQLExpr) Collectors(java.util.stream.Collectors) lombok(lombok) Nullable(org.jetbrains.annotations.Nullable) SQLExprParser(com.alibaba.druid.sql.parser.SQLExprParser) LocalDate(java.time.LocalDate) NotNull(org.jetbrains.annotations.NotNull) SimpleTemplateEngine(groovy.text.SimpleTemplateEngine) SQLMethodInvokeExpr(com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr) Template(groovy.text.Template) SimpleColumnInfo(io.mycat.SimpleColumnInfo) StringWriter(java.io.StringWriter) ImmutableList(com.google.common.collect.ImmutableList) SimpleTemplateEngine(groovy.text.SimpleTemplateEngine) ShardingTableType(io.mycat.ShardingTableType) Partition(io.mycat.Partition) SQLExpr(com.alibaba.druid.sql.ast.SQLExpr) ToIntFunction(java.util.function.ToIntFunction)

Aggregations

ShardingTableHandler (io.mycat.router.ShardingTableHandler)7 ImmutableList (com.google.common.collect.ImmutableList)2 MycatView (io.mycat.calcite.logical.MycatView)2 MycatHashAggregate (io.mycat.calcite.physical.MycatHashAggregate)2 CustomRuleFunction (io.mycat.router.CustomRuleFunction)2 java.util (java.util)2 Collectors (java.util.stream.Collectors)2 HepPlanner (org.apache.calcite.plan.hep.HepPlanner)2 HepProgramBuilder (org.apache.calcite.plan.hep.HepProgramBuilder)2 RelNode (org.apache.calcite.rel.RelNode)2 RelHint (org.apache.calcite.rel.hint.RelHint)2 RelColumnOrigin (org.apache.calcite.rel.metadata.RelColumnOrigin)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 SQLExprTableSource (com.alibaba.druid.sql.ast.statement.SQLExprTableSource)1 MySqlCheckTableStatement (com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCheckTableStatement)1 SQLExprParser (com.alibaba.druid.sql.parser.SQLExprParser)1 ImmutableSet (com.google.common.collect.ImmutableSet)1 SimpleTemplateEngine (groovy.text.SimpleTemplateEngine)1