Search in sources :

Example 26 with JoinNode

use of io.prestosql.spi.plan.JoinNode in project hetu-core by openlookeng.

the class PushAggregationThroughOuterJoin method apply.

@Override
public Result apply(AggregationNode aggregation, Captures captures, Context context) {
    JoinNode join = captures.get(JOIN);
    if (join.getFilter().isPresent() || !(join.getType() == JoinNode.Type.LEFT || join.getType() == JoinNode.Type.RIGHT) || !groupsOnAllColumns(aggregation, getOuterTable(join).getOutputSymbols()) || !isDistinct(context.getLookup().resolve(getOuterTable(join)), context.getLookup()::resolve)) {
        return Result.empty();
    }
    List<Symbol> groupingKeys = join.getCriteria().stream().map(join.getType() == JoinNode.Type.RIGHT ? JoinNode.EquiJoinClause::getLeft : JoinNode.EquiJoinClause::getRight).collect(toImmutableList());
    AggregationNode rewrittenAggregation = new AggregationNode(aggregation.getId(), getInnerTable(join), aggregation.getAggregations(), singleGroupingSet(groupingKeys), ImmutableList.of(), aggregation.getStep(), aggregation.getHashSymbol(), aggregation.getGroupIdSymbol(), aggregation.getAggregationType(), aggregation.getFinalizeSymbol());
    JoinNode rewrittenJoin;
    if (join.getType() == JoinNode.Type.LEFT) {
        rewrittenJoin = new JoinNode(join.getId(), join.getType(), join.getLeft(), rewrittenAggregation, join.getCriteria(), ImmutableList.<Symbol>builder().addAll(join.getLeft().getOutputSymbols()).addAll(rewrittenAggregation.getAggregations().keySet()).build(), join.getFilter(), join.getLeftHashSymbol(), join.getRightHashSymbol(), join.getDistributionType(), join.isSpillable(), join.getDynamicFilters());
    } else {
        rewrittenJoin = new JoinNode(join.getId(), join.getType(), rewrittenAggregation, join.getRight(), join.getCriteria(), ImmutableList.<Symbol>builder().addAll(rewrittenAggregation.getAggregations().keySet()).addAll(join.getRight().getOutputSymbols()).build(), join.getFilter(), join.getLeftHashSymbol(), join.getRightHashSymbol(), join.getDistributionType(), join.isSpillable(), join.getDynamicFilters());
    }
    Optional<PlanNode> resultNode = coalesceWithNullAggregation(rewrittenAggregation, rewrittenJoin, context.getSymbolAllocator(), context.getIdAllocator(), context.getLookup());
    if (!resultNode.isPresent()) {
        return Result.empty();
    }
    return Result.ofPlanNode(resultNode.get());
}
Also used : PlanNode(io.prestosql.spi.plan.PlanNode) JoinNode(io.prestosql.spi.plan.JoinNode) Symbol(io.prestosql.spi.plan.Symbol) AggregationNode(io.prestosql.spi.plan.AggregationNode)

Example 27 with JoinNode

use of io.prestosql.spi.plan.JoinNode in project hetu-core by openlookeng.

the class TablePushdown method updateOuterTableAndInnerTablePath.

/**
 * @param originalOuterJoinNode the original JoinNode captured by the rule
 * @param stack the stack which has all nodes from outer join to the TableScanNode of the table to be pushed down
 * @param lookup captured from the context
 * @return the final updated plan tree after all rearrangements
 */
