Search in sources :

Example 26 with RelOptCluster

use of org.apache.calcite.plan.RelOptCluster in project calcite by apache.

the class FrameworksTest method testOptimize.

@Test
public void testOptimize() {
    RelNode x = Frameworks.withPlanner(new Frameworks.PlannerAction<RelNode>() {

        public RelNode apply(RelOptCluster cluster, RelOptSchema relOptSchema, SchemaPlus rootSchema) {
            final RelDataTypeFactory typeFactory = cluster.getTypeFactory();
            final Table table = new AbstractTable() {

                public RelDataType getRowType(RelDataTypeFactory typeFactory) {
                    final RelDataType stringType = typeFactory.createJavaType(String.class);
                    final RelDataType integerType = typeFactory.createJavaType(Integer.class);
                    return typeFactory.builder().add("s", stringType).add("i", integerType).build();
                }
            };
            // "SELECT * FROM myTable"
            final RelOptAbstractTable relOptTable = new RelOptAbstractTable(relOptSchema, "myTable", table.getRowType(typeFactory)) {
            };
            final EnumerableTableScan tableRel = EnumerableTableScan.create(cluster, relOptTable);
            // "WHERE i > 1"
            final RexBuilder rexBuilder = cluster.getRexBuilder();
            final RexNode condition = rexBuilder.makeCall(SqlStdOperatorTable.GREATER_THAN, rexBuilder.makeFieldAccess(rexBuilder.makeRangeReference(tableRel), "i", true), rexBuilder.makeExactLiteral(BigDecimal.ONE));
            final LogicalFilter filter = LogicalFilter.create(tableRel, condition);
            // Specify that the result should be in Enumerable convention.
            final RelNode rootRel = filter;
            final RelOptPlanner planner = cluster.getPlanner();
            RelTraitSet desiredTraits = cluster.traitSet().replace(EnumerableConvention.INSTANCE);
            final RelNode rootRel2 = planner.changeTraits(rootRel, desiredTraits);
            planner.setRoot(rootRel2);
            // Now, plan.
            return planner.findBestExp();
        }
    });
    String s = RelOptUtil.dumpPlan("", x, SqlExplainFormat.TEXT, SqlExplainLevel.DIGEST_ATTRIBUTES);
    assertThat(Util.toLinux(s), equalTo("EnumerableFilter(condition=[>($1, 1)])\n" + "  EnumerableTableScan(table=[[myTable]])\n"));
}
Also used : RelOptCluster(org.apache.calcite.plan.RelOptCluster) RelOptSchema(org.apache.calcite.plan.RelOptSchema) RelOptAbstractTable(org.apache.calcite.plan.RelOptAbstractTable) Table(org.apache.calcite.schema.Table) AbstractTable(org.apache.calcite.schema.impl.AbstractTable) ModifiableTable(org.apache.calcite.schema.ModifiableTable) SqlStdOperatorTable(org.apache.calcite.sql.fun.SqlStdOperatorTable) RelOptTable(org.apache.calcite.plan.RelOptTable) ProjectableFilterableTable(org.apache.calcite.schema.ProjectableFilterableTable) LogicalFilter(org.apache.calcite.rel.logical.LogicalFilter) SchemaPlus(org.apache.calcite.schema.SchemaPlus) RelDataType(org.apache.calcite.rel.type.RelDataType) RelTraitSet(org.apache.calcite.plan.RelTraitSet) RelOptPlanner(org.apache.calcite.plan.RelOptPlanner) RelOptAbstractTable(org.apache.calcite.plan.RelOptAbstractTable) AbstractTable(org.apache.calcite.schema.impl.AbstractTable) RelNode(org.apache.calcite.rel.RelNode) EnumerableTableScan(org.apache.calcite.adapter.enumerable.EnumerableTableScan) RelDataTypeFactory(org.apache.calcite.rel.type.RelDataTypeFactory) RexBuilder(org.apache.calcite.rex.RexBuilder) RelOptAbstractTable(org.apache.calcite.plan.RelOptAbstractTable) RexNode(org.apache.calcite.rex.RexNode) Test(org.junit.Test)

Example 27 with RelOptCluster

use of org.apache.calcite.plan.RelOptCluster in project calcite by apache.

the class FrameworksTest method executeQuery.

