Search in sources :

Example 6 with Window

use of org.apache.calcite.rel.core.Window in project calcite by apache.

the class MutableRels method toMutable.

public static MutableRel toMutable(RelNode rel) {
    if (rel instanceof HepRelVertex) {
        return toMutable(((HepRelVertex) rel).getCurrentRel());
    }
    if (rel instanceof RelSubset) {
        return toMutable(Util.first(((RelSubset) rel).getBest(), ((RelSubset) rel).getOriginal()));
    }
    if (rel instanceof TableScan) {
        return MutableScan.of((TableScan) rel);
    }
    if (rel instanceof Values) {
        return MutableValues.of((Values) rel);
    }
    if (rel instanceof Project) {
        final Project project = (Project) rel;
        final MutableRel input = toMutable(project.getInput());
        return MutableProject.of(input, project.getProjects(), project.getRowType().getFieldNames());
    }
    if (rel instanceof Filter) {
        final Filter filter = (Filter) rel;
        final MutableRel input = toMutable(filter.getInput());
        return MutableFilter.of(input, filter.getCondition());
    }
    if (rel instanceof Aggregate) {
        final Aggregate aggregate = (Aggregate) rel;
        final MutableRel input = toMutable(aggregate.getInput());
        return MutableAggregate.of(input, aggregate.getGroupSet(), aggregate.getGroupSets(), aggregate.getAggCallList());
    }
    if (rel instanceof Sort) {
        final Sort sort = (Sort) rel;
        final MutableRel input = toMutable(sort.getInput());
        return MutableSort.of(input, sort.getCollation(), sort.offset, sort.fetch);
    }
    if (rel instanceof Calc) {
        final Calc calc = (Calc) rel;
        final MutableRel input = toMutable(calc.getInput());
        return MutableCalc.of(input, calc.getProgram());
    }
    if (rel instanceof Exchange) {
        final Exchange exchange = (Exchange) rel;
        final MutableRel input = toMutable(exchange.getInput());
        return MutableExchange.of(input, exchange.getDistribution());
    }
    if (rel instanceof Collect) {
        final Collect collect = (Collect) rel;
        final MutableRel input = toMutable(collect.getInput());
        return MutableCollect.of(collect.getRowType(), input, collect.getFieldName());
    }
    if (rel instanceof Uncollect) {
        final Uncollect uncollect = (Uncollect) rel;
        final MutableRel input = toMutable(uncollect.getInput());
        return MutableUncollect.of(uncollect.getRowType(), input, uncollect.withOrdinality);
    }
    if (rel instanceof Window) {
        final Window window = (Window) rel;
        final MutableRel input = toMutable(window.getInput());
        return MutableWindow.of(window.getRowType(), input, window.groups, window.getConstants());
    }
    if (rel instanceof TableModify) {
        final TableModify modify = (TableModify) rel;
        final MutableRel input = toMutable(modify.getInput());
        return MutableTableModify.of(modify.getRowType(), input, modify.getTable(), modify.getCatalogReader(), modify.getOperation(), modify.getUpdateColumnList(), modify.getSourceExpressionList(), modify.isFlattened());
    }
    if (rel instanceof Sample) {
        final Sample sample = (Sample) rel;
        final MutableRel input = toMutable(sample.getInput());
        return MutableSample.of(input, sample.getSamplingParameters());
    }
    if (rel instanceof TableFunctionScan) {
        final TableFunctionScan tableFunctionScan = (TableFunctionScan) rel;
        final List<MutableRel> inputs = toMutables(tableFunctionScan.getInputs());
        return MutableTableFunctionScan.of(tableFunctionScan.getCluster(), tableFunctionScan.getRowType(), inputs, tableFunctionScan.getCall(), tableFunctionScan.getElementType(), tableFunctionScan.getColumnMappings());
    }
    // is a sub-class of Join.
    if (rel instanceof SemiJoin) {
        final SemiJoin semiJoin = (SemiJoin) rel;
        final MutableRel left = toMutable(semiJoin.getLeft());
        final MutableRel right = toMutable(semiJoin.getRight());
        return MutableSemiJoin.of(semiJoin.getRowType(), left, right, semiJoin.getCondition(), semiJoin.getLeftKeys(), semiJoin.getRightKeys());
    }
    if (rel instanceof Join) {
        final Join join = (Join) rel;
        final MutableRel left = toMutable(join.getLeft());
        final MutableRel right = toMutable(join.getRight());
        return MutableJoin.of(join.getRowType(), left, right, join.getCondition(), join.getJoinType(), join.getVariablesSet());
    }
    if (rel instanceof Correlate) {
        final Correlate correlate = (Correlate) rel;
        final MutableRel left = toMutable(correlate.getLeft());
        final MutableRel right = toMutable(correlate.getRight());
        return MutableCorrelate.of(correlate.getRowType(), left, right, correlate.getCorrelationId(), correlate.getRequiredColumns(), correlate.getJoinType());
    }
    if (rel instanceof Union) {
        final Union union = (Union) rel;
        final List<MutableRel> inputs = toMutables(union.getInputs());
        return MutableUnion.of(union.getRowType(), inputs, union.all);
    }
    if (rel instanceof Minus) {
        final Minus minus = (Minus) rel;
        final List<MutableRel> inputs = toMutables(minus.getInputs());
        return MutableMinus.of(minus.getRowType(), inputs, minus.all);
    }
    if (rel instanceof Intersect) {
        final Intersect intersect = (Intersect) rel;
        final List<MutableRel> inputs = toMutables(intersect.getInputs());
        return MutableIntersect.of(intersect.getRowType(), inputs, intersect.all);
    }
    throw new RuntimeException("cannot translate " + rel + " to MutableRel");
}
Also used : Uncollect(org.apache.calcite.rel.core.Uncollect) Collect(org.apache.calcite.rel.core.Collect) Values(org.apache.calcite.rel.core.Values) Union(org.apache.calcite.rel.core.Union) HepRelVertex(org.apache.calcite.plan.hep.HepRelVertex) Intersect(org.apache.calcite.rel.core.Intersect) LogicalSort(org.apache.calcite.rel.logical.LogicalSort) Sort(org.apache.calcite.rel.core.Sort) SemiJoin(org.apache.calcite.rel.core.SemiJoin) LogicalTableModify(org.apache.calcite.rel.logical.LogicalTableModify) TableModify(org.apache.calcite.rel.core.TableModify) RelSubset(org.apache.calcite.plan.volcano.RelSubset) LogicalWindow(org.apache.calcite.rel.logical.LogicalWindow) Window(org.apache.calcite.rel.core.Window) TableScan(org.apache.calcite.rel.core.TableScan) Correlate(org.apache.calcite.rel.core.Correlate) LogicalCorrelate(org.apache.calcite.rel.logical.LogicalCorrelate) Sample(org.apache.calcite.rel.core.Sample) Join(org.apache.calcite.rel.core.Join) SemiJoin(org.apache.calcite.rel.core.SemiJoin) LogicalCalc(org.apache.calcite.rel.logical.LogicalCalc) Calc(org.apache.calcite.rel.core.Calc) Exchange(org.apache.calcite.rel.core.Exchange) LogicalExchange(org.apache.calcite.rel.logical.LogicalExchange) Project(org.apache.calcite.rel.core.Project) LogicalTableFunctionScan(org.apache.calcite.rel.logical.LogicalTableFunctionScan) TableFunctionScan(org.apache.calcite.rel.core.TableFunctionScan) Filter(org.apache.calcite.rel.core.Filter) Aggregate(org.apache.calcite.rel.core.Aggregate) Minus(org.apache.calcite.rel.core.Minus)

