Search in sources :

Example 1 with LEFT

use of org.apache.calcite.rel.core.JoinRelType.LEFT in project ignite-3 by apache.

the class IgniteMergeJoin method passThroughCollation.

/**
 * {@inheritDoc}
 */
@Override
public Pair<RelTraitSet, List<RelTraitSet>> passThroughCollation(RelTraitSet required, List<RelTraitSet> inputTraits) {
    RelCollation collation = TraitUtils.collation(required);
    RelTraitSet left = inputTraits.get(0);
    RelTraitSet right = inputTraits.get(1);
    if (joinType == FULL) {
        return defaultCollationPair(required, left, right);
    }
    int leftInputFieldCount = this.left.getRowType().getFieldCount();
    List<Integer> reqKeys = RelCollations.ordinals(collation);
    List<Integer> leftKeys = joinInfo.leftKeys.toIntegerList();
    List<Integer> rightKeys = joinInfo.rightKeys.incr(leftInputFieldCount).toIntegerList();
    ImmutableBitSet reqKeySet = ImmutableBitSet.of(reqKeys);
    ImmutableBitSet leftKeySet = ImmutableBitSet.of(joinInfo.leftKeys);
    ImmutableBitSet rightKeySet = ImmutableBitSet.of(rightKeys);
    RelCollation nodeCollation;
    RelCollation leftCollation;
    RelCollation rightCollation;
    if (reqKeySet.equals(leftKeySet)) {
        if (joinType == RIGHT) {
            return defaultCollationPair(required, left, right);
        }
        nodeCollation = collation;
        leftCollation = collation;
        rightCollation = collation.apply(buildTransposeMapping(true));
    } else if (containsOrderless(leftKeys, collation)) {
        if (joinType == RIGHT) {
            return defaultCollationPair(required, left, right);
        }
        // if sort keys are subset of left join keys, we can extend collations to make sure all join
        // keys are sorted.
        nodeCollation = collation;
        leftCollation = extendCollation(collation, leftKeys);
        rightCollation = leftCollation.apply(buildTransposeMapping(true));
    } else if (containsOrderless(collation, leftKeys) && reqKeys.stream().allMatch(i -> i < leftInputFieldCount)) {
        if (joinType == RIGHT) {
            return defaultCollationPair(required, left, right);
        }
        // if sort keys are superset of left join keys, and left join keys is prefix of sort keys
        // (order not matter), also sort keys are all from left join input.
        nodeCollation = collation;
        leftCollation = collation;
        rightCollation = leftCollation.apply(buildTransposeMapping(true));
    } else if (reqKeySet.equals(rightKeySet)) {
        if (joinType == LEFT) {
            return defaultCollationPair(required, left, right);
        }
        nodeCollation = collation;
        rightCollation = RelCollations.shift(collation, -leftInputFieldCount);
        leftCollation = rightCollation.apply(buildTransposeMapping(false));
    } else if (containsOrderless(rightKeys, collation)) {
        if (joinType == LEFT) {
            return defaultCollationPair(required, left, right);
        }
        nodeCollation = collation;
        rightCollation = RelCollations.shift(extendCollation(collation, rightKeys), -leftInputFieldCount);
        leftCollation = rightCollation.apply(buildTransposeMapping(false));
    } else {
        return defaultCollationPair(required, left, right);
    }
    return Pair.of(required.replace(nodeCollation), ImmutableList.of(left.replace(leftCollation), right.replace(rightCollation)));
}
Also used : EMPTY(org.apache.calcite.rel.RelCollations.EMPTY) RelOptCost(org.apache.calcite.plan.RelOptCost) Join(org.apache.calcite.rel.core.Join) ArrayList(java.util.ArrayList) RIGHT(org.apache.calcite.rel.core.JoinRelType.RIGHT) CorrelationId(org.apache.calcite.rel.core.CorrelationId) IgniteCostFactory(org.apache.ignite.internal.sql.engine.metadata.cost.IgniteCostFactory) ImmutableList(com.google.common.collect.ImmutableList) RexNode(org.apache.calcite.rex.RexNode) Pair(org.apache.calcite.util.Pair) RelInputEx(org.apache.ignite.internal.sql.engine.externalize.RelInputEx) RelCollations.containsOrderless(org.apache.calcite.rel.RelCollations.containsOrderless) RelTraitSet(org.apache.calcite.plan.RelTraitSet) RelOptCluster(org.apache.calcite.plan.RelOptCluster) RelCollations(org.apache.calcite.rel.RelCollations) ImmutableBitSet(org.apache.calcite.util.ImmutableBitSet) RelInput(org.apache.calcite.rel.RelInput) LEFT(org.apache.calcite.rel.core.JoinRelType.LEFT) Set(java.util.Set) FULL(org.apache.calcite.rel.core.JoinRelType.FULL) RelNode(org.apache.calcite.rel.RelNode) RelFieldCollation(org.apache.calcite.rel.RelFieldCollation) Commons(org.apache.ignite.internal.sql.engine.util.Commons) RelWriter(org.apache.calcite.rel.RelWriter) List(java.util.List) TraitUtils(org.apache.ignite.internal.sql.engine.trait.TraitUtils) RelMetadataQuery(org.apache.calcite.rel.metadata.RelMetadataQuery) RelCollation(org.apache.calcite.rel.RelCollation) IgniteCost(org.apache.ignite.internal.sql.engine.metadata.cost.IgniteCost) JoinRelType(org.apache.calcite.rel.core.JoinRelType) RelOptPlanner(org.apache.calcite.plan.RelOptPlanner) RelCollation(org.apache.calcite.rel.RelCollation) ImmutableBitSet(org.apache.calcite.util.ImmutableBitSet) RelTraitSet(org.apache.calcite.plan.RelTraitSet)

