Search in sources :

Example 1 with MutableRel

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);
}
Also used : AggregateCall(org.apache.calcite.rel.core.AggregateCall) ImmutableBitSet(org.apache.calcite.util.ImmutableBitSet) MutableRel(org.apache.calcite.rel.mutable.MutableRel)

Example 2 with MutableRel

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);
}
Also used : MutableRel(org.apache.calcite.rel.mutable.MutableRel)

Example 3 with MutableRel

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;
}
Also used : Collection(java.util.Collection) List(java.util.List) ArrayList(java.util.ArrayList) ImmutableList(com.google.common.collect.ImmutableList) MutableRel(org.apache.calcite.rel.mutable.MutableRel)

Example 4 with MutableRel

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);
}
Also used : RexExecutorImpl(org.apache.calcite.rex.RexExecutorImpl) MutableFilter(org.apache.calcite.rel.mutable.MutableFilter) MutableRel(org.apache.calcite.rel.mutable.MutableRel)

Example 5 with MutableRel

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);
}
Also used : RelBuilder(org.apache.calcite.tools.RelBuilder) HepProgram(org.apache.calcite.plan.hep.HepProgram) RelNode(org.apache.calcite.rel.RelNode) HepProgramBuilder(org.apache.calcite.plan.hep.HepProgramBuilder) RelDataType(org.apache.calcite.rel.type.RelDataType) HepPlanner(org.apache.calcite.plan.hep.HepPlanner) MutableRel(org.apache.calcite.rel.mutable.MutableRel)

Aggregations

MutableRel (org.apache.calcite.rel.mutable.MutableRel)6 ImmutableList (com.google.common.collect.ImmutableList)1 ArrayList (java.util.ArrayList)1 Collection (java.util.Collection)1 List (java.util.List)1 HepPlanner (org.apache.calcite.plan.hep.HepPlanner)1 HepProgram (org.apache.calcite.plan.hep.HepProgram)1 HepProgramBuilder (org.apache.calcite.plan.hep.HepProgramBuilder)1 RelNode (org.apache.calcite.rel.RelNode)1 AggregateCall (org.apache.calcite.rel.core.AggregateCall)1 MutableFilter (org.apache.calcite.rel.mutable.MutableFilter)1 RelDataType (org.apache.calcite.rel.type.RelDataType)1 RexExecutorImpl (org.apache.calcite.rex.RexExecutorImpl)1 RelBuilder (org.apache.calcite.tools.RelBuilder)1 ImmutableBitSet (org.apache.calcite.util.ImmutableBitSet)1