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)));
}
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));
}
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));
}
Aggregations