Source:
PlanNodeStatsEstimate addJoinComplementStats( PlanNodeStatsEstimate leftStats, PlanNodeStatsEstimate innerJoinStats, PlanNodeStatsEstimate joinComplementStats) { double innerJoinRowCount = innerJoinStats.getOutputRowCount(); double joinComplementRowCount = joinComplementStats.getOutputRowCount(); double outputRowCount = innerJoinRowCount + joinComplementRowCount; PlanNodeStatsEstimate.Builder outputStats = PlanNodeStatsEstimate.buildFrom(innerJoinStats); outputStats.setOutputRowCount(outputRowCount); for (Symbol symbol : joinComplementStats.getSymbolsWithKnownStatistics()) { SymbolStatsEstimate leftSymbolStats = leftStats.getSymbolStatistics(symbol); SymbolStatsEstimate innerJoinSymbolStats = innerJoinStats.getSymbolStatistics(symbol); SymbolStatsEstimate joinComplementSymbolStats = joinComplementStats.getSymbolStatistics(symbol); double newNullsFraction = outputRowCount == 0 ? 1 : ((innerJoinSymbolStats.getNullsFraction() * innerJoinRowCount + joinComplementSymbolStats.getNullsFraction() * joinComplementRowCount) / outputRowCount); outputStats.addSymbolStatistics(symbol, SymbolStatsEstimate.buildFrom(innerJoinSymbolStats) .setLowValue(leftSymbolStats.getLowValue()) .setHighValue(leftSymbolStats.getHighValue()) .setDistinctValuesCount(leftSymbolStats.getDistinctValuesCount()) .setNullsFraction(newNullsFraction) .build()); } for (Symbol symbol : difference(innerJoinStats.getSymbolsWithKnownStatistics(), joinComplementStats.getSymbolsWithKnownStatistics())) { SymbolStatsEstimate innerJoinSymbolStats = innerJoinStats.getSymbolStatistics(symbol); double newNullsFraction = outputRowCount == 0 ? 1 : ((innerJoinSymbolStats.getNullsFraction() * innerJoinRowCount + joinComplementRowCount) / outputRowCount); outputStats.addSymbolStatistics(symbol, innerJoinSymbolStats.mapNullsFraction(nullsFraction -> newNullsFraction)); } return outputStats.build(); }

Target:
PlanNodeStatsEstimate addJoinComplementStats( PlanNodeStatsEstimate leftStats, PlanNodeStatsEstimate innerJoinStats, PlanNodeStatsEstimate joinComplementStats) { double joinComplementRowCount = joinComplementStats.getOutputRowCount(); if (joinComplementRowCount == 0) { return innerJoinStats; } double innerJoinRowCount = innerJoinStats.getOutputRowCount(); double outputRowCount = innerJoinRowCount + joinComplementRowCount; PlanNodeStatsEstimate.Builder outputStats = PlanNodeStatsEstimate.buildFrom(innerJoinStats); outputStats.setOutputRowCount(outputRowCount); for (Symbol symbol : joinComplementStats.getSymbolsWithKnownStatistics()) { SymbolStatsEstimate leftSymbolStats = leftStats.getSymbolStatistics(symbol); SymbolStatsEstimate innerJoinSymbolStats = innerJoinStats.getSymbolStatistics(symbol); SymbolStatsEstimate joinComplementSymbolStats = joinComplementStats.getSymbolStatistics(symbol); double newNullsFraction = (innerJoinSymbolStats.getNullsFraction() * innerJoinRowCount + joinComplementSymbolStats.getNullsFraction() * joinComplementRowCount) / outputRowCount; outputStats.addSymbolStatistics(symbol, SymbolStatsEstimate.buildFrom(innerJoinSymbolStats) .setLowValue(leftSymbolStats.getLowValue()) .setHighValue(leftSymbolStats.getHighValue()) .setDistinctValuesCount(leftSymbolStats.getDistinctValuesCount()) .setNullsFraction(newNullsFraction) .build()); } for (Symbol symbol : difference(innerJoinStats.getSymbolsWithKnownStatistics(), joinComplementStats.getSymbolsWithKnownStatistics())) { SymbolStatsEstimate innerJoinSymbolStats = innerJoinStats.getSymbolStatistics(symbol); double newNullsFraction = (innerJoinSymbolStats.getNullsFraction() * innerJoinRowCount + joinComplementRowCount) / outputRowCount; outputStats.addSymbolStatistics(symbol, innerJoinSymbolStats.mapNullsFraction(nullsFraction -> newNullsFraction)); } return outputStats.build(); }