asolimando commented on code in PR #4562:
URL: https://github.com/apache/calcite/pull/4562#discussion_r2398035982
##########
core/src/main/java/org/apache/calcite/rel/rules/IntersectToSemiJoinRule.java:
##########
@@ -112,33 +114,50 @@ protected IntersectToSemiJoinRule(Config config) {
for (int i = 1; i < inputs.size(); i++) {
RelNode next = inputs.get(i);
- List<RexNode> conditions = new ArrayList<>();
- int fieldCount = current.getRowType().getFieldCount();
- for (int j = 0; j < fieldCount; j++) {
- RelDataType leftFieldType =
current.getRowType().getFieldList().get(j).getType();
- RelDataType rightFieldType =
next.getRowType().getFieldList().get(j).getType();
- RelDataType leastFieldType =
leastRowType.getFieldList().get(j).getType();
+ // cast columns of the join inputs to the least types (global)
+ final RelNode leftCasted = projectJoinInput(builder, leastRowType,
current);
+ final RelNode rightCasted = projectJoinInput(builder, leastRowType,
next);
+
+ builder.clear();
+ builder.push(leftCasted).push(rightCasted);
- conditions.add(
+ // compute the join condition over plain fields from the projections of
left/right inputs
+ final int fieldCount = leastRowType.getFieldCount();
+ final List<RexNode> joinPredicates = new ArrayList<>(fieldCount);
+ for (int j = 0; j < fieldCount; j++) {
+ joinPredicates.add(
builder.isNotDistinctFrom(
- rexBuilder.makeCast(leastFieldType,
- rexBuilder.makeInputRef(leftFieldType, j)),
- rexBuilder.makeCast(leastFieldType,
- rexBuilder.makeInputRef(rightFieldType, j + fieldCount))));
+ builder.field(2, 0, j),
+ builder.field(2, 1, j)));
}
- RexNode condition = RexUtil.composeConjunction(rexBuilder, conditions);
- builder.push(next)
- .join(JoinRelType.SEMI, condition);
+ final RexNode condition = RexUtil.composeConjunction(rexBuilder,
joinPredicates);
+ builder.join(JoinRelType.SEMI, condition);
current = builder.peek();
}
- builder.distinct()
- .convert(leastRowType, true);
+ builder.distinct().convert(leastRowType, true);
call.transformTo(builder.build());
}
+ private RelNode projectJoinInput(
+ RelBuilder builder, RelDataType leastRowType, RelNode joinInput) {
+ builder.clear();
+ builder.push(joinInput);
+
+ final int fieldCount = joinInput.getRowType().getFieldCount();
+ final List<String> names = leastRowType.getFieldNames();
+ final List<RexNode> joinKeys = new ArrayList<>(fieldCount);
+ final RexBuilder rexBuilder = builder.getRexBuilder();
+ for (int j = 0; j < fieldCount; j++) {
+ final RelDataType leastType =
leastRowType.getFieldList().get(j).getType();
+ joinKeys.add(rexBuilder.makeCast(leastType, builder.field(j)));
+ }
+
+ return builder.project(joinKeys, names).build();
Review Comment:
Because rules are generally reasoning "locally" unless strictly needed, they
generate the changes they need, and they count on other rules to compose nicely
and optimize away redundancies, it's separation of concerns.
There are exceptions to this where you bake a few transformations into a
single rule when costly or necessary to do otherwise (e.g., in CALCITE-7125 we
were forced to keep a "composite" rule as it wasn't possible to get that by
rule composition), which is not the case here.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]