Search in sources :

Example 1 with EquiJoinClause

use of io.trino.sql.planner.plan.JoinNode.EquiJoinClause in project trino by trinodb.

the class TransformFilteringSemiJoinToInnerJoin method apply.

@Override
public Result apply(FilterNode filterNode, Captures captures, Context context) {
    SemiJoinNode semiJoin = captures.get(SEMI_JOIN);
    // Do not transform semi-join in context of DELETE
    if (PlanNodeSearcher.searchFrom(semiJoin.getSource(), context.getLookup()).where(node -> node instanceof TableScanNode && ((TableScanNode) node).isUpdateTarget()).matches()) {
        return Result.empty();
    }
    Symbol semiJoinSymbol = semiJoin.getSemiJoinOutput();
    Predicate<Expression> isSemiJoinSymbol = expression -> expression.equals(semiJoinSymbol.toSymbolReference());
    List<Expression> conjuncts = extractConjuncts(filterNode.getPredicate());
    if (conjuncts.stream().noneMatch(isSemiJoinSymbol)) {
        return Result.empty();
    }
    Expression filteredPredicate = and(conjuncts.stream().filter(not(isSemiJoinSymbol)).collect(toImmutableList()));
    Expression simplifiedPredicate = inlineSymbols(symbol -> {
        if (symbol.equals(semiJoinSymbol)) {
            return TRUE_LITERAL;
        }
        return symbol.toSymbolReference();
    }, filteredPredicate);
    Optional<Expression> joinFilter = simplifiedPredicate.equals(TRUE_LITERAL) ? Optional.empty() : Optional.of(simplifiedPredicate);
    PlanNode filteringSourceDistinct = new AggregationNode(context.getIdAllocator().getNextId(), semiJoin.getFilteringSource(), ImmutableMap.of(), singleGroupingSet(ImmutableList.of(semiJoin.getFilteringSourceJoinSymbol())), ImmutableList.of(), SINGLE, Optional.empty(), Optional.empty());
    JoinNode innerJoin = new JoinNode(semiJoin.getId(), INNER, semiJoin.getSource(), filteringSourceDistinct, ImmutableList.of(new EquiJoinClause(semiJoin.getSourceJoinSymbol(), semiJoin.getFilteringSourceJoinSymbol())), semiJoin.getSource().getOutputSymbols(), ImmutableList.of(), false, joinFilter, Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), semiJoin.getDynamicFilterId().map(id -> ImmutableMap.of(id, semiJoin.getFilteringSourceJoinSymbol())).orElse(ImmutableMap.of()), Optional.empty());
    ProjectNode project = new ProjectNode(context.getIdAllocator().getNextId(), innerJoin, Assignments.builder().putIdentities(innerJoin.getOutputSymbols()).put(semiJoinSymbol, TRUE_LITERAL).build());
    return Result.ofPlanNode(project);
}
Also used : INNER(io.trino.sql.planner.plan.JoinNode.Type.INNER) Patterns.filter(io.trino.sql.planner.plan.Patterns.filter) SINGLE(io.trino.sql.planner.plan.AggregationNode.Step.SINGLE) SystemSessionProperties.isRewriteFilteringSemiJoinToInnerJoin(io.trino.SystemSessionProperties.isRewriteFilteringSemiJoinToInnerJoin) Capture.newCapture(io.trino.matching.Capture.newCapture) FilterNode(io.trino.sql.planner.plan.FilterNode) PlanNode(io.trino.sql.planner.plan.PlanNode) ExpressionSymbolInliner.inlineSymbols(io.trino.sql.planner.ExpressionSymbolInliner.inlineSymbols) ImmutableList(com.google.common.collect.ImmutableList) PlanNodeSearcher(io.trino.sql.planner.optimizations.PlanNodeSearcher) EquiJoinClause(io.trino.sql.planner.plan.JoinNode.EquiJoinClause) AggregationNode(io.trino.sql.planner.plan.AggregationNode) Rule(io.trino.sql.planner.iterative.Rule) JoinNode(io.trino.sql.planner.plan.JoinNode) ProjectNode(io.trino.sql.planner.plan.ProjectNode) TableScanNode(io.trino.sql.planner.plan.TableScanNode) Symbol(io.trino.sql.planner.Symbol) ImmutableMap(com.google.common.collect.ImmutableMap) Predicate(java.util.function.Predicate) ImmutableList.toImmutableList(com.google.common.collect.ImmutableList.toImmutableList) Assignments(io.trino.sql.planner.plan.Assignments) Patterns.semiJoin(io.trino.sql.planner.plan.Patterns.semiJoin) SemiJoinNode(io.trino.sql.planner.plan.SemiJoinNode) TRUE_LITERAL(io.trino.sql.tree.BooleanLiteral.TRUE_LITERAL) Capture(io.trino.matching.Capture) AggregationNode.singleGroupingSet(io.trino.sql.planner.plan.AggregationNode.singleGroupingSet) List(java.util.List) Pattern(io.trino.matching.Pattern) ExpressionUtils.and(io.trino.sql.ExpressionUtils.and) Patterns.source(io.trino.sql.planner.plan.Patterns.source) Captures(io.trino.matching.Captures) Optional(java.util.Optional) Expression(io.trino.sql.tree.Expression) ExpressionUtils.extractConjuncts(io.trino.sql.ExpressionUtils.extractConjuncts) Predicate.not(java.util.function.Predicate.not) Session(io.trino.Session) Symbol(io.trino.sql.planner.Symbol) JoinNode(io.trino.sql.planner.plan.JoinNode) SemiJoinNode(io.trino.sql.planner.plan.SemiJoinNode) EquiJoinClause(io.trino.sql.planner.plan.JoinNode.EquiJoinClause) AggregationNode(io.trino.sql.planner.plan.AggregationNode) SemiJoinNode(io.trino.sql.planner.plan.SemiJoinNode) PlanNode(io.trino.sql.planner.plan.PlanNode) TableScanNode(io.trino.sql.planner.plan.TableScanNode) Expression(io.trino.sql.tree.Expression) ProjectNode(io.trino.sql.planner.plan.ProjectNode)