private PlanNode updateOuterTableAndInnerTablePath(JoinNode originalOuterJoinNode, Stack<NodeWithTreeDirection> stack, Lookup lookup) {
    if (verifyIfJoinNodeInPath(stack)) {
        Stack<NodeWithTreeDirection> intermediateOuterTableStack = new Stack<>();
        // First pop the stack till we reach a join node and push into another intermediateOuterTableStack.
        while (!(stack.peek().getNode() instanceof JoinNode)) {
            intermediateOuterTableStack.push(stack.pop());
        }
        JoinNode originalInnerJoinNode = (JoinNode) stack.peek().getNode();
        PlanNode childOfInnerJoin = intermediateOuterTableStack.peek().getNode();
        List<Symbol> outerJoinOutputSymbols = originalOuterJoinNode.getOutputSymbols();
        // update the outputSymbol for the new outer Join node to same as previous outer join
        List<Symbol> newOuterOutputSymbols = ImmutableList.<Symbol>builder().addAll(outerJoinOutputSymbols).build();
        List<Symbol> newInnerOutputSymbols;
        /*
             * Based on which direction the outer table is from the original Outer JoinNode(orig-OJ), do the following-
             * Get the output symbols from opposite direction source of orig-OJ
             * Get the output symbols from the child of the original Inner JoinNode(orig-IJ), which will be moved.
             * Add them to a List in appropriate order. This list is the output symbols for new-IJ (created from orig-OJ)
             * */
        if (outerTableDirection == DIRECTION.LEFT) {
            newInnerOutputSymbols = ImmutableList.<Symbol>builder().addAll(childOfInnerJoin.getOutputSymbols()).addAll(originalOuterJoinNode.getRight().getOutputSymbols()).build();
        } else {
            newInnerOutputSymbols = ImmutableList.<Symbol>builder().addAll(originalOuterJoinNode.getLeft().getOutputSymbols()).addAll(childOfInnerJoin.getOutputSymbols()).build();
        }
        /*
             * this sets new outer join's join criteria
             * As the earlier inner is new outer, it's join criteria must borrow from both the earlier join criterias
             * hence choose the unchanged ones, as these were the ones which were forwarded to earlier outerjoin
             * For the original join node's unchanged child-
             * this join criteria must be present here also as it was used earlier
             * */
        List<JoinNode.EquiJoinClause> newInnerJoinCriteria = getNewInnerJoinCriteria(originalInnerJoinNode, originalOuterJoinNode);
        List<JoinNode.EquiJoinClause> newOuterJoinCriteria = getNewOuterJoinCriteria(originalInnerJoinNode, originalOuterJoinNode);
        JoinNode newOuterJoinNode;
        JoinNode newInnerJoinNode;
        /*
            * Create the final new inner JoinNode based on the requirement of a JoinFilter or not
            * */
        if (needNewInnerJoinFilter(originalOuterJoinNode, childOfInnerJoin)) {
            newInnerJoinNode = new JoinNode(originalOuterJoinNode.getId(), originalOuterJoinNode.getType(), childOfInnerJoin, resolveNodeFromGroupReference(originalOuterJoinNode, 1, lookup), newInnerJoinCriteria, newInnerOutputSymbols, originalOuterJoinNode.getFilter(), Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), originalOuterJoinNode.getDynamicFilters());
        } else {
            newInnerJoinNode = new JoinNode(originalOuterJoinNode.getId(), originalOuterJoinNode.getType(), childOfInnerJoin, resolveNodeFromGroupReference(originalOuterJoinNode, 1, lookup), newInnerJoinCriteria, newInnerOutputSymbols, Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), originalOuterJoinNode.getDynamicFilters());
        }
        /*
            * Create the new outer JoinNode based on the direction of the subquery table
            * */
        if (innerTableDirection == DIRECTION.LEFT) {
            newOuterJoinNode = new JoinNode(originalInnerJoinNode.getId(), originalInnerJoinNode.getType(), newInnerJoinNode, originalInnerJoinNode.getRight(), newOuterJoinCriteria, newOuterOutputSymbols, originalOuterJoinNode.getFilter(), Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), originalInnerJoinNode.getDynamicFilters());
        } else {
            newOuterJoinNode = new JoinNode(originalInnerJoinNode.getId(), originalInnerJoinNode.getType(), originalInnerJoinNode.getLeft(), newInnerJoinNode, newOuterJoinCriteria, newOuterOutputSymbols, originalOuterJoinNode.getFilter(), Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), originalInnerJoinNode.getDynamicFilters());
        }
        return updateInnerTable(newOuterJoinNode, newInnerJoinNode, innerTablePathStack, true);
    } else {
        /*
             * The outer table has a direct path to the JoinNode under consideration
             * We don't change the tree at all, instead just returning the current node.
             * */
        return updateInnerTable(originalOuterJoinNode, originalOuterJoinNode, innerTablePathStack, false);
    }
}
Also used : PlanNode(io.prestosql.spi.plan.PlanNode) JoinNode(io.prestosql.spi.plan.JoinNode) Symbol(io.prestosql.spi.plan.Symbol) Stack(java.util.Stack)

