use of io.trino.matching.Captures in project trino by trinodb.
the class PushDownDereferencesThroughSort method apply.
@Override
public Result apply(ProjectNode projectNode, Captures captures, Context context) {
SortNode sortNode = 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 used in ordering scheme to avoid replication of data
dereferences = dereferences.stream().filter(expression -> !sortNode.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(), sortNode.replaceChildren(ImmutableList.of(new ProjectNode(context.getIdAllocator().getNextId(), sortNode.getSource(), Assignments.builder().putIdentities(sortNode.getSource().getOutputSymbols()).putAll(dereferenceAssignments).build()))), newAssignments));
}
use of io.trino.matching.Captures in project trino by trinodb.
the class PushDownDereferenceThroughFilter method apply.
@Override
public Result apply(ProjectNode node, Captures captures, Rule.Context context) {
FilterNode filterNode = captures.get(CHILD);
// Pushdown superset of dereference expressions from projections and filtering predicate
List<Expression> expressions = ImmutableList.<Expression>builder().addAll(node.getAssignments().getExpressions()).add(filterNode.getPredicate()).build();
// Extract dereferences from project node assignments for pushdown
Set<SubscriptExpression> dereferences = extractRowSubscripts(expressions, false, context.getSession(), typeAnalyzer, context.getSymbolAllocator().getTypes());
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 assignments = node.getAssignments().rewrite(expression -> replaceExpression(expression, mappings));
PlanNode source = filterNode.getSource();
return Result.ofPlanNode(new ProjectNode(context.getIdAllocator().getNextId(), new FilterNode(context.getIdAllocator().getNextId(), new ProjectNode(context.getIdAllocator().getNextId(), source, Assignments.builder().putIdentities(source.getOutputSymbols()).putAll(dereferenceAssignments).build()), replaceExpression(filterNode.getPredicate(), mappings)), assignments));
}
use of io.trino.matching.Captures in project trino by trinodb.
the class SingleDistinctAggregationToGroupBy method apply.
@Override
public Result apply(AggregationNode aggregation, Captures captures, Context context) {
List<Set<Expression>> argumentSets = extractArgumentSets(aggregation).collect(Collectors.toList());
Set<Symbol> symbols = Iterables.getOnlyElement(argumentSets).stream().map(Symbol::from).collect(Collectors.toSet());
return Result.ofPlanNode(new AggregationNode(aggregation.getId(), new AggregationNode(context.getIdAllocator().getNextId(), aggregation.getSource(), ImmutableMap.of(), singleGroupingSet(ImmutableList.<Symbol>builder().addAll(aggregation.getGroupingKeys()).addAll(symbols).build()), ImmutableList.of(), SINGLE, Optional.empty(), Optional.empty()), // remove DISTINCT flag from function calls
aggregation.getAggregations().entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, e -> removeDistinct(e.getValue()))), aggregation.getGroupingSets(), emptyList(), aggregation.getStep(), aggregation.getHashSymbol(), aggregation.getGroupIdSymbol()));
}
use of io.trino.matching.Captures in project trino by trinodb.
the class TransformCorrelatedSingleRowSubqueryToProject method apply.
@Override
public Result apply(CorrelatedJoinNode parent, Captures captures, Context context) {
List<ValuesNode> values = searchFrom(parent.getSubquery(), context.getLookup()).recurseOnlyWhen(ProjectNode.class::isInstance).where(ValuesNode.class::isInstance).findAll();
if (values.size() != 1 || !isSingleRowValuesWithNoColumns(values.get(0))) {
return Result.empty();
}
List<ProjectNode> subqueryProjections = searchFrom(parent.getSubquery(), context.getLookup()).where(node -> node instanceof ProjectNode && !node.getOutputSymbols().equals(parent.getCorrelation())).findAll();
if (subqueryProjections.size() == 0) {
return Result.ofPlanNode(parent.getInput());
}
if (subqueryProjections.size() == 1) {
Assignments assignments = Assignments.builder().putIdentities(parent.getInput().getOutputSymbols()).putAll(subqueryProjections.get(0).getAssignments()).build();
return Result.ofPlanNode(projectNode(parent.getInput(), assignments, context));
}
return Result.empty();
}
use of io.trino.matching.Captures in project trino by trinodb.
the class TransformFilteringSemiJoinToInnerJoin method apply.
@Override
public Result apply(FilterNode filterNode, Captures captures, Context context) {
SemiJoinNode semiJoin = captures.get(SEMI_JOIN);
// Do not transform semi-join in context of DELETE
if (PlanNodeSearcher.searchFrom(semiJoin.getSource(), context.getLookup()).where(node -> node instanceof TableScanNode && ((TableScanNode) node).isUpdateTarget()).matches()) {
return Result.empty();
}
Symbol semiJoinSymbol = semiJoin.getSemiJoinOutput();
Predicate<Expression> isSemiJoinSymbol = expression -> expression.equals(semiJoinSymbol.toSymbolReference());
List<Expression> conjuncts = extractConjuncts(filterNode.getPredicate());
if (conjuncts.stream().noneMatch(isSemiJoinSymbol)) {
return Result.empty();
}
Expression filteredPredicate = and(conjuncts.stream().filter(not(isSemiJoinSymbol)).collect(toImmutableList()));
Expression simplifiedPredicate = inlineSymbols(symbol -> {
if (symbol.equals(semiJoinSymbol)) {
return TRUE_LITERAL;
}
return symbol.toSymbolReference();
}, filteredPredicate);
Optional<Expression> joinFilter = simplifiedPredicate.equals(TRUE_LITERAL) ? Optional.empty() : Optional.of(simplifiedPredicate);
PlanNode filteringSourceDistinct = new AggregationNode(context.getIdAllocator().getNextId(), semiJoin.getFilteringSource(), ImmutableMap.of(), singleGroupingSet(ImmutableList.of(semiJoin.getFilteringSourceJoinSymbol())), ImmutableList.of(), SINGLE, Optional.empty(), Optional.empty());
JoinNode innerJoin = new JoinNode(semiJoin.getId(), INNER, semiJoin.getSource(), filteringSourceDistinct, ImmutableList.of(new EquiJoinClause(semiJoin.getSourceJoinSymbol(), semiJoin.getFilteringSourceJoinSymbol())), semiJoin.getSource().getOutputSymbols(), ImmutableList.of(), false, joinFilter, Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), semiJoin.getDynamicFilterId().map(id -> ImmutableMap.of(id, semiJoin.getFilteringSourceJoinSymbol())).orElse(ImmutableMap.of()), Optional.empty());
ProjectNode project = new ProjectNode(context.getIdAllocator().getNextId(), innerJoin, Assignments.builder().putIdentities(innerJoin.getOutputSymbols()).put(semiJoinSymbol, TRUE_LITERAL).build());
return Result.ofPlanNode(project);
}
Aggregations