morrySnow commented on code in PR #12147:
URL: https://github.com/apache/doris/pull/12147#discussion_r957387267


##########
fe/fe-core/src/main/java/org/apache/doris/nereids/memo/Memo.java:
##########
@@ -277,12 +346,172 @@ public void addEnforcerPlan(GroupExpression 
groupExpression, Group group) {
         groupExpression.setOwnerGroup(group);
     }
 
+    private CopyInResult rewriteByExistsPlan(Group targetGroup, Plan 
existsPlan) {
+        GroupExpression existedLogicalExpression = existsPlan instanceof 
GroupPlan
+                ? ((GroupPlan) existsPlan).getGroup().getLogicalExpression() 
// get first logicalGroupExpression
+                : existsPlan.getGroupExpression().get();
+        if (targetGroup != null) {
+            Group existedGroup = existedLogicalExpression.getOwnerGroup();
+            // clear targetGroup, from exist group move all logical 
groupExpression
+            // and logicalProperties to target group
+            eliminateFromGroupAndMoveToTargetGroup(existedGroup, targetGroup, 
existsPlan.getLogicalProperties());
+        }
+        return CopyInResult.of(false, existedLogicalExpression);
+    }
+
+    private CopyInResult rewriteByNewGroupExpression(Group targetGroup, Plan 
newPlan,
+            GroupExpression newGroupExpression) {
+        if (targetGroup == null) {
+            // case 2:
+            // if not exist target group and not exist the same group 
expression,
+            // then create new group with the newGroupExpression
+            Group newGroup = new Group(groupIdGenerator.getNextId(), 
newGroupExpression,
+                    newPlan.getLogicalProperties());
+            groups.put(newGroup.getGroupId(), newGroup);
+            groupExpressions.put(newGroupExpression, newGroupExpression);
+        } else {
+            // case 3:
+            // if exist the target group, clear all origin group expressions 
in the
+            // existedExpression's owner group and reset logical properties, 
the
+            // newGroupExpression is the init logical group expression
+            reInitGroup(targetGroup, newGroupExpression, 
newPlan.getLogicalProperties());
+        }
+        return CopyInResult.of(true, newGroupExpression);
+    }
+
+    private CopyInResult rewriteByExistedGroupExpression(Group targetGroup, 
Plan existedPlan,
+            GroupExpression existedExpression, GroupExpression newExpression) {
+        if (targetGroup != null && 
!targetGroup.equals(existedExpression.getOwnerGroup())) {
+            // case 4:
+            existedExpression.propagateApplied(newExpression);
+            moveParentExpressionsReference(existedExpression.getOwnerGroup(), 
targetGroup);
+            recycleGroup(existedExpression.getOwnerGroup());
+            reInitGroup(targetGroup, newExpression, 
existedPlan.getLogicalProperties());
+            return CopyInResult.of(true, newExpression);
+        } else {
+            // case 5:
+            // if targetGroup is null or targetGroup equal to the 
existedExpression's ownerGroup,
+            // then recycle the temporary new group expression
+            recycleExpression(newExpression);
+            return CopyInResult.of(false, existedExpression);
+        }
+    }
+
+    /**
+     * eliminate fromGroup, clear targetGroup, then move the logical group 
expressions in the fromGroup to the toGroup.
+     *
+     * the scenario is:
+     * ```
+     *  Group 1(project, the targetGroup)                  Group 
1(logicalOlapScan, the targetGroup)
+     *               |                             =>
+     *  Group 0(logicalOlapScan, the fromGroup)
+     * ```
+     *
+     * we should recycle the group 0, and recycle all group expressions in 
group 1, then move the logicalOlapScan to
+     * the group 1, and reset logical properties of the group 1.
+     */
+    private void eliminateFromGroupAndMoveToTargetGroup(Group fromGroup, Group 
targetGroup,
+            LogicalProperties logicalProperties) {
+        if (fromGroup == targetGroup) {
+            return;
+        }
+        // simple check targetGroup is the ancestors of the fromGroup, not 
check completely because of performance
+        if (fromGroup == root) {
+            throw new IllegalStateException(
+                    "TargetGroup should be ancestors of fromGroup, but 
fromGroup is root. Maybe a bug");
+        }
+
+        List<GroupExpression> logicalExpressions = 
fromGroup.clearLogicalExpressions();
+        recycleGroup(fromGroup);
+
+        recycleLogicalExpressions(targetGroup);
+        recyclePhysicalExpressions(targetGroup);
+
+        for (GroupExpression logicalExpression : logicalExpressions) {
+            targetGroup.addLogicalExpression(logicalExpression);
+        }
+        targetGroup.setLogicalProperties(logicalProperties);
+    }
+
+    private void reInitGroup(Group group, GroupExpression 
initLogicalExpression, LogicalProperties logicalProperties) {
+        recycleLogicalExpressions(group);
+        recyclePhysicalExpressions(group);
+
+        group.setLogicalProperties(logicalProperties);
+        group.addLogicalExpression(initLogicalExpression);
+
+        // note: put newGroupExpression must behind recycle 
existedExpression(reInitGroup method),
+        //       because existedExpression maybe equal to the 
newGroupExpression and recycle
+        //       existedExpression will recycle newGroupExpression
+        groupExpressions.put(initLogicalExpression, initLogicalExpression);
+    }
+
     private Plan replaceChildrenToGroupPlan(Plan plan, List<Group> 
childrenGroups) {
+        if (childrenGroups.isEmpty()) {
+            return plan;
+        }
         List<Plan> groupPlanChildren = childrenGroups.stream()
                 .map(GroupPlan::new)
                 .collect(ImmutableList.toImmutableList());
         LogicalProperties logicalProperties = plan.getLogicalProperties();
         return plan.withChildren(groupPlanChildren)
             .withLogicalProperties(Optional.of(logicalProperties));
     }
+
+    private void moveParentExpressionsReference(Group fromGroup, Group 
toGroup) {
+        for (GroupExpression parentGroupExpression : 
fromGroup.getParentGroupExpressions()) {
+            /*
+             * the scenarios that 'parentGroupExpression == toGroup': 
eliminate the root group.
+             * the fromGroup is group 1, the toGroup is group 2, we can not 
replace group2's
+             * groupExpressions reference the child group which is group 2 
(reference itself).
+             *
+             *   A(group 2)            B(group 2)
+             *   |                     |
+             *   B(group 1)      =>    C(group 0)
+             *   |
+             *   C(group 0)
+             */
+            if (parentGroupExpression.getOwnerGroup() != toGroup) {
+                parentGroupExpression.replaceChild(fromGroup, toGroup);

Review Comment:
   if we do this separately, we need to add more comment to explain it. 
Otherwise this method may be used by mistake



-- 
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: commits-unsubscr...@doris.apache.org

For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscr...@doris.apache.org
For additional commands, e-mail: commits-h...@doris.apache.org

Reply via email to