silundong commented on code in PR #4392:
URL: https://github.com/apache/calcite/pull/4392#discussion_r2155842422
##########
core/src/main/java/org/apache/calcite/rel/rules/HyperEdge.java:
##########
@@ -73,10 +123,224 @@ public RexNode getCondition() {
@Override public String toString() {
StringBuilder sb = new StringBuilder();
- sb.append(LongBitmap.printBitmap(leftNodeBits))
+ sb.append(LongBitmap.printBitmap(getLeftEndpoint()))
.append("——[").append(joinType).append(",
").append(condition).append("]——")
- .append(LongBitmap.printBitmap(rightNodeBits));
+ .append(LongBitmap.printBitmap(getRightEndpoint()));
return sb.toString();
}
+ // It is convenient for the accept method in the HyperGraph class to call
+ public HyperEdge accept(RexShuttle shuttle) {
+ RexNode shuttleCondition = condition.accept(shuttle);
+ return new HyperEdge(
+ tes,
+ conflictRules,
+ leftNodeUsedInPredicate,
+ rightNodeUsedInPredicate,
+ initialLeftNodeBits,
+ initialRightNodeBits,
+ joinType,
+ shuttleCondition);
+ }
+
+ /**
+ * When {@link JoinToHyperGraphRule} constructs a hypergraph , if the right
child of Join is a
+ * HyperGraph class, all bitmaps related to inputs in this right child need
to be shifted
+ * according to the number of inputs in the left child of Join.
+ *
+ * @param nodeOffset number of inputs in the left child
+ * @return HyperEdge after shifted
+ */
+ public HyperEdge adjustNodeBit(int nodeOffset) {
+ RexShuttle shiftNodeIndexShuttle = new RexShuttle() {
+ @Override public RexNode visitNodeAndFieldIndex(RexNodeAndFieldIndex
nodeAndFieldIndex) {
+ return new RexNodeAndFieldIndex(
+ nodeAndFieldIndex.getNodeIndex() << nodeOffset,
+ nodeAndFieldIndex.getFieldIndex(),
+ nodeAndFieldIndex.getName(),
+ nodeAndFieldIndex.getType());
+ }
+ };
+ RexNode shiftedCondition = condition.accept(shiftNodeIndexShuttle);
+ List<ConflictRule> shiftedConflictRules = new ArrayList<>();
+ for (ConflictRule conflictRule : conflictRules) {
+ shiftedConflictRules.add(conflictRule.shift(nodeOffset));
+ }
+ return new HyperEdge(
+ tes.shift(nodeOffset),
+ shiftedConflictRules,
+ leftNodeUsedInPredicate << nodeOffset,
+ rightNodeUsedInPredicate << nodeOffset,
+ initialLeftNodeBits << nodeOffset,
+ initialRightNodeBits << nodeOffset,
+ joinType,
+ shiftedCondition);
+ }
+
+ /**
+ * Build hyperedges corresponding to a join operator. The construction of a
HyperEdge includes
+ * total eligibility set, conflict rules, node-related bitmaps, predicate
expressions (RexInputRef
+ * is replaced by RexNodeAndFieldIndex) and join type.
+ *
+ * @param inputRefToNodeIndexMap a map from inputRef to node index
+ * @param inputRefToFieldIndexMap a map from inputRef to field index
+ * @param joinConds join conditions
+ * @param conflictRules all conflict rules
+ * @param joinType join type
+ * @param leftNodeCount number of inputs in the left child of Join
+ * @param nodeCount number of inputs of Join
+ * @return HyperEdge list
+ */
+ public static List<HyperEdge> createHyperEdgesFromJoinConds(
+ Map<Integer, Integer> inputRefToNodeIndexMap,
+ Map<Integer, Integer> inputRefToFieldIndexMap,
+ List<RexNode> joinConds,
+ List<ConflictRule> conflictRules,
+ JoinRelType joinType,
+ int leftNodeCount,
+ int nodeCount) {
+ // for join operator o, generate bitmaps of the relations on the
left/right sides
+ long initialLeftNodeBits = LongBitmap.newBitmapBetween(0, leftNodeCount);
+ long initialRightNodeBits = LongBitmap.newBitmapBetween(leftNodeCount,
nodeCount);
+
+ List<HyperEdge> edges = new ArrayList<>();
+ for (RexNode joinCond : joinConds) {
+ List<Integer> leftRefs = new ArrayList<>();
+ List<Integer> rightRefs = new ArrayList<>();
+ RexShuttle inputRef2NodeAndFieldIndexShuttle = new RexShuttle() {
+ @Override public RexNode visitInputRef(RexInputRef inputRef) {
+ Integer nodeIndex = inputRefToNodeIndexMap.get(inputRef.getIndex());
+ assert nodeIndex != null;
+ // collect left input index and right input index
+ if (nodeIndex < leftNodeCount) {
+ leftRefs.add(nodeIndex);
+ } else {
+ rightRefs.add(nodeIndex);
+ }
+ Integer fieldIndex =
inputRefToFieldIndexMap.get(inputRef.getIndex());
+ assert fieldIndex != null;
+
+ return new RexNodeAndFieldIndex(
+ nodeIndex,
+ fieldIndex,
+ inputRef.getName(),
+ inputRef.getType());
+ }
+ };
+ RexNode hyperEdgeCondition =
joinCond.accept(inputRef2NodeAndFieldIndexShuttle);
+
+ long leftNodeUsedInPredicate = LongBitmap.newBitmapFromList(leftRefs);
+ long rightNodeUsedInPredicate = LongBitmap.newBitmapFromList(rightRefs);
+ TotalEligibilitySet tes;
+ List<ConflictRule> conflictRulesAfterAbsorb = new ArrayList<>();
+ if (leftNodeUsedInPredicate == 0 || rightNodeUsedInPredicate == 0) {
+ // when dealing with cross products or degenerate predicates,
construct total eligibility
+ // set using all nodes on the left and right sides (as the endpoint of
the hyperedge). Cross
+ // products and degenerate predicates should be rare in real queries,
this behavior
Review Comment:
Got it. I will update the comment.
--
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]