Example 2 with EquiJoinClause

use of io.trino.sql.planner.plan.JoinNode.EquiJoinClause in project trino by trinodb.

the class TestLocalDynamicFilterConsumer method testDynamicFilterPruning.

@Test
public void testDynamicFilterPruning() throws Exception {
    PlanBuilder planBuilder = new PlanBuilder(new PlanNodeIdAllocator(), dummyMetadata(), getQueryRunner().getDefaultSession());
    Symbol left1 = planBuilder.symbol("left1", BIGINT);
    Symbol left2 = planBuilder.symbol("left2", INTEGER);
    Symbol left3 = planBuilder.symbol("left3", SMALLINT);
    Symbol right1 = planBuilder.symbol("right1", BIGINT);
    Symbol right2 = planBuilder.symbol("right2", INTEGER);
    Symbol right3 = planBuilder.symbol("right3", SMALLINT);
    DynamicFilterId filter1 = new DynamicFilterId("filter1");
    DynamicFilterId filter2 = new DynamicFilterId("filter2");
    DynamicFilterId filter3 = new DynamicFilterId("filter3");
    JoinNode joinNode = planBuilder.join(INNER, planBuilder.values(left1, left2, left3), planBuilder.values(right1, right2, right3), ImmutableList.of(new EquiJoinClause(left1, right1), new EquiJoinClause(left2, right2), new EquiJoinClause(left3, right3)), ImmutableList.of(), ImmutableList.of(), Optional.empty(), Optional.empty(), Optional.empty(), ImmutableMap.of(filter1, right1, filter2, right2, filter3, right3));
    LocalDynamicFilterConsumer consumer = LocalDynamicFilterConsumer.create(joinNode, ImmutableList.of(BIGINT, INTEGER, SMALLINT), 1, ImmutableSet.of(filter1, filter3));
    assertEquals(consumer.getBuildChannels(), ImmutableMap.of(filter1, 0, filter3, 2));
    // make sure domain types got propagated correctly
    consumer.getTupleDomainConsumer().accept(TupleDomain.none());
    assertEquals(consumer.getDynamicFilterDomains().get(), ImmutableMap.of(filter1, Domain.none(BIGINT), filter3, Domain.none(SMALLINT)));
}
Also used : JoinNode(io.trino.sql.planner.plan.JoinNode) EquiJoinClause(io.trino.sql.planner.plan.JoinNode.EquiJoinClause) PlanBuilder(io.trino.sql.planner.iterative.rule.test.PlanBuilder) DynamicFilterId(io.trino.sql.planner.plan.DynamicFilterId) Test(org.testng.annotations.Test) BasePlanTest(io.trino.sql.planner.assertions.BasePlanTest)

