Search in sources :

Example 1 with ParamHolder

use of io.mycat.calcite.spm.ParamHolder in project Mycat2 by MyCATApache.

the class AsyncMycatDataContextImpl method getSqlMap.

public static List<PartitionGroup> getSqlMap(Map<RexNode, RexNode> constantMap, MycatView view, DrdsSqlWithParams drdsSqlWithParams, Optional<List<PartitionGroup>> hintDataMapping) {
    Distribution distribution = view.getDistribution();
    Distribution.Type type = distribution.type();
    switch(type) {
        case BROADCAST:
            {
                Map<String, Partition> builder = new HashMap<>();
                String targetName = null;
                for (GlobalTable globalTable : distribution.getGlobalTables()) {
                    if (targetName == null) {
                        int i = ThreadLocalRandom.current().nextInt(0, globalTable.getGlobalDataNode().size());
                        Partition partition = globalTable.getGlobalDataNode().get(i);
                        targetName = partition.getTargetName();
                    }
                    builder.put(globalTable.getUniqueName(), globalTable.getDataNode());
                }
                return Collections.singletonList(new PartitionGroup(targetName, builder));
            }
        case PHY:
            Map<String, Partition> builder = new HashMap<>();
            String targetName = null;
            for (GlobalTable globalTable : distribution.getGlobalTables()) {
                builder.put(globalTable.getUniqueName(), globalTable.getDataNode());
            }
            for (NormalTable normalTable : distribution.getNormalTables()) {
                if (targetName == null) {
                    targetName = normalTable.getDataNode().getTargetName();
                }
                builder.put(normalTable.getUniqueName(), normalTable.getDataNode());
            }
            return Collections.singletonList(new PartitionGroup(targetName, builder));
        case SHARDING:
            if (hintDataMapping.isPresent()) {
                return hintDataMapping.get();
            }
            ShardingTable shardingTable = distribution.getShardingTables().get(0);
            RexBuilder rexBuilder = MycatCalciteSupport.RexBuilder;
            RexNode condition = view.getCondition().orElse(MycatCalciteSupport.RexBuilder.makeLiteral(true));
            List<RexNode> inputConditions = new ArrayList<>(constantMap.size() + 1);
            inputConditions.add(condition);
            for (Map.Entry<RexNode, RexNode> rexNodeRexNodeEntry : constantMap.entrySet()) {
                inputConditions.add(rexBuilder.makeCall(SqlStdOperatorTable.EQUALS, rexNodeRexNodeEntry.getKey(), rexNodeRexNodeEntry.getValue()));
            }
            ParamHolder paramHolder = ParamHolder.CURRENT_THREAD_LOCAL.get();
            paramHolder.setData(drdsSqlWithParams.getParams(), drdsSqlWithParams.getTypeNames());
            try {
                ArrayList<RexNode> res = new ArrayList<>(inputConditions.size());
                MycatRexExecutor.INSTANCE.reduce(rexBuilder, inputConditions, res);
                condition = res.get(0);
                ValuePredicateAnalyzer predicateAnalyzer = new ValuePredicateAnalyzer(shardingTable.keyMetas(true), shardingTable.getColumns().stream().map(i -> i.getColumnName()).collect(Collectors.toList()));
                Map<QueryType, List<ValueIndexCondition>> indexConditionMap = predicateAnalyzer.translateMatch(condition);
                List<Partition> partitions = ValueIndexCondition.getPartitions(shardingTable.getShardingFuntion(), indexConditionMap, drdsSqlWithParams.getParams());
                return mapSharding(view, partitions);
            } finally {
                paramHolder.clear();
            }
        default:
            throw new IllegalStateException("Unexpected value: " + distribution.type());
    }
}
Also used : ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) SqlString(org.apache.calcite.sql.util.SqlString) ValuePredicateAnalyzer(io.mycat.calcite.rewriter.ValuePredicateAnalyzer) GlobalTable(io.mycat.calcite.table.GlobalTable) RexBuilder(org.apache.calcite.rex.RexBuilder) ImmutableList(com.google.common.collect.ImmutableList) ShardingTable(io.mycat.calcite.table.ShardingTable) NormalTable(io.mycat.calcite.table.NormalTable) ParamHolder(io.mycat.calcite.spm.ParamHolder) Distribution(io.mycat.calcite.rewriter.Distribution) ConcurrentMap(java.util.concurrent.ConcurrentMap) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) QueryType(io.mycat.querycondition.QueryType) RexNode(org.apache.calcite.rex.RexNode)