Example 2 with LEFT

use of org.apache.calcite.rel.core.JoinRelType.LEFT in project ignite-3 by apache.

the class MergeJoinExecutionTest method verifyJoin.

/**
 * Creates execution tree and executes it. Then compares the result of the execution with the given one.
 *
 * @param left     Data for left table.
 * @param right    Data for right table.
 * @param joinType Join type.
 * @param expRes   Expected result.
 */
private void verifyJoin(Object[][] left, Object[][] right, JoinRelType joinType, Object[][] expRes) {
    ExecutionContext<Object[]> ctx = executionContext(true);
    RelDataType leftType = TypeUtils.createRowType(ctx.getTypeFactory(), int.class, String.class, Integer.class);
    ScanNode<Object[]> leftNode = new ScanNode<>(ctx, leftType, Arrays.asList(left));
    RelDataType rightType = TypeUtils.createRowType(ctx.getTypeFactory(), int.class, String.class);
    ScanNode<Object[]> rightNode = new ScanNode<>(ctx, rightType, Arrays.asList(right));
    RelDataType outType;
    if (setOf(SEMI, ANTI).contains(joinType)) {
        outType = TypeUtils.createRowType(ctx.getTypeFactory(), int.class, String.class, Integer.class);
    } else {
        outType = TypeUtils.createRowType(ctx.getTypeFactory(), int.class, String.class, Integer.class, int.class, String.class);
    }
    MergeJoinNode<Object[]> join = MergeJoinNode.create(ctx, outType, leftType, rightType, joinType, (r1, r2) -> {
        Object o1 = r1[2];
        Object o2 = r2[0];
        if (o1 == null || o2 == null) {
            if (o1 != null) {
                return 1;
            } else if (o2 != null) {
                return -1;
            } else {
                return 0;
            }
        }
        return Integer.compare((Integer) o1, (Integer) o2);
    });
    join.register(asList(leftNode, rightNode));
    RelDataType rowType;
    ProjectNode<Object[]> project;
    if (setOf(SEMI, ANTI).contains(joinType)) {
        rowType = TypeUtils.createRowType(ctx.getTypeFactory(), int.class, String.class);
        project = new ProjectNode<>(ctx, rowType, r -> new Object[] { r[0], r[1] });
    } else {
        rowType = TypeUtils.createRowType(ctx.getTypeFactory(), int.class, String.class, String.class);
        project = new ProjectNode<>(ctx, rowType, r -> new Object[] { r[0], r[1], r[4] });
    }
    project.register(join);
    RootNode<Object[]> node = new RootNode<>(ctx, rowType);
    node.register(project);
    ArrayList<Object[]> rows = new ArrayList<>();
    while (node.hasNext()) {
        rows.add(node.next());
    }
    assertThat(rows.toArray(EMPTY), equalTo(expRes));
}
Also used : ArrayUtils.asList(org.apache.ignite.internal.util.ArrayUtils.asList) RelDataType(org.apache.calcite.rel.type.RelDataType) LEFT(org.apache.calcite.rel.core.JoinRelType.LEFT) Arrays(java.util.Arrays) ANTI(org.apache.calcite.rel.core.JoinRelType.ANTI) INNER(org.apache.calcite.rel.core.JoinRelType.INNER) SEMI(org.apache.calcite.rel.core.JoinRelType.SEMI) IsEqual.equalTo(org.hamcrest.core.IsEqual.equalTo) Set(java.util.Set) TypeUtils(org.apache.ignite.internal.sql.engine.util.TypeUtils) FULL(org.apache.calcite.rel.core.JoinRelType.FULL) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) Test(org.junit.jupiter.api.Test) RIGHT(org.apache.calcite.rel.core.JoinRelType.RIGHT) JoinRelType(org.apache.calcite.rel.core.JoinRelType) ExecutionContext(org.apache.ignite.internal.sql.engine.exec.ExecutionContext) MatcherAssert.assertThat(org.hamcrest.MatcherAssert.assertThat) ArrayList(java.util.ArrayList) RelDataType(org.apache.calcite.rel.type.RelDataType)

Example 3 with LEFT

use of org.apache.calcite.rel.core.JoinRelType.LEFT in project ignite-3 by apache.

the class NestedLoopJoinExecutionTest method verifyJoin.

/**
 * Creates execution tree and executes it. Then compares the result of the execution with the given one.
 *
 * @param left     Data for left table.
 * @param right    Data for right table.
 * @param joinType Join type.
 * @param expRes   Expected result.
 */