Example 3 with EquiJoinClause

use of io.trino.sql.planner.plan.JoinNode.EquiJoinClause in project trino by trinodb.

the class TestPushLimitThroughOuterJoin method testLimitWithPreSortedInputsRightJoin.

@Test
public void testLimitWithPreSortedInputsRightJoin() {
    tester().assertThat(new PushLimitThroughOuterJoin()).on(p -> {
        Symbol leftKey = p.symbol("leftKey");
        Symbol rightKey = p.symbol("rightKey");
        return p.limit(1, false, ImmutableList.of(leftKey), p.join(RIGHT, p.values(5, leftKey), p.values(5, rightKey), new EquiJoinClause(leftKey, rightKey)));
    }).doesNotFire();
    tester().assertThat(new PushLimitThroughOuterJoin()).on(p -> {
        Symbol leftKey = p.symbol("leftKey");
        Symbol rightKey = p.symbol("rightKey");
        return p.limit(1, false, ImmutableList.of(rightKey), p.join(RIGHT, p.values(5, leftKey), p.values(5, rightKey), new EquiJoinClause(leftKey, rightKey)));
    }).matches(limit(1, ImmutableList.of(), false, ImmutableList.of("rightKey"), join(RIGHT, ImmutableList.of(equiJoinClause("leftKey", "rightKey")), values("leftKey"), limit(1, ImmutableList.of(), true, ImmutableList.of("rightKey"), values("rightKey")))));
}
Also used : Symbol(io.trino.sql.planner.Symbol) PlanMatchPattern.limit(io.trino.sql.planner.assertions.PlanMatchPattern.limit) LEFT(io.trino.sql.planner.plan.JoinNode.Type.LEFT) ImmutableList(com.google.common.collect.ImmutableList) RIGHT(io.trino.sql.planner.plan.JoinNode.Type.RIGHT) BaseRuleTest(io.trino.sql.planner.iterative.rule.test.BaseRuleTest) EquiJoinClause(io.trino.sql.planner.plan.JoinNode.EquiJoinClause) FULL(io.trino.sql.planner.plan.JoinNode.Type.FULL) PlanMatchPattern.equiJoinClause(io.trino.sql.planner.assertions.PlanMatchPattern.equiJoinClause) Test(org.testng.annotations.Test) PlanMatchPattern.values(io.trino.sql.planner.assertions.PlanMatchPattern.values) PlanMatchPattern.join(io.trino.sql.planner.assertions.PlanMatchPattern.join) Symbol(io.trino.sql.planner.Symbol) EquiJoinClause(io.trino.sql.planner.plan.JoinNode.EquiJoinClause) BaseRuleTest(io.trino.sql.planner.iterative.rule.test.BaseRuleTest) Test(org.testng.annotations.Test)

Example 4 with EquiJoinClause

use of io.trino.sql.planner.plan.JoinNode.EquiJoinClause in project trino by trinodb.

the class TestReorderJoins method testRepartitionsWhenRequiredBySession.