Example 7 with Window

use of org.apache.calcite.rel.core.Window in project calcite by apache.

the class ProjectWindowTransposeRule method findReference.

private ImmutableBitSet findReference(final LogicalProject project, final LogicalWindow window) {
    final int windowInputColumn = window.getInput().getRowType().getFieldCount();
    final ImmutableBitSet.Builder beReferred = ImmutableBitSet.builder();
    final RexShuttle referenceFinder = new RexShuttle() {

        @Override
        public RexNode visitInputRef(RexInputRef inputRef) {
            final int index = inputRef.getIndex();
            if (index < windowInputColumn) {
                beReferred.set(index);
            }
            return inputRef;
        }
    };
    // Reference in LogicalProject
    for (RexNode rexNode : project.getChildExps()) {
        rexNode.accept(referenceFinder);
    }
    // Reference in LogicalWindow
    for (Window.Group group : window.groups) {
        // Reference in Partition-By
        for (int index : group.keys) {
            if (index < windowInputColumn) {
                beReferred.set(index);
            }
        }
        // Reference in Order-By
        for (RelFieldCollation relFieldCollation : group.orderKeys.getFieldCollations()) {
            if (relFieldCollation.getFieldIndex() < windowInputColumn) {
                beReferred.set(relFieldCollation.getFieldIndex());
            }
        }
        // Reference in Window Functions
        for (Window.RexWinAggCall rexWinAggCall : group.aggCalls) {
            rexWinAggCall.accept(referenceFinder);
        }
    }
    return beReferred.build();
}
Also used : Window(org.apache.calcite.rel.core.Window) LogicalWindow(org.apache.calcite.rel.logical.LogicalWindow) RexShuttle(org.apache.calcite.rex.RexShuttle) ImmutableBitSet(org.apache.calcite.util.ImmutableBitSet) RelFieldCollation(org.apache.calcite.rel.RelFieldCollation) RexInputRef(org.apache.calcite.rex.RexInputRef) RexNode(org.apache.calcite.rex.RexNode)

