use of org.apache.calcite.util.ImmutableIntList in project calcite by apache.
the class SemiJoinJoinTransposeRule method onMatch.
// ~ Methods ----------------------------------------------------------------
// implement RelOptRule
public void onMatch(RelOptRuleCall call) {
SemiJoin semiJoin = call.rel(0);
final Join join = call.rel(1);
if (join instanceof SemiJoin) {
return;
}
final ImmutableIntList leftKeys = semiJoin.getLeftKeys();
final ImmutableIntList rightKeys = semiJoin.getRightKeys();
// X is the left child of the join below the semi-join
// Y is the right child of the join below the semi-join
// Z is the right child of the semi-join
int nFieldsX = join.getLeft().getRowType().getFieldList().size();
int nFieldsY = join.getRight().getRowType().getFieldList().size();
int nFieldsZ = semiJoin.getRight().getRowType().getFieldList().size();
int nTotalFields = nFieldsX + nFieldsY + nFieldsZ;
List<RelDataTypeField> fields = new ArrayList<RelDataTypeField>();
// create a list of fields for the full join result; note that
// we can't simply use the fields from the semi-join because the
// row-type of a semi-join only includes the left hand side fields
List<RelDataTypeField> joinFields = semiJoin.getRowType().getFieldList();
for (int i = 0; i < (nFieldsX + nFieldsY); i++) {
fields.add(joinFields.get(i));
}
joinFields = semiJoin.getRight().getRowType().getFieldList();
for (int i = 0; i < nFieldsZ; i++) {
fields.add(joinFields.get(i));
}
// determine which operands below the semi-join are the actual
// Rels that participate in the semi-join
int nKeysFromX = 0;
for (int leftKey : leftKeys) {
if (leftKey < nFieldsX) {
nKeysFromX++;
}
}
// otherwise, a semi-join wouldn't have been created
assert (nKeysFromX == 0) || (nKeysFromX == leftKeys.size());
// need to convert the semi-join condition and possibly the keys
RexNode newSemiJoinFilter;
List<Integer> newLeftKeys;
int[] adjustments = new int[nTotalFields];
if (nKeysFromX > 0) {
// (X, Y, Z) --> (X, Z, Y)
// semiJoin(X, Z)
// pass 0 as Y's adjustment because there shouldn't be any
// references to Y in the semi-join filter
setJoinAdjustments(adjustments, nFieldsX, nFieldsY, nFieldsZ, 0, -nFieldsY);
newSemiJoinFilter = semiJoin.getCondition().accept(new RelOptUtil.RexInputConverter(semiJoin.getCluster().getRexBuilder(), fields, adjustments));
newLeftKeys = leftKeys;
} else {
// (X, Y, Z) --> (X, Y, Z)
// semiJoin(Y, Z)
setJoinAdjustments(adjustments, nFieldsX, nFieldsY, nFieldsZ, -nFieldsX, -nFieldsX);
newSemiJoinFilter = semiJoin.getCondition().accept(new RelOptUtil.RexInputConverter(semiJoin.getCluster().getRexBuilder(), fields, adjustments));
newLeftKeys = RelOptUtil.adjustKeys(leftKeys, -nFieldsX);
}
// create the new join
RelNode leftSemiJoinOp;
if (nKeysFromX > 0) {
leftSemiJoinOp = join.getLeft();
} else {
leftSemiJoinOp = join.getRight();
}
SemiJoin newSemiJoin = SemiJoin.create(leftSemiJoinOp, semiJoin.getRight(), newSemiJoinFilter, ImmutableIntList.copyOf(newLeftKeys), rightKeys);
RelNode leftJoinRel;
RelNode rightJoinRel;
if (nKeysFromX > 0) {
leftJoinRel = newSemiJoin;
rightJoinRel = join.getRight();
} else {
leftJoinRel = join.getLeft();
rightJoinRel = newSemiJoin;
}
RelNode newJoinRel = join.copy(join.getTraitSet(), join.getCondition(), leftJoinRel, rightJoinRel, join.getJoinType(), join.isSemiJoinDone());
call.transformTo(newJoinRel);
}
use of org.apache.calcite.util.ImmutableIntList in project calcite by apache.
the class SemiJoinRule method perform.
protected void perform(RelOptRuleCall call, Project project, Join join, RelNode left, Aggregate aggregate) {
final RelOptCluster cluster = join.getCluster();
final RexBuilder rexBuilder = cluster.getRexBuilder();
if (project != null) {
final ImmutableBitSet bits = RelOptUtil.InputFinder.bits(project.getProjects(), null);
final ImmutableBitSet rightBits = ImmutableBitSet.range(left.getRowType().getFieldCount(), join.getRowType().getFieldCount());
if (bits.intersects(rightBits)) {
return;
}
}
final JoinInfo joinInfo = join.analyzeCondition();
if (!joinInfo.rightSet().equals(ImmutableBitSet.range(aggregate.getGroupCount()))) {
// By the way, neither a super-set nor a sub-set would work.
return;
}
if (!joinInfo.isEqui()) {
return;
}
final RelBuilder relBuilder = call.builder();
relBuilder.push(left);
switch(join.getJoinType()) {
case INNER:
final List<Integer> newRightKeyBuilder = Lists.newArrayList();
final List<Integer> aggregateKeys = aggregate.getGroupSet().asList();
for (int key : joinInfo.rightKeys) {
newRightKeyBuilder.add(aggregateKeys.get(key));
}
final ImmutableIntList newRightKeys = ImmutableIntList.copyOf(newRightKeyBuilder);
relBuilder.push(aggregate.getInput());
final RexNode newCondition = RelOptUtil.createEquiJoinCondition(relBuilder.peek(2, 0), joinInfo.leftKeys, relBuilder.peek(2, 1), newRightKeys, rexBuilder);
relBuilder.semiJoin(newCondition);
break;
case LEFT:
// we can eliminate the semi-join.
break;
default:
throw new AssertionError(join.getJoinType());
}
if (project != null) {
relBuilder.project(project.getProjects(), project.getRowType().getFieldNames());
}
call.transformTo(relBuilder.build());
}
use of org.apache.calcite.util.ImmutableIntList in project hive by apache.
the class HiveSemiJoinRule method perform.
protected void perform(RelOptRuleCall call, ImmutableBitSet topRefs, RelNode topOperator, Join join, RelNode left, Aggregate aggregate) {
LOG.debug("Matched HiveSemiJoinRule");
final RelOptCluster cluster = join.getCluster();
final RexBuilder rexBuilder = cluster.getRexBuilder();
final ImmutableBitSet rightBits = ImmutableBitSet.range(left.getRowType().getFieldCount(), join.getRowType().getFieldCount());
if (topRefs.intersects(rightBits)) {
return;
}
final JoinInfo joinInfo = join.analyzeCondition();
if (!joinInfo.rightSet().equals(ImmutableBitSet.range(aggregate.getGroupCount()))) {
// By the way, neither a super-set nor a sub-set would work.
return;
}
if (join.getJoinType() == JoinRelType.LEFT) {
// since for LEFT join we are only interested in rows from LEFT we can get rid of right side
call.transformTo(topOperator.copy(topOperator.getTraitSet(), ImmutableList.of(left)));
return;
}
if (join.getJoinType() != JoinRelType.INNER) {
return;
}
if (!joinInfo.isEqui()) {
return;
}
LOG.debug("All conditions matched for HiveSemiJoinRule. Going to apply transformation.");
final List<Integer> newRightKeyBuilder = Lists.newArrayList();
final List<Integer> aggregateKeys = aggregate.getGroupSet().asList();
for (int key : joinInfo.rightKeys) {
newRightKeyBuilder.add(aggregateKeys.get(key));
}
final ImmutableIntList newRightKeys = ImmutableIntList.copyOf(newRightKeyBuilder);
final RelNode newRight = aggregate.getInput();
final RexNode newCondition = RelOptUtil.createEquiJoinCondition(left, joinInfo.leftKeys, newRight, newRightKeys, rexBuilder);
RelNode semi = null;
// is not expected further down the pipeline. see jira for more details
if (aggregate.getInput() instanceof HepRelVertex && ((HepRelVertex) aggregate.getInput()).getCurrentRel() instanceof Join) {
Join rightJoin = (Join) (((HepRelVertex) aggregate.getInput()).getCurrentRel());
List<RexNode> projects = new ArrayList<>();
for (int i = 0; i < rightJoin.getRowType().getFieldCount(); i++) {
projects.add(rexBuilder.makeInputRef(rightJoin, i));
}
RelNode topProject = call.builder().push(rightJoin).project(projects, rightJoin.getRowType().getFieldNames(), true).build();
semi = call.builder().push(left).push(topProject).semiJoin(newCondition).build();
} else {
semi = call.builder().push(left).push(aggregate.getInput()).semiJoin(newCondition).build();
}
call.transformTo(topOperator.copy(topOperator.getTraitSet(), ImmutableList.of(semi)));
}
use of org.apache.calcite.util.ImmutableIntList in project hive by apache.
the class HiveJoin method getSortedInputs.
public ImmutableBitSet getSortedInputs() throws CalciteSemanticException {
ImmutableBitSet.Builder sortedInputsBuilder = ImmutableBitSet.builder();
JoinPredicateInfo joinPredInfo = HiveCalciteUtil.JoinPredicateInfo.constructJoinPredicateInfo(this);
List<ImmutableIntList> joinKeysInChildren = new ArrayList<ImmutableIntList>();
joinKeysInChildren.add(ImmutableIntList.copyOf(joinPredInfo.getProjsFromLeftPartOfJoinKeysInChildSchema()));
joinKeysInChildren.add(ImmutableIntList.copyOf(joinPredInfo.getProjsFromRightPartOfJoinKeysInChildSchema()));
final RelMetadataQuery mq = this.left.getCluster().getMetadataQuery();
for (int i = 0; i < this.getInputs().size(); i++) {
List<RelCollation> collations = mq.collations(this.getInputs().get(i));
if (collations != null) {
boolean correctOrderFound = RelCollations.contains(collations, joinKeysInChildren.get(i));
if (correctOrderFound) {
sortedInputsBuilder.set(i);
}
}
}
return sortedInputsBuilder.build();
}
use of org.apache.calcite.util.ImmutableIntList in project calcite by apache.
the class RelMetadataTest method checkCollation.
private void checkCollation(RelOptCluster cluster, RelOptTable empTable, RelOptTable deptTable) {
final RexBuilder rexBuilder = cluster.getRexBuilder();
final LogicalTableScan empScan = LogicalTableScan.create(cluster, empTable);
List<RelCollation> collations = RelMdCollation.table(empScan.getTable());
assertThat(collations.size(), equalTo(0));
// ORDER BY field#0 ASC, field#1 ASC
final RelCollation collation = RelCollations.of(new RelFieldCollation(0), new RelFieldCollation(1));
collations = RelMdCollation.sort(collation);
assertThat(collations.size(), equalTo(1));
assertThat(collations.get(0).getFieldCollations().size(), equalTo(2));
final Sort empSort = LogicalSort.create(empScan, collation, null, null);
final List<RexNode> projects = ImmutableList.of(rexBuilder.makeInputRef(empSort, 1), rexBuilder.makeLiteral("foo"), rexBuilder.makeInputRef(empSort, 0), rexBuilder.makeCall(SqlStdOperatorTable.MINUS, rexBuilder.makeInputRef(empSort, 0), rexBuilder.makeInputRef(empSort, 3)));
final RelMetadataQuery mq = RelMetadataQuery.instance();
collations = RelMdCollation.project(mq, empSort, projects);
assertThat(collations.size(), equalTo(1));
assertThat(collations.get(0).getFieldCollations().size(), equalTo(2));
assertThat(collations.get(0).getFieldCollations().get(0).getFieldIndex(), equalTo(2));
assertThat(collations.get(0).getFieldCollations().get(1).getFieldIndex(), equalTo(0));
final LogicalProject project = LogicalProject.create(empSort, projects, ImmutableList.of("a", "b", "c", "d"));
final LogicalTableScan deptScan = LogicalTableScan.create(cluster, deptTable);
final RelCollation deptCollation = RelCollations.of(new RelFieldCollation(0), new RelFieldCollation(1));
final Sort deptSort = LogicalSort.create(deptScan, deptCollation, null, null);
final ImmutableIntList leftKeys = ImmutableIntList.of(2);
final ImmutableIntList rightKeys = ImmutableIntList.of(0);
final EnumerableMergeJoin join;
try {
join = EnumerableMergeJoin.create(project, deptSort, rexBuilder.makeLiteral(true), leftKeys, rightKeys, JoinRelType.INNER);
} catch (InvalidRelException e) {
throw new RuntimeException(e);
}
collations = RelMdCollation.mergeJoin(mq, project, deptSort, leftKeys, rightKeys);
assertThat(collations, equalTo(join.getTraitSet().getTraits(RelCollationTraitDef.INSTANCE)));
// Values (empty)
collations = RelMdCollation.values(mq, empTable.getRowType(), ImmutableList.<ImmutableList<RexLiteral>>of());
assertThat(collations.toString(), equalTo("[[0, 1, 2, 3, 4, 5, 6, 7, 8], " + "[1, 2, 3, 4, 5, 6, 7, 8], " + "[2, 3, 4, 5, 6, 7, 8], " + "[3, 4, 5, 6, 7, 8], " + "[4, 5, 6, 7, 8], " + "[5, 6, 7, 8], " + "[6, 7, 8], " + "[7, 8], " + "[8]]"));
final LogicalValues emptyValues = LogicalValues.createEmpty(cluster, empTable.getRowType());
assertThat(mq.collations(emptyValues), equalTo(collations));
// Values (non-empty)
final RelDataType rowType = cluster.getTypeFactory().builder().add("a", SqlTypeName.INTEGER).add("b", SqlTypeName.INTEGER).add("c", SqlTypeName.INTEGER).add("d", SqlTypeName.INTEGER).build();
final ImmutableList.Builder<ImmutableList<RexLiteral>> tuples = ImmutableList.builder();
// sort keys are [a], [a, b], [a, b, c], [a, b, c, d], [a, c], [b], [b, a],
// [b, d]
// algorithm deduces [a, b, c, d], [b, d] which is a useful sub-set
addRow(tuples, rexBuilder, 1, 1, 1, 1);
addRow(tuples, rexBuilder, 1, 2, 0, 3);
addRow(tuples, rexBuilder, 2, 3, 2, 2);
addRow(tuples, rexBuilder, 3, 3, 1, 4);
collations = RelMdCollation.values(mq, rowType, tuples.build());
assertThat(collations.toString(), equalTo("[[0, 1, 2, 3], [1, 3]]"));
final LogicalValues values = LogicalValues.create(cluster, rowType, tuples.build());
assertThat(mq.collations(values), equalTo(collations));
}
Aggregations