Search in sources :

Example 6 with Lookup

use of io.trino.sql.planner.iterative.Lookup in project trino by trinodb.

the class RuleAssert method applyRule.

private RuleApplication applyRule() {
    SymbolAllocator symbolAllocator = new SymbolAllocator(types.allTypes());
    Memo memo = new Memo(idAllocator, plan);
    Lookup lookup = Lookup.from(planNode -> Stream.of(memo.resolve(planNode)));
    PlanNode memoRoot = memo.getNode(memo.getRootGroup());
    return inTransaction(session -> applyRule(rule, memoRoot, ruleContext(statsCalculator, costCalculator, symbolAllocator, memo, lookup, session)));
}
Also used : SymbolAllocator(io.trino.sql.planner.SymbolAllocator) PlanNode(io.trino.sql.planner.plan.PlanNode) Lookup(io.trino.sql.planner.iterative.Lookup) Memo(io.trino.sql.planner.iterative.Memo)

Example 7 with Lookup

use of io.trino.sql.planner.iterative.Lookup in project trino by trinodb.

the class PruneDistinctAggregation method apply.

@Override
public Result apply(AggregationNode node, Captures captures, Context context) {
    Lookup lookup = context.getLookup();
    DistinctAggregationRewriter rewriter = new DistinctAggregationRewriter(lookup);
    List<PlanNode> newSources = node.getSources().stream().flatMap(lookup::resolveGroup).map(source -> source.accept(rewriter, true)).collect(Collectors.toList());
    if (rewriter.isRewritten()) {
        return Result.ofPlanNode(replaceChildren(node, newSources));
    } else {
        return Result.empty();
    }
}
Also used : UnionNode(io.trino.sql.planner.plan.UnionNode) Lookup(io.trino.sql.planner.iterative.Lookup) ChildReplacer.replaceChildren(io.trino.sql.planner.plan.ChildReplacer.replaceChildren) PlanVisitor(io.trino.sql.planner.plan.PlanVisitor) Iterables.getOnlyElement(com.google.common.collect.Iterables.getOnlyElement) Collectors(java.util.stream.Collectors) PlanNode(io.trino.sql.planner.plan.PlanNode) IntersectNode(io.trino.sql.planner.plan.IntersectNode) List(java.util.List) Pattern(io.trino.matching.Pattern) ExceptNode(io.trino.sql.planner.plan.ExceptNode) Patterns.aggregation(io.trino.sql.planner.plan.Patterns.aggregation) ImmutableList(com.google.common.collect.ImmutableList) Captures(io.trino.matching.Captures) AggregationNode(io.trino.sql.planner.plan.AggregationNode) Rule(io.trino.sql.planner.iterative.Rule) PlanNode(io.trino.sql.planner.plan.PlanNode) Lookup(io.trino.sql.planner.iterative.Lookup)

Example 8 with Lookup

use of io.trino.sql.planner.iterative.Lookup in project trino by trinodb.

the class TopNStatsRule method doCalculate.

@Override
protected Optional<PlanNodeStatsEstimate> doCalculate(TopNNode node, StatsProvider statsProvider, Lookup lookup, Session session, TypeProvider types) {
    PlanNodeStatsEstimate sourceStats = statsProvider.getStats(node.getSource());
    double rowCount = sourceStats.getOutputRowCount();
    if (node.getStep() != TopNNode.Step.SINGLE) {
        return Optional.empty();
    }
    if (rowCount <= node.getCount()) {
        return Optional.of(sourceStats);
    }
    long limitCount = node.getCount();
    PlanNodeStatsEstimate resultStats = PlanNodeStatsEstimate.buildFrom(sourceStats).setOutputRowCount(limitCount).build();
    if (limitCount == 0) {
        return Optional.of(resultStats);
    }
    // augment null fraction estimation for first ORDER BY symbol
    // Assuming not empty list
    Symbol firstOrderSymbol = node.getOrderingScheme().getOrderBy().get(0);
    SortOrder sortOrder = node.getOrderingScheme().getOrdering(firstOrderSymbol);
    resultStats = resultStats.mapSymbolColumnStatistics(firstOrderSymbol, symbolStats -> {
        SymbolStatsEstimate.Builder newStats = SymbolStatsEstimate.buildFrom(symbolStats);
        double nullCount = rowCount * symbolStats.getNullsFraction();
        if (sortOrder.isNullsFirst()) {
            if (nullCount > limitCount) {
                newStats.setNullsFraction(1.0);
            } else {
                newStats.setNullsFraction(nullCount / limitCount);
            }
        } else {
            double nonNullCount = (rowCount - nullCount);
            if (nonNullCount > limitCount) {
                newStats.setNullsFraction(0.0);
            } else {
                newStats.setNullsFraction((limitCount - nonNullCount) / limitCount);
            }
        }
        return newStats.build();
    });
    // TopN actually limits (or when there was no row count estimated for source)
    return Optional.of(resultStats);
}
Also used : Symbol(io.trino.sql.planner.Symbol) Pattern(io.trino.matching.Pattern) Lookup(io.trino.sql.planner.iterative.Lookup) TopNNode(io.trino.sql.planner.plan.TopNNode) TypeProvider(io.trino.sql.planner.TypeProvider) Optional(java.util.Optional) Patterns.topN(io.trino.sql.planner.plan.Patterns.topN) Session(io.trino.Session) SortOrder(io.trino.spi.connector.SortOrder) Symbol(io.trino.sql.planner.Symbol) SortOrder(io.trino.spi.connector.SortOrder)

