From d6615a47d464f74b5fc6de82d264e2248a76486a Mon Sep 17 00:00:00 2001 From: zhouliang Date: Tue, 26 Mar 2019 13:55:04 +0800 Subject: [PATCH] add sentences of DELETE and FIND (#220) --- src/parser/MutateSentences.cpp | 38 ++++++++++++++- src/parser/MutateSentences.h | 70 ++++++++++++++++++++++++++- src/parser/Sentence.h | 3 ++ src/parser/TraverseSentences.cpp | 14 ++++++ src/parser/TraverseSentences.h | 34 ++++++++++++++ src/parser/parser.yy | 46 ++++++++++++++++-- src/parser/scanner.lex | 4 ++ src/parser/test/ParserTest.cpp | 81 ++++++++++++++++++++++++++++++++ src/parser/test/ScannerTest.cpp | 6 +++ 9 files changed, 291 insertions(+), 5 deletions(-) diff --git a/src/parser/MutateSentences.cpp b/src/parser/MutateSentences.cpp index 1bd3a55c082..66a062367dd 100644 --- a/src/parser/MutateSentences.cpp +++ b/src/parser/MutateSentences.cpp @@ -3,7 +3,6 @@ * This source code is licensed under Apache 2.0 License * (found in the LICENSE.Apache file in the root directory) */ - #include "base/Base.h" #include "parser/MutateSentences.h" @@ -139,4 +138,41 @@ std::string UpdateEdgeSentence::toString() const { return buf; } +std::string DeleteVertexSentence::toString() const { + std::string buf; + buf.reserve(256); + buf += "DELETE VERTEX "; + buf += srcNodeList_->toString(); + if (whereClause_ != nullptr) { + buf += " "; + buf += whereClause_->toString(); + } + return buf; +} + +std::string EdgeList::toString() const { + std::string buf; + buf.reserve(256); + for (auto edge : edges_) { + buf += std::to_string(edge.first); + buf += "->"; + buf += std::to_string(edge.second); + buf += ","; + } + buf.resize(buf.size() - 1); + return buf; +} + +std::string DeleteEdgeSentence::toString() const { + std::string buf; + buf.reserve(256); + buf += "DELETE EDGE "; + buf += edgeList_->toString(); + if (whereClause_ != nullptr) { + buf += " "; + buf += whereClause_->toString(); + } + return buf; +} + } // namespace nebula diff --git a/src/parser/MutateSentences.h b/src/parser/MutateSentences.h index c92dfa14f41..5a3d9bdf558 100644 --- a/src/parser/MutateSentences.h +++ b/src/parser/MutateSentences.h @@ -267,6 +267,74 @@ class UpdateEdgeSentence final : public Sentence { std::unique_ptr yieldClause_; }; -} // namespace nebula +class DeleteVertexSentence final : public Sentence { +public: + explicit DeleteVertexSentence(SourceNodeList *srcNodeList) { + srcNodeList_.reset(srcNodeList); + kind_ = Kind::kDeleteVertex; + } + + SourceNodeList* srcNodeLists() const { + return srcNodeList_.get(); + } + + void setWhereClause(WhereClause *clause) { + whereClause_.reset(clause); + } + + WhereClause* whereClause() const { + return whereClause_.get(); + } + + std::string toString() const override; + +private: + std::unique_ptr srcNodeList_; + std::unique_ptr whereClause_; +}; + +class EdgeList final { +public: + void addEdge(int64_t srcid, int64_t dstid) { + edges_.emplace_back(std::make_pair(srcid, dstid)); + } + + const std::vector>& edges() const { + return edges_; + } + + std::string toString() const; + +private: + std::vector> edges_; +}; + +class DeleteEdgeSentence final : public Sentence { +public: + explicit DeleteEdgeSentence(EdgeList *edgeList) { + edgeList_.reset(edgeList); + kind_ = Kind::kDeleteEdge; + } + + EdgeList* edgeList() const { + return edgeList_.get(); + } + + void setWhereClause(WhereClause *clause) { + whereClause_.reset(clause); + } + + WhereClause* whereClause() const { + return whereClause_.get(); + } + + std::string toString() const override; + +private: + std::unique_ptr edgeList_; + std::unique_ptr whereClause_; +}; + +} // namespace nebula #endif // PARSER_MUTATESENTENCES_H_ diff --git a/src/parser/Sentence.h b/src/parser/Sentence.h index b7be586bcfd..35f303ac061 100644 --- a/src/parser/Sentence.h +++ b/src/parser/Sentence.h @@ -33,6 +33,9 @@ class Sentence { kInsertVertex, kInsertEdge, kShow, + kDeleteVertex, + kDeleteEdge, + kFind, }; Kind kind() const { diff --git a/src/parser/TraverseSentences.cpp b/src/parser/TraverseSentences.cpp index 671a29e81b8..18f6a8dab6f 100644 --- a/src/parser/TraverseSentences.cpp +++ b/src/parser/TraverseSentences.cpp @@ -40,6 +40,20 @@ std::string MatchSentence::toString() const { return "MATCH sentence"; } +std::string FindSentence::toString() const { + std::string buf; + buf.reserve(256); + buf += "FIND "; + buf += properties_->toString(); + buf += " FROM "; + buf += *type_; + if (whereClause_ != nullptr) { + buf += " WHERE "; + buf += whereClause_->toString(); + } + return buf; +} + std::string UseSentence::toString() const { return "USE SPACE " + *space_; } diff --git a/src/parser/TraverseSentences.h b/src/parser/TraverseSentences.h index 772fb353bc9..ca9442e5cb9 100644 --- a/src/parser/TraverseSentences.h +++ b/src/parser/TraverseSentences.h @@ -9,6 +9,7 @@ #include "base/Base.h" #include "parser/Sentence.h" #include "parser/Clauses.h" +#include "parser/MutateSentences.h" namespace nebula { @@ -79,6 +80,39 @@ class MatchSentence final : public Sentence { }; +class FindSentence final : public Sentence { +public: + FindSentence(std::string *type, PropertyList *props) { + type_.reset(type); + properties_.reset(props); + kind_ = Kind::kFind; + } + + std::string* type() const { + return type_.get(); + } + + std::vector properties() const { + return properties_->properties(); + } + + void setWhereClause(WhereClause *whereClause) { + whereClause_.reset(whereClause); + } + + WhereClause* whereClause() const { + return whereClause_.get(); + } + + std::string toString() const override; + +private: + std::unique_ptr type_; + std::unique_ptr properties_; + std::unique_ptr whereClause_; +}; + + class UseSentence final : public Sentence { public: explicit UseSentence(std::string *space) { diff --git a/src/parser/parser.yy b/src/parser/parser.yy index 86baf3211ed..9e0eb00b354 100644 --- a/src/parser/parser.yy +++ b/src/parser/parser.yy @@ -52,11 +52,12 @@ class GraphScanner; nebula::ValueList *value_list; nebula::UpdateList *update_list; nebula::UpdateItem *update_item; + nebula::EdgeList *edge_list; } /* keywords */ %token KW_GO KW_AS KW_TO KW_OR KW_USE KW_SET KW_FROM KW_WHERE KW_ALTER %token KW_MATCH KW_INSERT KW_VALUES KW_YIELD KW_RETURN KW_DEFINE KW_VERTEX KW_TTL -%token KW_EDGE KW_UPDATE KW_STEPS KW_OVER KW_UPTO KW_REVERSELY KW_SPACE +%token KW_EDGE KW_UPDATE KW_STEPS KW_OVER KW_UPTO KW_REVERSELY KW_SPACE KW_DELETE KW_FIND %token KW_INT KW_BIGINT KW_DOUBLE KW_STRING KW_BOOL KW_TAG KW_UNION KW_INTERSECT KW_MINUS %token KW_NO KW_OVERWRITE KW_IN KW_DESCRIBE KW_SHOW KW_HOSTS KW_TIMESTAMP /* symbols */ @@ -89,19 +90,20 @@ class GraphScanner; %type value_list %type update_list %type update_item +%type edge_list %type ttl_spec %type column_spec %type column_spec_list -%type go_sentence match_sentence use_sentence +%type go_sentence match_sentence use_sentence find_sentence %type define_tag_sentence define_edge_sentence %type alter_tag_sentence alter_edge_sentence %type describe_tag_sentence describe_edge_sentence %type traverse_sentence set_sentence piped_sentence assignment_sentence %type maintainance_sentence insert_vertex_sentence insert_edge_sentence -%type mutate_sentence update_vertex_sentence update_edge_sentence +%type mutate_sentence update_vertex_sentence update_edge_sentence delete_vertex_sentence delete_edge_sentence %type show_sentence %type sentence %type sentences @@ -389,6 +391,14 @@ match_sentence : KW_MATCH { $$ = new MatchSentence; } ; +find_sentence + : KW_FIND prop_list KW_FROM LABEL where_clause { + auto sentence = new FindSentence($4, $2); + sentence->setWhereClause($5); + $$ = sentence; + } + ; + use_sentence : KW_USE KW_SPACE LABEL { $$ = new UseSentence($3); } ; @@ -476,6 +486,7 @@ describe_edge_sentence traverse_sentence : go_sentence {} | match_sentence {} + | find_sentence {} ; set_sentence @@ -672,11 +683,40 @@ show_sentence } ; +delete_vertex_sentence + : KW_DELETE KW_VERTEX id_list where_clause { + auto sentence = new DeleteVertexSentence($3); + sentence->setWhereClause($4); + $$ = sentence; + } + ; + +edge_list + : INTEGER R_ARROW INTEGER { + $$ = new EdgeList(); + $$->addEdge($1, $3); + } + | edge_list COMMA INTEGER R_ARROW INTEGER { + $$ = $1; + $$->addEdge($3, $5); + } + ; + +delete_edge_sentence + : KW_DELETE KW_EDGE edge_list where_clause { + auto sentence = new DeleteEdgeSentence($3); + sentence->setWhereClause($4); + $$ = sentence; + } + ; + mutate_sentence : insert_vertex_sentence {} | insert_edge_sentence {} | update_vertex_sentence {} | update_edge_sentence {} + | delete_vertex_sentence {} + | delete_edge_sentence {} ; maintainance_sentence diff --git a/src/parser/scanner.lex b/src/parser/scanner.lex index f7ba373ac5e..fc9dce01aa0 100644 --- a/src/parser/scanner.lex +++ b/src/parser/scanner.lex @@ -38,6 +38,8 @@ DESCRIBE ([Dd][Ee][Ss][Cc][Rr][Ii][Bb][Ee]) VERTEX ([Vv][Ee][Rr][Tt][Ee][Xx]) EDGE ([Ee][Dd][Gg][Ee]) UPDATE ([Uu][Pp][Dd][Aa][Tt][Ee]) +DELETE ([Dd][Ee][Ll][Ee][Tt][Ee]) +FIND ([Ff][Ii][Nn][Dd]) ALTER ([Aa][Ll][Tt][Ee][Rr]) STEPS ([Ss][Tt][Ee][Pp][Ss]) OVER ([Oo][Vv][Ee][Rr]) @@ -92,6 +94,8 @@ OCT ([0-7]) {VERTEX} { return TokenType::KW_VERTEX; } {EDGE} { return TokenType::KW_EDGE; } {UPDATE} { return TokenType::KW_UPDATE; } +{DELETE} { return TokenType::KW_DELETE; } +{FIND} { return TokenType::KW_FIND; } {ALTER} { return TokenType::KW_ALTER; } {STEPS} { return TokenType::KW_STEPS; } {OVER} { return TokenType::KW_OVER; } diff --git a/src/parser/test/ParserTest.cpp b/src/parser/test/ParserTest.cpp index 99f1b8adbc1..f803b911223 100644 --- a/src/parser/test/ParserTest.cpp +++ b/src/parser/test/ParserTest.cpp @@ -289,4 +289,85 @@ TEST(Parser, UpdateEdge) { } } +TEST(Parser, DeleteVertex) { + { + GQLParser parser; + std::string query = "DELETE VERTEX 12345"; + auto result = parser.parse(query); + ASSERT_TRUE(result.ok()) << result.status(); + } + { + GQLParser parser; + std::string query = "DELETE VERTEX 123,456,789"; + auto result = parser.parse(query); + ASSERT_TRUE(result.ok()) << result.status(); + } + { + GQLParser parser; + std::string query = "DELETE VERTEX 12345 WHERE salary > 10000"; + auto result = parser.parse(query); + ASSERT_TRUE(result.ok()) << result.status(); + } + { + GQLParser parser; + std::string query = "DELETE VERTEX 123,456,789 WHERE salary > 10000"; + auto result = parser.parse(query); + ASSERT_TRUE(result.ok()) << result.status(); + } +} + +TEST(Parser, DeleteEdge) { + { + GQLParser parser; + std::string query = "DELETE EDGE 12345 -> 54321"; + auto result = parser.parse(query); + ASSERT_TRUE(result.ok()) << result.status(); + } + { + GQLParser parser; + std::string query = "DELETE EDGE 123 -> 321,456 -> 654,789 -> 987"; + auto result = parser.parse(query); + ASSERT_TRUE(result.ok()) << result.status(); + } + { + GQLParser parser; + std::string query = "DELETE EDGE 12345 -> 54321 WHERE amount > 3.14"; + auto result = parser.parse(query); + ASSERT_TRUE(result.ok()) << result.status(); + } + { + GQLParser parser; + std::string query = "DELETE EDGE 123 -> 321,456 -> 654,789 -> 987 WHERE amount > 3.14"; + auto result = parser.parse(query); + ASSERT_TRUE(result.ok()) << result.status(); + } +} + +TEST(Parser, Find) { + { + GQLParser parser; + std::string query = "FIND name FROM person"; + auto result = parser.parse(query); + ASSERT_TRUE(result.ok()) << result.status(); + } + { + GQLParser parser; + std::string query = "FIND name, salary, age FROM person"; + auto result = parser.parse(query); + ASSERT_TRUE(result.ok()) << result.status(); + } + { + GQLParser parser; + std::string query = "FIND name, salary, age FROM person WHERE gender == \"man\""; + auto result = parser.parse(query); + ASSERT_TRUE(result.ok()) << result.status(); + } + { + GQLParser parser; + std::string query = "FIND amount, time FROM transfer WHERE amount > 1000"; + auto result = parser.parse(query); + ASSERT_TRUE(result.ok()) << result.status(); + } +} + } // namespace nebula diff --git a/src/parser/test/ScannerTest.cpp b/src/parser/test/ScannerTest.cpp index 74318f709e6..c86689ebc03 100644 --- a/src/parser/test/ScannerTest.cpp +++ b/src/parser/test/ScannerTest.cpp @@ -212,6 +212,12 @@ TEST(Scanner, Basic) { CHECK_SEMANTIC_TYPE("TIMESTAMP", TokenType::KW_TIMESTAMP), CHECK_SEMANTIC_TYPE("timestamp", TokenType::KW_TIMESTAMP), CHECK_SEMANTIC_TYPE("Timestamp", TokenType::KW_TIMESTAMP), + CHECK_SEMANTIC_TYPE("DELETE", TokenType::KW_DELETE), + CHECK_SEMANTIC_TYPE("delete", TokenType::KW_DELETE), + CHECK_SEMANTIC_TYPE("Delete", TokenType::KW_DELETE), + CHECK_SEMANTIC_TYPE("FIND", TokenType::KW_FIND), + CHECK_SEMANTIC_TYPE("find", TokenType::KW_FIND), + CHECK_SEMANTIC_TYPE("Find", TokenType::KW_FIND), CHECK_SEMANTIC_TYPE("_type", TokenType::TYPE_PROP), CHECK_SEMANTIC_TYPE("_id", TokenType::ID_PROP),