private void executeQuery(FrameworkConfig config, @SuppressWarnings("SameParameterValue") String query, boolean debug) throws RelConversionException, SqlParseException, ValidationException {
    Planner planner = Frameworks.getPlanner(config);
    if (debug) {
        System.out.println("Query:" + query);
    }
    SqlNode n = planner.parse(query);
    n = planner.validate(n);
    RelNode root = planner.rel(n).project();
    if (debug) {
        System.out.println(RelOptUtil.dumpPlan("-- Logical Plan", root, SqlExplainFormat.TEXT, SqlExplainLevel.DIGEST_ATTRIBUTES));
    }
    RelOptCluster cluster = root.getCluster();
    final RelOptPlanner optPlanner = cluster.getPlanner();
    RelTraitSet desiredTraits = cluster.traitSet().replace(EnumerableConvention.INSTANCE);
    final RelNode newRoot = optPlanner.changeTraits(root, desiredTraits);
    if (debug) {
        System.out.println(RelOptUtil.dumpPlan("-- Mid Plan", newRoot, SqlExplainFormat.TEXT, SqlExplainLevel.DIGEST_ATTRIBUTES));
    }
    optPlanner.setRoot(newRoot);
    RelNode bestExp = optPlanner.findBestExp();
    if (debug) {
        System.out.println(RelOptUtil.dumpPlan("-- Best Plan", bestExp, SqlExplainFormat.TEXT, SqlExplainLevel.DIGEST_ATTRIBUTES));
    }
}
Also used : RelOptCluster(org.apache.calcite.plan.RelOptCluster) RelNode(org.apache.calcite.rel.RelNode) RelOptPlanner(org.apache.calcite.plan.RelOptPlanner) RelTraitSet(org.apache.calcite.plan.RelTraitSet) RelOptPlanner(org.apache.calcite.plan.RelOptPlanner) SqlNode(org.apache.calcite.sql.SqlNode)

Example 28 with RelOptCluster

use of org.apache.calcite.plan.RelOptCluster in project calcite by apache.

the class ProjectWindowTransposeRule method onMatch.

@Override
public void onMatch(RelOptRuleCall call) {
    final LogicalProject project = call.rel(0);
    final LogicalWindow window = call.rel(1);
    final RelOptCluster cluster = window.getCluster();
    final List<RelDataTypeField> rowTypeWindowInput = window.getInput().getRowType().getFieldList();
    final int windowInputColumn = rowTypeWindowInput.size();
    // Record the window input columns which are actually referred
    // either in the LogicalProject above LogicalWindow or LogicalWindow itself
    // (Note that the constants used in LogicalWindow are not considered here)
    final ImmutableBitSet beReferred = findReference(project, window);
    // it is impossible to trim anyone of them out
    if (beReferred.cardinality() == windowInputColumn) {
        return;
    }
    // Put a DrillProjectRel below LogicalWindow
    final List<RexNode> exps = new ArrayList<>();
    final RelDataTypeFactory.Builder builder = cluster.getTypeFactory().builder();
    // Keep only the fields which are referred
    for (int index : BitSets.toIter(beReferred)) {
        final RelDataTypeField relDataTypeField = rowTypeWindowInput.get(index);
        exps.add(new RexInputRef(index, relDataTypeField.getType()));
        builder.add(relDataTypeField);
    }
    final LogicalProject projectBelowWindow = new LogicalProject(cluster, window.getTraitSet(), window.getInput(), exps, builder.build());
    // Create a new LogicalWindow with necessary inputs only
    final List<Window.Group> groups = new ArrayList<>();
    // As the un-referred columns are trimmed by the LogicalProject,
    // the indices specified in LogicalWindow would need to be adjusted
    final RexShuttle indexAdjustment = new RexShuttle() {

        @Override
        public RexNode visitInputRef(RexInputRef inputRef) {
            final int newIndex = getAdjustedIndex(inputRef.getIndex(), beReferred, windowInputColumn);
            return new RexInputRef(newIndex, inputRef.getType());
        }

        @Override
        public RexNode visitCall(final RexCall call) {
            if (call instanceof Window.RexWinAggCall) {
                boolean[] update = { false };
                final List<RexNode> clonedOperands = visitList(call.operands, update);
                if (update[0]) {
                    return new Window.RexWinAggCall((SqlAggFunction) call.getOperator(), call.getType(), clonedOperands, ((Window.RexWinAggCall) call).ordinal, ((Window.RexWinAggCall) call).distinct);
                } else {
                    return call;
                }
            } else {
                return super.visitCall(call);
            }
        }
    };
    int aggCallIndex = windowInputColumn;
    final RelDataTypeFactory.Builder outputBuilder = cluster.getTypeFactory().builder();
    outputBuilder.addAll(projectBelowWindow.getRowType().getFieldList());
    for (Window.Group group : window.groups) {
        final ImmutableBitSet.Builder keys = ImmutableBitSet.builder();
        final List<RelFieldCollation> orderKeys = new ArrayList<>();
        final List<Window.RexWinAggCall> aggCalls = new ArrayList<>();
        // Adjust keys
        for (int index : group.keys) {
            keys.set(getAdjustedIndex(index, beReferred, windowInputColumn));
        }
        // Adjust orderKeys
        for (RelFieldCollation relFieldCollation : group.orderKeys.getFieldCollations()) {
            final int index = relFieldCollation.getFieldIndex();
            orderKeys.add(relFieldCollation.copy(getAdjustedIndex(index, beReferred, windowInputColumn)));
        }
        // Adjust Window Functions
        for (Window.RexWinAggCall rexWinAggCall : group.aggCalls) {
            aggCalls.add((Window.RexWinAggCall) rexWinAggCall.accept(indexAdjustment));
            final RelDataTypeField relDataTypeField = window.getRowType().getFieldList().get(aggCallIndex);
            outputBuilder.add(relDataTypeField);
            ++aggCallIndex;
        }
        groups.add(new Window.Group(keys.build(), group.isRows, group.lowerBound, group.upperBound, RelCollations.of(orderKeys), aggCalls));
    }
    final LogicalWindow newLogicalWindow = LogicalWindow.create(window.getTraitSet(), projectBelowWindow, window.constants, outputBuilder.build(), groups);
    // Modify the top LogicalProject
    final List<RexNode> topProjExps = new ArrayList<>();
    for (RexNode rexNode : project.getChildExps()) {
        topProjExps.add(rexNode.accept(indexAdjustment));
    }
    final LogicalProject newTopProj = project.copy(newLogicalWindow.getTraitSet(), newLogicalWindow, topProjExps, project.getRowType());
    if (ProjectRemoveRule.isTrivial(newTopProj)) {
        call.transformTo(newLogicalWindow);
    } else {
        call.transformTo(newTopProj);
    }
}
Also used : RelOptCluster(org.apache.calcite.plan.RelOptCluster) ImmutableBitSet(org.apache.calcite.util.ImmutableBitSet) ArrayList(java.util.ArrayList) RexCall(org.apache.calcite.rex.RexCall) LogicalWindow(org.apache.calcite.rel.logical.LogicalWindow) RelDataTypeFactory(org.apache.calcite.rel.type.RelDataTypeFactory) Window(org.apache.calcite.rel.core.Window) LogicalWindow(org.apache.calcite.rel.logical.LogicalWindow) RexShuttle(org.apache.calcite.rex.RexShuttle) RelDataTypeField(org.apache.calcite.rel.type.RelDataTypeField) RelFieldCollation(org.apache.calcite.rel.RelFieldCollation) RexInputRef(org.apache.calcite.rex.RexInputRef) LogicalProject(org.apache.calcite.rel.logical.LogicalProject) RexNode(org.apache.calcite.rex.RexNode)