private void verifyJoin(Object[][] left, Object[][] right, JoinRelType joinType, Object[][] expRes) {
    ExecutionContext<Object[]> ctx = executionContext(true);
    RelDataType leftType = TypeUtils.createRowType(ctx.getTypeFactory(), int.class, String.class, Integer.class);
    ScanNode<Object[]> leftNode = new ScanNode<>(ctx, leftType, Arrays.asList(left));
    RelDataType rightType = TypeUtils.createRowType(ctx.getTypeFactory(), int.class, String.class);
    ScanNode<Object[]> rightNode = new ScanNode<>(ctx, rightType, Arrays.asList(right));
    RelDataType outType;
    if (setOf(SEMI, ANTI).contains(joinType)) {
        outType = TypeUtils.createRowType(ctx.getTypeFactory(), int.class, String.class, Integer.class);
    } else {
        outType = TypeUtils.createRowType(ctx.getTypeFactory(), int.class, String.class, Integer.class, int.class, String.class);
    }
    RowHandler<Object[]> hnd = ctx.rowHandler();
    NestedLoopJoinNode<Object[]> join = NestedLoopJoinNode.create(ctx, outType, leftType, rightType, joinType, (r1, r2) -> getFieldFromBiRows(hnd, 2, r1, r2) == getFieldFromBiRows(hnd, 3, r1, r2));
    join.register(asList(leftNode, rightNode));
    RelDataType rowType;
    ProjectNode<Object[]> project;
    if (setOf(SEMI, ANTI).contains(joinType)) {
        rowType = TypeUtils.createRowType(ctx.getTypeFactory(), int.class, String.class);
        project = new ProjectNode<>(ctx, rowType, r -> new Object[] { r[0], r[1] });
    } else {
        rowType = TypeUtils.createRowType(ctx.getTypeFactory(), int.class, String.class, String.class);
        project = new ProjectNode<>(ctx, rowType, r -> new Object[] { r[0], r[1], r[4] });
    }
    project.register(join);
    RootNode<Object[]> node = new RootNode<>(ctx, rowType);
    node.register(project);
    ArrayList<Object[]> rows = new ArrayList<>();
    while (node.hasNext()) {
        rows.add(node.next());
    }
    assertArrayEquals(expRes, rows.toArray(EMPTY));
}
Also used : ArrayUtils.asList(org.apache.ignite.internal.util.ArrayUtils.asList) RelDataType(org.apache.calcite.rel.type.RelDataType) LEFT(org.apache.calcite.rel.core.JoinRelType.LEFT) Arrays(java.util.Arrays) ANTI(org.apache.calcite.rel.core.JoinRelType.ANTI) INNER(org.apache.calcite.rel.core.JoinRelType.INNER) RowHandler(org.apache.ignite.internal.sql.engine.exec.RowHandler) SEMI(org.apache.calcite.rel.core.JoinRelType.SEMI) Set(java.util.Set) TypeUtils(org.apache.ignite.internal.sql.engine.util.TypeUtils) FULL(org.apache.calcite.rel.core.JoinRelType.FULL) ArrayList(java.util.ArrayList) Assertions.assertArrayEquals(org.junit.jupiter.api.Assertions.assertArrayEquals) HashSet(java.util.HashSet) Test(org.junit.jupiter.api.Test) RIGHT(org.apache.calcite.rel.core.JoinRelType.RIGHT) Commons.getFieldFromBiRows(org.apache.ignite.internal.sql.engine.util.Commons.getFieldFromBiRows) JoinRelType(org.apache.calcite.rel.core.JoinRelType) ExecutionContext(org.apache.ignite.internal.sql.engine.exec.ExecutionContext) ArrayList(java.util.ArrayList) RelDataType(org.apache.calcite.rel.type.RelDataType)

Aggregations

ArrayList (java.util.ArrayList)3 Set (java.util.Set)3 JoinRelType (org.apache.calcite.rel.core.JoinRelType)3 FULL (org.apache.calcite.rel.core.JoinRelType.FULL)3 LEFT (org.apache.calcite.rel.core.JoinRelType.LEFT)3 RIGHT (org.apache.calcite.rel.core.JoinRelType.RIGHT)3 Arrays (java.util.Arrays)2 HashSet (java.util.HashSet)2 ANTI (org.apache.calcite.rel.core.JoinRelType.ANTI)2 INNER (org.apache.calcite.rel.core.JoinRelType.INNER)2 SEMI (org.apache.calcite.rel.core.JoinRelType.SEMI)2 RelDataType (org.apache.calcite.rel.type.RelDataType)2 ExecutionContext (org.apache.ignite.internal.sql.engine.exec.ExecutionContext)2 TypeUtils (org.apache.ignite.internal.sql.engine.util.TypeUtils)2 ArrayUtils.asList (org.apache.ignite.internal.util.ArrayUtils.asList)2 Test (org.junit.jupiter.api.Test)2 ImmutableList (com.google.common.collect.ImmutableList)1 List (java.util.List)1 RelOptCluster (org.apache.calcite.plan.RelOptCluster)1 RelOptCost (org.apache.calcite.plan.RelOptCost)1