Skip to content

Commit

Permalink
Go reversely. (vesoft-inc#1349)
Browse files Browse the repository at this point in the history
* Support go reversely.

* Save column types.

* Get edges with ranking when travese reversely.

* Address comment.
  • Loading branch information
CPWstatic authored and dutor committed Nov 28, 2019
1 parent 464ad34 commit 55c458c
Show file tree
Hide file tree
Showing 10 changed files with 550 additions and 76 deletions.
9 changes: 2 additions & 7 deletions src/graph/FindPathExecutor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -118,13 +118,8 @@ Status FindPathExecutor::prepareOver() {
}

auto v = edgeStatus.value();
if (e->isReversely()) {
over_.edgeTypes_.emplace_back(-v);
over_.oppositeTypes_.emplace_back(v);
} else {
over_.edgeTypes_.emplace_back(v);
over_.oppositeTypes_.emplace_back(-v);
}
over_.edgeTypes_.emplace_back(v);
over_.oppositeTypes_.emplace_back(-v);

if (e->alias() != nullptr) {
if (!expCtx_->addEdge(*e->alias(), v)) {
Expand Down
328 changes: 289 additions & 39 deletions src/graph/GoExecutor.cpp

Large diffs are not rendered by default.

29 changes: 29 additions & 0 deletions src/graph/GoExecutor.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,10 @@ class GoExecutor final : public TraverseExecutor {
return upto_;
}

bool isReversely() const {
return isReversely_;
}

/**
* To obtain the source ids from various places,
* such as the literal id list, inputs from the pipeline or results of variable.
Expand Down Expand Up @@ -106,6 +110,8 @@ class GoExecutor final : public TraverseExecutor {

void fetchVertexProps(std::vector<VertexID> ids, RpcResponse &&rpcResp);

void maybeFinishExecution(RpcResponse &&rpcResp);

/**
* To retrieve or generate the column names for the execution result.
*/
Expand Down Expand Up @@ -187,6 +193,27 @@ class GoExecutor final : public TraverseExecutor {
std::unordered_map<VertexID, VertexID> mapping_;
};

class EdgeHolder final {
public:
Status add(const storage::cpp2::EdgePropResponse &resp);
OptVariantType get(VertexID src,
VertexID dst,
EdgeType type,
const std::string &prop) const;
nebula::cpp2::SupportedType getType(VertexID src,
VertexID dst,
EdgeType type,
const std::string &prop) const;
OptVariantType getDefaultProp(EdgeType type,
const std::string &prop);

private:
using EdgeKey = std::tuple<VertexID, VertexID, EdgeType>;
using EdgeValue = std::pair<std::shared_ptr<ResultSchemaProvider>, std::string>;
std::unordered_map<EdgeKey, EdgeValue> edges_;
std::unordered_map<EdgeType, std::shared_ptr<ResultSchemaProvider>> schemas_;
};

OptVariantType getPropFromInterim(VertexID id, const std::string &prop) const;

nebula::cpp2::SupportedType getPropTypeFromInterim(const std::string &prop) const;
Expand All @@ -203,6 +230,7 @@ class GoExecutor final : public TraverseExecutor {
uint32_t steps_{1};
uint32_t curStep_{1};
bool upto_{false};
bool isReversely_{false};
std::vector<EdgeType> edgeTypes_;
std::string *varname_{nullptr};
std::string *colname_{nullptr};
Expand All @@ -217,6 +245,7 @@ class GoExecutor final : public TraverseExecutor {
std::unique_ptr<ExpressionContext> expCtx_;
std::vector<VertexID> starts_;
std::unique_ptr<VertexHolder> vertexHolder_;
std::unique_ptr<EdgeHolder> edgeHolder_;
std::unique_ptr<VertexBackTracker> backTracker_;
std::unique_ptr<cpp2::ExecutionResponse> resp_;
// The name of Tag or Edge, index of prop in data
Expand Down
186 changes: 186 additions & 0 deletions src/graph/test/GoTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -895,5 +895,191 @@ TEST_F(GoTest, returnTest) {
ASSERT_EQ(cpp2::ErrorCode::E_EXECUTION_ERROR, code);
}
}


TEST_F(GoTest, ReverselyOneStep) {
{
cpp2::ExecutionResponse resp;
auto query = "GO FROM hash('Tim Duncan') OVER like REVERSELY "
"YIELD like._src";
client_->execute(query, resp);
std::vector<std::tuple<int64_t>> expected = {
{ players_["Tony Parker"].vid() },
{ players_["Manu Ginobili"].vid() },
{ players_["LaMarcus Aldridge"].vid() },
{ players_["Marco Belinelli"].vid() },
{ players_["Danny Green"].vid() },
{ players_["Aron Baynes"].vid() },
{ players_["Boris Diaw"].vid() },
{ players_["Tiago Splitter"].vid() },
{ players_["Dejounte Murray"].vid() },
{ players_["Shaquile O'Neal"].vid() },
};
ASSERT_TRUE(verifyResult(resp, expected));
}
{
cpp2::ExecutionResponse resp;
auto query = "GO FROM hash('Tim Duncan') OVER like REVERSELY "
"YIELD $$.player.name";
client_->execute(query, resp);
std::vector<std::tuple<std::string>> expected = {
{ "Tony Parker" },
{ "Manu Ginobili" },
{ "LaMarcus Aldridge" },
{ "Marco Belinelli" },
{ "Danny Green" },
{ "Aron Baynes" },
{ "Boris Diaw" },
{ "Tiago Splitter" },
{ "Dejounte Murray" },
{ "Shaquile O'Neal" },
};
ASSERT_TRUE(verifyResult(resp, expected));
}
{
cpp2::ExecutionResponse resp;
auto query = "GO FROM hash('Tim Duncan') OVER like REVERSELY "
"WHERE $$.player.age < 35 "
"YIELD $$.player.name";
client_->execute(query, resp);
std::vector<std::tuple<std::string>> expected = {
{ "LaMarcus Aldridge" },
{ "Marco Belinelli" },
{ "Danny Green" },
{ "Aron Baynes" },
{ "Tiago Splitter" },
{ "Dejounte Murray" },
};
ASSERT_TRUE(verifyResult(resp, expected));
}
}


TEST_F(GoTest, ReverselyTwoStep) {
{
cpp2::ExecutionResponse resp;
auto query = "GO 2 STEPS FROM hash('Kobe Bryant') OVER like REVERSELY "
"YIELD $$.player.name";
client_->execute(query, resp);
std::vector<std::tuple<std::string>> expected = {
{ "Marc Gasol" },
{ "Vince Carter" },
{ "Yao Ming" },
{ "Grant Hill" },
};
ASSERT_TRUE(verifyResult(resp, expected));
}
}


TEST_F(GoTest, ReverselyWithPipe) {
{
cpp2::ExecutionResponse resp;
auto query = "GO FROM hash('LeBron James') OVER serve YIELD serve._dst AS id |"
"GO FROM $-.id OVER serve REVERSELY YIELD $^.team.name, $$.player.name";
client_->execute(query, resp);
std::vector<std::tuple<std::string, std::string>> expected = {
{ "Cavaliers", "Kyrie Irving" },
{ "Cavaliers", "Dwyane Wade" },
{ "Cavaliers", "Shaquile O'Neal" },
{ "Cavaliers", "Danny Green" },
{ "Cavaliers", "LeBron James" },
{ "Heat", "Dwyane Wade" },
{ "Heat", "LeBron James" },
{ "Heat", "Ray Allen" },
{ "Heat", "Shaquile O'Neal" },
{ "Heat", "Amar'e Stoudemire" },
{ "Lakers", "Kobe Bryant" },
{ "Lakers", "LeBron James" },
{ "Lakers", "Rajon Rondo" },
{ "Lakers", "Steve Nash" },
{ "Lakers", "Paul Gasol" },
{ "Lakers", "Shaquile O'Neal" },
{ "Lakers", "JaVale McGee" },
{ "Lakers", "Dwight Howard" },
};

ASSERT_TRUE(verifyResult(resp, expected));
}
{
cpp2::ExecutionResponse resp;
auto query = "GO FROM hash('LeBron James') OVER serve "
"YIELD serve._dst AS id |"
"GO FROM $-.id OVER serve REVERSELY "
"WHERE $$.player.name != 'LeBron James' "
"YIELD $^.team.name, $$.player.name";
client_->execute(query, resp);
std::vector<std::tuple<std::string, std::string>> expected = {
{ "Cavaliers", "Kyrie Irving" },
{ "Cavaliers", "Dwyane Wade" },
{ "Cavaliers", "Shaquile O'Neal" },
{ "Cavaliers", "Danny Green" },
{ "Heat", "Dwyane Wade" },
{ "Heat", "Ray Allen" },
{ "Heat", "Shaquile O'Neal" },
{ "Heat", "Amar'e Stoudemire" },
{ "Lakers", "Kobe Bryant" },
{ "Lakers", "Rajon Rondo" },
{ "Lakers", "Steve Nash" },
{ "Lakers", "Paul Gasol" },
{ "Lakers", "Shaquile O'Neal" },
{ "Lakers", "JaVale McGee" },
{ "Lakers", "Dwight Howard" },
};

ASSERT_TRUE(verifyResult(resp, expected));
}
{
cpp2::ExecutionResponse resp;
auto query = "GO FROM hash('Manu Ginobili') OVER like REVERSELY "
"YIELD like._src AS id |"
"GO FROM $-.id OVER serve";
client_->execute(query, resp);
std::vector<std::tuple<int64_t>> expected = {
{ teams_["Spurs"].vid() },
{ teams_["Spurs"].vid() },
{ teams_["Hornets"].vid() },
{ teams_["Spurs"].vid() },
{ teams_["Hawks"].vid() },
{ teams_["76ers"].vid() },
{ teams_["Spurs"].vid() },
};

ASSERT_TRUE(verifyResult(resp, expected));
}
/**
* TODO(dutor)
* For the time being, reference to the pipe inputs is faulty.
* Because there might be multiple associated records with the same column value,
* which is used as the source id by the right statement.
*
* So the following case is disabled temporarily.
*/
/*
{
cpp2::ExecutionResponse resp;
auto query = "GO FROM hash('LeBron James') OVER serve "
"YIELD serve._dst AS id, serve.start_year AS start, "
"serve.end_year AS end |"
"GO FROM $-.id OVER serve REVERSELY "
"WHERE $$.player.name != 'LeBron James' && "
"serve.start_year <= $-.end && serve.end_year >= $-.end "
"YIELD $^.team.name, $$.player.name";
client_->execute(query, resp);
std::vector<std::tuple<std::string, std::string>> expected = {
{ "Cavaliers", "Kyrie Irving" },
{ "Cavaliers", "Shaquile O'Neal" },
{ "Cavaliers", "Danny Green" },
{ "Cavaliers", "Dwyane Wade" },
{ "Heat", "Dwyane Wade" },
{ "Heat", "Ray Allen" },
{ "Lakers", "Rajon Rondo" },
{ "Lakers", "JaVale McGee" },
};
ASSERT_TRUE(verifyResult(resp, expected));
}
*/
}

} // namespace graph
} // namespace nebula
13 changes: 10 additions & 3 deletions src/parser/Clauses.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ std::string ToClause::toString() const {

Status OverClause::prepare(Over &over) const {
over.edges_ = edges();
over.isReversely_ = isReversely_;
return Status::OK();
}

Expand All @@ -130,9 +131,7 @@ std::string OverEdge::toString() const {
buf += " AS ";
buf += *alias_;
}
if (isReversely_) {
buf += " REVERSELY";
}

return buf;
}

Expand All @@ -145,6 +144,10 @@ std::string OverEdges::toString() const {
}
buf.pop_back();

if (!buf.empty()) {
buf.resize(buf.size() - 1);
}

return buf;
}

Expand All @@ -154,6 +157,10 @@ std::string OverClause::toString() const {
buf += "OVER ";
buf += overEdges_->toString();

if (isReversely()) {
buf += " REVERSELY";
}

return buf;
}

Expand Down
15 changes: 9 additions & 6 deletions src/parser/Clauses.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ class Clause {
};

struct Over {
bool isReversely_{false};
std::vector<OverEdge*> edges_{nullptr};
std::vector<EdgeType> edgeTypes_;
std::vector<EdgeType> oppositeTypes_;
Expand Down Expand Up @@ -179,14 +180,11 @@ class ToClause final : public VerticesClause {

class OverEdge final {
public:
explicit OverEdge(std::string *edge, std::string *alias = nullptr, bool isReversely = false) {
explicit OverEdge(std::string *edge, std::string *alias = nullptr) {
edge_.reset(edge);
alias_.reset(alias);
isReversely_ = isReversely;
}

bool isReversely() const { return isReversely_; }

bool isOverAll() const { return *edge_ == "*"; }

std::string *edge() const { return edge_.get(); }
Expand All @@ -196,7 +194,6 @@ class OverEdge final {
std::string toString() const;

private:
bool isReversely_{false};
std::unique_ptr<std::string> edge_;
std::unique_ptr<std::string> alias_;
};
Expand All @@ -222,9 +219,10 @@ class OverEdges final {

class OverClause final : public Clause {
public:
explicit OverClause(OverEdges *edges) {
explicit OverClause(OverEdges *edges, bool isReversely = false) {
kind_ = kOverClause;
overEdges_.reset(edges);
isReversely_ = isReversely;
}

std::vector<OverEdge *> edges() const { return overEdges_->edges(); }
Expand All @@ -233,7 +231,12 @@ class OverClause final : public Clause {

std::string toString() const;

bool isReversely() const {
return isReversely_;
}

private:
bool isReversely_{false};
std::unique_ptr<OverEdges> overEdges_;
};

Expand Down
Loading

0 comments on commit 55c458c

Please sign in to comment.