Skip to content
Snippets Groups Projects
Unverified Commit 86df8f80 authored by jimingquan's avatar jimingquan Committed by GitHub
Browse files

add Subgraph executor & refactor subgraph (#660)

* add subgraph executor

* add subgraph excutor & refactor subgraph

* fix error

* fix error second

* fix miss edge

* fix test case

* remove useless code

* change to hash(Edge)

* change hash(edge)

* change hash(string) to hash(Value)

* address comment

* address comment

* remove useless code
parent 9f10e807
No related branches found
No related tags found
No related merge requests found
Showing
with 722 additions and 718 deletions
...@@ -35,6 +35,7 @@ nebula_add_library( ...@@ -35,6 +35,7 @@ nebula_add_library(
algo/ProduceSemiShortestPathExecutor.cpp algo/ProduceSemiShortestPathExecutor.cpp
algo/ProduceAllPathsExecutor.cpp algo/ProduceAllPathsExecutor.cpp
algo/CartesianProductExecutor.cpp algo/CartesianProductExecutor.cpp
algo/SubgraphExecutor.cpp
admin/SwitchSpaceExecutor.cpp admin/SwitchSpaceExecutor.cpp
admin/CreateUserExecutor.cpp admin/CreateUserExecutor.cpp
admin/DropUserExecutor.cpp admin/DropUserExecutor.cpp
......
...@@ -49,6 +49,7 @@ ...@@ -49,6 +49,7 @@
#include "executor/algo/ConjunctPathExecutor.h" #include "executor/algo/ConjunctPathExecutor.h"
#include "executor/algo/ProduceAllPathsExecutor.h" #include "executor/algo/ProduceAllPathsExecutor.h"
#include "executor/algo/CartesianProductExecutor.h" #include "executor/algo/CartesianProductExecutor.h"
#include "executor/algo/SubgraphExecutor.h"
#include "executor/logic/LoopExecutor.h" #include "executor/logic/LoopExecutor.h"
#include "executor/logic/PassThroughExecutor.h" #include "executor/logic/PassThroughExecutor.h"
#include "executor/logic/SelectExecutor.h" #include "executor/logic/SelectExecutor.h"
...@@ -418,6 +419,9 @@ Executor *Executor::makeExecutor(QueryContext *qctx, const PlanNode *node) { ...@@ -418,6 +419,9 @@ Executor *Executor::makeExecutor(QueryContext *qctx, const PlanNode *node) {
case PlanNode::Kind::kCartesianProduct: { case PlanNode::Kind::kCartesianProduct: {
return pool->add(new CartesianProductExecutor(node, qctx)); return pool->add(new CartesianProductExecutor(node, qctx));
} }
case PlanNode::Kind::kSubgraph: {
return pool->add(new SubgraphExecutor(node, qctx));
}
case PlanNode::Kind::kAddGroup: { case PlanNode::Kind::kAddGroup: {
return pool->add(new AddGroupExecutor(node, qctx)); return pool->add(new AddGroupExecutor(node, qctx));
} }
......
/* Copyright (c) 2021 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 "executor/algo/SubgraphExecutor.h"
#include "planner/Algo.h"
namespace nebula {
namespace graph {
folly::Future<Status> SubgraphExecutor::execute() {
SCOPED_TIMER(&execTime_);
auto* subgraph = asNode<Subgraph>(node());
DataSet ds;
ds.colNames = subgraph->colNames();
uint32_t steps = subgraph->steps();
const auto& currentStepVal = ectx_->getValue(subgraph->currentStepVar());
DCHECK(currentStepVal.isInt());
auto currentStep = currentStepVal.getInt();
VLOG(1) << "Current Step is: " << currentStep << " Total Steps is: " << steps;
if (currentStep == steps) {
oneMoreStep();
return finish(ResultBuilder().value(Value(std::move(ds))).finish());
}
VLOG(1) << "input: " << subgraph->inputVar() << " output: " << node()->outputVar();
auto iter = ectx_->getResult(subgraph->inputVar()).iter();
DCHECK(iter && iter->isGetNeighborsIter());
ds.rows.reserve(iter->size());
if (currentStep == 1) {
for (; iter->valid(); iter->next()) {
const auto& src = iter->getColumn(nebula::kVid);
historyVids_.emplace(src);
}
iter->reset();
}
for (; iter->valid(); iter->next()) {
const auto& dst = iter->getEdgeProp("*", nebula::kDst);
if (historyVids_.emplace(dst).second) {
Row row;
row.values.emplace_back(std::move(dst));
ds.rows.emplace_back(std::move(row));
}
}
VLOG(1) << "Next step vid is : " << ds;
return finish(ResultBuilder().value(Value(std::move(ds))).finish());
}
void SubgraphExecutor::oneMoreStep() {
auto* subgraph = asNode<Subgraph>(node());
auto output = subgraph->oneMoreStepOutput();
VLOG(1) << "OneMoreStep Input: " << subgraph->inputVar() << " Output: " << output;
auto iter = ectx_->getResult(subgraph->inputVar()).iter();
DCHECK(iter && iter->isGetNeighborsIter());
ResultBuilder builder;
builder.value(iter->valuePtr());
while (iter->valid()) {
const auto& dst = iter->getEdgeProp("*", nebula::kDst);
if (historyVids_.find(dst) == historyVids_.end()) {
iter->unstableErase();
} else {
iter->next();
}
}
iter->reset();
builder.iter(std::move(iter));
ectx_->setResult(output, builder.finish());
}
} // namespace graph
} // namespace nebula
/* Copyright (c) 2021 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 EXECUTOR_ALGO_SUBGRAPHEXECUTOR_H_
#define EXECUTOR_ALGO_SUBGRAPHEXECUTOR_H_
#include "executor/Executor.h"
namespace nebula {
namespace graph {
class SubgraphExecutor : public Executor {
public:
SubgraphExecutor(const PlanNode* node, QueryContext* qctx)
: Executor("SubgraphExecutor", node, qctx) {}
folly::Future<Status> execute() override;
private:
void oneMoreStep();
private:
std::unordered_set<Value> historyVids_;
};
} // namespace graph
} // namespace nebula
#endif // EXECUTOR_ALGO_SUBGRAPHEXECUTOR_H_
...@@ -62,11 +62,14 @@ Status DataCollectExecutor::collectSubgraph(const std::vector<std::string>& vars ...@@ -62,11 +62,14 @@ Status DataCollectExecutor::collectSubgraph(const std::vector<std::string>& vars
ds.colNames = std::move(colNames_); ds.colNames = std::move(colNames_);
// the subgraph not need duplicate vertices or edges, so dedup here directly // the subgraph not need duplicate vertices or edges, so dedup here directly
std::unordered_set<Value> uniqueVids; std::unordered_set<Value> uniqueVids;
std::unordered_set<std::tuple<Value, std::string, int64_t, Value>> uniqueEdges; std::unordered_set<std::tuple<Value, EdgeType, EdgeRanking, Value>> uniqueEdges;
for (auto& var : vars) { for (auto i = vars.begin(); i != vars.end(); ++i) {
auto& hist = ectx_->getHistory(var); const auto& hist = ectx_->getHistory(*i);
for (auto& result : hist) { for (auto j = hist.begin(); j != hist.end(); ++j) {
auto iter = result.iter(); if (i == vars.begin() && j == hist.end() - 1) {
continue;
}
auto iter = (*j).iter();
if (!iter->isGetNeighborsIter()) { if (!iter->isGetNeighborsIter()) {
std::stringstream msg; std::stringstream msg;
msg << "Iterator should be kind of GetNeighborIter, but was: " << iter->kind(); msg << "Iterator should be kind of GetNeighborIter, but was: " << iter->kind();
...@@ -85,14 +88,14 @@ Status DataCollectExecutor::collectSubgraph(const std::vector<std::string>& vars ...@@ -85,14 +88,14 @@ Status DataCollectExecutor::collectSubgraph(const std::vector<std::string>& vars
} }
} }
auto originEdges = gnIter->getEdges(); auto originEdges = gnIter->getEdges();
for (auto& e : originEdges.values) { for (auto& edge : originEdges.values) {
if (!e.isEdge()) { if (!edge.isEdge()) {
continue; continue;
} }
auto edgeKey = std::make_tuple( const auto& e = edge.getEdge();
e.getEdge().src, e.getEdge().name, e.getEdge().ranking, e.getEdge().dst); auto edgeKey = std::make_tuple(e.src, e.type, e.ranking, e.dst);
if (uniqueEdges.emplace(std::move(edgeKey)).second) { if (uniqueEdges.emplace(std::move(edgeKey)).second) {
edges.emplace_back(std::move(e)); edges.emplace_back(std::move(edge));
} }
} }
ds.rows.emplace_back(Row({std::move(vertices), std::move(edges)})); ds.rows.emplace_back(Row({std::move(vertices), std::move(edges)}));
......
...@@ -87,12 +87,16 @@ protected: ...@@ -87,12 +87,16 @@ protected:
List datasets; List datasets;
datasets.values.emplace_back(std::move(ds1)); datasets.values.emplace_back(std::move(ds1));
datasets.values.emplace_back(std::move(ds2));
ResultBuilder builder; ResultBuilder builder;
builder.value(Value(std::move(datasets))).iter(Iterator::Kind::kGetNeighbors); builder.value(Value(std::move(datasets))).iter(Iterator::Kind::kGetNeighbors);
qctx_->symTable()->newVariable("input_datasets"); qctx_->symTable()->newVariable("input_datasets");
qctx_->ectx()->setResult("input_datasets", builder.finish()); qctx_->ectx()->setResult("input_datasets", builder.finish());
qctx_->ectx()->setResult("input_datasets",
ResultBuilder()
.value(Value(std::move(ds2)))
.iter(Iterator::Kind::kGetNeighbors)
.finish());
} }
{ {
DataSet ds; DataSet ds;
...@@ -115,6 +119,11 @@ protected: ...@@ -115,6 +119,11 @@ protected:
"_edge:+edge1:prop1:prop2:_dst:_rank", "_edge:+edge1:prop1:prop2:_dst:_rank",
"_expr"}; "_expr"};
qctx_->symTable()->newVariable("empty_get_neighbors"); qctx_->symTable()->newVariable("empty_get_neighbors");
qctx_->ectx()->setResult("empty_get_neighbors",
ResultBuilder()
.value(Value(ds))
.iter(Iterator::Kind::kGetNeighbors)
.finish());
qctx_->ectx()->setResult("empty_get_neighbors", qctx_->ectx()->setResult("empty_get_neighbors",
ResultBuilder() ResultBuilder()
.value(Value(std::move(ds))) .value(Value(std::move(ds)))
...@@ -140,8 +149,8 @@ TEST_F(DataCollectTest, CollectSubgraph) { ...@@ -140,8 +149,8 @@ TEST_F(DataCollectTest, CollectSubgraph) {
DataSet expected; DataSet expected;
expected.colNames = {"_vertices", "_edges"}; expected.colNames = {"_vertices", "_edges"};
auto& input = qctx_->ectx()->getResult("input_datasets"); auto& hist = qctx_->ectx()->getHistory("input_datasets");
auto iter = input.iter(); auto iter = hist[0].iter();
auto* gNIter = static_cast<GetNeighborsIter*>(iter.get()); auto* gNIter = static_cast<GetNeighborsIter*>(iter.get());
Row row; Row row;
std::unordered_set<Value> vids; std::unordered_set<Value> vids;
......
...@@ -139,6 +139,45 @@ private: ...@@ -139,6 +139,45 @@ private:
std::vector<std::vector<std::string>> allColNames_; std::vector<std::vector<std::string>> allColNames_;
}; };
class Subgraph final : public SingleInputNode {
public:
static Subgraph* make(QueryContext* qctx,
PlanNode* input,
const std::string& oneMoreStepOutput,
const std::string& currentStepVar,
uint32_t steps) {
return qctx->objPool()->add(
new Subgraph(qctx, input, oneMoreStepOutput, currentStepVar, steps));
}
const std::string& oneMoreStepOutput() const {
return oneMoreStepOutput_;
}
const std::string& currentStepVar() const {
return currentStepVar_;
}
uint32_t steps() const {
return steps_;
}
private:
Subgraph(QueryContext* qctx,
PlanNode* input,
const std::string& oneMoreStepOutput,
const std::string& currentStepVar,
uint32_t steps)
: SingleInputNode(qctx, Kind::kSubgraph, input),
oneMoreStepOutput_(oneMoreStepOutput),
currentStepVar_(currentStepVar),
steps_(steps) {}
std::string oneMoreStepOutput_;
std::string currentStepVar_;
uint32_t steps_;
};
} // namespace graph } // namespace graph
} // namespace nebula } // namespace nebula
#endif // PLANNER_ALGO_H_ #endif // PLANNER_ALGO_H_
...@@ -207,6 +207,8 @@ const char* PlanNode::toString(PlanNode::Kind kind) { ...@@ -207,6 +207,8 @@ const char* PlanNode::toString(PlanNode::Kind kind) {
return "ProduceAllPaths"; return "ProduceAllPaths";
case Kind::kCartesianProduct: case Kind::kCartesianProduct:
return "CartesianProduct"; return "CartesianProduct";
case Kind::kSubgraph:
return "Subgraph";
// Group and Zone // Group and Zone
case Kind::kAddGroup: case Kind::kAddGroup:
return "AddGroup"; return "AddGroup";
......
...@@ -118,6 +118,7 @@ public: ...@@ -118,6 +118,7 @@ public:
kConjunctPath, kConjunctPath,
kProduceAllPaths, kProduceAllPaths,
kCartesianProduct, kCartesianProduct,
kSubgraph,
// zone related // zone related
kAddGroup, kAddGroup,
kDropGroup, kDropGroup,
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include "parser/TraverseSentences.h" #include "parser/TraverseSentences.h"
#include "planner/Logic.h" #include "planner/Logic.h"
#include "planner/Query.h" #include "planner/Query.h"
#include "planner/Algo.h"
namespace nebula { namespace nebula {
namespace graph { namespace graph {
...@@ -101,54 +102,6 @@ Status GetSubgraphValidator::validateBothInOutBound(BothInOutClause* out) { ...@@ -101,54 +102,6 @@ Status GetSubgraphValidator::validateBothInOutBound(BothInOutClause* out) {
return Status::OK(); return Status::OK();
} }
/*
* 1 steps history: collectVid{0}
* 2 steps history: collectVid{-1} collectVid{0}
* 3 steps history: collectVid{-2} collectVid{-1} collectVid{0}
* ...
* n steps history: collectVid{-n+1} ... collectVid{-1} collectVid{0}
*/
Expression* GetSubgraphValidator::buildFilterCondition(int64_t step) {
// where *._dst IN startVids(*._dst IN runtimeStartVar_) OR *._dst IN collectVid{0}[0][0] OR
// *._dst IN collectVid{-1}[0][0] OR ... *._dst IN collectVid{-step+1}[0][0]
if (step == 1) {
Expression* left = nullptr;
if (!runtimeStartVar_.empty()) {
auto* startDataSet = new VersionedVariableExpression(new std::string(runtimeStartVar_),
new ConstantExpression(0));
auto* runtimeStartList = new SubscriptExpression(
new SubscriptExpression(startDataSet, new ConstantExpression(0)),
new ConstantExpression(0));
left = new RelationalExpression(Expression::Kind::kRelIn,
new EdgeDstIdExpression(new std::string("*")),
runtimeStartList);
} else {
left = new RelationalExpression(Expression::Kind::kRelIn,
new EdgeDstIdExpression(new std::string("*")),
new SetExpression(startVidList_.release()));
}
auto* lastestVidsDataSet = new VersionedVariableExpression(new std::string(collectVar_),
new ConstantExpression(0));
auto* lastestVidsList = new SubscriptExpression(
new SubscriptExpression(lastestVidsDataSet, new ConstantExpression(0)),
new ConstantExpression(0));
auto* right = new RelationalExpression(Expression::Kind::kRelIn,
new EdgeDstIdExpression(new std::string("*")),
lastestVidsList);
return new LogicalExpression(Expression::Kind::kLogicalOr, left, right);
}
auto* historyVidsDataSet = new VersionedVariableExpression(new std::string(collectVar_),
new ConstantExpression(1 - step));
auto* historyVidsList = new SubscriptExpression(
new SubscriptExpression(historyVidsDataSet, new ConstantExpression(0)),
new ConstantExpression(0));
auto* left = new RelationalExpression(
Expression::Kind::kRelIn, new EdgeDstIdExpression(new std::string("*")), historyVidsList);
auto* right = buildFilterCondition(step - 1);
auto* result = new LogicalExpression(Expression::Kind::kLogicalOr, left, right);
return result;
}
StatusOr<GetNeighbors::EdgeProps> GetSubgraphValidator::buildEdgeProps() { StatusOr<GetNeighbors::EdgeProps> GetSubgraphValidator::buildEdgeProps() {
if (edgeTypes_.empty()) { if (edgeTypes_.empty()) {
auto allEdgePropResult = buildAllEdgeProp(); auto allEdgePropResult = buildAllEdgeProp();
...@@ -243,39 +196,19 @@ Status GetSubgraphValidator::zeroStep(PlanNode* depend, const std::string& input ...@@ -243,39 +196,19 @@ Status GetSubgraphValidator::zeroStep(PlanNode* depend, const std::string& input
Status GetSubgraphValidator::toPlan() { Status GetSubgraphValidator::toPlan() {
auto& space = vctx_->whichSpace(); auto& space = vctx_->whichSpace();
// gn <- filter <- DataCollect
// |
// loop(step) -> Agg(collect) -> project -> gn -> bodyStart
auto* bodyStart = StartNode::make(qctx_); auto* bodyStart = StartNode::make(qctx_);
std::string startVidsVar; std::string startVidsVar;
SingleInputNode* collectRunTimeStartVids = nullptr; PlanNode* loopDep = nullptr;
if (!from_.vids.empty() && from_.originalSrc == nullptr) { if (!from_.vids.empty() && from_.originalSrc == nullptr) {
buildConstantInput(from_, startVidsVar); buildConstantInput(from_, startVidsVar);
} else { } else {
PlanNode* dedupStartVid = buildRuntimeInput(from_, projectStartVid_); loopDep = buildRuntimeInput(from_, projectStartVid_);
startVidsVar = dedupStartVid->outputVar(); startVidsVar = loopDep->outputVar();
// collect runtime startVids
auto var = vctx_->anonVarGen()->getVar();
auto* column = new VariablePropertyExpression(new std::string(var), new std::string(kVid));
auto* func = new AggregateExpression(new std::string("COLLECT_SET"), column, true);
qctx_->objPool()->add(func);
collectRunTimeStartVids =
Aggregate::make(qctx_,
dedupStartVid,
{},
{func});
collectRunTimeStartVids->setInputVar(dedupStartVid->outputVar());
collectRunTimeStartVids->setColNames({kVid});
runtimeStartVar_ = collectRunTimeStartVids->outputVar();
} }
if (steps_.steps == 0) { if (steps_.steps == 0) {
if (collectRunTimeStartVids == nullptr) { return zeroStep(loopDep == nullptr ? bodyStart : loopDep, startVidsVar);
return zeroStep(bodyStart, startVidsVar);
}
return zeroStep(collectRunTimeStartVids, startVidsVar);
} }
auto vertexPropsResult = buildVertexProp(); auto vertexPropsResult = buildVertexProp();
...@@ -288,51 +221,19 @@ Status GetSubgraphValidator::toPlan() { ...@@ -288,51 +221,19 @@ Status GetSubgraphValidator::toPlan() {
NG_RETURN_IF_ERROR(edgePropsResult); NG_RETURN_IF_ERROR(edgePropsResult);
gn->setEdgeProps( gn->setEdgeProps(
std::make_unique<std::vector<storage::cpp2::EdgeProp>>(*edgePropsResult.value())); std::make_unique<std::vector<storage::cpp2::EdgeProp>>(*edgePropsResult.value()));
gn->setEdgeDirection(storage::cpp2::EdgeDirection::BOTH);
gn->setInputVar(startVidsVar); gn->setInputVar(startVidsVar);
auto* projectVids = projectDstVidsFromGN(gn, startVidsVar); auto oneMoreStepOutput = vctx_->anonVarGen()->getVar();
auto* subgraph = Subgraph::make(qctx_, gn, oneMoreStepOutput, loopSteps_, steps_.steps + 1);
subgraph->setOutputVar(startVidsVar);
subgraph->setColNames({nebula::kVid});
auto var = vctx_->anonVarGen()->getVar(); auto* loopCondition = buildNStepLoopCondition(steps_.steps + 1);
auto* column = new VariablePropertyExpression(new std::string(var), new std::string(kVid)); auto* loop = Loop::make(qctx_, loopDep, subgraph, loopCondition);
auto* func = new AggregateExpression(new std::string("COLLECT_SET"), column, true);
qctx_->objPool()->add(func);
auto* collect =
Aggregate::make(qctx_,
projectVids,
{},
{func});
collect->setInputVar(projectVids->outputVar());
collect->setColNames({kVid});
collectVar_ = collect->outputVar();
// TODO(jmq) add condition when gn get empty result std::vector<std::string> collects = {gn->outputVar(), oneMoreStepOutput};
auto* condition = buildNStepLoopCondition(steps_.steps);
auto* loop = Loop::make(qctx_, collectRunTimeStartVids, collect, condition);
vertexPropsResult = buildVertexProp();
NG_RETURN_IF_ERROR(vertexPropsResult);
auto edgeProps = std::make_unique<std::vector<storage::cpp2::EdgeProp>>();
auto* gn1 = GetNeighbors::make(qctx_, loop, space.id);
gn1->setSrc(from_.src);
gn1->setVertexProps(std::make_unique<std::vector<storage::cpp2::VertexProp>>(
std::move(vertexPropsResult).value()));
auto allEdgePropResult = buildAllEdgeProp();
NG_RETURN_IF_ERROR(allEdgePropResult);
gn1->setEdgeProps(std::make_unique<std::vector<storage::cpp2::EdgeProp>>(
std::move(allEdgePropResult).value()));
gn1->setEdgeDirection(storage::cpp2::EdgeDirection::BOTH);
gn1->setInputVar(projectVids->outputVar());
auto* filter =
Filter::make(qctx_, gn1, qctx_->objPool()->add(buildFilterCondition(steps_.steps)));
filter->setInputVar(gn1->outputVar());
filter->setColNames({kVid});
// datacollect
std::vector<std::string> collects = {gn->outputVar(), filter->outputVar()};
auto* dc = auto* dc =
DataCollect::make(qctx_, filter, DataCollect::CollectKind::kSubgraph, std::move(collects)); DataCollect::make(qctx_, loop, DataCollect::CollectKind::kSubgraph, std::move(collects));
dc->setColNames({"_vertices", "_edges"}); dc->setColNames({"_vertices", "_edges"});
root_ = dc; root_ = dc;
tail_ = projectStartVid_ != nullptr ? projectStartVid_ : loop; tail_ = projectStartVid_ != nullptr ? projectStartVid_ : loop;
......
...@@ -29,8 +29,6 @@ private: ...@@ -29,8 +29,6 @@ private:
Status validateBothInOutBound(BothInOutClause* out); Status validateBothInOutBound(BothInOutClause* out);
Expression* buildFilterCondition(int64_t step);
StatusOr<GetNeighbors::EdgeProps> buildEdgeProps(); StatusOr<GetNeighbors::EdgeProps> buildEdgeProps();
Status zeroStep(PlanNode* depend, const std::string& inputVar); Status zeroStep(PlanNode* depend, const std::string& inputVar);
...@@ -44,8 +42,6 @@ private: ...@@ -44,8 +42,6 @@ private:
private: private:
std::unordered_set<EdgeType> edgeTypes_; std::unordered_set<EdgeType> edgeTypes_;
std::string collectVar_;
std::string runtimeStartVar_;
}; };
} // namespace graph } // namespace graph
} // namespace nebula } // namespace nebula
......
...@@ -199,13 +199,11 @@ PlanNode* TraversalValidator::buildRuntimeInput(Starts& starts, PlanNode*& proje ...@@ -199,13 +199,11 @@ PlanNode* TraversalValidator::buildRuntimeInput(Starts& starts, PlanNode*& proje
Expression* TraversalValidator::buildNStepLoopCondition(uint32_t steps) const { Expression* TraversalValidator::buildNStepLoopCondition(uint32_t steps) const {
VLOG(1) << "steps: " << steps; VLOG(1) << "steps: " << steps;
// ++loopSteps{0} <= steps // ++loopSteps{0} <= steps
auto loopSteps = vctx_->anonVarGen()->getVar(); qctx_->ectx()->setValue(loopSteps_, 0);
qctx_->ectx()->setValue(loopSteps, 0);
return qctx_->objPool()->add(new RelationalExpression( return qctx_->objPool()->add(new RelationalExpression(
Expression::Kind::kRelLE, Expression::Kind::kRelLE,
new UnaryExpression( new UnaryExpression(Expression::Kind::kUnaryIncr,
Expression::Kind::kUnaryIncr, new VariableExpression(new std::string(loopSteps_))),
new VersionedVariableExpression(new std::string(loopSteps), new ConstantExpression(0))),
new ConstantExpression(static_cast<int32_t>(steps)))); new ConstantExpression(static_cast<int32_t>(steps))));
} }
......
...@@ -47,6 +47,7 @@ protected: ...@@ -47,6 +47,7 @@ protected:
protected: protected:
TraversalValidator(Sentence* sentence, QueryContext* qctx) : Validator(sentence, qctx) { TraversalValidator(Sentence* sentence, QueryContext* qctx) : Validator(sentence, qctx) {
startVidList_.reset(new ExpressionList()); startVidList_.reset(new ExpressionList());
loopSteps_ = vctx_->anonVarGen()->getVar();
} }
Status validateStarts(const VerticesClause* clause, Starts& starts); Status validateStarts(const VerticesClause* clause, Starts& starts);
...@@ -68,6 +69,7 @@ protected: ...@@ -68,6 +69,7 @@ protected:
Steps steps_; Steps steps_;
std::string srcVidColName_; std::string srcVidColName_;
PlanNode* projectStartVid_{nullptr}; PlanNode* projectStartVid_{nullptr};
std::string loopSteps_;
std::unique_ptr<ExpressionList> startVidList_; std::unique_ptr<ExpressionList> startVidList_;
}; };
......
...@@ -24,13 +24,9 @@ TEST_F(GetSubgraphValidatorTest, Base) { ...@@ -24,13 +24,9 @@ TEST_F(GetSubgraphValidatorTest, Base) {
std::string query = "GET SUBGRAPH FROM \"1\""; std::string query = "GET SUBGRAPH FROM \"1\"";
std::vector<PlanNode::Kind> expected = { std::vector<PlanNode::Kind> expected = {
PK::kDataCollect, PK::kDataCollect,
PK::kFilter,
PK::kGetNeighbors,
PK::kLoop, PK::kLoop,
PK::kStart, PK::kStart,
PK::kAggregate, PK::kSubgraph,
PK::kDedup,
PK::kProject,
PK::kGetNeighbors, PK::kGetNeighbors,
PK::kStart, PK::kStart,
}; };
...@@ -40,13 +36,9 @@ TEST_F(GetSubgraphValidatorTest, Base) { ...@@ -40,13 +36,9 @@ TEST_F(GetSubgraphValidatorTest, Base) {
std::string query = "GET SUBGRAPH 3 STEPS FROM \"1\""; std::string query = "GET SUBGRAPH 3 STEPS FROM \"1\"";
std::vector<PlanNode::Kind> expected = { std::vector<PlanNode::Kind> expected = {
PK::kDataCollect, PK::kDataCollect,
PK::kFilter,
PK::kGetNeighbors,
PK::kLoop, PK::kLoop,
PK::kStart, PK::kStart,
PK::kAggregate, PK::kSubgraph,
PK::kDedup,
PK::kProject,
PK::kGetNeighbors, PK::kGetNeighbors,
PK::kStart, PK::kStart,
}; };
...@@ -56,13 +48,9 @@ TEST_F(GetSubgraphValidatorTest, Base) { ...@@ -56,13 +48,9 @@ TEST_F(GetSubgraphValidatorTest, Base) {
std::string query = "GET SUBGRAPH FROM \"1\" BOTH like"; std::string query = "GET SUBGRAPH FROM \"1\" BOTH like";
std::vector<PlanNode::Kind> expected = { std::vector<PlanNode::Kind> expected = {
PK::kDataCollect, PK::kDataCollect,
PK::kFilter,
PK::kGetNeighbors,
PK::kLoop, PK::kLoop,
PK::kStart, PK::kStart,
PK::kAggregate, PK::kSubgraph,
PK::kDedup,
PK::kProject,
PK::kGetNeighbors, PK::kGetNeighbors,
PK::kStart, PK::kStart,
}; };
...@@ -72,13 +60,9 @@ TEST_F(GetSubgraphValidatorTest, Base) { ...@@ -72,13 +60,9 @@ TEST_F(GetSubgraphValidatorTest, Base) {
std::string query = "GET SUBGRAPH FROM \"1\", \"2\" IN like"; std::string query = "GET SUBGRAPH FROM \"1\", \"2\" IN like";
std::vector<PlanNode::Kind> expected = { std::vector<PlanNode::Kind> expected = {
PK::kDataCollect, PK::kDataCollect,
PK::kFilter,
PK::kGetNeighbors,
PK::kLoop, PK::kLoop,
PK::kStart, PK::kStart,
PK::kAggregate, PK::kSubgraph,
PK::kDedup,
PK::kProject,
PK::kGetNeighbors, PK::kGetNeighbors,
PK::kStart, PK::kStart,
}; };
...@@ -92,19 +76,14 @@ TEST_F(GetSubgraphValidatorTest, Input) { ...@@ -92,19 +76,14 @@ TEST_F(GetSubgraphValidatorTest, Input) {
"GO FROM \"1\" OVER like YIELD like._src AS src | GET SUBGRAPH FROM $-.src"; "GO FROM \"1\" OVER like YIELD like._src AS src | GET SUBGRAPH FROM $-.src";
std::vector<PlanNode::Kind> expected = { std::vector<PlanNode::Kind> expected = {
PK::kDataCollect, PK::kDataCollect,
PK::kFilter,
PK::kGetNeighbors,
PK::kLoop, PK::kLoop,
PK::kAggregate,
PK::kAggregate,
PK::kDedup,
PK::kDedup, PK::kDedup,
PK::kSubgraph,
PK::kProject, PK::kProject,
PK::kProject,
PK::kProject,
PK::kGetNeighbors,
PK::kGetNeighbors, PK::kGetNeighbors,
PK::kProject,
PK::kStart, PK::kStart,
PK::kGetNeighbors,
PK::kStart, PK::kStart,
}; };
EXPECT_TRUE(checkResult(query, expected)); EXPECT_TRUE(checkResult(query, expected));
...@@ -114,19 +93,14 @@ TEST_F(GetSubgraphValidatorTest, Input) { ...@@ -114,19 +93,14 @@ TEST_F(GetSubgraphValidatorTest, Input) {
"$a = GO FROM \"1\" OVER like YIELD like._src AS src; GET SUBGRAPH FROM $a.src"; "$a = GO FROM \"1\" OVER like YIELD like._src AS src; GET SUBGRAPH FROM $a.src";
std::vector<PlanNode::Kind> expected = { std::vector<PlanNode::Kind> expected = {
PK::kDataCollect, PK::kDataCollect,
PK::kFilter,
PK::kGetNeighbors,
PK::kLoop, PK::kLoop,
PK::kAggregate,
PK::kAggregate,
PK::kDedup,
PK::kDedup, PK::kDedup,
PK::kSubgraph,
PK::kProject, PK::kProject,
PK::kProject,
PK::kProject,
PK::kGetNeighbors,
PK::kGetNeighbors, PK::kGetNeighbors,
PK::kProject,
PK::kStart, PK::kStart,
PK::kGetNeighbors,
PK::kStart, PK::kStart,
}; };
EXPECT_TRUE(checkResult(query, expected)); EXPECT_TRUE(checkResult(query, expected));
...@@ -155,7 +129,6 @@ TEST_F(GetSubgraphValidatorTest, Input) { ...@@ -155,7 +129,6 @@ TEST_F(GetSubgraphValidatorTest, Input) {
std::vector<PlanNode::Kind> expected = { std::vector<PlanNode::Kind> expected = {
PK::kAggregate, PK::kAggregate,
PK::kGetVertices, PK::kGetVertices,
PK::kAggregate,
PK::kDedup, PK::kDedup,
PK::kProject, PK::kProject,
PK::kProject, PK::kProject,
...@@ -170,7 +143,6 @@ TEST_F(GetSubgraphValidatorTest, Input) { ...@@ -170,7 +143,6 @@ TEST_F(GetSubgraphValidatorTest, Input) {
std::vector<PlanNode::Kind> expected = { std::vector<PlanNode::Kind> expected = {
PK::kAggregate, PK::kAggregate,
PK::kGetVertices, PK::kGetVertices,
PK::kAggregate,
PK::kDedup, PK::kDedup,
PK::kProject, PK::kProject,
PK::kProject, PK::kProject,
......
This diff is collapsed.
This diff is collapsed.
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment