julianhyde commented on a change in pull request #1589: [CALCITE-3508] 
Strengthen outer Join to inner if it is under a Filter that discards null values
URL: https://github.com/apache/calcite/pull/1589#discussion_r347670650
 
 

 ##########
 File path: core/src/main/java/org/apache/calcite/rel/rules/FilterJoinRule.java
 ##########
 @@ -156,6 +161,52 @@ protected void perform(RelOptRuleCall call, Filter filter,
     final List<RexNode> leftFilters = new ArrayList<>();
     final List<RexNode> rightFilters = new ArrayList<>();
 
+    final int nFieldsLeft = join
+        .getInputs()
+        .get(0)
+        .getRowType()
+        .getFieldList()
+        .size();
+    final int nFieldsRight = join
+        .getInputs()
+        .get(1)
+        .getRowType()
+        .getFieldList()
+        .size();
+
+    final int nTotalFields = join.getRowType().getFieldList().size();
+    final int nSysFields = 0; // joinRel.getSystemFieldList().size();
+
+    // Setup two bit sets, one for the left side of the join indicating what 
fields are present
+    // in the left side of the join and the other for the right side.
+    final ImmutableBitSet leftBitmap = ImmutableBitSet.range(
+        nSysFields, nSysFields + nFieldsLeft);
+    final ImmutableBitSet rightBitmap = ImmutableBitSet.range(
+        nSysFields + nFieldsLeft, nTotalFields);
+
+    // When a join can create nulls on the left (or right) leverage the filter 
to determine if
+    // the join can cancel nulls on left (or right).
+    if (joinType.generatesNullsOnLeft() && filter != null) {
+      final RexVisitor<Boolean> mustMatchSideVisitor = new 
TableNotNullable(leftBitmap);
+      final Boolean filterMustMatch = 
filter.getCondition().accept(mustMatchSideVisitor);
+      if (filterMustMatch != null) {
+        if (filterMustMatch != Boolean.FALSE) {
+          joinType = joinType.cancelNullsOnLeft();
+        }
+      }
+    }
+
+    // When a join can create nulls on the right (or left) leverage the filter 
to determine if
+    // the join can cancel nulls on right (or left).
+    if (joinType.generatesNullsOnRight() && filter != null) {
+      final RexVisitor<Boolean> mustMatchSideVisitor = new 
TableNotNullable(rightBitmap);
+      final Boolean filterMustMatch = 
filter.getCondition().accept(mustMatchSideVisitor);
+      if (filterMustMatch != null) {
+        if (filterMustMatch != Boolean.FALSE) {
 
 Review comment:
   I don't know what would be troublesome. I do know what we don't know what we 
don't know. And therefore starting from scratch is a mistake.
   
   A couple of examples: 
   * '(x IS NOT TRUE) IS NOT NULL' (the IS functions convert 3vl to 2vl, so, 
like NOT they have complex truth tables)
   * '(CASE WHEN x = 1 THEN 5 ELSE y END) > z' (you can isolate the expression 
to left or right input only if you push '> z' into the CASE)
   * and any expression that is deeply nested (e.g. contains NOT inside CASE 
inside NOT)

----------------------------------------------------------------
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.
 
For queries about this service, please contact Infrastructure at:
[email protected]


With regards,
Apache Git Services

Reply via email to