Skip to content
This repository has been archived by the owner on Dec 1, 2022. It is now read-only.

Commit

Permalink
Added planners. (#344)
Browse files Browse the repository at this point in the history
* Rename planner to plan and add planners dir.

* Add planner framework.

* Implement SequentialPlanner.

* Add ast context.

* Refactor the toPlan and address comment.

* Refactor: planners could be instantiated.

* Fix initialization-order-fiasco.

* Update namings.
  • Loading branch information
CPWstatic authored Oct 28, 2020
1 parent 9571ffb commit 14d5147
Show file tree
Hide file tree
Showing 13 changed files with 276 additions and 62 deletions.
21 changes: 21 additions & 0 deletions src/context/AstContext.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/* Copyright (c) 2020 vesoft inc. All rights reserved.
*
* This source code is licensed under Apache 2.0 License,
* attached with Common Clause Condition 1.0, found in the LICENSES directory.
*/

#ifndef CONTEXT_ASTCONTEXT_H_
#define CONTEXT_ASTCONTEXT_H_

#include "context/QueryContext.h"
#include "parser/Sentence.h"

namespace nebula {
namespace graph {
struct AstContext {
QueryContext* qctx;
Sentence* sentence;
};
} // namespace graph
} // namespace nebula
#endif // CONTEXT_ASTCONTEXT_H_
2 changes: 2 additions & 0 deletions src/planner/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,6 @@ nebula_add_library(
Query.cpp
Mutate.cpp
Maintain.cpp
Planner.cpp
planners/SequentialPlanner.cpp
)
32 changes: 32 additions & 0 deletions src/planner/Planner.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/* Copyright (c) 2020 vesoft inc. All rights reserved.
*
* This source code is licensed under Apache 2.0 License,
* attached with Common Clause Condition 1.0, found in the LICENSES directory.
*/

#include "planner/Planner.h"

#include "validator/Validator.h"

namespace nebula {
namespace graph {

StatusOr<SubPlan> Planner::toPlan(AstContext* astCtx) {
if (astCtx == nullptr) {
return Status::Error("AstContext nullptr.");
}
const auto* sentence = astCtx->sentence;
DCHECK(sentence != nullptr);
auto planners = plannersMap().find(sentence->kind());
if (planners == plannersMap().end()) {
return Status::Error("No planners for sentence: %s", sentence->toString().c_str());
}
for (auto& planner : planners->second) {
if (planner.match(astCtx)) {
return planner.instantiate()->transform(astCtx);
}
}
return Status::Error("No planner matches sentence: %s", sentence->toString().c_str());
}
} // namespace graph
} // namespace nebula
51 changes: 51 additions & 0 deletions src/planner/Planner.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/* Copyright (c) 2020 vesoft inc. All rights reserved.
*
* This source code is licensed under Apache 2.0 License,
* attached with Common Clause Condition 1.0, found in the LICENSES directory.
*/

#ifndef PLANNER_PLANNERS_PLANNER_H_
#define PLANNER_PLANNERS_PLANNER_H_

#include "common/base/Base.h"
#include "planner/PlanNode.h"
#include "context/AstContext.h"

namespace nebula {
namespace graph {
class Planner;

struct SubPlan {
// root and tail of a subplan.
PlanNode* root{nullptr};
PlanNode* tail{nullptr};
};

using MatchFunc = std::function<bool(AstContext* astContext)>;
using PlannerInstantiateFunc = std::function<std::unique_ptr<Planner>()>;
struct MatchAndInstantiate {
MatchAndInstantiate(MatchFunc m, PlannerInstantiateFunc p)
: match(std::move(m)), instantiate(std::move(p)) {}
MatchFunc match;
PlannerInstantiateFunc instantiate;
};

class Planner {
public:
virtual ~Planner() = default;

static auto& plannersMap() {
static std::unordered_map<Sentence::Kind, std::vector<MatchAndInstantiate>> plannersMap;
return plannersMap;
}

static StatusOr<SubPlan> toPlan(AstContext* astCtx);

virtual StatusOr<SubPlan> transform(AstContext* astCtx) = 0;

protected:
Planner() = default;
};
} // namespace graph
} // namespace nebula
#endif // PLANNER_PLANNERS_PLANNER_H_
64 changes: 64 additions & 0 deletions src/planner/planners/SequentialPlanner.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/* Copyright (c) 2020 vesoft inc. All rights reserved.
*
* This source code is licensed under Apache 2.0 License,
* attached with Common Clause Condition 1.0, found in the LICENSES directory.
*/

#include "planner/planners/SequentialPlanner.h"

#include "parser/Sentence.h"
#include "planner/Logic.h"
#include "planner/Query.h"
#include "validator/SequentialValidator.h"

namespace nebula {
namespace graph {
SequentialPlannerRegister SequentialPlannerRegister::instance_;

bool SequentialPlanner::match(AstContext* astCtx) {
if (astCtx->sentence->kind() == Sentence::Kind::kSequential) {
return true;
} else {
return false;
}
}

StatusOr<SubPlan> SequentialPlanner::transform(AstContext* astCtx) {
SubPlan subPlan;
auto* seqCtx = static_cast<SequentialAstContext*>(astCtx);
auto* qctx = seqCtx->qctx;
const auto& validators = seqCtx->validators;
subPlan.root = validators.back()->root();
ifBuildDataCollect(subPlan, qctx);
for (auto iter = validators.begin(); iter < validators.end() - 1; ++iter) {
NG_RETURN_IF_ERROR((iter + 1)->get()->appendPlan(iter->get()->root()));
}
subPlan.tail = StartNode::make(qctx);
NG_RETURN_IF_ERROR(validators.front()->appendPlan(subPlan.tail));
VLOG(1) << "root: " << subPlan.root->kind() << " tail: " << subPlan.tail->kind();
return subPlan;
}

void SequentialPlanner::ifBuildDataCollect(SubPlan& subPlan, QueryContext* qctx) {
switch (subPlan.root->kind()) {
case PlanNode::Kind::kSort:
case PlanNode::Kind::kLimit:
case PlanNode::Kind::kDedup:
case PlanNode::Kind::kUnion:
case PlanNode::Kind::kIntersect:
case PlanNode::Kind::kMinus:
case PlanNode::Kind::kFilter: {
auto* dc = DataCollect::make(qctx,
subPlan.root,
DataCollect::CollectKind::kRowBasedMove,
{subPlan.root->outputVar()});
dc->setColNames(subPlan.root->colNames());
subPlan.root = dc;
break;
}
default:
break;
}
}
} // namespace graph
} // namespace nebula
46 changes: 46 additions & 0 deletions src/planner/planners/SequentialPlanner.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/* Copyright (c) 2020 vesoft inc. All rights reserved.
*
* This source code is licensed under Apache 2.0 License,
* attached with Common Clause Condition 1.0, found in the LICENSES directory.
*/

#ifndef PLANNER_PLANNERS_SEQUENTIALPLANNER_H_
#define PLANNER_PLANNERS_SEQUENTIALPLANNER_H_

#include "planner/Planner.h"
#include "context/QueryContext.h"

namespace nebula {
namespace graph {
class SequentialPlanner final : public Planner {
public:
static std::unique_ptr<SequentialPlanner> make() {
return std::unique_ptr<SequentialPlanner>(new SequentialPlanner());
}

static bool match(AstContext* astCtx);

/**
* Each sentence would be converted to a sub-plan, and they would
* be cascaded together into a complete execution plan.
*/
StatusOr<SubPlan> transform(AstContext* astCtx) override;

void ifBuildDataCollect(SubPlan& subPlan, QueryContext* qctx);

private:
SequentialPlanner() = default;
};

class SequentialPlannerRegister final {
private:
SequentialPlannerRegister() {
auto& planners = Planner::plannersMap()[Sentence::Kind::kSequential];
planners.emplace_back(&SequentialPlanner::match, &SequentialPlanner::make);
}

static SequentialPlannerRegister instance_;
};
} // namespace graph
} // namespace nebula
#endif // PLANNER_PLANNERS_SEQUENTIALPLANNER_H_
9 changes: 6 additions & 3 deletions src/validator/ExplainValidator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,12 @@ Status ExplainValidator::validateImpl() {
}

Status ExplainValidator::toPlan() {
NG_RETURN_IF_ERROR(validator_->toPlan());
root_ = validator_->root();
tail_ = validator_->tail();
auto subPlanStatus = Planner::toPlan(validator_->getAstContext());
NG_RETURN_IF_ERROR(subPlanStatus);
auto subPlan = std::move(subPlanStatus).value();
root_ = subPlan.root;
tail_ = subPlan.tail;
VLOG(1) << "root: " << root_->kind() << " tail: " << tail_->kind();
return Status::OK();
}

Expand Down
3 changes: 2 additions & 1 deletion src/validator/ExplainValidator.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,11 @@ class ExplainValidator final : public Validator {
public:
ExplainValidator(Sentence* sentence, QueryContext* context);

private:
Status validateImpl() override;

Status toPlan() override;

private:
std::unique_ptr<SequentialValidator> validator_;
};

Expand Down
41 changes: 5 additions & 36 deletions src/validator/SequentialValidator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,13 @@
* attached with Common Clause Condition 1.0, found in the LICENSES directory.
*/

#include "common/base/Base.h"
#include "validator/SequentialValidator.h"
#include "service/GraphFlags.h"
#include "service/PermissionCheck.h"

#include "common/base/Base.h"
#include "planner/Logic.h"
#include "planner/Query.h"
#include "service/GraphFlags.h"
#include "service/PermissionCheck.h"

DECLARE_uint32(max_allowed_statements);

Expand Down Expand Up @@ -44,50 +45,18 @@ Status SequentialValidator::validateImpl() {
for (auto* sentence : sentences) {
auto validator = makeValidator(sentence, qctx_);
NG_RETURN_IF_ERROR(validator->validate());
validators_.emplace_back(std::move(validator));
seqAstCtx_->validators.emplace_back(std::move(validator));
}

return Status::OK();
}

Status SequentialValidator::toPlan() {
root_ = validators_.back()->root();
ifBuildDataCollectForRoot(root_);
for (auto iter = validators_.begin(); iter < validators_.end() - 1; ++iter) {
NG_RETURN_IF_ERROR((iter + 1)->get()->appendPlan(iter->get()->root()));
}
tail_ = StartNode::make(qctx_);
NG_RETURN_IF_ERROR(validators_.front()->appendPlan(tail_));
VLOG(1) << "root: " << root_->kind() << " tail: " << tail_->kind();
return Status::OK();
}

const Sentence* SequentialValidator::getFirstSentence(const Sentence* sentence) const {
if (sentence->kind() != Sentence::Kind::kPipe) {
return sentence;
}
auto pipe = static_cast<const PipedSentence *>(sentence);
return getFirstSentence(pipe->left());
}

void SequentialValidator::ifBuildDataCollectForRoot(PlanNode* root) {
switch (root->kind()) {
case PlanNode::Kind::kSort:
case PlanNode::Kind::kLimit:
case PlanNode::Kind::kDedup:
case PlanNode::Kind::kUnion:
case PlanNode::Kind::kIntersect:
case PlanNode::Kind::kMinus:
case PlanNode::Kind::kFilter: {
auto* dc = DataCollect::make(
qctx_, root, DataCollect::CollectKind::kRowBasedMove, {root->outputVar()});
dc->setColNames(root->colNames());
root_ = dc;
break;
}
default:
break;
}
}
} // namespace graph
} // namespace nebula
22 changes: 12 additions & 10 deletions src/validator/SequentialValidator.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,16 @@
#define VALIDATOR_SEQUENTIALVALIDATOR_H_