Example 28 with JoinNode

use of io.prestosql.spi.plan.JoinNode in project hetu-core by openlookeng.

the class TablePushdown method getNewOuterJoinCriteria.

/**
 * @param innerJoinNode the original InnerJoinNode which joined the two outer tables
 * @param originalJoinNode the original JoinNode captured by the rule
 * @return the new join criteria for the newly created outer join nodes
 */
private List<JoinNode.EquiJoinClause> getNewOuterJoinCriteria(JoinNode innerJoinNode, JoinNode originalJoinNode) {
    Symbol joinSymbolOfInnerJoinFixedSource;
    Symbol joinSymbolOfOuterJoinFixedSource;
    JoinNode.EquiJoinClause newJoinClause;
    if (outerTableDirection == DIRECTION.LEFT) {
        joinSymbolOfOuterJoinFixedSource = originalJoinNode.getCriteria().get(0).getRight();
    } else {
        joinSymbolOfOuterJoinFixedSource = originalJoinNode.getCriteria().get(0).getLeft();
    }
    if (innerTableDirection == DIRECTION.LEFT) {
        joinSymbolOfInnerJoinFixedSource = innerJoinNode.getCriteria().get(0).getRight();
        newJoinClause = new JoinNode.EquiJoinClause(joinSymbolOfOuterJoinFixedSource, joinSymbolOfInnerJoinFixedSource);
    } else {
        joinSymbolOfInnerJoinFixedSource = innerJoinNode.getCriteria().get(0).getLeft();
        newJoinClause = new JoinNode.EquiJoinClause(joinSymbolOfInnerJoinFixedSource, joinSymbolOfOuterJoinFixedSource);
    }
    return ImmutableList.of(newJoinClause);
}
Also used : Symbol(io.prestosql.spi.plan.Symbol) JoinNode(io.prestosql.spi.plan.JoinNode)

Example 29 with JoinNode

use of io.prestosql.spi.plan.JoinNode in project hetu-core by openlookeng.

the class TablePushdown method getNewInnerJoinCriteria.

/**
 * @param innerJoinNode the original InnerJoinNode which joined the two outer tables
 * @param originalOuterJoin the original JoinNode captured by the rule
 * @return the new join criteria for the newly created inner join nodes
 */
private List<JoinNode.EquiJoinClause> getNewInnerJoinCriteria(JoinNode innerJoinNode, JoinNode originalOuterJoin) {
    Symbol joinSymbolOfInnerJoinTransferSource;
    Symbol joinSymbolOfOuterJoinFixedSource;
    JoinNode.EquiJoinClause newJoinClause;
    if (innerTableDirection == DIRECTION.LEFT) {
        joinSymbolOfInnerJoinTransferSource = innerJoinNode.getCriteria().get(0).getLeft();
    } else {
        joinSymbolOfInnerJoinTransferSource = innerJoinNode.getCriteria().get(0).getRight();
    }
    if (outerTableDirection == DIRECTION.LEFT) {
        joinSymbolOfOuterJoinFixedSource = originalOuterJoin.getCriteria().get(0).getRight();
        newJoinClause = new JoinNode.EquiJoinClause(joinSymbolOfInnerJoinTransferSource, joinSymbolOfOuterJoinFixedSource);
    } else {
        joinSymbolOfOuterJoinFixedSource = originalOuterJoin.getCriteria().get(0).getLeft();
        newJoinClause = new JoinNode.EquiJoinClause(joinSymbolOfOuterJoinFixedSource, joinSymbolOfOuterJoinFixedSource);
    }
    return ImmutableList.of(newJoinClause);
}
Also used : Symbol(io.prestosql.spi.plan.Symbol) JoinNode(io.prestosql.spi.plan.JoinNode)