Example 29 with RelOptCluster

use of org.apache.calcite.plan.RelOptCluster in project calcite by apache.

the class SemiJoinRule method perform.

protected void perform(RelOptRuleCall call, Project project, Join join, RelNode left, Aggregate aggregate) {
    final RelOptCluster cluster = join.getCluster();
    final RexBuilder rexBuilder = cluster.getRexBuilder();
    if (project != null) {
        final ImmutableBitSet bits = RelOptUtil.InputFinder.bits(project.getProjects(), null);
        final ImmutableBitSet rightBits = ImmutableBitSet.range(left.getRowType().getFieldCount(), join.getRowType().getFieldCount());
        if (bits.intersects(rightBits)) {
            return;
        }
    }
    final JoinInfo joinInfo = join.analyzeCondition();
    if (!joinInfo.rightSet().equals(ImmutableBitSet.range(aggregate.getGroupCount()))) {
        // By the way, neither a super-set nor a sub-set would work.
        return;
    }
    if (!joinInfo.isEqui()) {
        return;
    }
    final RelBuilder relBuilder = call.builder();
    relBuilder.push(left);
    switch(join.getJoinType()) {
        case INNER:
            final List<Integer> newRightKeyBuilder = Lists.newArrayList();
            final List<Integer> aggregateKeys = aggregate.getGroupSet().asList();
            for (int key : joinInfo.rightKeys) {
                newRightKeyBuilder.add(aggregateKeys.get(key));
            }
            final ImmutableIntList newRightKeys = ImmutableIntList.copyOf(newRightKeyBuilder);
            relBuilder.push(aggregate.getInput());
            final RexNode newCondition = RelOptUtil.createEquiJoinCondition(relBuilder.peek(2, 0), joinInfo.leftKeys, relBuilder.peek(2, 1), newRightKeys, rexBuilder);
            relBuilder.semiJoin(newCondition);
            break;
        case LEFT:
            // we can eliminate the semi-join.
            break;
        default:
            throw new AssertionError(join.getJoinType());
    }
    if (project != null) {
        relBuilder.project(project.getProjects(), project.getRowType().getFieldNames());
    }
    call.transformTo(relBuilder.build());
}
Also used : RelOptCluster(org.apache.calcite.plan.RelOptCluster) JoinInfo(org.apache.calcite.rel.core.JoinInfo) RelBuilder(org.apache.calcite.tools.RelBuilder) ImmutableBitSet(org.apache.calcite.util.ImmutableBitSet) RexBuilder(org.apache.calcite.rex.RexBuilder) ImmutableIntList(org.apache.calcite.util.ImmutableIntList) RexNode(org.apache.calcite.rex.RexNode)

