use of io.mycat.calcite.logical.MycatView 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);
}
}
}
use of io.mycat.calcite.logical.MycatView in project Mycat2 by MyCATApache.
the class SQLRBORewriter method project.
public static Optional<RelNode> project(RelNode original, Project project) {
Distribution dataNodeInfo = null;
RelNode input = original;
MycatView mycatView = null;
if (RexUtil.isIdentity(project.getProjects(), original.getRowType())) {
// ProjectRemoveRule
return Optional.empty();
}
if (input instanceof MycatView) {
dataNodeInfo = ((MycatView) input).getDistribution();
mycatView = (MycatView) original;
input = ((MycatView) input).getRelNode();
if (mycatView.banPushdown() && !(input instanceof Aggregate)) {
return Optional.empty();
}
if (project.containsOver()) {
if (dataNodeInfo.type() == Distribution.Type.PHY || (dataNodeInfo.type() == Distribution.Type.BROADCAST)) {
input = project.copy(project.getTraitSet(), ImmutableList.of(input));
return Optional.of(mycatView.changeTo(input, dataNodeInfo));
}
}
}
if (input instanceof QueryBuilder) {
QueryBuilder queryBuilder = (QueryBuilder) input;
Optional<QueryBuilder> builder = queryBuilder.project(ImmutableIntList.identity(project.getRowType().getFieldCount()).toIntArray());
return (Optional) builder;
}
input = project.copy(project.getTraitSet(), ImmutableList.of(input));
if (mycatView != null) {
return Optional.of(mycatView.changeTo(input, dataNodeInfo));
} else {
return Optional.empty();
}
}
use of io.mycat.calcite.logical.MycatView in project Mycat2 by MyCATApache.
the class SQLRBORewriter method sort.
public static Optional<RelNode> sort(RelNode original, Sort sort) {
RelNode input = original;
MycatView view = null;
Distribution dataNodeInfo = null;
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 (input instanceof QueryBuilder) {
RexNode fetchRex = sort.fetch;
RexNode offsetRex = sort.offset;
Long fetchNumber = Long.MAX_VALUE;
Long offsetNumber = 0L;
RelCollation collation = sort.getCollation();
QueryBuilder mycatCustomTable = (QueryBuilder) input;
if (fetchRex instanceof RexLiteral) {
Object fetchValue = ((RexLiteral) fetchRex).getValue();
if (fetchValue != null && fetchValue instanceof Number) {
fetchNumber = ((Number) fetchValue).longValue();
}
}
if (offsetRex instanceof RexLiteral) {
Object offsetValue = ((RexLiteral) offsetRex).getValue();
if (offsetValue != null && offsetValue instanceof Number) {
offsetNumber = ((Number) offsetValue).longValue();
}
}
Optional<QueryBuilder> queryBuilder = mycatCustomTable.sort(offsetNumber, fetchNumber, collation);
if (queryBuilder.isPresent()) {
return Optional.of(queryBuilder.get());
}
return Optional.of(sort.copy(sort.getTraitSet().replace(MycatConvention.INSTANCE), mycatCustomTable, collation));
}
if (dataNodeInfo.type() == Distribution.Type.PHY || dataNodeInfo.type() == Distribution.Type.BROADCAST) {
input = sort.copy(input.getTraitSet(), ImmutableList.of(input));
return Optional.of(view.changeTo(input, dataNodeInfo));
} else {
if (sort.offset == null && sort.fetch == null) {
input = LogicalSort.create(input, sort.getCollation(), null, null);
input = view.changeTo(LocalSort.create((LogicalSort) input, ((LogicalSort) input).getInput()), dataNodeInfo);
return Optional.of(input);
}
RexBuilder rexBuilder = MycatCalciteSupport.INSTANCE.RexBuilder;
RexNode rexNode;
if (sort.offset == null && sort.fetch != null) {
rexNode = sort.fetch;
} else if (sort.offset != null && sort.fetch == null) {
rexNode = sort.offset;
} else {
if (sort.offset instanceof RexLiteral && sort.fetch instanceof RexLiteral) {
BigDecimal decimal = ((RexLiteral) sort.offset).getValueAs(BigDecimal.class).add(((RexLiteral) sort.fetch).getValueAs(BigDecimal.class));
rexNode = rexBuilder.makeExactLiteral(decimal);
} else {
rexNode = rexBuilder.makeCall(SqlStdOperatorTable.PLUS, sort.offset, sort.fetch);
}
}
input = LogicalSort.create(input, sort.getCollation(), rexBuilder.makeExactLiteral(BigDecimal.ZERO), rexNode);
input = view.changeTo(LocalSort.create((LogicalSort) input, ((LogicalSort) input).getInput()), dataNodeInfo);
return Optional.of(input);
}
}
use of io.mycat.calcite.logical.MycatView in project Mycat2 by MyCATApache.
the class SQLRBORewriter method filter.
public static Optional<RelNode> filter(RelNode original, Filter filter) {
RelNode input = original;
Distribution dataNodeInfo = null;
MycatView view = null;
if (input instanceof MycatView) {
dataNodeInfo = ((MycatView) input).getDistribution();
view = (MycatView) original;
if (view.banPushdown()) {
return Optional.empty();
}
input = ((MycatView) input).getRelNode();
}
if (input instanceof TableScan) {
RexNode condition = filter.getCondition();
RelOptTable table = input.getTable();
MycatLogicTable mycatTable = table.unwrap(MycatLogicTable.class);
return Optional.of(MycatView.ofCondition(filter.copy(filter.getTraitSet(), input, condition), mycatTable.createDistribution(), (condition)));
}
if (input instanceof QueryBuilder) {
QueryBuilder queryBuilder = (QueryBuilder) input;
return (Optional<RelNode>) (Optional) queryBuilder.filter(filter.getCondition());
}
filter = (Filter) filter.copy(filter.getTraitSet(), ImmutableList.of(input));
if (view != null) {
return Optional.of(view.changeTo(filter, dataNodeInfo));
} else {
return Optional.empty();
}
}
use of io.mycat.calcite.logical.MycatView in project Mycat2 by MyCATApache.
the class SQLRBORewriter method view.
public static Optional<RelNode> view(List<RelNode> inputs, Union union) {
List<RelNode> backup = new ArrayList<>(inputs);
List<RelNode> children = new ArrayList<>();
for (RelNode input : inputs) {
if (input instanceof LogicalUnion) {
Union bottomUnion = (Union) input;
children.addAll(bottomUnion.getInputs());
} else {
children.add(input);
}
}
inputs = children;
List<MycatView> inputViews = new LinkedList<>();
List<RelNode> newViews = new ArrayList<>();
List<RelNode> others = new ArrayList<>();
for (RelNode input : inputs) {
if (input instanceof MycatView && !((MycatView) input).banPushdown()) {
MycatView curView = (MycatView) input;
if (curView.getDistribution().type() == Distribution.Type.SHARDING) {
if (!unionAllInPartitonKey(curView)) {
return Optional.empty();
}
}
inputViews.add((MycatView) input);
} else {
others.add(input);
}
}
if (inputViews.isEmpty()) {
return Optional.empty();
}
if (inputViews.size() > 1 && inputViews.stream().mapToInt(i -> i.getDistribution().getShardingTables().size()).sum() < 2) {
MycatView left = inputViews.get(0);
List<MycatView> matchViews = new ArrayList<>();
matchViews.add(left);
List<MycatView> failViews = new ArrayList<>();
Distribution distribution = null;
for (MycatView right : inputViews.subList(1, inputViews.size())) {
Optional<Distribution> distributionOptional = left.getDistribution().join(right.getDistribution());
if (distributionOptional.isPresent()) {
distribution = distributionOptional.get();
Distribution.Type type = distribution.type();
if (type == Distribution.Type.PHY || type == Distribution.Type.BROADCAST) {
matchViews.add(right);
continue;
} else if (type == Distribution.Type.SHARDING && unionAllInPartitonKey(left) && unionAllInPartitonKey(right) && left.getDistribution().getTargets().equals(right.getDistribution().getTargets())) {
matchViews.add(right);
continue;
}
}
failViews.add(right);
}
if (distribution != null) {
newViews.add(left.changeTo(union.copy(union.getTraitSet(), (List) matchViews.stream().map(i -> i.getRelNode()).collect(Collectors.toList())), distribution));
} else {
newViews.addAll(matchViews);
}
newViews.addAll(failViews);
} else {
newViews.addAll(inputViews);
}
inputs = (List) ImmutableList.builder().addAll(newViews).addAll(others).build();
if (inputs.size() == 1) {
return Optional.of(inputs.get(0));
}
if (backup.equals(inputs)) {
return Optional.empty();
}
return Optional.of(union.copy(union.getTraitSet(), inputs));
}
Aggregations