Example 30 with JoinNode

use of io.prestosql.spi.plan.JoinNode in project hetu-core by openlookeng.

the class TransformCorrelatedInPredicateToJoin method buildInPredicateEquivalent.

private PlanNode buildInPredicateEquivalent(ApplyNode apply, InPredicate inPredicate, Symbol inPredicateOutputSymbol, Decorrelated decorrelated, PlanNodeIdAllocator idAllocator, PlanSymbolAllocator planSymbolAllocator) {
    Expression correlationCondition = and(decorrelated.getCorrelatedPredicates());
    PlanNode decorrelatedBuildSource = decorrelated.getDecorrelatedNode();
    AssignUniqueId probeSide = new AssignUniqueId(idAllocator.getNextId(), apply.getInput(), planSymbolAllocator.newSymbol("unique", BIGINT));
    Symbol buildSideKnownNonNull = planSymbolAllocator.newSymbol("buildSideKnownNonNull", BIGINT);
    ProjectNode buildSide = new ProjectNode(idAllocator.getNextId(), decorrelatedBuildSource, Assignments.builder().putAll(identityAsSymbolReferences(decorrelatedBuildSource.getOutputSymbols())).put(buildSideKnownNonNull, castToRowExpression(bigint(0))).build());
    Symbol probeSideSymbol = SymbolUtils.from(inPredicate.getValue());
    Symbol buildSideSymbol = SymbolUtils.from(inPredicate.getValueList());
    Expression joinExpression = and(or(new IsNullPredicate(toSymbolReference(probeSideSymbol)), new ComparisonExpression(ComparisonExpression.Operator.EQUAL, toSymbolReference(probeSideSymbol), toSymbolReference(buildSideSymbol)), new IsNullPredicate(toSymbolReference(buildSideSymbol))), correlationCondition);
    JoinNode leftOuterJoin = leftOuterJoin(idAllocator, probeSide, buildSide, joinExpression);
    Symbol matchConditionSymbol = planSymbolAllocator.newSymbol("matchConditionSymbol", BOOLEAN);
    Expression matchCondition = and(isNotNull(probeSideSymbol), isNotNull(buildSideSymbol));
    Symbol nullMatchConditionSymbol = planSymbolAllocator.newSymbol("nullMatchConditionSymbol", BOOLEAN);
    Expression nullMatchCondition = and(isNotNull(buildSideKnownNonNull), not(matchCondition));
    ProjectNode preProjection = new ProjectNode(idAllocator.getNextId(), leftOuterJoin, Assignments.builder().putAll(AssignmentUtils.identityAsSymbolReferences(leftOuterJoin.getOutputSymbols())).put(matchConditionSymbol, castToRowExpression(matchCondition)).put(nullMatchConditionSymbol, castToRowExpression(nullMatchCondition)).build());
    Symbol countMatchesSymbol = planSymbolAllocator.newSymbol("countMatches", BIGINT);
    Symbol countNullMatchesSymbol = planSymbolAllocator.newSymbol("countNullMatches", BIGINT);
    AggregationNode aggregation = new AggregationNode(idAllocator.getNextId(), preProjection, ImmutableMap.<Symbol, AggregationNode.Aggregation>builder().put(countMatchesSymbol, countWithFilter(matchConditionSymbol)).put(countNullMatchesSymbol, countWithFilter(nullMatchConditionSymbol)).build(), singleGroupingSet(probeSide.getOutputSymbols()), ImmutableList.of(), AggregationNode.Step.SINGLE, Optional.empty(), Optional.empty(), AggregationNode.AggregationType.HASH, Optional.empty());
    // TODO since we care only about "some count > 0", we could have specialized node instead of leftOuterJoin that does the job without materializing join results
    SearchedCaseExpression inPredicateEquivalent = new SearchedCaseExpression(ImmutableList.of(new WhenClause(isGreaterThan(countMatchesSymbol, 0), booleanConstant(true)), new WhenClause(isGreaterThan(countNullMatchesSymbol, 0), booleanConstant(null))), Optional.of(booleanConstant(false)));
    return new ProjectNode(idAllocator.getNextId(), aggregation, Assignments.builder().putAll(identityAsSymbolReferences(apply.getInput().getOutputSymbols())).put(inPredicateOutputSymbol, castToRowExpression(inPredicateEquivalent)).build());
}
Also used : ComparisonExpression(io.prestosql.sql.tree.ComparisonExpression) WhenClause(io.prestosql.sql.tree.WhenClause) PlanNode(io.prestosql.spi.plan.PlanNode) AssignUniqueId(io.prestosql.sql.planner.plan.AssignUniqueId) SearchedCaseExpression(io.prestosql.sql.tree.SearchedCaseExpression) CallExpression(io.prestosql.spi.relation.CallExpression) OriginalExpressionUtils.castToRowExpression(io.prestosql.sql.relational.OriginalExpressionUtils.castToRowExpression) OriginalExpressionUtils.castToExpression(io.prestosql.sql.relational.OriginalExpressionUtils.castToExpression) SearchedCaseExpression(io.prestosql.sql.tree.SearchedCaseExpression) NotExpression(io.prestosql.sql.tree.NotExpression) ComparisonExpression(io.prestosql.sql.tree.ComparisonExpression) Expression(io.prestosql.sql.tree.Expression) Symbol(io.prestosql.spi.plan.Symbol) JoinNode(io.prestosql.spi.plan.JoinNode) IsNullPredicate(io.prestosql.sql.tree.IsNullPredicate) ProjectNode(io.prestosql.spi.plan.ProjectNode) AggregationNode(io.prestosql.spi.plan.AggregationNode)

