Search in sources :

Example 31 with RelTraitSet

use of org.apache.calcite.plan.RelTraitSet in project drill by apache.

the class DrillAggregateRule method onMatch.

@Override
public void onMatch(RelOptRuleCall call) {
    final LogicalAggregate aggregate = (LogicalAggregate) call.rel(0);
    final RelNode input = call.rel(1);
    if (aggregate.containsDistinctCall()) {
        // currently, don't use this rule if any of the aggregates contains DISTINCT
        return;
    }
    final RelTraitSet traits = aggregate.getTraitSet().plus(DrillRel.DRILL_LOGICAL);
    final RelNode convertedInput = convert(input, input.getTraitSet().plus(DrillRel.DRILL_LOGICAL));
    try {
        call.transformTo(new DrillAggregateRel(aggregate.getCluster(), traits, convertedInput, aggregate.indicator, aggregate.getGroupSet(), aggregate.getGroupSets(), aggregate.getAggCallList()));
    } catch (InvalidRelException e) {
        tracer.warning(e.toString());
    }
}
Also used : InvalidRelException(org.apache.calcite.rel.InvalidRelException) LogicalAggregate(org.apache.calcite.rel.logical.LogicalAggregate) RelNode(org.apache.calcite.rel.RelNode) RelTraitSet(org.apache.calcite.plan.RelTraitSet)

Example 32 with RelTraitSet

use of org.apache.calcite.plan.RelTraitSet in project drill by apache.

the class DefaultSqlHandler method convertToPrel.

