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());
}
}
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;
}
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();
}
Aggregations