Example 8 with Window

use of org.apache.calcite.rel.core.Window in project calcite by apache.

the class LogicalWindow method create.

/**
 * Creates a LogicalWindow by parsing a {@link RexProgram}.
 */
public static RelNode create(RelOptCluster cluster, RelTraitSet traitSet, RelBuilder relBuilder, RelNode child, final RexProgram program) {
    final RelDataType outRowType = program.getOutputRowType();
    // Build a list of distinct groups, partitions and aggregate
    // functions.
    final Multimap<WindowKey, RexOver> windowMap = LinkedListMultimap.create();
    final int inputFieldCount = child.getRowType().getFieldCount();
    final Map<RexLiteral, RexInputRef> constantPool = new HashMap<>();
    final List<RexLiteral> constants = new ArrayList<>();
    // Identify constants in the expression tree and replace them with
    // references to newly generated constant pool.
    RexShuttle replaceConstants = new RexShuttle() {

        @Override
        public RexNode visitLiteral(RexLiteral literal) {
            RexInputRef ref = constantPool.get(literal);
            if (ref != null) {
                return ref;
            }
            constants.add(literal);
            ref = new RexInputRef(constantPool.size() + inputFieldCount, literal.getType());
            constantPool.put(literal, ref);
            return ref;
        }
    };
    // Build a list of groups, partitions, and aggregate functions. Each
    // aggregate function will add its arguments as outputs of the input
    // program.
    final Map<RexOver, RexOver> origToNewOver = new IdentityHashMap<>();
    for (RexNode agg : program.getExprList()) {
        if (agg instanceof RexOver) {
            final RexOver origOver = (RexOver) agg;
            final RexOver newOver = (RexOver) origOver.accept(replaceConstants);
            origToNewOver.put(origOver, newOver);
            addWindows(windowMap, newOver, inputFieldCount);
        }
    }
    final Map<RexOver, Window.RexWinAggCall> aggMap = new HashMap<>();
    List<Group> groups = new ArrayList<>();
    for (Map.Entry<WindowKey, Collection<RexOver>> entry : windowMap.asMap().entrySet()) {
        final WindowKey windowKey = entry.getKey();
        final List<RexWinAggCall> aggCalls = new ArrayList<>();
        for (RexOver over : entry.getValue()) {
            final RexWinAggCall aggCall = new RexWinAggCall(over.getAggOperator(), over.getType(), toInputRefs(over.operands), aggMap.size(), over.isDistinct());
            aggCalls.add(aggCall);
            aggMap.put(over, aggCall);
        }
        RexShuttle toInputRefs = new RexShuttle() {

            @Override
            public RexNode visitLocalRef(RexLocalRef localRef) {
                return new RexInputRef(localRef.getIndex(), localRef.getType());
            }
        };
        groups.add(new Group(windowKey.groupSet, windowKey.isRows, windowKey.lowerBound.accept(toInputRefs), windowKey.upperBound.accept(toInputRefs), windowKey.orderKeys, aggCalls));
    }
    // Figure out the type of the inputs to the output program.
    // They are: the inputs to this rel, followed by the outputs of
    // each window.
    final List<Window.RexWinAggCall> flattenedAggCallList = new ArrayList<>();
    final List<Map.Entry<String, RelDataType>> fieldList = new ArrayList<Map.Entry<String, RelDataType>>(child.getRowType().getFieldList());
    final int offset = fieldList.size();
    // Use better field names for agg calls that are projected.
    final Map<Integer, String> fieldNames = new HashMap<>();
    for (Ord<RexLocalRef> ref : Ord.zip(program.getProjectList())) {
        final int index = ref.e.getIndex();
        if (index >= offset) {
            fieldNames.put(index - offset, outRowType.getFieldNames().get(ref.i));
        }
    }
    for (Ord<Group> window : Ord.zip(groups)) {
        for (Ord<RexWinAggCall> over : Ord.zip(window.e.aggCalls)) {
            // Add the k-th over expression of
            // the i-th window to the output of the program.
            String name = fieldNames.get(over.i);
            if (name == null || name.startsWith("$")) {
                name = "w" + window.i + "$o" + over.i;
            }
            fieldList.add(Pair.of(name, over.e.getType()));
            flattenedAggCallList.add(over.e);
        }
    }
    final RelDataType intermediateRowType = cluster.getTypeFactory().createStructType(fieldList);
    // The output program is the windowed agg's program, combined with
    // the output calc (if it exists).
    RexShuttle shuttle = new RexShuttle() {

        public RexNode visitOver(RexOver over) {
            // Look up the aggCall which this expr was translated to.
            final Window.RexWinAggCall aggCall = aggMap.get(origToNewOver.get(over));
            assert aggCall != null;
            assert RelOptUtil.eq("over", over.getType(), "aggCall", aggCall.getType(), Litmus.THROW);
            // Find the index of the aggCall among all partitions of all
            // groups.
            final int aggCallIndex = flattenedAggCallList.indexOf(aggCall);
            assert aggCallIndex >= 0;
            // Replace expression with a reference to the window slot.
            final int index = inputFieldCount + aggCallIndex;
            assert RelOptUtil.eq("over", over.getType(), "intermed", intermediateRowType.getFieldList().get(index).getType(), Litmus.THROW);
            return new RexInputRef(index, over.getType());
        }

        public RexNode visitLocalRef(RexLocalRef localRef) {
            final int index = localRef.getIndex();
            if (index < inputFieldCount) {
                // Reference to input field.
                return localRef;
            }
            return new RexLocalRef(flattenedAggCallList.size() + index, localRef.getType());
        }
    };
    final LogicalWindow window = LogicalWindow.create(traitSet, child, constants, intermediateRowType, groups);
    // The order that the "over" calls occur in the groups and
    // partitions may not match the order in which they occurred in the
    // original expression.
    // Add a project to permute them.
    final List<RexNode> rexNodesWindow = new ArrayList<>();
    for (RexNode rexNode : program.getExprList()) {
        rexNodesWindow.add(rexNode.accept(shuttle));
    }
    final List<RexNode> refToWindow = toInputRefs(rexNodesWindow);
    final List<RexNode> projectList = new ArrayList<>();
    for (RexLocalRef inputRef : program.getProjectList()) {
        final int index = inputRef.getIndex();
        final RexInputRef ref = (RexInputRef) refToWindow.get(index);
        projectList.add(ref);
    }
    return relBuilder.push(window).project(projectList, outRowType.getFieldNames()).build();
}
Also used : RexLiteral(org.apache.calcite.rex.RexLiteral) HashMap(java.util.HashMap) IdentityHashMap(java.util.IdentityHashMap) IdentityHashMap(java.util.IdentityHashMap) ArrayList(java.util.ArrayList) RelDataType(org.apache.calcite.rel.type.RelDataType) RexOver(org.apache.calcite.rex.RexOver) RexWindow(org.apache.calcite.rex.RexWindow) Window(org.apache.calcite.rel.core.Window) RexShuttle(org.apache.calcite.rex.RexShuttle) RexInputRef(org.apache.calcite.rex.RexInputRef) Collection(java.util.Collection) RexLocalRef(org.apache.calcite.rex.RexLocalRef) HashMap(java.util.HashMap) Map(java.util.Map) IdentityHashMap(java.util.IdentityHashMap) RexNode(org.apache.calcite.rex.RexNode)

