This is an automated email from the ASF dual-hosted git repository.
morrysnow pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/doris.git
The following commit(s) were added to refs/heads/master by this push:
new 160d2be0d8 [minimal](Nereids) add more comments for the rewriter
(#19788)
160d2be0d8 is described below
commit 160d2be0d823496a134ee2031fc4680557c99e9a
Author: Chengpeng Yan <[email protected]>
AuthorDate: Thu May 18 14:47:25 2023 +0800
[minimal](Nereids) add more comments for the rewriter (#19788)
Only add some comments to the rewriter. Because it is fewer comments before
and it's hard to understand for the newbie.
---
.../nereids/jobs/rewrite/CustomRewriteJob.java | 3 ++
.../jobs/rewrite/PlanTreeRewriteBottomUpJob.java | 37 +++++++++++++++++++---
.../jobs/rewrite/PlanTreeRewriteTopDownJob.java | 7 +++-
3 files changed, 41 insertions(+), 6 deletions(-)
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/jobs/rewrite/CustomRewriteJob.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/jobs/rewrite/CustomRewriteJob.java
index a05ad215a3..cf163010b7 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/jobs/rewrite/CustomRewriteJob.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/jobs/rewrite/CustomRewriteJob.java
@@ -31,6 +31,9 @@ import java.util.function.Supplier;
/**
* Custom rewrite the plan.
+ * Just pass the plan node to the 'CustomRewriter', and the 'CustomRewriter'
rule will handle it.
+ * The 'CustomRewriter' rule use the 'Visitor' design pattern to implement the
rule.
+ * You can check the 'CustomRewriter' interface to see which rules use this
way to do rewrite.
*/
public class CustomRewriteJob implements RewriteJob {
private final RuleType ruleType;
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/jobs/rewrite/PlanTreeRewriteBottomUpJob.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/jobs/rewrite/PlanTreeRewriteBottomUpJob.java
index 8e625b638d..5652298266 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/jobs/rewrite/PlanTreeRewriteBottomUpJob.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/jobs/rewrite/PlanTreeRewriteBottomUpJob.java
@@ -26,31 +26,50 @@ import java.util.List;
import java.util.Objects;
import java.util.Optional;
-/** PlanTreeRewriteBottomUpJob */
+/**
+ * PlanTreeRewriteBottomUpJob
+ * The job is used for bottom-up rewrite. If some rewrite rules can take
effect,
+ * we will process all the rules from the leaf node again. So there are some
rules that can take effect interactively,
+ * we should use the 'Bottom-Up' job to handle it.
+ */
public class PlanTreeRewriteBottomUpJob extends PlanTreeRewriteJob {
+ // REWRITE_STATE_KEY represents the key to store the 'RewriteState'. Each
plan node has their own 'RewriteState'.
+ // Different 'RewriteState' has different actions,
+ // so we will do specified action for each node based on their
'RewriteState'.
private static final String REWRITE_STATE_KEY = "rewrite_state";
private RewriteJobContext rewriteJobContext;
private List<Rule> rules;
enum RewriteState {
- ENSURE_CHILDREN_REWRITTEN, REWRITE_THIS, REWRITTEN
+ // 'REWRITE_THIS' means the current plan node can be handled
immediately. If the plan state is 'REWRITE_THIS',
+ // it means all of its children's state are 'REWRITTEN'. Because we
handle the plan tree bottom up.
+ REWRITE_THIS,
+ // 'REWRITTEN' means the current plan have been handled already, we
don't need to do anything else.
+ REWRITTEN,
+ // 'ENSURE_CHILDREN_REWRITTEN' means we need to check the children for
the current plan node first.
+ // It means some plans have changed after rewrite, so we need traverse
the plan tree and reset their state.
+ // All the plan nodes need to be handled again.
+ ENSURE_CHILDREN_REWRITTEN
}
public PlanTreeRewriteBottomUpJob(RewriteJobContext rewriteJobContext,
JobContext context, List<Rule> rules) {
- super(JobType.TOP_DOWN_REWRITE, context);
+ super(JobType.BOTTOM_UP_REWRITE, context);
this.rewriteJobContext = Objects.requireNonNull(rewriteJobContext,
"rewriteContext cannot be null");
this.rules = Objects.requireNonNull(rules, "rules cannot be null");
}
@Override
public void execute() {
- // use childrenVisited to judge whether clear the state in the
previous batch
+ // For the bottom-up rewrite job, we need to reset the state of its
children
+ // if the plan has changed after the rewrite. So we use the
'childrenVisited' to check this situation.
boolean clearStatePhase = !rewriteJobContext.childrenVisited;
if (clearStatePhase) {
traverseClearState();
return;
}
+ // We'll do different actions based on their different states.
+ // You can check the comment in 'RewriteState' structure for more
details.
Plan plan = rewriteJobContext.plan;
RewriteState state = getState(plan);
switch (state) {
@@ -69,10 +88,13 @@ public class PlanTreeRewriteBottomUpJob extends
PlanTreeRewriteJob {
}
private void traverseClearState() {
+ // Reset the state for current node.
RewriteJobContext clearedStateContext =
rewriteJobContext.withChildrenVisited(true);
setState(clearedStateContext.plan, RewriteState.REWRITE_THIS);
pushJob(new PlanTreeRewriteBottomUpJob(clearedStateContext, context,
rules));
+ // Generate the new rewrite job for its children. Because the
character of stack is 'first in, last out',
+ // so we can traverse reset the state for the plan node until the leaf
node.
List<Plan> children = clearedStateContext.plan.children();
for (int i = children.size() - 1; i >= 0; i--) {
Plan child = children.get(i);
@@ -83,25 +105,30 @@ public class PlanTreeRewriteBottomUpJob extends
PlanTreeRewriteJob {
}
private void rewriteThis() {
+ // Link the current node with the sub-plan to get the current plan
which is used in the rewrite phase later.
Plan plan = linkChildren(rewriteJobContext.plan,
rewriteJobContext.childrenContext);
RewriteResult rewriteResult = rewrite(plan, rules, rewriteJobContext);
if (rewriteResult.hasNewPlan) {
RewriteJobContext newJobContext =
rewriteJobContext.withPlan(rewriteResult.plan);
RewriteState state = getState(rewriteResult.plan);
- // some eliminate rule will return a rewritten plan
+ // Some eliminate rule will return a rewritten plan, for example
the current node is eliminated
+ // and return the child plan. So we don't need to handle it again.
if (state == RewriteState.REWRITTEN) {
newJobContext.setResult(rewriteResult.plan);
return;
}
+ // After the rewrite take effect, we should handle the children
part again.
pushJob(new PlanTreeRewriteBottomUpJob(newJobContext, context,
rules));
setState(rewriteResult.plan,
RewriteState.ENSURE_CHILDREN_REWRITTEN);
} else {
+ // No new plan is generated, so just set the state of the current
plan to 'REWRITTEN'.
setState(rewriteResult.plan, RewriteState.REWRITTEN);
rewriteJobContext.setResult(rewriteResult.plan);
}
}
private void ensureChildrenRewritten() {
+ // Similar to the function 'traverseClearState'.
Plan plan = rewriteJobContext.plan;
setState(plan, RewriteState.REWRITE_THIS);
pushJob(new PlanTreeRewriteBottomUpJob(rewriteJobContext, context,
rules));
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/jobs/rewrite/PlanTreeRewriteTopDownJob.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/jobs/rewrite/PlanTreeRewriteTopDownJob.java
index e92dd15f27..d280159a01 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/jobs/rewrite/PlanTreeRewriteTopDownJob.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/jobs/rewrite/PlanTreeRewriteTopDownJob.java
@@ -25,7 +25,11 @@ import org.apache.doris.nereids.trees.plans.Plan;
import java.util.List;
import java.util.Objects;
-/** PlanTreeRewriteTopDownJob */
+/**
+ * PlanTreeRewriteTopDownJob
+ * It's easier than the 'BottomUp' job, it handles the plan tree top-down. If
some new plans generated after rewrite,
+ * it only processes the current node again. Otherwise, it just recursively
handles its children.
+ */
public class PlanTreeRewriteTopDownJob extends PlanTreeRewriteJob {
private RewriteJobContext rewriteJobContext;
private List<Rule> rules;
@@ -57,6 +61,7 @@ public class PlanTreeRewriteTopDownJob extends
PlanTreeRewriteJob {
pushJob(new PlanTreeRewriteTopDownJob(childRewriteJobContext,
context, rules));
}
} else {
+ // All the children part are already visited. Just link the
children plan to the current node.
Plan result = linkChildrenAndParent(rewriteJobContext.plan,
rewriteJobContext);
if (rewriteJobContext.parentContext == null) {
context.getCascadesContext().setRewritePlan(result);
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]