hsyuan commented on a change in pull request #1451: [CALCITE-3334] Refinement 
for Substitution-Based MV Matching
URL: https://github.com/apache/calcite/pull/1451#discussion_r338194445
 
 

 ##########
 File path: core/src/main/java/org/apache/calcite/plan/SubstitutionVisitor.java
 ##########
 @@ -1252,11 +1564,221 @@ public UnifyResult apply(UnifyRuleCall call) {
       if (!target.groupSet.contains(query.groupSet)) {
         return null;
       }
-      MutableRel result = unifyAggregates(query, target);
+      MutableRel result = unifyAggregates(query, null, target);
       if (result == null) {
         return null;
       }
-      return call.result(result);
+      return tryMergeParentCalcAndGenResult(call, result);
+    }
+  }
+
+  /**
+   * {@link SubstitutionVisitor.UnifyRule} that matches a
+   * {@link MutableUnion} to a {@link MutableUnion} where the query and target
+   * have the same inputs but might not have the same order.
+   */
+  private static class UnionToUnionUnifyRule extends AbstractUnifyRule {
+    public static final UnionToUnionUnifyRule INSTANCE = new 
UnionToUnionUnifyRule();
+
+    private UnionToUnionUnifyRule() {
+      super(any(MutableUnion.class), any(MutableUnion.class), 0);
+    }
+
+    public UnifyResult apply(UnifyRuleCall call) {
+      final MutableUnion query = (MutableUnion) call.query;
+      final MutableUnion target = (MutableUnion) call.target;
+      final List<MutableRel> queryInputs = new ArrayList<>(query.getInputs());
+      final List<MutableRel> targetInputs = new 
ArrayList<>(target.getInputs());
+      if (query.isAll() == target.isAll()
+          && sameRelCollectionNoOrderConsidered(queryInputs, targetInputs)) {
+        return call.result(target);
+      }
+      return null;
+    }
+  }
+
+  /**
+   * A {@link SubstitutionVisitor.UnifyRule} that matches a {@link 
MutableUnion}
+   * which has {@link MutableCalc} as child to a {@link MutableUnion}.
+   * We try to pull up the {@link MutableCalc} to top of {@link MutableUnion},
+   * then match the {@link MutableUnion} in query to {@link MutableUnion} in 
target.
+   */
+  private static class UnionOnCalcsToUnionUnifyRule extends AbstractUnifyRule {
+    public static final UnionOnCalcsToUnionUnifyRule INSTANCE =
+        new UnionOnCalcsToUnionUnifyRule();
+
+    private UnionOnCalcsToUnionUnifyRule() {
+      super(any(MutableUnion.class), any(MutableUnion.class), 0);
+    }
+
+    public UnifyResult apply(UnifyRuleCall call) {
+      final MutableUnion query = (MutableUnion) call.query;
+      final MutableUnion target = (MutableUnion) call.target;
+      final List<MutableCalc> queryInputs = new ArrayList<>();
+      final List<MutableRel> queryGrandInputs = new ArrayList<>();
+      List<MutableRel> targetInputs = new ArrayList<>(target.getInputs());
+
+      final RexBuilder rexBuilder = call.getCluster().getRexBuilder();
+
+      for (MutableRel rel: query.getInputs()) {
+        if (rel instanceof MutableCalc) {
+          queryInputs.add((MutableCalc) rel);
+          queryGrandInputs.add(((MutableCalc) rel).getInput());
+        } else {
+          return null;
+        }
+      }
+
+      if (query.isAll() && target.isAll()
+          && sameRelCollectionNoOrderConsidered(queryGrandInputs, 
targetInputs)) {
+        Pair<RexNode, List<RexNode>> queryInputExplained0 =
+            explainCalc(queryInputs.get(0));
+        for (int i = 1; i < queryGrandInputs.size(); i++) {
+          Pair<RexNode, List<RexNode>> queryInputExplained =
+              explainCalc(queryInputs.get(i));
+          // Matching fails when filtering conditions are not equal or 
projects are not equal.
+          if (!splitFilter(call.getSimplify(), queryInputExplained0.left,
+              queryInputExplained.left).isAlwaysTrue()) {
+            return null;
+          }
+          for (Pair<RexNode, RexNode> pair : Pair.zip(
+              queryInputExplained0.right, queryInputExplained.right)) {
+            if (!pair.left.equals(pair.right)) {
+              return null;
+            }
+          }
+        }
+        RexProgram compenRexProgram = RexProgram.create(
+            target.rowType, queryInputExplained0.right, 
queryInputExplained0.left,
+            query.rowType, rexBuilder);
+        MutableCalc compenCalc = MutableCalc.of(target, compenRexProgram);
+        return tryMergeParentCalcAndGenResult(call, compenCalc);
+      }
+
+      return null;
+    }
+  }
+
+  /** Check if list0 and list1 contains the same nodes -- order is not 
considered. */
+  private static boolean sameRelCollectionNoOrderConsidered(
+      List<MutableRel> list0, List<MutableRel> list1) {
+    if (list0.size() == list1.size()) {
 
 Review comment:
   Can we use 
   ```
   if (list0.size() != list1.size()) {
       return false;
   }
   .......

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