presto-main/src/main/java/io/prestosql/sql/planner/RelationPlanner.java/RelationPlanner/planCorrelatedJoin
class RelationPlanner:    private RelationPlan planCorrelatedJoin(Join join, RelationPlan leftPlan, Lateral lateral)
    {
        RelationPlan rightPlan = process(lateral.getQuery(), null);
        PlanBuilder leftPlanBuilder = initializePlanBuilder(leftPlan);
        PlanBuilder rightPlanBuilder = initializePlanBuilder(rightPlan);

        Expression filterExpression;
        if (!join.getCriteria().isPresent()) {
            filterExpression = TRUE_LITERAL;
        }
        else {
            JoinCriteria criteria = join.getCriteria().get();
            if (criteria instanceof JoinUsing || criteria instanceof NaturalJoin) {
                throw semanticException(NOT_SUPPORTED, join, "Correlated join with criteria other than ON is not supported");
            }
            filterExpression = (Expression) getOnlyElement(criteria.getNodes());
        }

        List<Symbol> rewriterOutputSymbols = ImmutableList.<Symbol>builder()
                .addAll(leftPlan.getFieldMappings())
                .addAll(rightPlan.getFieldMappings())
                .build();
        TranslationMap translationMap = translationMapFromSourceOutputs(
                ImmutableList.<Symbol>builder()
                        .addAll(leftPlanBuilder.getRoot().getOutputSymbols())
                        .addAll(rightPlanBuilder.getRoot().getOutputSymbols())
                        .build(),
                join,
                rewriterOutputSymbols);
        translationMap.setFieldMappings(rewriterOutputSymbols);
        translationMap.putExpressionMappingsFrom(leftPlanBuilder.getTranslations());
        translationMap.putExpressionMappingsFrom(rightPlanBuilder.getTranslations());

        Expression rewrittenFilterCondition = translationMap.rewrite(filterExpression);

        PlanBuilder planBuilder = subqueryPlanner.appendCorrelatedJoin(
                leftPlanBuilder,
                rightPlanBuilder,
                lateral.getQuery(),
                true,
                CorrelatedJoinNode.Type.typeConvert(join.getType()),
                rewrittenFilterCondition);

        List<Symbol> outputSymbols = ImmutableList.<Symbol>builder()
                .addAll(leftPlan.getRoot().getOutputSymbols())
                .addAll(rightPlan.getRoot().getOutputSymbols())
                .build();
        return new RelationPlan(planBuilder.getRoot(), analysis.getScope(join), outputSymbols);
    }