@Test
public void testRepartitionsWhenRequiredBySession() {
    // variable width so that average row size is respected
    Type symbolType = createUnboundedVarcharType();
    assertReorderJoins().on(p -> {
        Symbol a1 = p.symbol("A1", symbolType);
        Symbol b1 = p.symbol("B1", symbolType);
        return p.join(INNER, p.values(new PlanNodeId("valuesA"), 2, a1), p.values(new PlanNodeId("valuesB"), 2, b1), ImmutableList.of(new EquiJoinClause(a1, b1)), ImmutableList.of(a1), ImmutableList.of(b1), Optional.empty());
    }).setSystemProperty(JOIN_DISTRIBUTION_TYPE, JoinDistributionType.PARTITIONED.name()).overrideStats("valuesA", PlanNodeStatsEstimate.builder().setOutputRowCount(100).addSymbolStatistics(ImmutableMap.of(new Symbol("A1"), new SymbolStatsEstimate(0, 100, 0, 6400, 100))).build()).overrideStats("valuesB", PlanNodeStatsEstimate.builder().setOutputRowCount(10000).addSymbolStatistics(ImmutableMap.of(new Symbol("B1"), new SymbolStatsEstimate(0, 100, 0, 640000, 100))).build()).matches(join(INNER, ImmutableList.of(equiJoinClause("B1", "A1")), Optional.empty(), Optional.of(PARTITIONED), values(ImmutableMap.of("B1", 0)), values(ImmutableMap.of("A1", 0))));
}
Also used : PlanNodeId(io.trino.sql.planner.plan.PlanNodeId) Type(io.trino.spi.type.Type) VarcharType.createUnboundedVarcharType(io.trino.spi.type.VarcharType.createUnboundedVarcharType) JoinDistributionType(io.trino.sql.planner.OptimizerConfig.JoinDistributionType) Symbol(io.trino.sql.planner.Symbol) EquiJoinClause(io.trino.sql.planner.plan.JoinNode.EquiJoinClause) SymbolStatsEstimate(io.trino.cost.SymbolStatsEstimate) Test(org.testng.annotations.Test)

Example 5 with EquiJoinClause

use of io.trino.sql.planner.plan.JoinNode.EquiJoinClause in project trino by trinodb.

the class TestReorderJoins method testReplicatesWhenNotRestricted.

