public SymbolReference toSymbolReference() { return new SymbolReference(name); }
@Override public Expression rewriteIdentifier(Identifier node, Void context, ExpressionTreeRewriter<Void> treeRewriter) { return new SymbolReference(node.getValue()); }
private static SymbolReference nameReference(String symbol) { return new SymbolReference(symbol); }
public static Optional<Expression> getHashExpression(List<Symbol> symbols) { if (symbols.isEmpty()) { return Optional.empty(); } Expression result = new LongLiteral(String.valueOf(INITIAL_HASH_VALUE)); for (Symbol symbol : symbols) { Expression hashField = new FunctionCall( QualifiedName.of(HASH_CODE), Optional.empty(), false, ImmutableList.of(new SymbolReference(symbol.getName()))); hashField = new CoalesceExpression(hashField, new LongLiteral(String.valueOf(NULL_HASH_CODE))); result = new FunctionCall(QualifiedName.of("combine_hash"), ImmutableList.of(result, hashField)); } return Optional.of(result); }
private static void assertGetSortExpression(Expression expression, String expectedSymbol, List<Expression> searchExpressions) { Optional<SortExpressionContext> expected = Optional.of(new SortExpressionContext(new SymbolReference(expectedSymbol), searchExpressions)); Optional<SortExpressionContext> actual = SortExpressionExtractor.extractSortExpression(BUILD_SYMBOLS, expression); assertEquals(actual, expected); } }
@Test public void dependentWindowsAreNotReordered() { Optional<Window> windowA = Optional.of(new Window(ImmutableList.of(new SymbolReference("a")), Optional.empty(), Optional.empty())); tester().assertThat(new GatherAndMergeWindows.SwapAdjacentWindowsBySpecifications(0)) .on(p -> p.window(new WindowNode.Specification( ImmutableList.of(p.symbol("a")), Optional.empty()), ImmutableMap.of(p.symbol("avg_1"), new WindowNode.Function(new FunctionCall(QualifiedName.of("avg"), windowA, false, ImmutableList.of(new SymbolReference("avg_2"))), signature, frame)), p.window(new WindowNode.Specification( ImmutableList.of(p.symbol("a"), p.symbol("b")), Optional.empty()), ImmutableMap.of(p.symbol("avg_2"), new WindowNode.Function(new FunctionCall(QualifiedName.of("avg"), windowA, false, ImmutableList.of(new SymbolReference("a"))), signature, frame)), p.values(p.symbol("a"), p.symbol("b"))))) .doesNotFire(); } }
@Test public void testCastUnknown() { assertCalculate(new Cast(new SymbolReference("a"), "bigint"), PlanNodeStatsEstimate.unknown()) .lowValueUnknown() .highValueUnknown() .distinctValuesCountUnknown() .nullsFractionUnknown() .dataSizeUnknown(); }
@Test public void testFiresForInPredicate() { tester().assertThat(new TransformUncorrelatedInPredicateSubqueryToSemiJoin()) .on(p -> p.apply( Assignments.of( p.symbol("x"), new InPredicate( new SymbolReference("y"), new SymbolReference("z"))), emptyList(), p.values(p.symbol("y")), p.values(p.symbol("z")))) .matches(node(SemiJoinNode.class, values("y"), values("z"))); } }
@Test public void test() { Expression actual = expression("NOT(orderkey = 3 AND custkey = 3 AND orderkey < 10)"); SymbolAliases symbolAliases = SymbolAliases.builder() .put("X", new SymbolReference("orderkey")) .put("Y", new SymbolReference("custkey")) .build(); ExpressionVerifier verifier = new ExpressionVerifier(symbolAliases); assertTrue(verifier.process(actual, expression("NOT(X = 3 AND Y = 3 AND X < 10)"))); assertThrows(() -> verifier.process(actual, expression("NOT(X = 3 AND Y = 3 AND Z < 10)"))); assertFalse(verifier.process(actual, expression("NOT(X = 3 AND X = 3 AND X < 10)"))); }
@Test public void testCast() { SymbolAliases aliases = SymbolAliases.builder() .put("X", new SymbolReference("orderkey")) .build(); ExpressionVerifier verifier = new ExpressionVerifier(aliases); assertTrue(verifier.process(expression("CAST('2' AS varchar)"), expression("CAST('2' AS varchar)"))); assertFalse(verifier.process(expression("CAST('2' AS varchar)"), expression("CAST('2' AS bigint)"))); assertTrue(verifier.process(expression("CAST(orderkey AS varchar)"), expression("CAST(X AS varchar)"))); }
@Test public void symbolToCastExpressionNotEqual() { double rowCount = 807.3; assertCalculate(new ComparisonExpression(NOT_EQUAL, new SymbolReference("u"), new Cast(new SymbolReference("w"), BIGINT))) .outputRowsCount(rowCount) .symbolStats("u", equalTo(capNDV(zeroNullsFraction(uStats), rowCount))) .symbolStats("w", equalTo(capNDV(wStats, rowCount))) .symbolStats("z", equalTo(capNDV(zStats, rowCount))); rowCount = 897.0; assertCalculate(new ComparisonExpression(NOT_EQUAL, new SymbolReference("u"), new Cast(new LongLiteral("10"), BIGINT))) .outputRowsCount(rowCount) .symbolStats("u", equalTo(capNDV(updateNDV(zeroNullsFraction(uStats), -1), rowCount))) .symbolStats("z", equalTo(capNDV(zStats, rowCount))); }
private static Expression ensureScalarSubquery() { return new SimpleCaseExpression( new SymbolReference("is_distinct"), ImmutableList.of(new WhenClause(TRUE_LITERAL, TRUE_LITERAL)), Optional.of(new Cast(new FunctionCall( QualifiedName.of("fail"), ImmutableList.of( new LongLiteral(Long.toString(StandardErrorCode.SUBQUERY_MULTIPLE_ROWS.ordinal())), new StringLiteral("Scalar sub-query has returned multiple rows"))), StandardTypes.BOOLEAN))); } }
@Test public void testGiveUpOnNonIdentityProjections() { PlanNode plan = joinNode( projectNode( joinNode( values(symbol("a1")), values(symbol("b"))), symbol("a2"), new ArithmeticUnaryExpression(MINUS, new SymbolReference("a1"))), values(symbol("c")), symbol("a2"), symbol("c"), symbol("c"), symbol("b")); assertEquals(JoinGraph.buildFrom(plan).size(), 2); }
@Test public void testBetween() { SymbolAliases symbolAliases = SymbolAliases.builder() .put("X", new SymbolReference("orderkey")) .put("Y", new SymbolReference("custkey")) .build(); ExpressionVerifier verifier = new ExpressionVerifier(symbolAliases); // Complete match assertTrue(verifier.process(expression("orderkey BETWEEN 1 AND 2"), expression("X BETWEEN 1 AND 2"))); // Different value assertFalse(verifier.process(expression("orderkey BETWEEN 1 AND 2"), expression("Y BETWEEN 1 AND 2"))); assertFalse(verifier.process(expression("custkey BETWEEN 1 AND 2"), expression("X BETWEEN 1 AND 2"))); // Different min or max assertFalse(verifier.process(expression("orderkey BETWEEN 2 AND 4"), expression("X BETWEEN 1 AND 2"))); assertFalse(verifier.process(expression("orderkey BETWEEN 1 AND 2"), expression("X BETWEEN '1' AND '2'"))); assertFalse(verifier.process(expression("orderkey BETWEEN 1 AND 2"), expression("X BETWEEN 4 AND 7"))); }
@Test public void testProject() { TableScanNode tableScan = tableScan("ts", "orderkey"); PlanNode project = project("project", tableScan, "string", new Cast(new SymbolReference("orderkey"), "STRING")); Map<String, PlanNodeCostEstimate> costs = ImmutableMap.of("ts", cpuCost(1000)); Map<String, PlanNodeStatsEstimate> stats = ImmutableMap.of( "project", statsEstimate(project, 4000), "ts", statsEstimate(tableScan, 1000)); Map<String, Type> types = ImmutableMap.of( "orderkey", BIGINT, "string", VARCHAR); assertCost(project, costs, stats, types) .cpu(1000 + 4000 * OFFSET_AND_IS_NULL_OVERHEAD) .memory(0) .network(0); assertCostEstimatedExchanges(project, costs, stats, types) .cpu(1000 + 4000 * OFFSET_AND_IS_NULL_OVERHEAD) .memory(0) .network(0); assertCostFragmentedPlan(project, costs, stats, types) .cpu(1000 + 4000 * OFFSET_AND_IS_NULL_OVERHEAD) .memory(0) .network(0); assertCostHasUnknownComponentsForUnknownStats(project, types); }
@Test public void testFunctionCall() { assertCalculate( new FunctionCall( QualifiedName.of("length"), ImmutableList.of(new Cast(new NullLiteral(), "VARCHAR(10)")))) .distinctValuesCount(0.0) .lowValueUnknown() .highValueUnknown() .nullsFraction(1.0); assertCalculate( new FunctionCall( QualifiedName.of("length"), ImmutableList.of(new SymbolReference("x"))), PlanNodeStatsEstimate.unknown(), TypeProvider.viewOf(ImmutableMap.of(new Symbol("x"), createVarcharType(2)))) .distinctValuesCountUnknown() .lowValueUnknown() .highValueUnknown() .nullsFractionUnknown(); }
@Test public void testCastDoubleToShortRangeUnknownDistinctValuesCount() { PlanNodeStatsEstimate inputStatistics = PlanNodeStatsEstimate.builder() .addSymbolStatistics(new Symbol("a"), SymbolStatsEstimate.builder() .setNullsFraction(0.3) .setLowValue(1.6) .setHighValue(3.3) .setAverageRowSize(2.0) .build()) .build(); assertCalculate(new Cast(new SymbolReference("a"), "bigint"), inputStatistics) .lowValue(2.0) .highValue(3.0) .distinctValuesCountUnknown() .nullsFraction(0.3) .dataSizeUnknown(); }
@Test public void testCastDoubleToShortRange() { PlanNodeStatsEstimate inputStatistics = PlanNodeStatsEstimate.builder() .addSymbolStatistics(new Symbol("a"), SymbolStatsEstimate.builder() .setNullsFraction(0.3) .setLowValue(1.6) .setHighValue(3.3) .setDistinctValuesCount(10) .setAverageRowSize(2.0) .build()) .build(); assertCalculate(new Cast(new SymbolReference("a"), "bigint"), inputStatistics) .lowValue(2.0) .highValue(3.0) .distinctValuesCount(2) .nullsFraction(0.3) .dataSizeUnknown(); }
@Test public void testCastDoubleToBigint() { PlanNodeStatsEstimate inputStatistics = PlanNodeStatsEstimate.builder() .addSymbolStatistics(new Symbol("a"), SymbolStatsEstimate.builder() .setNullsFraction(0.3) .setLowValue(1.6) .setHighValue(17.3) .setDistinctValuesCount(10) .setAverageRowSize(2.0) .build()) .build(); assertCalculate(new Cast(new SymbolReference("a"), "bigint"), inputStatistics) .lowValue(2.0) .highValue(17.0) .distinctValuesCount(10) .nullsFraction(0.3) .dataSizeUnknown(); }
@Test public void testCastBigintToDouble() { PlanNodeStatsEstimate inputStatistics = PlanNodeStatsEstimate.builder() .addSymbolStatistics(new Symbol("a"), SymbolStatsEstimate.builder() .setNullsFraction(0.3) .setLowValue(2.0) .setHighValue(10.0) .setDistinctValuesCount(4) .setAverageRowSize(2.0) .build()) .build(); assertCalculate(new Cast(new SymbolReference("a"), "double"), inputStatistics) .lowValue(2.0) .highValue(10.0) .distinctValuesCount(4) .nullsFraction(0.3) .dataSizeUnknown(); }