Example 9 with Lookup

use of io.trino.sql.planner.iterative.Lookup in project trino by trinodb.

the class SetOperationMerge method merge.

/**
 * Merge all matching source nodes. This method is assumed to be used only for associative set operations: UNION and INTERSECT.
 *
 * @return Merged plan node if applied.
 */
public Optional<SetOperationNode> merge() {
    checkState(node instanceof UnionNode || node instanceof IntersectNode, "unexpected node type: %s", node.getClass().getSimpleName());
    Lookup lookup = context.getLookup();
    List<PlanNode> sources = node.getSources().stream().flatMap(lookup::resolveGroup).collect(Collectors.toList());
    ImmutableListMultimap.Builder<Symbol, Symbol> newMappingsBuilder = ImmutableListMultimap.builder();
    boolean resultIsDistinct = false;
    boolean rewritten = false;
    for (int i = 0; i < sources.size(); i++) {
        PlanNode source = sources.get(i);
        // Determine if set operations can be merged and whether the resulting set operation is quantified DISTINCT or ALL
        Optional<Boolean> mergedQuantifier = mergedQuantifierIsDistinct(node, source);
        if (mergedQuantifier.isPresent()) {
            addMergedMappings((SetOperationNode) source, i, newMappingsBuilder);
            resultIsDistinct |= mergedQuantifier.get();
            rewritten = true;
        } else {
            // Keep mapping as it is
            addOriginalMappings(source, i, newMappingsBuilder);
        }
    }
    if (!rewritten) {
        return Optional.empty();
    }
    if (node instanceof UnionNode) {
        return Optional.of(new UnionNode(node.getId(), newSources, newMappingsBuilder.build(), node.getOutputSymbols()));
    }
    return Optional.of(new IntersectNode(node.getId(), newSources, newMappingsBuilder.build(), node.getOutputSymbols(), resultIsDistinct));
}
Also used : PlanNode(io.trino.sql.planner.plan.PlanNode) UnionNode(io.trino.sql.planner.plan.UnionNode) Symbol(io.trino.sql.planner.Symbol) ImmutableListMultimap(com.google.common.collect.ImmutableListMultimap) Lookup(io.trino.sql.planner.iterative.Lookup) IntersectNode(io.trino.sql.planner.plan.IntersectNode)

Aggregations

Lookup (io.trino.sql.planner.iterative.Lookup)9 PlanNode (io.trino.sql.planner.plan.PlanNode)7 Symbol (io.trino.sql.planner.Symbol)6 Session (io.trino.Session)5 TypeProvider (io.trino.sql.planner.TypeProvider)4 Optional (java.util.Optional)4 Pattern (io.trino.matching.Pattern)3 PlanNodeIdAllocator (io.trino.sql.planner.PlanNodeIdAllocator)3 List (java.util.List)3 Map (java.util.Map)3 Preconditions.checkState (com.google.common.base.Preconditions.checkState)2 ImmutableList.toImmutableList (com.google.common.collect.ImmutableList.toImmutableList)2 ImmutableListMultimap (com.google.common.collect.ImmutableListMultimap)2 ImmutableSet (com.google.common.collect.ImmutableSet)2 ImmutableSet.toImmutableSet (com.google.common.collect.ImmutableSet.toImmutableSet)2 Streams (com.google.common.collect.Streams)2 PlannerContext (io.trino.sql.PlannerContext)2 DeterminismEvaluator.isDeterministic (io.trino.sql.planner.DeterminismEvaluator.isDeterministic)2 SymbolsExtractor (io.trino.sql.planner.SymbolsExtractor)2 SymbolsExtractor.extractUnique (io.trino.sql.planner.SymbolsExtractor.extractUnique)2