xiedeyantu commented on code in PR #4562:
URL: https://github.com/apache/calcite/pull/4562#discussion_r2398330079


##########
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:
   Sorry, I’m not sure if I didn’t explain it clearly multiple times or if 
there was some other reason, but I feel like we’re not quite on the same page. 
What I meant is that during the processing of the current PR, a PROJECT was 
added to each INPUT of the INTERSECT before forming the JOIN. From a 
correctness perspective, I believe this is fine. However, I think this PROJECT 
might be unnecessary—ideally, we should use the simplest approach for rule 
transformation rather than adding a PROJECT for convenience. That said, 
considering that PROJECT pushdown might generate a plan like yours in later 
stages, I’m unsure whether adding this PROJECT is a good practice. If I still 
haven’t made myself clear, please feel free to ask for clarification. Of 
course, the correctness of the current plan is not in question, and if you’d 
like to merge it, I have no objections.



-- 
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]

Reply via email to