use of io.trino.sql.tree.SubscriptExpression in project trino by trinodb.
the class ExtractDereferencesFromFilterAboveScan method apply.
@Override
public Result apply(FilterNode node, Captures captures, Context context) {
Set<SubscriptExpression> dereferences = extractRowSubscripts(ImmutableList.of(node.getPredicate()), true, context.getSession(), typeAnalyzer, context.getSymbolAllocator().getTypes());
if (dereferences.isEmpty()) {
return Result.empty();
}
Assignments assignments = Assignments.of(dereferences, context.getSession(), context.getSymbolAllocator(), typeAnalyzer);
Map<Expression, SymbolReference> mappings = HashBiMap.create(assignments.getMap()).inverse().entrySet().stream().collect(toImmutableMap(Map.Entry::getKey, entry -> entry.getValue().toSymbolReference()));
PlanNode source = node.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(assignments).build()), replaceExpression(node.getPredicate(), mappings)), Assignments.identity(node.getOutputSymbols())));
}
use of io.trino.sql.tree.SubscriptExpression in project trino by trinodb.
the class DereferencePushdown method prefixExists.
private static boolean prefixExists(Expression expression, Set<Expression> expressions) {
Expression current = expression;
while (current instanceof SubscriptExpression) {
current = ((SubscriptExpression) current).getBase();
if (expressions.contains(current)) {
return true;
}
}
verify(current instanceof SymbolReference);
return false;
}
use of io.trino.sql.tree.SubscriptExpression in project trino by trinodb.
the class PushDownDereferenceThroughJoin method apply.
@Override
public Result apply(ProjectNode projectNode, Captures captures, Context context) {
JoinNode joinNode = captures.get(CHILD);
// Consider dereferences in projections and join filter for pushdown
ImmutableList.Builder<Expression> expressionsBuilder = ImmutableList.builder();
expressionsBuilder.addAll(projectNode.getAssignments().getExpressions());
joinNode.getFilter().ifPresent(expressionsBuilder::add);
Set<SubscriptExpression> dereferences = extractRowSubscripts(expressionsBuilder.build(), false, context.getSession(), typeAnalyzer, context.getSymbolAllocator().getTypes());
// Exclude criteria symbols
ImmutableSet.Builder<Symbol> criteriaSymbolsBuilder = ImmutableSet.builder();
joinNode.getCriteria().forEach(criteria -> {
criteriaSymbolsBuilder.add(criteria.getLeft());
criteriaSymbolsBuilder.add(criteria.getRight());
});
Set<Symbol> excludeSymbols = criteriaSymbolsBuilder.build();
dereferences = dereferences.stream().filter(expression -> !excludeSymbols.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));
Assignments.Builder leftAssignmentsBuilder = Assignments.builder();
Assignments.Builder rightAssignmentsBuilder = Assignments.builder();
// Separate dereferences coming from left and right nodes
dereferenceAssignments.entrySet().stream().forEach(entry -> {
Symbol baseSymbol = getOnlyElement(extractAll(entry.getValue()));
if (joinNode.getLeft().getOutputSymbols().contains(baseSymbol)) {
leftAssignmentsBuilder.put(entry.getKey(), entry.getValue());
} else if (joinNode.getRight().getOutputSymbols().contains(baseSymbol)) {
rightAssignmentsBuilder.put(entry.getKey(), entry.getValue());
} else {
throw new IllegalArgumentException(format("Unexpected symbol %s in projectNode", baseSymbol));
}
});
Assignments leftAssignments = leftAssignmentsBuilder.build();
Assignments rightAssignments = rightAssignmentsBuilder.build();
PlanNode leftNode = createProjectNodeIfRequired(joinNode.getLeft(), leftAssignments, context.getIdAllocator());
PlanNode rightNode = createProjectNodeIfRequired(joinNode.getRight(), rightAssignments, context.getIdAllocator());
// Prepare new output symbols for join node
List<Symbol> referredSymbolsInAssignments = newAssignments.getExpressions().stream().flatMap(expression -> extractAll(expression).stream()).collect(toList());
List<Symbol> newLeftOutputSymbols = referredSymbolsInAssignments.stream().filter(symbol -> leftNode.getOutputSymbols().contains(symbol)).collect(toList());
List<Symbol> newRightOutputSymbols = referredSymbolsInAssignments.stream().filter(symbol -> rightNode.getOutputSymbols().contains(symbol)).collect(toList());
JoinNode newJoinNode = new JoinNode(context.getIdAllocator().getNextId(), joinNode.getType(), leftNode, rightNode, joinNode.getCriteria(), newLeftOutputSymbols, newRightOutputSymbols, joinNode.isMaySkipOutputDuplicates(), // Use newly created symbols in filter
joinNode.getFilter().map(expression -> replaceExpression(expression, mappings)), joinNode.getLeftHashSymbol(), joinNode.getRightHashSymbol(), joinNode.getDistributionType(), joinNode.isSpillable(), joinNode.getDynamicFilters(), joinNode.getReorderJoinStatsAndCost());
return Result.ofPlanNode(new ProjectNode(context.getIdAllocator().getNextId(), newJoinNode, newAssignments));
}
use of io.trino.sql.tree.SubscriptExpression in project trino by trinodb.
the class PushDownDereferenceThroughProject method apply.
@Override
public Result apply(ProjectNode node, Captures captures, Context context) {
ProjectNode child = captures.get(CHILD);
// Extract dereferences from project node assignments for pushdown
Set<SubscriptExpression> dereferences = extractRowSubscripts(node.getAssignments().getExpressions(), false, context.getSession(), typeAnalyzer, context.getSymbolAllocator().getTypes());
// Exclude dereferences on symbols being synthesized within child
dereferences = dereferences.stream().filter(expression -> child.getSource().getOutputSymbols().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 assignments = node.getAssignments().rewrite(expression -> replaceExpression(expression, mappings));
return Result.ofPlanNode(new ProjectNode(context.getIdAllocator().getNextId(), new ProjectNode(context.getIdAllocator().getNextId(), child.getSource(), Assignments.builder().putAll(child.getAssignments()).putAll(dereferenceAssignments).build()), assignments));
}
use of io.trino.sql.tree.SubscriptExpression in project trino by trinodb.
the class PushDownDereferenceThroughSemiJoin method apply.
@Override
public Result apply(ProjectNode projectNode, Captures captures, Context context) {
SemiJoinNode semiJoinNode = 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());
// All dereferences can be assumed on the symbols coming from source, since filteringSource output is not propagated,
// and semiJoinOutput is of type boolean. We exclude pushdown of dereferences on sourceJoinSymbol.
dereferences = dereferences.stream().filter(expression -> !getBase(expression).equals(semiJoinNode.getSourceJoinSymbol())).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 assignments = projectNode.getAssignments().rewrite(expression -> replaceExpression(expression, mappings));
PlanNode newSource = new ProjectNode(context.getIdAllocator().getNextId(), semiJoinNode.getSource(), Assignments.builder().putIdentities(semiJoinNode.getSource().getOutputSymbols()).putAll(dereferenceAssignments).build());
PlanNode newSemiJoin = semiJoinNode.replaceChildren(ImmutableList.of(newSource, semiJoinNode.getFilteringSource()));
return Result.ofPlanNode(new ProjectNode(context.getIdAllocator().getNextId(), newSemiJoin, assignments));
}
Aggregations