Aggregations

Window (org.apache.calcite.rel.core.Window)8 RexInputRef (org.apache.calcite.rex.RexInputRef)5 RexNode (org.apache.calcite.rex.RexNode)5 RelTraitSet (org.apache.calcite.plan.RelTraitSet)4 RelNode (org.apache.calcite.rel.RelNode)4 LogicalWindow (org.apache.calcite.rel.logical.LogicalWindow)3 RelDataType (org.apache.calcite.rel.type.RelDataType)3 RexShuttle (org.apache.calcite.rex.RexShuttle)3 ArrayList (java.util.ArrayList)2 RelCollation (org.apache.calcite.rel.RelCollation)2 RelFieldCollation (org.apache.calcite.rel.RelFieldCollation)2 RelDataTypeField (org.apache.calcite.rel.type.RelDataTypeField)2 Collection (java.util.Collection)1 HashMap (java.util.HashMap)1 IdentityHashMap (java.util.IdentityHashMap)1 Map (java.util.Map)1 RelOptCluster (org.apache.calcite.plan.RelOptCluster)1 HepRelVertex (org.apache.calcite.plan.hep.HepRelVertex)1 RelSubset (org.apache.calcite.plan.volcano.RelSubset)1 Aggregate (org.apache.calcite.rel.core.Aggregate)1