Skip to content

Commit

Permalink
Add validator for OptGroup
Browse files Browse the repository at this point in the history
  • Loading branch information
yixinglu committed Dec 6, 2022
1 parent 9707c93 commit e4ba34e
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 3 deletions.
2 changes: 1 addition & 1 deletion src/graph/optimizer/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ nebula_add_library(
rule/PushFilterDownAggregateRule.cpp
rule/PushFilterDownProjectRule.cpp
rule/PushFilterDownLeftJoinRule.cpp
rule/PushFilterDownHashInnerJoinRule.cpp
# rule/PushFilterDownHashInnerJoinRule.cpp
rule/PushFilterDownInnerJoinRule.cpp
rule/PushFilterDownNodeRule.cpp
rule/PushFilterDownScanVerticesRule.cpp
Expand Down
67 changes: 65 additions & 2 deletions src/graph/optimizer/OptGroup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,28 @@ Status OptGroup::validateSubPlan(const OptGroupNode *gn,
return Status::OK();
}

Status OptGroup::validate(const OptRule *rule) const {
if (groupNodes_.empty() && !groupNodesReferenced_.empty()) {
return Status::Error(
"The OptGroup has no any OptGroupNode but used by other OptGroupNode "
"when applying the rule: %s, numGroupNodesRef: %lu",
rule->toString().c_str(),
groupNodesReferenced_.size());
}
for (auto *gn : groupNodes_) {
NG_RETURN_IF_ERROR(gn->validate(rule));
if (gn->node()->outputVar() != outputVar_) {
return Status::Error(
"The output columns of the OptGroupNode is different from OptGroup "
"when applying the rule: %s, %s vs. %s",
rule->toString().c_str(),
gn->node()->outputVar().c_str(),
outputVar_.c_str());
}
}
return Status::OK();
}

void OptGroup::addGroupNode(OptGroupNode *groupNode) {
DCHECK_EQ(this, DCHECK_NOTNULL(groupNode)->group());
if (outputVar_.empty()) {
Expand Down Expand Up @@ -144,6 +166,10 @@ Status OptGroup::explore(const OptRule *rule) {
auto resStatus = rule->transform(ctx_, matched);
NG_RETURN_IF_ERROR(resStatus);
auto result = std::move(resStatus).value();

// for (auto *ngn : result.newGroupNodes) {
// NG_RETURN_IF_ERROR(validateSubPlan(ngn, rule, leaves));
// }
// In some cases, we can apply optimization rules even if the control flow and data flow are
// inconsistent. For now, let the optimization rules themselves guarantee correctness.
if (result.eraseAll) {
Expand All @@ -152,15 +178,15 @@ Status OptGroup::explore(const OptRule *rule) {
}
groupNodes_.clear();
for (auto ngn : result.newGroupNodes) {
NG_RETURN_IF_ERROR(validateSubPlan(ngn, rule, leaves));
// NG_RETURN_IF_ERROR(validateSubPlan(ngn, rule, leaves));
addGroupNode(ngn);
}
break;
}

if (!result.newGroupNodes.empty()) {
for (auto ngn : result.newGroupNodes) {
NG_RETURN_IF_ERROR(validateSubPlan(ngn, rule, leaves));
// NG_RETURN_IF_ERROR(validateSubPlan(ngn, rule, leaves));
addGroupNode(ngn);
}

Expand Down Expand Up @@ -300,5 +326,42 @@ void OptGroupNode::release() {
}
}

Status OptGroupNode::validate(const OptRule *rule) const {
if (!node_) {
return Status::Error("The OptGroupNode does not have plan node when applying the rule: %s",
rule->toString().c_str());
}
if (!group_) {
return Status::Error(
"The OptGroupNode does not have the right OptGroup when applying the rule: %s",
rule->toString().c_str());
}
if (!bodies_.empty()) {
if (node_->kind() != PlanNode::Kind::kLoop) {
return Status::Error(
"The plan node is not Loop in OptGroupNode when applying the rule: %s, planNode: %s",
rule->toString().c_str(),
PlanNode::toString(node_->kind()));
}
for (auto *g : bodies_) {
NG_RETURN_IF_ERROR(g->validate(rule));
}
}
if (dependencies_.empty()) {
if (node_->kind() != PlanNode::Kind::kStart && node_->kind() != PlanNode::Kind::kArgument) {
return Status::Error(
"The leaf plan node is not Start or Argument in OptGroupNode when applying the rule: %s, "
"planNode: %s",
rule->toString().c_str(),
PlanNode::toString(node_->kind()));
}
} else {
for (auto *g : dependencies_) {
NG_RETURN_IF_ERROR(g->validate(rule));
}
}
return Status::OK();
}

} // namespace opt
} // namespace nebula
4 changes: 4 additions & 0 deletions src/graph/optimizer/OptGroup.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ class OptGroup final {
isRootGroup_ = true;
}

Status validate(const OptRule *rule) const;

private:
friend ObjectPool;
explicit OptGroup(OptContext *ctx) noexcept;
Expand Down Expand Up @@ -133,6 +135,8 @@ class OptGroupNode final {
// Release the opt group node from its opt group
void release();

Status validate(const OptRule *rule) const;

private:
friend ObjectPool;
OptGroupNode(graph::PlanNode *node, const OptGroup *group) noexcept;
Expand Down
1 change: 1 addition & 0 deletions src/graph/optimizer/Optimizer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ Status Optimizer::doExploration(OptContext *octx, OptGroup *rootGroup) {
for (auto rule : ruleSet->rules()) {
// Explore until the maximum number of iterations(Rules) is reached
NG_RETURN_IF_ERROR(rootGroup->exploreUntilMaxRound(rule));
NG_RETURN_IF_ERROR(rootGroup->validate(rule));
rootGroup->setUnexplored(rule);
}
}
Expand Down

0 comments on commit e4ba34e

Please sign in to comment.