presto-main/src/main/java/io/prestosql/cost/SemiJoinStatsCalculator.java/SemiJoinStatsCalculator/compute
class SemiJoinStatsCalculator:    private static PlanNodeStatsEstimate compute(
            PlanNodeStatsEstimate sourceStats,
            PlanNodeStatsEstimate filteringSourceStats,
            Symbol sourceJoinSymbol,
            Symbol filteringSourceJoinSymbol,
            BiFunction<SymbolStatsEstimate, SymbolStatsEstimate, Double> retainedNdvProvider)
    {
        SymbolStatsEstimate sourceJoinSymbolStats = sourceStats.getSymbolStatistics(sourceJoinSymbol);
        SymbolStatsEstimate filteringSourceJoinSymbolStats = filteringSourceStats.getSymbolStatistics(filteringSourceJoinSymbol);

        double retainedNdv = retainedNdvProvider.apply(sourceJoinSymbolStats, filteringSourceJoinSymbolStats);
        SymbolStatsEstimate newSourceJoinSymbolStats = SymbolStatsEstimate.buildFrom(sourceJoinSymbolStats)
                .setNullsFraction(0)
                .setDistinctValuesCount(retainedNdv)
                .build();

        double sourceDistinctValuesCount = sourceJoinSymbolStats.getDistinctValuesCount();
        if (sourceDistinctValuesCount == 0) {
            return PlanNodeStatsEstimate.buildFrom(sourceStats)
                    .addSymbolStatistics(sourceJoinSymbol, newSourceJoinSymbolStats)
                    .setOutputRowCount(0)
                    .build();
        }

        double filterFactor = sourceJoinSymbolStats.getValuesFraction() * retainedNdv / sourceDistinctValuesCount;
        double outputRowCount = sourceStats.getOutputRowCount() * filterFactor;
        return PlanNodeStatsEstimate.buildFrom(sourceStats)
                .addSymbolStatistics(sourceJoinSymbol, newSourceJoinSymbolStats)
                .setOutputRowCount(outputRowCount)
                .build();
    }