Search in sources :

Example 1 with Captures

use of io.crate.planner.optimizer.matcher.Captures in project crate by crate.

the class MoveFilterBeneathWindowAgg method apply.

@Override
public LogicalPlan apply(Filter filter, Captures captures, TableStats tableStats, TransactionContext txnCtx, NodeContext nodeCtx) {
    WindowAgg windowAgg = captures.get(windowAggCapture);
    WindowDefinition windowDefinition = windowAgg.windowDefinition();
    List<WindowFunction> windowFunctions = windowAgg.windowFunctions();
    Predicate<Symbol> containsWindowFunction = symbol -> symbol instanceof WindowFunction && windowFunctions.contains(symbol);
    Symbol predicate = filter.query();
    List<Symbol> filterParts = AndOperator.split(predicate);
    ArrayList<Symbol> remainingFilterSymbols = new ArrayList<>();
    ArrayList<Symbol> windowPartitionedBasedFilters = new ArrayList<>();
    for (Symbol part : filterParts) {
        if (SymbolVisitors.any(containsWindowFunction, part) == false && windowDefinition.partitions().containsAll(extractColumns(part))) {
            windowPartitionedBasedFilters.add(part);
        } else {
            remainingFilterSymbols.add(part);
        }
    }
    assert remainingFilterSymbols.size() > 0 || windowPartitionedBasedFilters.size() > 0 : "Splitting the filter symbol must result in at least one group";
    /* SELECT ROW_NUMBER() OVER(PARTITION BY id)
         * WHERE `x = 1`
         *
         * `x` is not the window partition column.
         * We cannot push down the filter as it would change the window aggregation value
         *
         */
    if (windowPartitionedBasedFilters.isEmpty()) {
        return null;
    }
    /* SELECT ROW_NUMBER() OVER(PARTITION BY id)
         * WHERE `id = 1`
         * remainingFilterSymbols:                  []
         * windowPartitionedBasedFilters:           [id = 1]
         *
         * Filter
         *  |
         * WindowsAgg
         *
         * transforms to
         *
         * WindowAgg
         *  |
         * Filter (id = 1)
         */
    if (remainingFilterSymbols.isEmpty()) {
        return transpose(filter, windowAgg);
    }
    /* WHERE `ROW_NUMBER() OVER(PARTITION BY id) = 2 AND id = 1`
         * remainingFilterSymbols:                  [ROW_NUMBER() OVER(PARTITION BY id) = 2]
         * windowPartitionedBasedFilters:           [id = 1]
         *
         * Filter
         *  |
         * WindowsAgg
         *
         * transforms to
         *
         * Filter (ROW_NUMBER() OVER(PARTITION BY id) = 2)
         *  |
         * WindowAgg
         *  |
         * Filter (id = 1)
         */
    LogicalPlan newWindowAgg = windowAgg.replaceSources(List.of(new Filter(windowAgg.source(), AndOperator.join(windowPartitionedBasedFilters))));
    return new Filter(newWindowAgg, AndOperator.join(remainingFilterSymbols));
}
Also used : TransactionContext(io.crate.metadata.TransactionContext) NodeContext(io.crate.metadata.NodeContext) LogicalPlanner.extractColumns(io.crate.planner.operators.LogicalPlanner.extractColumns) LogicalPlan(io.crate.planner.operators.LogicalPlan) Captures(io.crate.planner.optimizer.matcher.Captures) Predicate(java.util.function.Predicate) Util.transpose(io.crate.planner.optimizer.rule.Util.transpose) Pattern(io.crate.planner.optimizer.matcher.Pattern) Rule(io.crate.planner.optimizer.Rule) SymbolVisitors(io.crate.expression.symbol.SymbolVisitors) ArrayList(java.util.ArrayList) List(java.util.List) AndOperator(io.crate.expression.operator.AndOperator) TableStats(io.crate.statistics.TableStats) WindowDefinition(io.crate.analyze.WindowDefinition) Symbol(io.crate.expression.symbol.Symbol) Pattern.typeOf(io.crate.planner.optimizer.matcher.Pattern.typeOf) WindowFunction(io.crate.expression.symbol.WindowFunction) Patterns.source(io.crate.planner.optimizer.matcher.Patterns.source) Filter(io.crate.planner.operators.Filter) WindowAgg(io.crate.planner.operators.WindowAgg) Capture(io.crate.planner.optimizer.matcher.Capture) WindowFunction(io.crate.expression.symbol.WindowFunction) WindowAgg(io.crate.planner.operators.WindowAgg) Filter(io.crate.planner.operators.Filter) Symbol(io.crate.expression.symbol.Symbol) ArrayList(java.util.ArrayList) LogicalPlan(io.crate.planner.operators.LogicalPlan) WindowDefinition(io.crate.analyze.WindowDefinition)

Example 2 with Captures

use of io.crate.planner.optimizer.matcher.Captures in project crate by crate.

