presto-main/src/main/java/io/prestosql/sql/planner/iterative/rule/TransformCorrelatedJoinToJoin.java/TransformCorrelatedJoinToJoin/apply
class TransformCorrelatedJoinToJoin:    @Override
    public Result apply(CorrelatedJoinNode correlatedJoinNode, Captures captures, Context context)
    {
        checkArgument(correlatedJoinNode.getType().equals(INNER) || correlatedJoinNode.getType().equals(LEFT), "correlation in %s JOIN", correlatedJoinNode.getType().name());
        PlanNode subquery = correlatedJoinNode.getSubquery();

        PlanNodeDecorrelator planNodeDecorrelator = new PlanNodeDecorrelator(metadata, context.getSymbolAllocator(), context.getLookup());
        Optional<DecorrelatedNode> decorrelatedNodeOptional = planNodeDecorrelator.decorrelateFilters(subquery, correlatedJoinNode.getCorrelation());
        if (!decorrelatedNodeOptional.isPresent()) {
            return Result.empty();
        }
        DecorrelatedNode decorrelatedSubquery = decorrelatedNodeOptional.get();

        Expression filter = combineConjuncts(
                metadata,
                decorrelatedSubquery.getCorrelatedPredicates().orElse(TRUE_LITERAL),
                correlatedJoinNode.getFilter());

        return Result.ofPlanNode(new JoinNode(
                correlatedJoinNode.getId(),
                correlatedJoinNode.getType().toJoinNodeType(),
                correlatedJoinNode.getInput(),
                decorrelatedSubquery.getNode(),
                ImmutableList.of(),
                correlatedJoinNode.getOutputSymbols(),
                filter.equals(TRUE_LITERAL) ? Optional.empty() : Optional.of(filter),
                Optional.empty(),
                Optional.empty(),
                Optional.empty(),
                Optional.empty(),
                ImmutableMap.of()));
    }