Example 2 with ParamHolder

use of io.mycat.calcite.spm.ParamHolder in project Mycat2 by MyCATApache.

the class MycatView method estimateRowCount.

@Override
public double estimateRowCount(RelMetadataQuery mq) {
    if (relNode instanceof Sort) {
        Sort relNode = (Sort) this.relNode;
        ParamHolder paramHolder = ParamHolder.CURRENT_THREAD_LOCAL.get();
        List<Object> params = paramHolder.getParams();
        if (params != null && !params.isEmpty()) {
            RexNode fetch = relNode.fetch;
            RexNode offset = relNode.offset;
            Long fetchValue = null;
            if (fetch != null && fetch instanceof RexCall && fetch.isA(SqlKind.PLUS)) {
                List<RexNode> operands = ((RexCall) fetch).getOperands();
                Long one = resolveParam(params, operands.get(0));
                Long two = resolveParam(params, operands.get(1));
                if (one != null && two != null) {
                    fetchValue = one + two;
                }
            } else if (fetch instanceof RexLiteral) {
                fetchValue = resolveParam(params, fetch);
            }
            Long offsetValue = resolveParam(params, offset);
            if (offsetValue == null && fetchValue != null)
                return fetchValue;
            if (offsetValue != null && fetchValue != null)
                return fetchValue - offsetValue;
        }
    }
    List<IndexCondition> conditionOptional = getPredicateIndexCondition();
    double v = relNode.estimateRowCount(mq);
    if (!conditionOptional.isEmpty()) {
        IndexCondition indexCondition = conditionOptional.get(0);
        QueryType queryType = indexCondition.getQueryType();
        double factor = queryType.factor();
        switch(queryType) {
            case PK_POINT_QUERY:
                if (v > 1000) {
                    return 1000;
                } else {
                    return v;
                }
            case PK_RANGE_QUERY:
                return factor * v;
            case PK_FULL_SCAN:
                return factor * v;
        }
    }
    return v;
}
Also used : ParamHolder(io.mycat.calcite.spm.ParamHolder) MycatMergeSort(io.mycat.calcite.physical.MycatMergeSort) IndexCondition(io.mycat.calcite.rewriter.IndexCondition) QueryType(io.mycat.querycondition.QueryType)

Example 3 with ParamHolder

use of io.mycat.calcite.spm.ParamHolder in project Mycat2 by MyCATApache.

the class DrdsSqlWithParams method getHintDataNodeFilter.