protected Prel convertToPrel(RelNode drel) throws RelConversionException, SqlUnsupportedException {
    Preconditions.checkArgument(drel.getConvention() == DrillRel.DRILL_LOGICAL);
    final RelTraitSet traits = drel.getTraitSet().plus(Prel.DRILL_PHYSICAL).plus(DrillDistributionTrait.SINGLETON);
    Prel phyRelNode;
    try {
        final Stopwatch watch = Stopwatch.createStarted();
        final RelNode relNode = transform(PlannerType.VOLCANO, PlannerPhase.PHYSICAL, drel, traits, false);
        phyRelNode = (Prel) relNode.accept(new PrelFinalizer());
        // log externally as we need to finalize before traversing the tree.
        log(PlannerType.VOLCANO, PlannerPhase.PHYSICAL, phyRelNode, logger, watch);
    } catch (RelOptPlanner.CannotPlanException ex) {
        logger.error(ex.getMessage());
        if (JoinUtils.checkCartesianJoin(drel, new ArrayList<Integer>(), new ArrayList<Integer>(), new ArrayList<Boolean>())) {
            throw new UnsupportedRelOperatorException("This query cannot be planned possibly due to either a cartesian join or an inequality join");
        } else {
            throw ex;
        }
    }
    OptionManager queryOptions = context.getOptions();
    if (context.getPlannerSettings().isMemoryEstimationEnabled() && !MemoryEstimationVisitor.enoughMemory(phyRelNode, queryOptions, context.getActiveEndpoints().size())) {
        log("Not enough memory for this plan", phyRelNode, logger, null);
        logger.debug("Re-planning without hash operations.");
        queryOptions.setOption(OptionValue.createBoolean(OptionValue.OptionType.QUERY, PlannerSettings.HASHJOIN.getOptionName(), false));
        queryOptions.setOption(OptionValue.createBoolean(OptionValue.OptionType.QUERY, PlannerSettings.HASHAGG.getOptionName(), false));
        try {
            final RelNode relNode = transform(PlannerType.VOLCANO, PlannerPhase.PHYSICAL, drel, traits);
            phyRelNode = (Prel) relNode.accept(new PrelFinalizer());
        } catch (RelOptPlanner.CannotPlanException ex) {
            logger.error(ex.getMessage());
            if (JoinUtils.checkCartesianJoin(drel, new ArrayList<Integer>(), new ArrayList<Integer>(), new ArrayList<Boolean>())) {
                throw new UnsupportedRelOperatorException("This query cannot be planned possibly due to either a cartesian join or an inequality join");
            } else {
                throw ex;
            }
        }
    }
    /* The order of the following transformations is important */
    /*
     * 0.) For select * from join query, we need insert project on top of scan and a top project just
     * under screen operator. The project on top of scan will rename from * to T1*, while the top project
     * will rename T1* to *, before it output the final result. Only the top project will allow
     * duplicate columns, since user could "explicitly" ask for duplicate columns ( select *, col, *).
     * The rest of projects will remove the duplicate column when we generate POP in json format.
     */
    phyRelNode = StarColumnConverter.insertRenameProject(phyRelNode);
    /*
     * 1.)
     * Join might cause naming conflicts from its left and right child.
     * In such case, we have to insert Project to rename the conflicting names.
     */
    phyRelNode = JoinPrelRenameVisitor.insertRenameProject(phyRelNode);
    /*
     * 1.1) Swap left / right for INNER hash join, if left's row count is < (1 + margin) right's row count.
     * We want to have smaller dataset on the right side, since hash table builds on right side.
     */
    if (context.getPlannerSettings().isHashJoinSwapEnabled()) {
        phyRelNode = SwapHashJoinVisitor.swapHashJoin(phyRelNode, new Double(context.getPlannerSettings().getHashJoinSwapMarginFactor()));
    }
    if (context.getPlannerSettings().isParquetRowGroupFilterPushdownPlanningEnabled()) {
        phyRelNode = (Prel) transform(PlannerType.HEP_BOTTOM_UP, PlannerPhase.PHYSICAL_PARTITION_PRUNING, phyRelNode);
    }
    /*
     * 1.2) Break up all expressions with complex outputs into their own project operations
     */
    phyRelNode = phyRelNode.accept(new SplitUpComplexExpressions(config.getConverter().getTypeFactory(), context.getDrillOperatorTable(), context.getPlannerSettings().functionImplementationRegistry), null);
    /*
     * 1.3) Projections that contain reference to flatten are rewritten as Flatten operators followed by Project
     */
    phyRelNode = phyRelNode.accept(new RewriteProjectToFlatten(config.getConverter().getTypeFactory(), context.getDrillOperatorTable()), null);
    /*
     * 2.)
     * Since our operators work via names rather than indices, we have to make to reorder any
     * output before we return data to the user as we may have accidentally shuffled things.
     * This adds a trivial project to reorder columns prior to output.
     */
    phyRelNode = FinalColumnReorderer.addFinalColumnOrdering(phyRelNode);
    /*
     * 3.)
     * If two fragments are both estimated to be parallelization one, remove the exchange
     * separating them
     */
    phyRelNode = ExcessiveExchangeIdentifier.removeExcessiveEchanges(phyRelNode, targetSliceSize);
    /* 5.)
     * if the client does not support complex types (Map, Repeated)
     * insert a project which which would convert
     */
    if (!context.getSession().isSupportComplexTypes()) {
        logger.debug("Client does not support complex types, add ComplexToJson operator.");
        phyRelNode = ComplexToJsonPrelVisitor.addComplexToJsonPrel(phyRelNode);
    }
    /* 6.)
     * Insert LocalExchange (mux and/or demux) nodes
     */
    phyRelNode = InsertLocalExchangeVisitor.insertLocalExchanges(phyRelNode, queryOptions);
    /* 7.)
     * Next, we add any required selection vector removers given the supported encodings of each
     * operator. This will ultimately move to a new trait but we're managing here for now to avoid
     * introducing new issues in planning before the next release
     */
    phyRelNode = SelectionVectorPrelVisitor.addSelectionRemoversWhereNecessary(phyRelNode);
    /* 8.)
     * Finally, Make sure that the no rels are repeats.
     * This could happen in the case of querying the same table twice as Optiq may canonicalize these.
     */
    phyRelNode = RelUniqifier.uniqifyGraph(phyRelNode);
    return phyRelNode;
}
Also used : UnsupportedRelOperatorException(org.apache.drill.exec.work.foreman.UnsupportedRelOperatorException) RewriteProjectToFlatten(org.apache.drill.exec.planner.physical.visitor.RewriteProjectToFlatten) Stopwatch(com.google.common.base.Stopwatch) ArrayList(java.util.ArrayList) RelTraitSet(org.apache.calcite.plan.RelTraitSet) SplitUpComplexExpressions(org.apache.drill.exec.planner.physical.visitor.SplitUpComplexExpressions) RelOptPlanner(org.apache.calcite.plan.RelOptPlanner) OptionManager(org.apache.drill.exec.server.options.OptionManager) Prel(org.apache.drill.exec.planner.physical.Prel) RelNode(org.apache.calcite.rel.RelNode)

