use of io.trino.sql.planner.plan.TopNNode in project trino by trinodb.
the class PushDownDereferencesThroughTopN method apply.
@Override
public Result apply(ProjectNode projectNode, Captures captures, Context context) {
TopNNode topNNode = 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 orderBy
dereferences = dereferences.stream().filter(expression -> !topNNode.getOrderingScheme().getOrderBy().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(), topNNode.replaceChildren(ImmutableList.of(new ProjectNode(context.getIdAllocator().getNextId(), topNNode.getSource(), Assignments.builder().putIdentities(topNNode.getSource().getOutputSymbols()).putAll(dereferenceAssignments).build()))), newAssignments));
}
use of io.trino.sql.planner.plan.TopNNode in project trino by trinodb.
the class PushTopNIntoTableScan method apply.
@Override
public Result apply(TopNNode topNNode, Captures captures, Context context) {
TableScanNode tableScan = captures.get(TABLE_SCAN);
long topNCount = topNNode.getCount();
List<SortItem> sortItems = topNNode.getOrderingScheme().toSortItems();
Map<String, ColumnHandle> assignments = tableScan.getAssignments().entrySet().stream().collect(toImmutableMap(entry -> entry.getKey().getName(), Map.Entry::getValue));
return metadata.applyTopN(context.getSession(), tableScan.getTable(), topNCount, sortItems, assignments).map(result -> {
PlanNode node = new TableScanNode(context.getIdAllocator().getNextId(), result.getHandle(), tableScan.getOutputSymbols(), tableScan.getAssignments(), TupleDomain.all(), deriveTableStatisticsForPushdown(context.getStatsProvider(), context.getSession(), result.isPrecalculateStatistics(), result.isTopNGuaranteed() ? topNNode : tableScan), tableScan.isUpdateTarget(), // table scan partitioning might have changed with new table handle
Optional.empty());
if (!result.isTopNGuaranteed()) {
node = topNNode.replaceChildren(ImmutableList.of(node));
}
return Result.ofPlanNode(node);
}).orElseGet(Result::empty);
}
use of io.trino.sql.planner.plan.TopNNode in project trino by trinodb.
the class PushTopNThroughProject method apply.
@Override
public Result apply(TopNNode parent, Captures captures, Context context) {
ProjectNode projectNode = captures.get(PROJECT_CHILD);
// Do not push down if the projection is made up of symbol references and exclusive dereferences. This prevents
// undoing of PushDownDereferencesThroughTopN. We still push topN in the case of overlapping dereferences since
// it enables PushDownDereferencesThroughTopN rule to push optimal dereferences.
Set<Expression> projections = ImmutableSet.copyOf(projectNode.getAssignments().getExpressions());
if (!extractRowSubscripts(projections, false, context.getSession(), typeAnalyzer, context.getSymbolAllocator().getTypes()).isEmpty() && exclusiveDereferences(projections, context.getSession(), typeAnalyzer, context.getSymbolAllocator().getTypes())) {
return Result.empty();
}
// do not push topN between projection and filter(table scan) so that they can be merged into a PageProcessor
PlanNode projectSource = context.getLookup().resolve(projectNode.getSource());
if (projectSource instanceof FilterNode) {
PlanNode filterSource = context.getLookup().resolve(((FilterNode) projectSource).getSource());
if (filterSource instanceof TableScanNode) {
return Result.empty();
}
}
Optional<SymbolMapper> symbolMapper = symbolMapper(parent.getOrderingScheme().getOrderBy(), projectNode.getAssignments());
if (symbolMapper.isEmpty()) {
return Result.empty();
}
TopNNode mappedTopN = symbolMapper.get().map(parent, projectNode.getSource(), context.getIdAllocator().getNextId());
return Result.ofPlanNode(projectNode.replaceChildren(ImmutableList.of(mappedTopN)));
}
use of io.trino.sql.planner.plan.TopNNode in project trino by trinodb.
the class TestEffectivePredicateExtractor method testTopN.
@Test
public void testTopN() {
PlanNode node = new TopNNode(newId(), filter(baseTableScan, and(equals(AE, BE), equals(BE, CE), lessThan(CE, bigintLiteral(10)))), 1, new OrderingScheme(ImmutableList.of(A), ImmutableMap.of(A, SortOrder.ASC_NULLS_LAST)), TopNNode.Step.PARTIAL);
Expression effectivePredicate = effectivePredicateExtractor.extract(SESSION, node, TypeProvider.empty(), typeAnalyzer);
// Pass through
assertEquals(normalizeConjuncts(effectivePredicate), normalizeConjuncts(equals(AE, BE), equals(BE, CE), lessThan(CE, bigintLiteral(10))));
}
Aggregations