Aggregations

JoinNode (io.prestosql.spi.plan.JoinNode)55 Symbol (io.prestosql.spi.plan.Symbol)44 PlanNode (io.prestosql.spi.plan.PlanNode)31 RowExpression (io.prestosql.spi.relation.RowExpression)22 TableScanNode (io.prestosql.spi.plan.TableScanNode)19 Test (org.testng.annotations.Test)18 FilterNode (io.prestosql.spi.plan.FilterNode)17 ImmutableList (com.google.common.collect.ImmutableList)16 Expression (io.prestosql.sql.tree.Expression)16 ProjectNode (io.prestosql.spi.plan.ProjectNode)15 CallExpression (io.prestosql.spi.relation.CallExpression)14 ImmutableList.toImmutableList (com.google.common.collect.ImmutableList.toImmutableList)13 ColumnHandle (io.prestosql.spi.connector.ColumnHandle)13 OriginalExpressionUtils.castToRowExpression (io.prestosql.sql.relational.OriginalExpressionUtils.castToRowExpression)13 ComparisonExpression (io.prestosql.sql.tree.ComparisonExpression)13 Assignments (io.prestosql.spi.plan.Assignments)12 SemiJoinNode (io.prestosql.sql.planner.plan.SemiJoinNode)12 Optional (java.util.Optional)12 Session (io.prestosql.Session)11 List (java.util.List)11