Example 33 with RelTraitSet

use of org.apache.calcite.plan.RelTraitSet in project drill by apache.

the class UnionAllPrule method onMatch.

@Override
public void onMatch(RelOptRuleCall call) {
    final DrillUnionRel union = (DrillUnionRel) call.rel(0);
    final List<RelNode> inputs = union.getInputs();
    List<RelNode> convertedInputList = Lists.newArrayList();
    PlannerSettings settings = PrelUtil.getPlannerSettings(call.getPlanner());
    boolean allHashDistributed = true;
    for (int i = 0; i < inputs.size(); i++) {
        RelNode child = inputs.get(i);
        List<DistributionField> childDistFields = Lists.newArrayList();
        RelNode convertedChild;
        for (RelDataTypeField f : child.getRowType().getFieldList()) {
            childDistFields.add(new DistributionField(f.getIndex()));
        }
        if (settings.isUnionAllDistributeEnabled()) {
            /*
         * Strictly speaking, union-all does not need re-distribution of data; but in Drill's execution
         * model, the data distribution and parallelism operators are the same. Here, we insert a
         * hash distribution operator to allow parallelism to be determined independently for the parent
         * and children. (See DRILL-4833).
         * Note that a round robin distribution would have sufficed but we don't have one.
         */
            DrillDistributionTrait hashChild = new DrillDistributionTrait(DrillDistributionTrait.DistributionType.HASH_DISTRIBUTED, ImmutableList.copyOf(childDistFields));
            RelTraitSet traitsChild = call.getPlanner().emptyTraitSet().plus(Prel.DRILL_PHYSICAL).plus(hashChild);
            convertedChild = convert(child, PrelUtil.fixTraits(call, traitsChild));
        } else {
            RelTraitSet traitsChild = call.getPlanner().emptyTraitSet().plus(Prel.DRILL_PHYSICAL);
            convertedChild = convert(child, PrelUtil.fixTraits(call, traitsChild));
            allHashDistributed = false;
        }
        convertedInputList.add(convertedChild);
    }
    try {
        RelTraitSet traits;
        if (allHashDistributed) {
            // since all children of union-all are hash distributed, propagate the traits of the left child
            traits = convertedInputList.get(0).getTraitSet();
        } else {
            // output distribution trait is set to ANY since union-all inputs may be distributed in different ways
            // and unlike a join there are no join keys that allow determining how the output would be distributed.
            // Note that a downstream operator may impose a required distribution which would be satisfied by
            // inserting an Exchange after the Union-All.
            traits = call.getPlanner().emptyTraitSet().plus(Prel.DRILL_PHYSICAL).plus(DrillDistributionTrait.ANY);
        }
        Preconditions.checkArgument(convertedInputList.size() >= 2, "Union list must be at least two items.");
        RelNode left = convertedInputList.get(0);
        for (int i = 1; i < convertedInputList.size(); i++) {
            left = new UnionAllPrel(union.getCluster(), traits, ImmutableList.of(left, convertedInputList.get(i)), false);
        }
        call.transformTo(left);
    } catch (InvalidRelException e) {
        tracer.warning(e.toString());
    }
}
Also used : InvalidRelException(org.apache.calcite.rel.InvalidRelException) RelTraitSet(org.apache.calcite.plan.RelTraitSet) RelDataTypeField(org.apache.calcite.rel.type.RelDataTypeField) RelNode(org.apache.calcite.rel.RelNode) DrillUnionRel(org.apache.drill.exec.planner.logical.DrillUnionRel) DistributionField(org.apache.drill.exec.planner.physical.DrillDistributionTrait.DistributionField)

Example 34 with RelTraitSet

use of org.apache.calcite.plan.RelTraitSet in project drill by apache.

the class UnionDistinctPrule method onMatch.

