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

Feature/fetch vertices on multi tags #310

Merged
42 changes: 42 additions & 0 deletions src/parser/Clauses.h
Original file line number Diff line number Diff line change
Expand Up @@ -387,5 +387,47 @@ using InBoundClause = BoundClause;
using OutBoundClause = BoundClause;
using BothInOutClause = BoundClause;

class NameLabelList {
public:
NameLabelList() = default;

void add(std::string *label) {
labels_.emplace_back(label);
}

bool empty() const {
return labels_.empty();
}

std::size_t size() const {
return labels_.size();
}

const std::string* front() const {
return labels_.front().get();
}

std::vector<const std::string*> labels() const {
std::vector<const std::string*> labels;
labels.reserve(labels_.size());
for (const auto& it : labels_) {
labels.emplace_back(it.get());
}
return labels;
}
Shylock-Hg marked this conversation as resolved.
Show resolved Hide resolved

std::string toString() const {
std::stringstream ss;
for (std::size_t i = 0; i < labels_.size() - 1; ++i) {
ss << *labels_[i].get() << ",";
}
ss << *labels_.back();
return ss.str();
}

private:
std::vector<std::unique_ptr<std::string>> labels_;
};

} // namespace nebula
#endif // PARSER_CLAUSES_H_
4 changes: 2 additions & 2 deletions src/parser/TraverseSentences.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ std::string FetchVerticesSentence::toString() const {
std::string buf;
buf.reserve(256);
buf += "FETCH PROP ON ";
buf += *tag_;
buf += tags_->toString();
buf += " ";
if (isRef()) {
buf += vidRef_->toString();
Expand All @@ -146,7 +146,7 @@ std::string FetchEdgesSentence::toString() const {
std::string buf;
buf.reserve(256);
buf += "FETCH PROP ON ";
buf += *edge_;
buf += edge_->toString();
buf += " ";
if (isRef()) {
buf += keyRef_->toString();
Expand Down
42 changes: 23 additions & 19 deletions src/parser/TraverseSentences.h
Original file line number Diff line number Diff line change
Expand Up @@ -297,44 +297,44 @@ class OrderBySentence final : public Sentence {

class FetchVerticesSentence final : public Sentence {
public:
FetchVerticesSentence(std::string *tag,
FetchVerticesSentence(NameLabelList *tags,
VertexIDList *vidList,
YieldClause *clause) {
kind_ = Kind::kFetchVertices;
tag_.reset(tag);
tags_.reset(tags);
vidList_.reset(vidList);
yieldClause_.reset(clause);
}

FetchVerticesSentence(std::string *tag,
FetchVerticesSentence(NameLabelList *tags,
Expression *ref,
YieldClause *clause) {
kind_ = Kind::kFetchVertices;
tag_.reset(tag);
tags_.reset(tags);
vidRef_.reset(ref);
yieldClause_.reset(clause);
}

explicit FetchVerticesSentence(Expression *ref, YieldClause *clause) {
kind_ = Kind::kFetchVertices;
tag_ = std::make_unique<std::string>("*");
tags_ = std::make_unique<NameLabelList>();
vidRef_.reset(ref);
yieldClause_.reset(clause);
}

explicit FetchVerticesSentence(VertexIDList *vidList, YieldClause *clause) {
kind_ = Kind::kFetchVertices;
tag_ = std::make_unique<std::string>("*");
tags_ = std::make_unique<NameLabelList>();
vidList_.reset(vidList);
yieldClause_.reset(clause);
}

bool isAllTagProps() {
return *tag_ == "*";
return tags_->empty();
}

auto tag() const {
return tag_.get();
const NameLabelList* tags() const {
return tags_.get();
}

auto vidList() const {
Expand All @@ -360,26 +360,26 @@ class FetchVerticesSentence final : public Sentence {
std::string toString() const override;

private:
std::unique_ptr<std::string> tag_;
std::unique_ptr<NameLabelList> tags_;
std::unique_ptr<VertexIDList> vidList_;
std::unique_ptr<Expression> vidRef_;
std::unique_ptr<YieldClause> yieldClause_;
};

class FetchEdgesSentence final : public Sentence {
public:
FetchEdgesSentence(std::string *edge,
EdgeKeys *keys,
YieldClause *clause) {
FetchEdgesSentence(NameLabelList *edge,
EdgeKeys *keys,
YieldClause *clause) {
kind_ = Kind::kFetchEdges;
edge_.reset(edge);
edgeKeys_.reset(keys);
yieldClause_.reset(clause);
}

FetchEdgesSentence(std::string *edge,
EdgeKeyRef *ref,
YieldClause *clause) {
FetchEdgesSentence(NameLabelList *edge,
EdgeKeyRef *ref,
YieldClause *clause) {
kind_ = Kind::kFetchEdges;
edge_.reset(edge);
keyRef_.reset(ref);
Expand Down Expand Up @@ -414,14 +414,18 @@ class FetchEdgesSentence final : public Sentence {
return yieldClause_.get();
}

std::string* edge() const {
return edge_.get();
const std::string* edge() const {
Shylock-Hg marked this conversation as resolved.
Show resolved Hide resolved
return edge_->front();
}

std::size_t edgeSize() const {
return edge_->size();
}

std::string toString() const override;

private:
std::unique_ptr<std::string> edge_;
std::unique_ptr<NameLabelList> edge_;
std::unique_ptr<EdgeKeys> edgeKeys_;
std::unique_ptr<EdgeKeyRef> keyRef_;
std::unique_ptr<YieldClause> yieldClause_;
Expand Down
21 changes: 17 additions & 4 deletions src/parser/parser.yy
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ static constexpr size_t MAX_ABS_INTEGER = 9223372036854775808ULL;
nebula::FromClause *from_clause;
nebula::ToClause *to_clause;
nebula::VertexIDList *vid_list;
nebula::NameLabelList *name_label_list;
nebula::OverEdge *over_edge;
nebula::OverEdges *over_edges;
nebula::OverClause *over_clause;
Expand Down Expand Up @@ -275,6 +276,7 @@ static constexpr size_t MAX_ABS_INTEGER = 9223372036854775808ULL;
%type <role_type_clause> role_type_clause
%type <acl_item_clause> acl_item_clause

%type <name_label_list> name_label_list
%type <index_field> index_field
%type <index_field_list> index_field_list

Expand Down Expand Up @@ -343,6 +345,17 @@ name_label
| unreserved_keyword { $$ = $1; }
;

name_label_list
: name_label {
$$ = new NameLabelList();
$$->add($1);
}
| name_label_list COMMA name_label {
$1->add($3);
$$ = $1;
}
;

legal_integer
: INTEGER {
ifOutOfRange($1, @1);
Expand Down Expand Up @@ -1367,10 +1380,10 @@ order_by_sentence
;

fetch_vertices_sentence
: KW_FETCH KW_PROP KW_ON name_label vid_list yield_clause {
: KW_FETCH KW_PROP KW_ON name_label_list vid_list yield_clause {
$$ = new FetchVerticesSentence($4, $5, $6);
}
| KW_FETCH KW_PROP KW_ON name_label vid_ref_expression yield_clause {
| KW_FETCH KW_PROP KW_ON name_label_list vid_ref_expression yield_clause {
$$ = new FetchVerticesSentence($4, $5, $6);
}
| KW_FETCH KW_PROP KW_ON STAR vid_list yield_clause {
Expand Down Expand Up @@ -1421,11 +1434,11 @@ edge_key_ref:
;

fetch_edges_sentence
: KW_FETCH KW_PROP KW_ON name_label edge_keys yield_clause {
: KW_FETCH KW_PROP KW_ON name_label_list edge_keys yield_clause {
auto fetch = new FetchEdgesSentence($4, $5, $6);
$$ = fetch;
}
| KW_FETCH KW_PROP KW_ON name_label edge_key_ref yield_clause {
| KW_FETCH KW_PROP KW_ON name_label_list edge_key_ref yield_clause {
auto fetch = new FetchEdgesSentence($4, $5, $6);
$$ = fetch;
}
Expand Down
31 changes: 31 additions & 0 deletions src/parser/test/ParserTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1156,6 +1156,30 @@ TEST(Parser, FetchVertex) {
auto result = parser.parse(query);
ASSERT_TRUE(result.ok()) << result.status();
}
{
GQLParser parser;
std::string query = "FETCH PROP ON * \"1\", \"2\"";
auto result = parser.parse(query);
ASSERT_TRUE(result.ok()) << result.status();
}
{
GQLParser parser;
std::string query = "FETCH PROP ON * $-.id";
auto result = parser.parse(query);
ASSERT_TRUE(result.ok()) << result.status();
}
{
GQLParser parser;
std::string query = "yield \"1\" as id | FETCH PROP ON * $-.id";
auto result = parser.parse(query);
ASSERT_TRUE(result.ok()) << result.status();
}
{
GQLParser parser;
std::string query = "yield \"1\" as id | FETCH PROP ON * $-.id yield friend.id, person.id";
auto result = parser.parse(query);
ASSERT_TRUE(result.ok()) << result.status();
}
}

TEST(Parser, FetchEdge) {
Expand Down Expand Up @@ -1195,6 +1219,13 @@ TEST(Parser, FetchEdge) {
auto result = parser.parse(query);
ASSERT_TRUE(result.ok()) << result.status();
}
// this will be denied in Semantic Analysis
{
GQLParser parser;
std::string query = "FETCH PROP ON transfer, another \"12345\" -> \"-54321\"";
auto result = parser.parse(query);
ASSERT_TRUE(result.ok()) << result.status();
}
}

TEST(Parser, Lookup) {
Expand Down
3 changes: 3 additions & 0 deletions src/validator/FetchEdgesValidator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,9 @@ Status FetchEdgesValidator::toPlan() {

Status FetchEdgesValidator::check() {
auto *sentence = static_cast<FetchEdgesSentence *>(sentence_);
if (sentence->edgeSize() > 1) {
return Status::SemanticError("Only allow fetch on one edge.");
}
spaceId_ = vctx_->whichSpace().id;
edgeTypeName_ = *sentence->edge();
auto edgeStatus = qctx_->schemaMng()->toEdgeType(spaceId_, edgeTypeName_);
Expand Down
22 changes: 12 additions & 10 deletions src/validator/FetchVerticesValidator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,18 +65,20 @@ Status FetchVerticesValidator::check() {

if (!sentence->isAllTagProps()) {
onStar_ = false;
auto tagName = *(sentence->tag());
auto tagStatus = qctx_->schemaMng()->toTagID(space_.id, tagName);
NG_RETURN_IF_ERROR(tagStatus);
auto tagId = tagStatus.value();
auto tags = sentence->tags()->labels();
for (const auto& tag : tags) {
auto tagStatus = qctx_->schemaMng()->toTagID(space_.id, *tag);
NG_RETURN_IF_ERROR(tagStatus);
auto tagId = tagStatus.value();

tags_.emplace(tagName, tagId);
auto schema = qctx_->schemaMng()->getTagSchema(space_.id, tagId);
if (schema == nullptr) {
LOG(ERROR) << "No schema found for " << tagName;
return Status::SemanticError("No schema found for `%s'", tagName.c_str());
tags_.emplace(*tag, tagId);
auto schema = qctx_->schemaMng()->getTagSchema(space_.id, tagId);
if (schema == nullptr) {
LOG(ERROR) << "No schema found for " << *tag;
return Status::SemanticError("No schema found for `%s'", tag->c_str());
}
tagsSchema_.emplace(tagId, schema);
}
tagsSchema_.emplace(tagId, schema);
} else {
onStar_ = true;
const auto allTagsResult = qctx_->schemaMng()->getAllVerTagSchema(space_.id);
Expand Down
3 changes: 3 additions & 0 deletions src/validator/test/FetchEdgesTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -418,6 +418,9 @@ TEST_F(FetchEdgesValidatorTest, FetchEdgesPropFailed) {

ASSERT_FALSE(validate("FETCH PROP ON like \"1\"->\"2\" YIELD $^.like.start + 1"));
ASSERT_FALSE(validate("FETCH PROP ON like \"1\"->\"2\" YIELD $$.like.start + 1"));

// Fetch on multi-edges
ASSERT_FALSE(validate("FETCH PROP ON like, serve \"1\"->\"2\""));
}

TEST_F(FetchEdgesValidatorTest, FetchEdgesInputFailed) {
Expand Down
Loading