public Optional<List<PartitionGroup>> getHintDataNodeFilter() {
    for (MycatHint hint : this.getHints()) {
        for (MycatHint.Function hintFunction : hint.getFunctions()) {
            if ("SCAN".equalsIgnoreCase(hintFunction.getName())) {
                List<MycatHint.Argument> arguments = hintFunction.getArguments();
                Map<String, List<String>> collect = arguments.stream().collect(Collectors.toMap(m -> SQLUtils.toSQLString(m.getName()), v -> Arrays.stream(SQLUtils.normalize(SQLUtils.toSQLString((v.getValue())).replace("'", "").replace("(", "").replace(")", "").trim()).split(",")).map(i -> SQLUtils.normalize(i)).collect(Collectors.toList())));
                NameMap<List<String>> nameMap = NameMap.immutableCopyOf(collect);
                List<String> condition = new LinkedList<>(Optional.ofNullable(nameMap.get("CONDITION", false)).orElse(Collections.emptyList()));
                List<String> logicalTables = new LinkedList<>(Optional.ofNullable(nameMap.get("TABLE", false)).orElse(Collections.emptyList()));
                List<List<String>> physicalTables = new LinkedList<>(Optional.ofNullable(nameMap.get("PARTITION", false)).orElse(Collections.emptyList()).stream().map(i -> Arrays.asList(i.split(","))).collect(Collectors.toList()));
                if (!physicalTables.isEmpty()) {
                    for (MycatHint.Argument argument : arguments) {
                        if ("PARTITION".equals(argument.getName().toString())) {
                            if (argument.getValue() instanceof SQLListExpr) {
                                physicalTables.clear();
                                SQLListExpr argumentValue = (SQLListExpr) argument.getValue();
                                for (Object o : argumentValue.getItems()) {
                                    ArrayList<String> objects = new ArrayList<>();
                                    physicalTables.add(objects);
                                    for (String s : Arrays.asList(SQLUtils.normalize(o.toString()).split(","))) {
                                        objects.add(SQLUtils.normalize(s));
                                    }
                                }
                            }
                        }
                    }
                }
                HashSet<String> targets = new HashSet<>(Optional.ofNullable(nameMap.get("TARGET", false)).orElse(Collections.emptyList()));
                Predicate<PartitionGroup> targetFilter = targets.isEmpty() ? (u) -> true : new Predicate<PartitionGroup>() {

                    @Override
                    public boolean test(PartitionGroup stringPartitionMap) {
                        String targetName = stringPartitionMap.getTargetName();
                        boolean contains = targets.contains(targetName);
                        return contains;
                    }
                };
                SQLStatement parameterizedStatement = this.getParameterizedStatement();
                Detector detector = new Detector();
                parameterizedStatement.accept(detector);
                if (logicalTables.isEmpty()) {
                    logicalTables.addAll(detector.tableHandlerMap.keySet());
                }
                if (condition.isEmpty()) {
                    condition.add("true");
                }
                if (!detector.isSharding) {
                    List<Partition> partitions = Collections.emptyList();
                    List<Partition> newPartitions = Collections.emptyList();
                    if (!logicalTables.isEmpty()) {
                        if (!condition.isEmpty()) {
                            String sql = "select * from " + logicalTables.get(0) + "where " + condition;
                            QueryPlanner queryPlanner = MetaClusterCurrent.wrapper(QueryPlanner.class);
                            DrdsSqlWithParams drdsSqlWithParams = DrdsRunnerHelper.preParse(sql, null);
                            CodeExecuterContext codeExecuterContext = queryPlanner.innerComputeMinCostCodeExecuterContext(drdsSqlWithParams);
                            List<PartitionGroup> collect2 = codeExecuterContext.getRelContext().values().stream().flatMap(i -> AsyncMycatDataContextImpl.getSqlMap(codeExecuterContext.getConstantMap(), i.getRelNode(), drdsSqlWithParams, Optional.empty()).stream()).filter(targetFilter).collect(Collectors.toList());
                            return Optional.of(collect2);
                        } else if (!physicalTables.isEmpty()) {
                            newPartitions = physicalTables.get(0).stream().map(dataNodeParser()).collect(Collectors.toList());
                        }
                        if (!targets.isEmpty()) {
                            newPartitions = partitions.stream().filter(dataNode -> {
                                return targets.contains(dataNode.getTargetName());
                            }).collect(Collectors.toList());
                        }
                        List<Partition> finalNewPartitions = newPartitions;
                        List<PartitionGroup> maps = finalNewPartitions.stream().map(i -> {
                            return new PartitionGroup(i.getTargetName(), ImmutableMap.of(logicalTables.get(0), i));
                        }).collect(Collectors.toList());
                        return Optional.of(maps);
                    }
                } else {
                    Map<String, List<Partition>> logicalPhysicalMap = new HashMap<>();
                    int physicalTableCount = 0;
                    if (!physicalTables.isEmpty()) {
                        int size = logicalTables.size();
                        for (int i = 0; i < size; i++) {
                            String alias = logicalTables.get(i);
                            List<Partition> phyTableList = physicalTables.get(i).stream().map(dataNodeParser()).collect(Collectors.toList());
                            physicalTableCount += phyTableList.size();
                            alias = detector.tableHandlerMap.get(alias).getUniqueName();
                            List<Partition> partitions = logicalPhysicalMap.computeIfAbsent(alias, s -> new ArrayList<>());
                            partitions.addAll(phyTableList);
                        }
                    }
                    if (!logicalTables.isEmpty() && !condition.isEmpty()) {
                        String where = condition.get(0);
                        SQLExpr oneSqlExpr = SQLUtils.toMySqlExpr(where);
                        List<SQLExpr> sqlExprs;
                        if (oneSqlExpr instanceof SQLBinaryOpExpr && ((SQLBinaryOpExpr) oneSqlExpr).getOperator() == SQLBinaryOperator.BooleanAnd) {
                            sqlExprs = SQLUtils.split((SQLBinaryOpExpr) oneSqlExpr);
                        } else {
                            sqlExprs = Collections.singletonList(oneSqlExpr);
                        }
                        Map<String, TableHandler> aliasTableMap = detector.tableHandlerMap;
                        int whereIndex = 0;
                        List<List<PartitionGroup>> partitionGroupMap = new ArrayList<>();
                        for (Map.Entry<String, TableHandler> e : aliasTableMap.entrySet()) {
                            TableHandler table = e.getValue();
                            String schemaName = table.getSchemaName();
                            String tableName = table.getTableName();
                            String sql = "select *  from `" + schemaName + "`.`" + tableName + "` as `" + e.getKey() + "` where " + ((whereIndex < sqlExprs.size()) ? sqlExprs.get(whereIndex).toString() : "true");
                            whereIndex++;
                            DrdsSqlWithParams hintSql = DrdsRunnerHelper.preParse(sql, null);
                            QueryPlanner planner = MetaClusterCurrent.wrapper(QueryPlanner.class);
                            ParamHolder paramHolder = ParamHolder.CURRENT_THREAD_LOCAL.get();
                            paramHolder.setData(hintSql.getParams(), hintSql.getTypeNames());
                            try {
                                CodeExecuterContext codeExecuterContext = planner.innerComputeMinCostCodeExecuterContext(hintSql);
                                partitionGroupMap.add(codeExecuterContext.getRelContext().values().stream().flatMap(i -> AsyncMycatDataContextImpl.getSqlMap(codeExecuterContext.getConstantMap(), i.getRelNode(), hintSql, Optional.empty()).stream()).filter(targetFilter).collect(Collectors.toList()));
                            } finally {
                                paramHolder.clear();
                            }
                        }
                        List<PartitionGroup> partitionGroups = partitionGroupMap.stream().reduce(new BinaryOperator<List<PartitionGroup>>() {

                            @Override
                            public List<PartitionGroup> apply(List<PartitionGroup> partitionGroups, List<PartitionGroup> partitionGroups2) {
                                for (PartitionGroup partitionGroup : partitionGroups) {
                                    Optional<PartitionGroup> first = partitionGroups2.stream().filter(i -> i.getTargetName().equals(partitionGroup.getTargetName())).findFirst();
                                    first.ifPresent(group -> partitionGroup.map.putAll(group.map));
                                }
                                return partitionGroups;
                            }
                        }).orElse(Collections.emptyList());
                        if (!logicalPhysicalMap.isEmpty()) {
                            int index = 0;
                            for (PartitionGroup group : new ArrayList<>(partitionGroups)) {
                                for (Map.Entry<String, Partition> entry : new ArrayList<>(group.getMap().entrySet())) {
                                    List<Partition> partitions = logicalPhysicalMap.get(entry.getKey());
                                    if (partitions == null)
                                        continue;
                                    if (index >= partitions.size()) {
                                        partitionGroups.remove(group);
                                        continue;
                                    }
                                    entry.setValue(partitions.get(index));
                                }
                                ++index;
                            }
                        }
                        return Optional.of(partitionGroups);
                    }
                }
            }
        }
    }
    return Optional.empty();
}
Also used : QueryPlanner(io.mycat.calcite.spm.QueryPlanner) java.util(java.util) LoggerFactory(org.slf4j.LoggerFactory) Function(java.util.function.Function) SQLBinaryOpExpr(com.alibaba.druid.sql.ast.expr.SQLBinaryOpExpr) SQLBinaryOperator(com.alibaba.druid.sql.ast.expr.SQLBinaryOperator) ParamHolder(io.mycat.calcite.spm.ParamHolder) SQLListExpr(com.alibaba.druid.sql.ast.expr.SQLListExpr) MySqlASTVisitorAdapter(com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitorAdapter) ImmutableMap(org.apache.curator.shaded.com.google.common.collect.ImmutableMap) ToString(lombok.ToString) SQLUtils(com.alibaba.druid.sql.SQLUtils) Logger(org.slf4j.Logger) SqlTypeName(org.apache.calcite.sql.type.SqlTypeName) Predicate(java.util.function.Predicate) SQLExpr(com.alibaba.druid.sql.ast.SQLExpr) Collectors(java.util.stream.Collectors) BinaryOperator(java.util.function.BinaryOperator) NameMap(io.mycat.util.NameMap) SQLNumericLiteralExpr(com.alibaba.druid.sql.ast.expr.SQLNumericLiteralExpr) CodeExecuterContext(io.mycat.calcite.CodeExecuterContext) DrdsRunnerHelper(io.mycat.calcite.DrdsRunnerHelper) SQLStatement(com.alibaba.druid.sql.ast.SQLStatement) MycatHint(io.mycat.calcite.MycatHint) NotNull(org.jetbrains.annotations.NotNull) SQLExprTableSource(com.alibaba.druid.sql.ast.statement.SQLExprTableSource) CodeExecuterContext(io.mycat.calcite.CodeExecuterContext) ToString(lombok.ToString) SQLStatement(com.alibaba.druid.sql.ast.SQLStatement) SQLBinaryOpExpr(com.alibaba.druid.sql.ast.expr.SQLBinaryOpExpr) SQLBinaryOperator(com.alibaba.druid.sql.ast.expr.SQLBinaryOperator) BinaryOperator(java.util.function.BinaryOperator) MycatHint(io.mycat.calcite.MycatHint) QueryPlanner(io.mycat.calcite.spm.QueryPlanner) MycatHint(io.mycat.calcite.MycatHint) SQLExpr(com.alibaba.druid.sql.ast.SQLExpr) ParamHolder(io.mycat.calcite.spm.ParamHolder) SQLListExpr(com.alibaba.druid.sql.ast.expr.SQLListExpr) ImmutableMap(org.apache.curator.shaded.com.google.common.collect.ImmutableMap) NameMap(io.mycat.util.NameMap)

