use of io.trino.sql.planner.plan.FilterNode in project trino by trinodb.
the class PushPredicateIntoTableScan method arePlansSame.
private boolean arePlansSame(FilterNode filter, TableScanNode tableScan, PlanNode rewritten) {
if (!(rewritten instanceof FilterNode)) {
return false;
}
FilterNode rewrittenFilter = (FilterNode) rewritten;
if (!Objects.equals(filter.getPredicate(), rewrittenFilter.getPredicate())) {
return false;
}
if (!(rewrittenFilter.getSource() instanceof TableScanNode)) {
return false;
}
TableScanNode rewrittenTableScan = (TableScanNode) rewrittenFilter.getSource();
return Objects.equals(tableScan.getEnforcedConstraint(), rewrittenTableScan.getEnforcedConstraint()) && Objects.equals(tableScan.getTable(), rewrittenTableScan.getTable());
}
use of io.trino.sql.planner.plan.FilterNode 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.sql.planner.plan.FilterNode in project trino by trinodb.
the class SimplifyFilterPredicate method apply.
@Override
public Result apply(FilterNode node, Captures captures, Context context) {
List<Expression> conjuncts = extractConjuncts(node.getPredicate());
ImmutableList.Builder<Expression> newConjuncts = ImmutableList.builder();
boolean simplified = false;
for (Expression conjunct : conjuncts) {
Optional<Expression> simplifiedConjunct = simplifyFilterExpression(conjunct);
if (simplifiedConjunct.isPresent()) {
simplified = true;
newConjuncts.add(simplifiedConjunct.get());
} else {
newConjuncts.add(conjunct);
}
}
if (!simplified) {
return Result.empty();
}
return Result.ofPlanNode(new FilterNode(node.getId(), node.getSource(), combineConjuncts(metadata, newConjuncts.build())));
}
use of io.trino.sql.planner.plan.FilterNode in project trino by trinodb.
the class ReplaceRedundantJoinWithSource method apply.
@Override
public Result apply(JoinNode node, Captures captures, Context context) {
if (isAtMost(node.getLeft(), context.getLookup(), 0) || isAtMost(node.getRight(), context.getLookup(), 0)) {
return Result.empty();
}
boolean leftSourceScalarWithNoOutputs = node.getLeft().getOutputSymbols().isEmpty() && isScalar(node.getLeft(), context.getLookup());
boolean rightSourceScalarWithNoOutputs = node.getRight().getOutputSymbols().isEmpty() && isScalar(node.getRight(), context.getLookup());
switch(node.getType()) {
case INNER:
PlanNode source;
List<Symbol> sourceOutputs;
if (leftSourceScalarWithNoOutputs) {
source = node.getRight();
sourceOutputs = node.getRightOutputSymbols();
} else if (rightSourceScalarWithNoOutputs) {
source = node.getLeft();
sourceOutputs = node.getLeftOutputSymbols();
} else {
return Result.empty();
}
if (node.getFilter().isPresent()) {
source = new FilterNode(context.getIdAllocator().getNextId(), source, node.getFilter().get());
}
return Result.ofPlanNode(restrictOutputs(context.getIdAllocator(), source, ImmutableSet.copyOf(sourceOutputs)).orElse(source));
case LEFT:
if (rightSourceScalarWithNoOutputs) {
return Result.ofPlanNode(restrictOutputs(context.getIdAllocator(), node.getLeft(), ImmutableSet.copyOf(node.getLeftOutputSymbols())).orElse(node.getLeft()));
}
break;
case RIGHT:
if (leftSourceScalarWithNoOutputs) {
return Result.ofPlanNode(restrictOutputs(context.getIdAllocator(), node.getRight(), ImmutableSet.copyOf(node.getRightOutputSymbols())).orElse(node.getRight()));
}
break;
case FULL:
if (leftSourceScalarWithNoOutputs && isAtLeastScalar(node.getRight(), context.getLookup())) {
return Result.ofPlanNode(restrictOutputs(context.getIdAllocator(), node.getRight(), ImmutableSet.copyOf(node.getRightOutputSymbols())).orElse(node.getRight()));
}
if (rightSourceScalarWithNoOutputs && isAtLeastScalar(node.getLeft(), context.getLookup())) {
return Result.ofPlanNode(restrictOutputs(context.getIdAllocator(), node.getLeft(), ImmutableSet.copyOf(node.getLeftOutputSymbols())).orElse(node.getLeft()));
}
}
return Result.empty();
}
use of io.trino.sql.planner.plan.FilterNode in project trino by trinodb.
the class TransformCorrelatedScalarSubquery method apply.
@Override
public Result apply(CorrelatedJoinNode correlatedJoinNode, Captures captures, Context context) {
PlanNode subquery = context.getLookup().resolve(correlatedJoinNode.getSubquery());
if (!searchFrom(subquery, context.getLookup()).where(EnforceSingleRowNode.class::isInstance).recurseOnlyWhen(ProjectNode.class::isInstance).matches()) {
return Result.empty();
}
PlanNode rewrittenSubquery = searchFrom(subquery, context.getLookup()).where(EnforceSingleRowNode.class::isInstance).recurseOnlyWhen(ProjectNode.class::isInstance).removeFirst();
Range<Long> subqueryCardinality = extractCardinality(rewrittenSubquery, context.getLookup());
boolean producesAtMostOneRow = Range.closed(0L, 1L).encloses(subqueryCardinality);
if (producesAtMostOneRow) {
boolean producesSingleRow = Range.singleton(1L).encloses(subqueryCardinality);
return Result.ofPlanNode(new CorrelatedJoinNode(context.getIdAllocator().getNextId(), correlatedJoinNode.getInput(), rewrittenSubquery, correlatedJoinNode.getCorrelation(), producesSingleRow ? correlatedJoinNode.getType() : LEFT, correlatedJoinNode.getFilter(), correlatedJoinNode.getOriginSubquery()));
}
Symbol unique = context.getSymbolAllocator().newSymbol("unique", BigintType.BIGINT);
CorrelatedJoinNode rewrittenCorrelatedJoinNode = new CorrelatedJoinNode(context.getIdAllocator().getNextId(), new AssignUniqueId(context.getIdAllocator().getNextId(), correlatedJoinNode.getInput(), unique), rewrittenSubquery, correlatedJoinNode.getCorrelation(), LEFT, correlatedJoinNode.getFilter(), correlatedJoinNode.getOriginSubquery());
Symbol isDistinct = context.getSymbolAllocator().newSymbol("is_distinct", BOOLEAN);
MarkDistinctNode markDistinctNode = new MarkDistinctNode(context.getIdAllocator().getNextId(), rewrittenCorrelatedJoinNode, isDistinct, rewrittenCorrelatedJoinNode.getInput().getOutputSymbols(), Optional.empty());
FilterNode filterNode = new FilterNode(context.getIdAllocator().getNextId(), markDistinctNode, new SimpleCaseExpression(isDistinct.toSymbolReference(), ImmutableList.of(new WhenClause(TRUE_LITERAL, TRUE_LITERAL)), Optional.of(new Cast(FunctionCallBuilder.resolve(context.getSession(), metadata).setName(QualifiedName.of("fail")).addArgument(INTEGER, new LongLiteral(Integer.toString(SUBQUERY_MULTIPLE_ROWS.toErrorCode().getCode()))).addArgument(VARCHAR, new StringLiteral("Scalar sub-query has returned multiple rows")).build(), toSqlType(BOOLEAN)))));
return Result.ofPlanNode(new ProjectNode(context.getIdAllocator().getNextId(), filterNode, Assignments.identity(correlatedJoinNode.getOutputSymbols())));
}
Aggregations