the class MoveOrderBeneathNestedLoop method apply.

@Override
public LogicalPlan apply(Order order, Captures captures, TableStats tableStats, TransactionContext txnCtx, NodeContext nodeCtx) {
    NestedLoopJoin nestedLoop = captures.get(nlCapture);
    Set<RelationName> relationsInOrderBy = Collections.newSetFromMap(new IdentityHashMap<>());
    Consumer<ScopedSymbol> gatherRelationsFromField = f -> relationsInOrderBy.add(f.relation());
    Consumer<Reference> gatherRelationsFromRef = r -> relationsInOrderBy.add(r.ident().tableIdent());
    OrderBy orderBy = order.orderBy();
    for (Symbol orderExpr : orderBy.orderBySymbols()) {
        FieldsVisitor.visitFields(orderExpr, gatherRelationsFromField);
        RefVisitor.visitRefs(orderExpr, gatherRelationsFromRef);
    }
    if (relationsInOrderBy.size() == 1) {
        RelationName relationInOrderBy = relationsInOrderBy.iterator().next();
        if (relationInOrderBy == nestedLoop.topMostLeftRelation().relationName()) {
            LogicalPlan lhs = nestedLoop.sources().get(0);
            LogicalPlan newLhs = order.replaceSources(List.of(lhs));
            return new NestedLoopJoin(newLhs, nestedLoop.sources().get(1), nestedLoop.joinType(), nestedLoop.joinCondition(), nestedLoop.isFiltered(), nestedLoop.topMostLeftRelation(), true, nestedLoop.isRewriteFilterOnOuterJoinToInnerJoinDone());
        }
    }
    return null;
}
Also used : TransactionContext(io.crate.metadata.TransactionContext) NodeContext(io.crate.metadata.NodeContext) LogicalPlan(io.crate.planner.operators.LogicalPlan) Captures(io.crate.planner.optimizer.matcher.Captures) IdentityHashMap(java.util.IdentityHashMap) RelationName(io.crate.metadata.RelationName) Reference(io.crate.metadata.Reference) Pattern(io.crate.planner.optimizer.matcher.Pattern) Set(java.util.Set) NestedLoopJoin(io.crate.planner.operators.NestedLoopJoin) Rule(io.crate.planner.optimizer.Rule) Consumer(java.util.function.Consumer) Order(io.crate.planner.operators.Order) RefVisitor(io.crate.expression.symbol.RefVisitor) List(java.util.List) OrderBy(io.crate.analyze.OrderBy) TableStats(io.crate.statistics.TableStats) Symbol(io.crate.expression.symbol.Symbol) Pattern.typeOf(io.crate.planner.optimizer.matcher.Pattern.typeOf) ScopedSymbol(io.crate.expression.symbol.ScopedSymbol) Patterns.source(io.crate.planner.optimizer.matcher.Patterns.source) Collections(java.util.Collections) FieldsVisitor(io.crate.expression.symbol.FieldsVisitor) Capture(io.crate.planner.optimizer.matcher.Capture) OrderBy(io.crate.analyze.OrderBy) Reference(io.crate.metadata.Reference) Symbol(io.crate.expression.symbol.Symbol) ScopedSymbol(io.crate.expression.symbol.ScopedSymbol) NestedLoopJoin(io.crate.planner.operators.NestedLoopJoin) RelationName(io.crate.metadata.RelationName) LogicalPlan(io.crate.planner.operators.LogicalPlan) ScopedSymbol(io.crate.expression.symbol.ScopedSymbol)

Aggregations

Symbol (io.crate.expression.symbol.Symbol)2 NodeContext (io.crate.metadata.NodeContext)2 TransactionContext (io.crate.metadata.TransactionContext)2 LogicalPlan (io.crate.planner.operators.LogicalPlan)2 Rule (io.crate.planner.optimizer.Rule)2 Capture (io.crate.planner.optimizer.matcher.Capture)2 Captures (io.crate.planner.optimizer.matcher.Captures)2 Pattern (io.crate.planner.optimizer.matcher.Pattern)2 Pattern.typeOf (io.crate.planner.optimizer.matcher.Pattern.typeOf)2 Patterns.source (io.crate.planner.optimizer.matcher.Patterns.source)2 TableStats (io.crate.statistics.TableStats)2 List (java.util.List)2 OrderBy (io.crate.analyze.OrderBy)1 WindowDefinition (io.crate.analyze.WindowDefinition)1 AndOperator (io.crate.expression.operator.AndOperator)1 FieldsVisitor (io.crate.expression.symbol.FieldsVisitor)1 RefVisitor (io.crate.expression.symbol.RefVisitor)1 ScopedSymbol (io.crate.expression.symbol.ScopedSymbol)1 SymbolVisitors (io.crate.expression.symbol.SymbolVisitors)1 WindowFunction (io.crate.expression.symbol.WindowFunction)1