@Test
public void testReplicatesWhenNotRestricted() {
    // variable width so that average row size is respected
    Type symbolType = createUnboundedVarcharType();
    int aRows = 10_000;
    int bRows = 10;
    PlanNodeStatsEstimate probeSideStatsEstimate = PlanNodeStatsEstimate.builder().setOutputRowCount(aRows).addSymbolStatistics(ImmutableMap.of(new Symbol("A1"), new SymbolStatsEstimate(0, 100, 0, 640000, 10))).build();
    PlanNodeStatsEstimate buildSideStatsEstimate = PlanNodeStatsEstimate.builder().setOutputRowCount(bRows).addSymbolStatistics(ImmutableMap.of(new Symbol("B1"), new SymbolStatsEstimate(0, 100, 0, 640000, 10))).build();
    // B table is small enough to be replicated in AUTOMATIC_RESTRICTED mode
    assertReorderJoins().setSystemProperty(JOIN_DISTRIBUTION_TYPE, AUTOMATIC.name()).setSystemProperty(JOIN_MAX_BROADCAST_TABLE_SIZE, "100MB").on(p -> {
        Symbol a1 = p.symbol("A1", symbolType);
        Symbol b1 = p.symbol("B1", symbolType);
        return p.join(INNER, p.values(new PlanNodeId("valuesA"), aRows, a1), p.values(new PlanNodeId("valuesB"), bRows, b1), ImmutableList.of(new EquiJoinClause(a1, b1)), ImmutableList.of(a1), ImmutableList.of(b1), Optional.empty());
    }).overrideStats("valuesA", probeSideStatsEstimate).overrideStats("valuesB", buildSideStatsEstimate).matches(join(INNER, ImmutableList.of(equiJoinClause("A1", "B1")), Optional.empty(), Optional.of(REPLICATED), values(ImmutableMap.of("A1", 0)), values(ImmutableMap.of("B1", 0))));
    probeSideStatsEstimate = PlanNodeStatsEstimate.builder().setOutputRowCount(aRows).addSymbolStatistics(ImmutableMap.of(new Symbol("A1"), new SymbolStatsEstimate(0, 100, 0, 640000d * 10000, 10))).build();
    buildSideStatsEstimate = PlanNodeStatsEstimate.builder().setOutputRowCount(bRows).addSymbolStatistics(ImmutableMap.of(new Symbol("B1"), new SymbolStatsEstimate(0, 100, 0, 640000d * 10000, 10))).build();
    // B table exceeds AUTOMATIC_RESTRICTED limit therefore it is partitioned
    assertReorderJoins().setSystemProperty(JOIN_DISTRIBUTION_TYPE, AUTOMATIC.name()).setSystemProperty(JOIN_MAX_BROADCAST_TABLE_SIZE, "100MB").on(p -> {
        Symbol a1 = p.symbol("A1", symbolType);
        Symbol b1 = p.symbol("B1", symbolType);
        return p.join(INNER, p.values(new PlanNodeId("valuesA"), aRows, a1), p.values(new PlanNodeId("valuesB"), bRows, b1), ImmutableList.of(new EquiJoinClause(a1, b1)), ImmutableList.of(a1), ImmutableList.of(b1), Optional.empty());
    }).overrideStats("valuesA", probeSideStatsEstimate).overrideStats("valuesB", buildSideStatsEstimate).matches(join(INNER, ImmutableList.of(equiJoinClause("A1", "B1")), Optional.empty(), Optional.of(PARTITIONED), values(ImmutableMap.of("A1", 0)), values(ImmutableMap.of("B1", 0))));
}
Also used : TypeAnalyzer.createTestingTypeAnalyzer(io.trino.sql.planner.TypeAnalyzer.createTestingTypeAnalyzer) PARTITIONED(io.trino.sql.planner.plan.JoinNode.DistributionType.PARTITIONED) INNER(io.trino.sql.planner.plan.JoinNode.Type.INNER) TestingFunctionResolution(io.trino.metadata.TestingFunctionResolution) Type(io.trino.spi.type.Type) VarcharType.createUnboundedVarcharType(io.trino.spi.type.VarcharType.createUnboundedVarcharType) PlanMatchPattern(io.trino.sql.planner.assertions.PlanMatchPattern) Test(org.testng.annotations.Test) REPLICATED(io.trino.sql.planner.plan.JoinNode.DistributionType.REPLICATED) BROADCAST(io.trino.sql.planner.OptimizerConfig.JoinDistributionType.BROADCAST) RuleAssert(io.trino.sql.planner.iterative.rule.test.RuleAssert) ImmutableList(com.google.common.collect.ImmutableList) EquiJoinClause(io.trino.sql.planner.plan.JoinNode.EquiJoinClause) PlanNodeId(io.trino.sql.planner.plan.PlanNodeId) JoinReorderingStrategy(io.trino.sql.planner.OptimizerConfig.JoinReorderingStrategy) ArithmeticUnaryExpression(io.trino.sql.tree.ArithmeticUnaryExpression) PlanMatchPattern.equiJoinClause(io.trino.sql.planner.assertions.PlanMatchPattern.equiJoinClause) AUTOMATIC(io.trino.sql.planner.OptimizerConfig.JoinDistributionType.AUTOMATIC) JOIN_REORDERING_STRATEGY(io.trino.SystemSessionProperties.JOIN_REORDERING_STRATEGY) PlanMatchPattern.join(io.trino.sql.planner.assertions.PlanMatchPattern.join) PlanNodeStatsEstimate(io.trino.cost.PlanNodeStatsEstimate) JOIN_MAX_BROADCAST_TABLE_SIZE(io.trino.SystemSessionProperties.JOIN_MAX_BROADCAST_TABLE_SIZE) Symbol(io.trino.sql.planner.Symbol) AfterClass(org.testng.annotations.AfterClass) PlanMatchPattern.expression(io.trino.sql.planner.assertions.PlanMatchPattern.expression) SymbolStatsEstimate(io.trino.cost.SymbolStatsEstimate) RuleTester.defaultRuleTester(io.trino.sql.planner.iterative.rule.test.RuleTester.defaultRuleTester) ImmutableMap(com.google.common.collect.ImmutableMap) BeforeClass(org.testng.annotations.BeforeClass) Assignments(io.trino.sql.planner.plan.Assignments) RuleTester(io.trino.sql.planner.iterative.rule.test.RuleTester) PlanMatchPattern.values(io.trino.sql.planner.assertions.PlanMatchPattern.values) LESS_THAN(io.trino.sql.tree.ComparisonExpression.Operator.LESS_THAN) JoinDistributionType(io.trino.sql.planner.OptimizerConfig.JoinDistributionType) CostComparator(io.trino.cost.CostComparator) ComparisonExpression(io.trino.sql.tree.ComparisonExpression) QualifiedName(io.trino.sql.tree.QualifiedName) EQUAL(io.trino.sql.tree.ComparisonExpression.Operator.EQUAL) Closeables.closeAllRuntimeException(io.airlift.testing.Closeables.closeAllRuntimeException) PlanMatchPattern.strictProject(io.trino.sql.planner.assertions.PlanMatchPattern.strictProject) PLANNER_CONTEXT(io.trino.sql.planner.TestingPlannerContext.PLANNER_CONTEXT) JOIN_DISTRIBUTION_TYPE(io.trino.SystemSessionProperties.JOIN_DISTRIBUTION_TYPE) Optional(java.util.Optional) MINUS(io.trino.sql.tree.ArithmeticUnaryExpression.Sign.MINUS) PlanNodeId(io.trino.sql.planner.plan.PlanNodeId) Type(io.trino.spi.type.Type) VarcharType.createUnboundedVarcharType(io.trino.spi.type.VarcharType.createUnboundedVarcharType) JoinDistributionType(io.trino.sql.planner.OptimizerConfig.JoinDistributionType) PlanNodeStatsEstimate(io.trino.cost.PlanNodeStatsEstimate) Symbol(io.trino.sql.planner.Symbol) EquiJoinClause(io.trino.sql.planner.plan.JoinNode.EquiJoinClause) SymbolStatsEstimate(io.trino.cost.SymbolStatsEstimate) Test(org.testng.annotations.Test)

