use of org.apache.calcite.rel.mutable.MutableRel in project calcite by apache.
the class SubstitutionVisitor method unifyAggregates.
public static MutableRel unifyAggregates(MutableAggregate query, MutableAggregate target) {
if (query.getGroupType() != Aggregate.Group.SIMPLE || target.getGroupType() != Aggregate.Group.SIMPLE) {
throw new AssertionError(Bug.CALCITE_461_FIXED);
}
MutableRel result;
if (query.groupSet.equals(target.groupSet)) {
// Same level of aggregation. Generate a project.
final List<Integer> projects = Lists.newArrayList();
final int groupCount = query.groupSet.cardinality();
for (int i = 0; i < groupCount; i++) {
projects.add(i);
}
for (AggregateCall aggregateCall : query.aggCalls) {
int i = target.aggCalls.indexOf(aggregateCall);
if (i < 0) {
return null;
}
projects.add(groupCount + i);
}
result = MutableRels.createProject(target, projects);
} else {
// Target is coarser level of aggregation. Generate an aggregate.
final ImmutableBitSet.Builder groupSet = ImmutableBitSet.builder();
final List<Integer> targetGroupList = target.groupSet.asList();
for (int c : query.groupSet) {
int c2 = targetGroupList.indexOf(c);
if (c2 < 0) {
return null;
}
groupSet.set(c2);
}
final List<AggregateCall> aggregateCalls = Lists.newArrayList();
for (AggregateCall aggregateCall : query.aggCalls) {
if (aggregateCall.isDistinct()) {
return null;
}
int i = target.aggCalls.indexOf(aggregateCall);
if (i < 0) {
return null;
}
aggregateCalls.add(AggregateCall.create(getRollup(aggregateCall.getAggregation()), aggregateCall.isDistinct(), aggregateCall.isApproximate(), ImmutableList.of(target.groupSet.cardinality() + i), -1, aggregateCall.type, aggregateCall.name));
}
result = MutableAggregate.of(target, groupSet.build(), null, aggregateCalls);
}
return MutableRels.createCastRel(result, query.rowType, true);
}
use of org.apache.calcite.rel.mutable.MutableRel in project calcite by apache.
the class SubstitutionVisitor method go0.
public RelNode go0(RelNode replacement_) {
// not called
assert false;
MutableRel replacement = MutableRels.toMutable(replacement_);
assert equalType("target", target, "replacement", replacement, Litmus.THROW);
replacementMap.put(target, replacement);
final UnifyResult unifyResult = matchRecurse(target);
if (unifyResult == null) {
return null;
}
final MutableRel node0 = unifyResult.result;
// replaceAncestors(node0);
MutableRel node = node0;
if (DEBUG) {
System.out.println("Convert: query:\n" + query.deep() + "\nunify.query:\n" + unifyResult.call.query.deep() + "\nunify.result:\n" + unifyResult.result.deep() + "\nunify.target:\n" + unifyResult.call.target.deep() + "\nnode0:\n" + node0.deep() + "\nnode:\n" + node.deep());
}
return MutableRels.fromMutable(node, relBuilder);
}
use of org.apache.calcite.rel.mutable.MutableRel in project calcite by apache.
the class SubstitutionVisitor method go.
/**
* Substitutes the query with replacement whenever possible but meanwhile
* keeps track of all the substitutions and their original rel before
* replacement, so that in later processing stage, the replacement can be
* recovered individually to produce a list of all possible rels with
* substitution in different places.
*/
private List<List<Replacement>> go(MutableRel replacement) {
assert equalType("target", target, "replacement", replacement, Litmus.THROW);
final List<MutableRel> queryDescendants = MutableRels.descendants(query);
final List<MutableRel> targetDescendants = MutableRels.descendants(target);
// Populate "equivalents" with (q, t) for each query descendant q and
// target descendant t that are equal.
final Map<MutableRel, MutableRel> map = Maps.newHashMap();
for (MutableRel queryDescendant : queryDescendants) {
map.put(queryDescendant, queryDescendant);
}
for (MutableRel targetDescendant : targetDescendants) {
MutableRel queryDescendant = map.get(targetDescendant);
if (queryDescendant != null) {
assert queryDescendant.rowType.equals(targetDescendant.rowType);
equivalents.put(queryDescendant, targetDescendant);
}
}
map.clear();
final List<Replacement> attempted = Lists.newArrayList();
List<List<Replacement>> substitutions = Lists.newArrayList();
for (; ; ) {
int count = 0;
MutableRel queryDescendant = query;
outer: while (queryDescendant != null) {
for (Replacement r : attempted) {
if (queryDescendant == r.after) {
// This node has been replaced by previous iterations in the
// hope to match its ancestors, so the node itself should not
// be matched again.
queryDescendant = MutableRels.preOrderTraverseNext(queryDescendant);
continue outer;
}
}
final MutableRel next = MutableRels.preOrderTraverseNext(queryDescendant);
final MutableRel childOrNext = queryDescendant.getInputs().isEmpty() ? next : queryDescendant.getInputs().get(0);
for (MutableRel targetDescendant : targetDescendants) {
for (UnifyRule rule : applicableRules(queryDescendant, targetDescendant)) {
UnifyRuleCall call = rule.match(this, queryDescendant, targetDescendant);
if (call != null) {
final UnifyResult result = rule.apply(call);
if (result != null) {
++count;
attempted.add(new Replacement(result.call.query, result.result));
MutableRel parent = result.call.query.replaceInParent(result.result);
// the tree.
for (int i = 0; i < rule.slotCount; i++) {
Collection<MutableRel> equi = equivalents.get(slots[i]);
if (!equi.isEmpty()) {
equivalents.remove(slots[i], equi.iterator().next());
}
}
assert result.result.rowType.equals(result.call.query.rowType) : Pair.of(result.result, result.call.query);
equivalents.put(result.result, result.call.query);
if (targetDescendant == target) {
// to the next subtree in pre-order traversal.
if (!target.equals(replacement)) {
Replacement r = replace(query.getInput(), target, replacement.clone());
assert r != null : rule + "should have returned a result containing the target.";
attempted.add(r);
}
substitutions.add(ImmutableList.copyOf(attempted));
attempted.clear();
queryDescendant = next;
continue outer;
}
// attempt.
break outer;
}
}
}
}
queryDescendant = childOrNext;
}
// thus count == 0 && !attempted.isEmpty().
if (count == 0 || attempted.isEmpty()) {
break;
}
}
if (!attempted.isEmpty()) {
// We had done some replacement attempt in the previous walk, but that
// did not lead to any substitutions in this walk, so we need to recover
// the replacement.
undoReplacement(attempted);
}
return substitutions;
}
use of org.apache.calcite.rel.mutable.MutableRel in project calcite by apache.
the class SubstitutionVisitor method isWeaker.
/**
* Returns if one rel is weaker than another.
*/
protected boolean isWeaker(MutableRel rel0, MutableRel rel) {
if (rel0 == rel || equivalents.get(rel0).contains(rel)) {
return false;
}
if (!(rel0 instanceof MutableFilter) || !(rel instanceof MutableFilter)) {
return false;
}
if (!rel.rowType.equals(rel0.rowType)) {
return false;
}
final MutableRel rel0input = ((MutableFilter) rel0).getInput();
final MutableRel relinput = ((MutableFilter) rel).getInput();
if (rel0input != relinput && !equivalents.get(rel0input).contains(relinput)) {
return false;
}
RexExecutorImpl rexImpl = (RexExecutorImpl) (rel.cluster.getPlanner().getExecutor());
RexImplicationChecker rexImplicationChecker = new RexImplicationChecker(rel.cluster.getRexBuilder(), rexImpl, rel.rowType);
return rexImplicationChecker.implies(((MutableFilter) rel0).condition, ((MutableFilter) rel).condition);
}
use of org.apache.calcite.rel.mutable.MutableRel in project calcite by apache.
the class MutableRelTest method checkConvertMutableRel.
/**
* Verifies that after conversion to and from a MutableRel, the new
* RelNode remains identical to the original RelNode.
*/
private static void checkConvertMutableRel(String rel, String sql, boolean decorrelate, List<RelOptRule> rules) {
final SqlToRelTestBase test = new SqlToRelTestBase() {
};
RelNode origRel = test.createTester().convertSqlToRel(sql).rel;
if (decorrelate) {
final RelBuilder relBuilder = RelFactories.LOGICAL_BUILDER.create(origRel.getCluster(), null);
origRel = RelDecorrelator.decorrelateQuery(origRel, relBuilder);
}
if (rules != null) {
final HepProgram hepProgram = new HepProgramBuilder().addRuleCollection(rules).build();
final HepPlanner hepPlanner = new HepPlanner(hepProgram);
hepPlanner.setRoot(origRel);
origRel = hepPlanner.findBestExp();
}
// Convert to and from a mutable rel.
final MutableRel mutableRel = MutableRels.toMutable(origRel);
final RelNode newRel = MutableRels.fromMutable(mutableRel);
// Check if the mutable rel digest contains the target rel.
final String mutableRelStr = mutableRel.deep();
final String msg1 = "Mutable rel: " + mutableRelStr + " does not contain target rel: " + rel;
Assert.assertTrue(msg1, mutableRelStr.contains(rel));
// Check if the mutable rel's row-type is identical to the original
// rel's row-type.
final RelDataType origRelType = origRel.getRowType();
final RelDataType mutableRelType = mutableRel.rowType;
final String msg2 = "Mutable rel's row type does not match with the original rel.\n" + "Original rel type: " + origRelType + ";\nMutable rel type: " + mutableRelType;
Assert.assertTrue(msg2, RelOptUtil.equal("origRelType", origRelType, "mutableRelType", mutableRelType, Litmus.IGNORE));
// Check if the new rel converted from the mutable rel is identical
// to the original rel.
final String origRelStr = RelOptUtil.toString(origRel);
final String newRelStr = RelOptUtil.toString(newRel);
final String msg3 = "The converted new rel is different from the original rel.\n" + "Original rel: " + origRelStr + ";\nNew rel: " + newRelStr;
Assert.assertEquals(msg3, origRelStr, newRelStr);
}
Aggregations