Example 30 with RelOptCluster

use of org.apache.calcite.plan.RelOptCluster in project calcite by apache.

the class SortProjectTransposeRule method onMatch.

// ~ Methods ----------------------------------------------------------------
public void onMatch(RelOptRuleCall call) {
    final Sort sort = call.rel(0);
    final Project project = call.rel(1);
    final RelOptCluster cluster = project.getCluster();
    if (sort.getConvention() != project.getConvention()) {
        return;
    }
    // Determine mapping between project input and output fields. If sort
    // relies on non-trivial expressions, we can't push.
    final Mappings.TargetMapping map = RelOptUtil.permutationIgnoreCast(project.getProjects(), project.getInput().getRowType());
    for (RelFieldCollation fc : sort.getCollation().getFieldCollations()) {
        if (map.getTargetOpt(fc.getFieldIndex()) < 0) {
            return;
        }
        final RexNode node = project.getProjects().get(fc.getFieldIndex());
        if (node.isA(SqlKind.CAST)) {
            // Check whether it is a monotonic preserving cast, otherwise we cannot push
            final RexCall cast = (RexCall) node;
            final RexCallBinding binding = RexCallBinding.create(cluster.getTypeFactory(), cast, ImmutableList.of(RelCollations.of(RexUtil.apply(map, fc))));
            if (cast.getOperator().getMonotonicity(binding) == SqlMonotonicity.NOT_MONOTONIC) {
                return;
            }
        }
    }
    final RelCollation newCollation = cluster.traitSet().canonize(RexUtil.apply(map, sort.getCollation()));
    final Sort newSort = sort.copy(sort.getTraitSet().replace(newCollation), project.getInput(), newCollation, sort.offset, sort.fetch);
    RelNode newProject = project.copy(sort.getTraitSet(), ImmutableList.<RelNode>of(newSort));
    // Not only is newProject equivalent to sort;
    // newSort is equivalent to project's input
    // (but only if the sort is not also applying an offset/limit).
    Map<RelNode, RelNode> equiv;
    if (sort.offset == null && sort.fetch == null && cluster.getPlanner().getRelTraitDefs().contains(RelCollationTraitDef.INSTANCE)) {
        equiv = ImmutableMap.of((RelNode) newSort, project.getInput());
    } else {
        equiv = ImmutableMap.of();
    }
    call.transformTo(newProject, equiv);
}
Also used : RelOptCluster(org.apache.calcite.plan.RelOptCluster) RexCall(org.apache.calcite.rex.RexCall) Project(org.apache.calcite.rel.core.Project) LogicalProject(org.apache.calcite.rel.logical.LogicalProject) RexCallBinding(org.apache.calcite.rex.RexCallBinding) RelCollation(org.apache.calcite.rel.RelCollation) Mappings(org.apache.calcite.util.mapping.Mappings) RelNode(org.apache.calcite.rel.RelNode) RelFieldCollation(org.apache.calcite.rel.RelFieldCollation) Sort(org.apache.calcite.rel.core.Sort) RexNode(org.apache.calcite.rex.RexNode)

Aggregations

RelOptCluster (org.apache.calcite.plan.RelOptCluster)117 RelNode (org.apache.calcite.rel.RelNode)63 RelTraitSet (org.apache.calcite.plan.RelTraitSet)36 RexBuilder (org.apache.calcite.rex.RexBuilder)35 RexNode (org.apache.calcite.rex.RexNode)31 ArrayList (java.util.ArrayList)25 RelDataType (org.apache.calcite.rel.type.RelDataType)23 Test (org.junit.Test)21 ImmutableBitSet (org.apache.calcite.util.ImmutableBitSet)15 List (java.util.List)13 RelDataTypeField (org.apache.calcite.rel.type.RelDataTypeField)13 RelBuilder (org.apache.calcite.tools.RelBuilder)13 RelCollation (org.apache.calcite.rel.RelCollation)12 RelMetadataQuery (org.apache.calcite.rel.metadata.RelMetadataQuery)11 RelOptTable (org.apache.calcite.plan.RelOptTable)10 ImmutableList (com.google.common.collect.ImmutableList)9 HashMap (java.util.HashMap)9 RelOptPlanner (org.apache.calcite.plan.RelOptPlanner)9 Join (org.apache.calcite.rel.core.Join)9 LogicalJoin (org.apache.calcite.rel.logical.LogicalJoin)9