@Override
public void onMatch(RelOptRuleCall call) {
    final DrillUnionRel union = (DrillUnionRel) call.rel(0);
    final List<RelNode> inputs = union.getInputs();
    List<RelNode> convertedInputList = Lists.newArrayList();
    RelTraitSet traits = call.getPlanner().emptyTraitSet().plus(Prel.DRILL_PHYSICAL);
    try {
        for (int i = 0; i < inputs.size(); i++) {
            RelNode convertedInput = convert(inputs.get(i), PrelUtil.fixTraits(call, traits));
            convertedInputList.add(convertedInput);
        }
        traits = call.getPlanner().emptyTraitSet().plus(Prel.DRILL_PHYSICAL).plus(DrillDistributionTrait.SINGLETON);
        UnionDistinctPrel unionDistinct = new UnionDistinctPrel(union.getCluster(), traits, convertedInputList, false);
        call.transformTo(unionDistinct);
    } catch (InvalidRelException e) {
        tracer.warning(e.toString());
    }
}
Also used : InvalidRelException(org.apache.calcite.rel.InvalidRelException) RelNode(org.apache.calcite.rel.RelNode) DrillUnionRel(org.apache.drill.exec.planner.logical.DrillUnionRel) RelTraitSet(org.apache.calcite.plan.RelTraitSet)

Example 35 with RelTraitSet

use of org.apache.calcite.plan.RelTraitSet in project drill by apache.

the class WriterPrule method onMatch.

@Override
public void onMatch(RelOptRuleCall call) {
    final DrillWriterRel writer = call.rel(0);
    final RelNode input = call.rel(1);
    final List<Integer> keys = writer.getPartitionKeys();
    final RelCollation collation = getCollation(keys);
    final boolean hashDistribute = PrelUtil.getPlannerSettings(call.getPlanner()).getOptions().getOption(ExecConstants.CTAS_PARTITIONING_HASH_DISTRIBUTE_VALIDATOR);
    final RelTraitSet traits = hashDistribute ? input.getTraitSet().plus(Prel.DRILL_PHYSICAL).plus(collation).plus(getDistribution(keys)) : input.getTraitSet().plus(Prel.DRILL_PHYSICAL).plus(collation);
    final RelNode convertedInput = convert(input, traits);
    if (!new WriteTraitPull(call).go(writer, convertedInput)) {
        DrillWriterRelBase newWriter = new WriterPrel(writer.getCluster(), convertedInput.getTraitSet(), convertedInput, writer.getCreateTableEntry());
        call.transformTo(newWriter);
    }
}
Also used : RelCollation(org.apache.calcite.rel.RelCollation) RelNode(org.apache.calcite.rel.RelNode) DrillWriterRel(org.apache.drill.exec.planner.logical.DrillWriterRel) RelTraitSet(org.apache.calcite.plan.RelTraitSet) DrillWriterRelBase(org.apache.drill.exec.planner.common.DrillWriterRelBase)

Aggregations

RelTraitSet (org.apache.calcite.plan.RelTraitSet)37 RelNode (org.apache.calcite.rel.RelNode)26 InvalidRelException (org.apache.calcite.rel.InvalidRelException)8 ArrayList (java.util.ArrayList)5 RexNode (org.apache.calcite.rex.RexNode)5 RelOptCluster (org.apache.calcite.plan.RelOptCluster)4 RelCollation (org.apache.calcite.rel.RelCollation)4 RelDataTypeField (org.apache.calcite.rel.type.RelDataTypeField)4 RelOptPlanner (org.apache.calcite.plan.RelOptPlanner)3 RexInputRef (org.apache.calcite.rex.RexInputRef)3 Stopwatch (com.google.common.base.Stopwatch)2 ImmutableList (com.google.common.collect.ImmutableList)2 RelOptTable (org.apache.calcite.plan.RelOptTable)2 Sort (org.apache.calcite.rel.core.Sort)2 Window (org.apache.calcite.rel.core.Window)2 RelDataType (org.apache.calcite.rel.type.RelDataType)2 Table (org.apache.calcite.schema.Table)2 DrillDirectScanRel (org.apache.drill.exec.planner.logical.DrillDirectScanRel)2 DrillRel (org.apache.drill.exec.planner.logical.DrillRel)2 DrillUnionRel (org.apache.drill.exec.planner.logical.DrillUnionRel)2