use of io.trino.sql.planner.plan.LimitNode in project trino by trinodb.
the class MergeLimits method apply.
@Override
public Result apply(LimitNode parent, Captures captures, Context context) {
LimitNode child = captures.get(CHILD);
List<Symbol> sortedInputs = ImmutableList.of();
if (child.requiresPreSortedInputs()) {
sortedInputs = child.getPreSortedInputs();
} else if (parent.requiresPreSortedInputs()) {
sortedInputs = parent.getPreSortedInputs();
}
// parent and child are without ties
if (!child.isWithTies()) {
return Result.ofPlanNode(new LimitNode(parent.getId(), child.getSource(), Math.min(parent.getCount(), child.getCount()), parent.getTiesResolvingScheme(), parent.isPartial(), sortedInputs));
}
// parent is without ties and child is with ties
if (parent.getCount() > child.getCount()) {
return Result.ofPlanNode(child.replaceChildren(ImmutableList.of(parent.replaceChildren(ImmutableList.of(child.getSource())))));
}
return Result.ofPlanNode(parent.replaceChildren(ImmutableList.of(child.getSource())));
}
use of io.trino.sql.planner.plan.LimitNode in project trino by trinodb.
the class LimitMatcher method detailMatches.
@Override
public MatchResult detailMatches(PlanNode node, StatsProvider stats, Session session, Metadata metadata, SymbolAliases symbolAliases) {
checkState(shapeMatches(node));
LimitNode limitNode = (LimitNode) node;
if (!limitNode.isWithTies()) {
return match();
}
OrderingScheme tiesResolvingScheme = limitNode.getTiesResolvingScheme().get();
if (orderingSchemeMatches(tiesResolvers, tiesResolvingScheme, symbolAliases)) {
return match();
}
if (!limitNode.requiresPreSortedInputs()) {
return match();
}
if (preSortedInputs.stream().map(alias -> alias.toSymbol(symbolAliases)).collect(toImmutableSet()).equals(ImmutableSet.copyOf(limitNode.getPreSortedInputs()))) {
return match();
}
return NO_MATCH;
}
use of io.trino.sql.planner.plan.LimitNode in project trino by trinodb.
the class PushDownDereferencesThroughLimit method apply.
@Override
public Result apply(ProjectNode projectNode, Captures captures, Context context) {
LimitNode limitNode = captures.get(CHILD);
// Extract dereferences from project node assignments for pushdown
Set<SubscriptExpression> dereferences = extractRowSubscripts(projectNode.getAssignments().getExpressions(), false, context.getSession(), typeAnalyzer, context.getSymbolAllocator().getTypes());
// Exclude dereferences on symbols being used in tiesResolvingScheme and requiresPreSortedInputs
Set<Symbol> excludedSymbols = ImmutableSet.<Symbol>builder().addAll(limitNode.getTiesResolvingScheme().map(OrderingScheme::getOrderBy).orElse(ImmutableList.of())).addAll(limitNode.getPreSortedInputs()).build();
dereferences = dereferences.stream().filter(expression -> !excludedSymbols.contains(getBase(expression))).collect(toImmutableSet());
if (dereferences.isEmpty()) {
return Result.empty();
}
// Create new symbols for dereference expressions
Assignments dereferenceAssignments = Assignments.of(dereferences, context.getSession(), context.getSymbolAllocator(), typeAnalyzer);
// Rewrite project node assignments using new symbols for dereference expressions
Map<Expression, SymbolReference> mappings = HashBiMap.create(dereferenceAssignments.getMap()).inverse().entrySet().stream().collect(toImmutableMap(Map.Entry::getKey, entry -> entry.getValue().toSymbolReference()));
Assignments newAssignments = projectNode.getAssignments().rewrite(expression -> replaceExpression(expression, mappings));
return Result.ofPlanNode(new ProjectNode(context.getIdAllocator().getNextId(), limitNode.replaceChildren(ImmutableList.of(new ProjectNode(context.getIdAllocator().getNextId(), limitNode.getSource(), Assignments.builder().putIdentities(limitNode.getSource().getOutputSymbols()).putAll(dereferenceAssignments).build()))), newAssignments));
}
use of io.trino.sql.planner.plan.LimitNode in project trino by trinodb.
the class PushLimitThroughUnion method apply.
@Override
public Result apply(LimitNode parent, Captures captures, Context context) {
UnionNode unionNode = captures.get(CHILD);
ImmutableList.Builder<PlanNode> builder = ImmutableList.builder();
boolean shouldApply = false;
for (PlanNode source : unionNode.getSources()) {
// This check is to ensure that we don't fire the optimizer if it was previously applied.
if (isAtMost(source, context.getLookup(), parent.getCount())) {
builder.add(source);
} else {
shouldApply = true;
builder.add(new LimitNode(context.getIdAllocator().getNextId(), source, parent.getCount(), true));
}
}
if (!shouldApply) {
return Result.empty();
}
return Result.ofPlanNode(parent.replaceChildren(ImmutableList.of(unionNode.replaceChildren(builder.build()))));
}
use of io.trino.sql.planner.plan.LimitNode in project trino by trinodb.
the class PushLimitThroughOffset method apply.
@Override
public Result apply(LimitNode parent, Captures captures, Context context) {
OffsetNode child = captures.get(CHILD);
long count;
try {
count = addExact(parent.getCount(), child.getCount());
} catch (ArithmeticException e) {
return Result.empty();
}
return Result.ofPlanNode(child.replaceChildren(ImmutableList.of(new LimitNode(parent.getId(), child.getSource(), count, parent.getTiesResolvingScheme(), parent.isPartial(), parent.getPreSortedInputs()))));
}
Aggregations