public static PlanNodeStatsAssertion assertThat(PlanNodeStatsEstimate actual) { return new PlanNodeStatsAssertion(actual); }
assertThat(computeSemiJoin(inputStatistics, inputStatistics, x, w)) .symbolStats(x, stats -> stats .lowValue(xStats.getLowValue()) .highValue(xStats.getHighValue()) .nullsFraction(0) .distinctValuesCount(wStats.getDistinctValuesCount())) .symbolStats(w, stats -> stats.isEqualTo(wStats)) .symbolStats(z, stats -> stats.isEqualTo(zStats)) .outputRowsCount(inputStatistics.getOutputRowCount() * xStats.getValuesFraction() * (wStats.getDistinctValuesCount() / xStats.getDistinctValuesCount())); assertThat(computeSemiJoin(inputStatistics, inputStatistics, x, u)) .symbolStats(x, stats -> stats .lowValue(xStats.getLowValue()) .highValue(xStats.getHighValue()) .nullsFraction(0) .distinctValuesCount(xStats.getDistinctValuesCount())) .symbolStats(u, stats -> stats.isEqualTo(uStats)) .symbolStats(z, stats -> stats.isEqualTo(zStats)) .outputRowsCount(inputStatistics.getOutputRowCount() * xStats.getValuesFraction()); assertThat(computeSemiJoin(inputStatistics, inputStatistics, unknown, u)) .symbolStats(unknown, stats -> stats .nullsFraction(0) .distinctValuesCountUnknown() .unknownRange()) .symbolStats(u, stats -> stats.isEqualTo(uStats)) .symbolStats(z, stats -> stats.isEqualTo(zStats)) .outputRowsCountUnknown();
@Test public void testBooleanLiteralStats() { assertExpression("true") .equalTo(standardInputStatistics); assertExpression("false") .outputRowsCount(0.0) .symbolStats("x", SymbolStatsAssertion::empty) .symbolStats("y", SymbolStatsAssertion::empty) .symbolStats("z", SymbolStatsAssertion::empty) .symbolStats("leftOpen", SymbolStatsAssertion::empty) .symbolStats("rightOpen", SymbolStatsAssertion::empty) .symbolStats("emptyRange", SymbolStatsAssertion::empty) .symbolStats("unknownRange", SymbolStatsAssertion::empty); }
@Test public void testIsNotNullFilter() { assertExpression("x IS NOT NULL") .outputRowsCount(750.0) .symbolStats("x", symbolStats -> symbolStats.distinctValuesCount(40.0) .lowValue(-10.0) .highValue(10.0) .nullsFraction(0.0)); assertExpression("emptyRange IS NOT NULL") .outputRowsCount(0.0) .symbolStats("emptyRange", SymbolStatsAssertion::empty); }
@Test public void testAddJoinComplementStats() { double statsToAddNdv = 5; PlanNodeStatsEstimate statsToAdd = planNodeStats(RIGHT_ROWS_COUNT, symbolStatistics(LEFT_JOIN_COLUMN, 0.0, 5.0, 0.2, statsToAddNdv)); PlanNodeStatsEstimate addedStats = planNodeStats(TOTAL_ROWS_COUNT, symbolStatistics(LEFT_JOIN_COLUMN, 0.0, 20.0, (LEFT_ROWS_COUNT * LEFT_JOIN_COLUMN_NULLS + RIGHT_ROWS_COUNT * 0.2) / TOTAL_ROWS_COUNT, LEFT_JOIN_COLUMN_NDV), symbolStatistics(LEFT_OTHER_COLUMN, 42, 42, (0.42 * LEFT_ROWS_COUNT + RIGHT_ROWS_COUNT) / TOTAL_ROWS_COUNT, 1)); assertThat(JOIN_STATS_RULE.addJoinComplementStats( LEFT_STATS, LEFT_STATS, statsToAdd)) .equalTo(addedStats); }
.build()) .check(check -> { check.outputRowsCount(144) .symbolStats("a", assertion -> assertion.isEqualTo(expectedANotInC)) .symbolStats("b", assertion -> assertion.isEqualTo(bStats)) .symbolStatsUnknown("c") .symbolStatsUnknown("sjo"); });
.outputRowsCount(281.25) .symbolStats(new Symbol("x"), symbolAssert -> symbolAssert.averageRowSize(4.0) .lowValue(-7.5) .outputRowsCount(0) .symbolStats(new Symbol("x"), SymbolStatsAssertion::emptyRange) .symbolStats(new Symbol("y"), SymbolStatsAssertion::emptyRange); .outputRowsCount(337.5) .symbolStats(new Symbol("x"), symbolAssert -> symbolAssert.lowValue(-10) .highValue(0) .outputRowsCount(337.5) .symbolStats(new Symbol("x"), symbolAssert -> symbolAssert.lowValue(-10) .highValue(0) .outputRowsCountUnknown(); .outputRowsCount(0);
@Test public void testDropNonOutputSymbols() { Symbol a = new Symbol("a"); Symbol b = new Symbol("b"); Symbol c = new Symbol("c"); PlanNodeStatsEstimate estimate = PlanNodeStatsEstimate.builder() .setOutputRowCount(40) .addSymbolStatistics(a, SymbolStatsEstimate.builder().setDistinctValuesCount(20).build()) .addSymbolStatistics(b, SymbolStatsEstimate.builder().setDistinctValuesCount(30).build()) .addSymbolStatistics(c, SymbolStatsEstimate.unknown()) .build(); PlanNodeStatsAssertion.assertThat(normalizer.normalize(estimate, ImmutableList.of(b, c), TypeProvider.copyOf(ImmutableMap.of(b, BIGINT, c, BIGINT)))) .symbolsWithKnownStats(b) .symbolStats(b, symbolAssert -> symbolAssert.distinctValuesCount(30)); }
@Test public void testStatsForValuesNodeWithJustNulls() { PlanNodeStatsEstimate nullAStats = PlanNodeStatsEstimate.builder() .setOutputRowCount(1) .addSymbolStatistics(new Symbol("a"), SymbolStatsEstimate.zero()) .build(); tester().assertStatsFor(pb -> pb .values(ImmutableList.of(pb.symbol("a", BIGINT)), ImmutableList.of( ImmutableList.of(expression("3 + null"))))) .check(outputStats -> outputStats.equalTo(nullAStats)); tester().assertStatsFor(pb -> pb .values(ImmutableList.of(pb.symbol("a", BIGINT)), ImmutableList.of( ImmutableList.of(expression("null"))))) .check(outputStats -> outputStats.equalTo(nullAStats)); tester().assertStatsFor(pb -> pb .values(ImmutableList.of(pb.symbol("a", UNKNOWN)), ImmutableList.of( ImmutableList.of(expression("null"))))) .check(outputStats -> outputStats.equalTo(nullAStats)); }
public PlanNodeStatsAssertion symbolStats(String symbolName, Consumer<SymbolStatsAssertion> symbolStatsAssertionConsumer) { return symbolStats(new Symbol(symbolName), symbolStatsAssertionConsumer); }
private PlanNodeStatsAssertion assertExpression(Expression expression) { return PlanNodeStatsAssertion.assertThat(statsCalculator.filterStats( standardInputStatistics, expression, session, standardTypes)); } }
@Test public void testUnsupportedExpression() { assertExpression("sin(x)") .outputRowsCountUnknown(); assertExpression("x = sin(x)") .outputRowsCountUnknown(); }
public PlanNodeStatsAssertion symbolStatsUnknown(String symbolName) { return symbolStatsUnknown(new Symbol(symbolName)); }
public PlanNodeStatsAssertion equalTo(PlanNodeStatsEstimate expected) { assertEstimateEquals(actual.getOutputRowCount(), expected.getOutputRowCount(), "outputRowCount mismatch"); for (Symbol symbol : union(expected.getSymbolsWithKnownStatistics(), actual.getSymbolsWithKnownStatistics())) { assertSymbolStatsEqual(symbol, actual.getSymbolStatistics(symbol), expected.getSymbolStatistics(symbol)); } return this; }
@Test public void testAggregationStatsCappedToInputRows() { tester().assertStatsFor(pb -> pb .aggregation(ab -> ab .addAggregation(pb.symbol("count_on_x", BIGINT), expression("count(x)"), ImmutableList.of(BIGINT)) .singleGroupingSet(pb.symbol("y", BIGINT), pb.symbol("z", BIGINT)) .source(pb.values(pb.symbol("x", BIGINT), pb.symbol("y", BIGINT), pb.symbol("z", BIGINT))))) .withSourceStats(PlanNodeStatsEstimate.builder() .setOutputRowCount(100) .addSymbolStatistics(new Symbol("y"), SymbolStatsEstimate.builder().setDistinctValuesCount(50).build()) .addSymbolStatistics(new Symbol("z"), SymbolStatsEstimate.builder().setDistinctValuesCount(50).build()) .build()) .check(check -> check.outputRowsCount(100)); } }
@Test public void testIsNullFilter() { assertExpression("x IS NULL") .outputRowsCount(250.0) .symbolStats(new Symbol("x"), symbolStats -> symbolStats.distinctValuesCount(0) .emptyRange() .nullsFraction(1.0)); assertExpression("emptyRange IS NULL") .outputRowsCount(1000.0) .symbolStats(new Symbol("emptyRange"), SymbolStatsAssertion::empty); }
.build()) .check(check -> { check.outputRowsCount(180) .symbolStats("a", assertion -> assertion.isEqualTo(expectedAInC)) .symbolStatsUnknown("b") .symbolStatsUnknown("c") .symbolStatsUnknown("sjo"); });
@Test public void testNotStats() { assertExpression("NOT(x < 0e0)") .outputRowsCount(625) // FIXME - nulls shouldn't be restored .symbolStats(new Symbol("x"), symbolAssert -> symbolAssert.averageRowSize(4.0) .lowValue(-10.0) .highValue(10.0) .distinctValuesCount(20.0) .nullsFraction(0.4)) // FIXME - nulls shouldn't be restored .symbolStats(new Symbol("y"), symbolAssert -> symbolAssert.isEqualTo(yStats)); assertExpression("NOT(x IS NULL)") .outputRowsCount(750) .symbolStats(new Symbol("x"), symbolAssert -> symbolAssert.averageRowSize(4.0) .lowValue(-10.0) .highValue(10.0) .distinctValuesCount(40.0) .nullsFraction(0)) .symbolStats(new Symbol("y"), symbolAssert -> symbolAssert.isEqualTo(yStats)); assertExpression("NOT(json_array_contains(JSON '[]', x))") .outputRowsCountUnknown(); }
@Test public void testStatsForEmptyValues() { tester().assertStatsFor(pb -> pb .values(ImmutableList.of(pb.symbol("a", BIGINT)), ImmutableList.of())) .check(outputStats -> outputStats.equalTo( PlanNodeStatsEstimate.builder() .setOutputRowCount(0) .addSymbolStatistics(new Symbol("a"), SymbolStatsEstimate.zero()) .build())); } }
public PlanNodeStatsAssertion symbolStatsUnknown(Symbol symbol) { return symbolStats(symbol, columnStats -> columnStats .lowValueUnknown() .highValueUnknown() .nullsFractionUnknown() .distinctValuesCountUnknown()); }