#include "common/base/Base.h"
#include "validator/Validator.h"
#include "parser/SequentialSentences.h"
#include "validator/Validator.h"

namespace nebula {
namespace graph {

struct SequentialAstContext final : AstContext {
std::vector<std::unique_ptr<Validator>> validators;
};

/**
* A SequentialValidator is the entrance of validators.
*/
Expand All @@ -22,15 +26,16 @@ class SequentialValidator final : public Validator {
SequentialValidator(Sentence* sentence, QueryContext* context)
: Validator(sentence, context) {
setNoSpaceRequired();
seqAstCtx_ = std::make_unique<SequentialAstContext>();
seqAstCtx_->sentence = sentence;
seqAstCtx_->qctx = context;
}

Status validateImpl() override;

/**
* Each sentence would be converted to a sub-plan, and they would
* be cascaded together into a complete execution plan.
*/
Status toPlan() override;
AstContext* getAstContext() override {
return seqAstCtx_.get();
}

private:
/**
Expand All @@ -42,10 +47,7 @@ class SequentialValidator final : public Validator {

const Sentence* getFirstSentence(const Sentence* sentence) const;

void ifBuildDataCollectForRoot(PlanNode* root);

private:
std::vector<std::unique_ptr<Validator>> validators_;
std::unique_ptr<SequentialAstContext> seqAstCtx_;
};
} // namespace graph
} // namespace nebula
Expand Down
9 changes: 9 additions & 0 deletions src/validator/Validator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -366,5 +366,14 @@ StatusOr<std::string> Validator::checkRef(const Expression* ref, Value::Type typ
}
}

Status Validator::toPlan() {
auto subPlanStatus = Planner::toPlan(getAstContext());
NG_RETURN_IF_ERROR(subPlanStatus);
auto subPlan = std::move(subPlanStatus).value();
root_ = subPlan.root;
tail_ = subPlan.tail;
VLOG(1) << "root: " << root_->kind() << " tail: " << tail_->kind();
return Status::OK();
}
} // namespace graph
} // namespace nebula
Loading

0 comments on commit 14d5147

Please sign in to comment.