Aggregations

EquiJoinClause (io.trino.sql.planner.plan.JoinNode.EquiJoinClause)18 Symbol (io.trino.sql.planner.Symbol)15 Test (org.testng.annotations.Test)15 ImmutableList (com.google.common.collect.ImmutableList)11 Optional (java.util.Optional)10 ImmutableMap (com.google.common.collect.ImmutableMap)9 PlanMatchPattern.values (io.trino.sql.planner.assertions.PlanMatchPattern.values)9 INNER (io.trino.sql.planner.plan.JoinNode.Type.INNER)9 PlanMatchPattern.equiJoinClause (io.trino.sql.planner.assertions.PlanMatchPattern.equiJoinClause)8 PlanMatchPattern.join (io.trino.sql.planner.assertions.PlanMatchPattern.join)8 Assignments (io.trino.sql.planner.plan.Assignments)7 Type (io.trino.spi.type.Type)6 SymbolStatsEstimate (io.trino.cost.SymbolStatsEstimate)5 VarcharType.createUnboundedVarcharType (io.trino.spi.type.VarcharType.createUnboundedVarcharType)5 JoinDistributionType (io.trino.sql.planner.OptimizerConfig.JoinDistributionType)5 PLANNER_CONTEXT (io.trino.sql.planner.TestingPlannerContext.PLANNER_CONTEXT)5 TypeAnalyzer.createTestingTypeAnalyzer (io.trino.sql.planner.TypeAnalyzer.createTestingTypeAnalyzer)5 PlanMatchPattern.expression (io.trino.sql.planner.assertions.PlanMatchPattern.expression)5 LEFT (io.trino.sql.planner.plan.JoinNode.Type.LEFT)5 RIGHT (io.trino.sql.planner.plan.JoinNode.Type.RIGHT)5