Aggregations

ParamHolder (io.mycat.calcite.spm.ParamHolder)3 QueryType (io.mycat.querycondition.QueryType)2 SQLUtils (com.alibaba.druid.sql.SQLUtils)1 SQLExpr (com.alibaba.druid.sql.ast.SQLExpr)1 SQLStatement (com.alibaba.druid.sql.ast.SQLStatement)1 SQLBinaryOpExpr (com.alibaba.druid.sql.ast.expr.SQLBinaryOpExpr)1 SQLBinaryOperator (com.alibaba.druid.sql.ast.expr.SQLBinaryOperator)1 SQLListExpr (com.alibaba.druid.sql.ast.expr.SQLListExpr)1 SQLNumericLiteralExpr (com.alibaba.druid.sql.ast.expr.SQLNumericLiteralExpr)1 SQLExprTableSource (com.alibaba.druid.sql.ast.statement.SQLExprTableSource)1 MySqlASTVisitorAdapter (com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitorAdapter)1 ImmutableList (com.google.common.collect.ImmutableList)1 CodeExecuterContext (io.mycat.calcite.CodeExecuterContext)1 DrdsRunnerHelper (io.mycat.calcite.DrdsRunnerHelper)1 MycatHint (io.mycat.calcite.MycatHint)1 MycatMergeSort (io.mycat.calcite.physical.MycatMergeSort)1 Distribution (io.mycat.calcite.rewriter.Distribution)1 IndexCondition (io.mycat.calcite.rewriter.IndexCondition)1 ValuePredicateAnalyzer (io.mycat.calcite.rewriter.ValuePredicateAnalyzer)1 QueryPlanner (io.mycat.calcite.spm.QueryPlanner)1