diff --git a/src/parser/AdminSentences.cpp b/src/parser/AdminSentences.cpp index d00285aee4f666b6d33d01ea1ec1dddf409da1f6..b138d57f9bc53c73667caee1cc1e0b26da667480 100644 --- a/src/parser/AdminSentences.cpp +++ b/src/parser/AdminSentences.cpp @@ -174,16 +174,39 @@ std::string ShowListenerSentence::toString() const { std::string AdminJobSentence::toString() const { switch (op_) { - case meta::cpp2::AdminJobOp::ADD: - return "add job"; - case meta::cpp2::AdminJobOp::SHOW_All: - return "show jobs"; - case meta::cpp2::AdminJobOp::SHOW: - return "show job"; - case meta::cpp2::AdminJobOp::STOP: - return "stop job"; - case meta::cpp2::AdminJobOp::RECOVER: - return "recover job"; + case meta::cpp2::AdminJobOp::ADD: { + switch (cmd_) { + case meta::cpp2::AdminCmd::COMPACT: + return paras_.empty() ? "SUBMIT JOB COMPACT" + : folly::stringPrintf("SUBMIT JOB COMPACT %s", paras_[0].c_str()); + case meta::cpp2::AdminCmd::FLUSH: + return paras_.empty() ? "SUBMIT JOB FLUSH" + : folly::stringPrintf("SUBMIT JOB FLUSH %s", paras_[0].c_str()); + case meta::cpp2::AdminCmd::REBUILD_TAG_INDEX: + return folly::stringPrintf("REBUILD TAG INDEX %s", + folly::join(",", paras_).c_str()); + case meta::cpp2::AdminCmd::REBUILD_EDGE_INDEX: + return folly::stringPrintf("REBUILD EDGE INDEX %s", + folly::join(",", paras_).c_str()); + case meta::cpp2::AdminCmd::STATS: + return paras_.empty() ? "SUBMIT JOB STATS" + : folly::stringPrintf("SUBMIT JOB STATS %s", paras_[0].c_str()); + case meta::cpp2::AdminCmd::DATA_BALANCE: + case meta::cpp2::AdminCmd::UNKNOWN: + return folly::stringPrintf("Unsupported AdminCmd: %s", + meta::cpp2::_AdminCmd_VALUES_TO_NAMES.at(cmd_)); + } + } + case meta::cpp2::AdminJobOp::SHOW_All: + return "SHOW JOBS"; + case meta::cpp2::AdminJobOp::SHOW: + CHECK_EQ(paras_.size(), 1U); + return folly::stringPrintf("SHOW JOB %s", paras_[0].c_str()); + case meta::cpp2::AdminJobOp::STOP: + CHECK_EQ(paras_.size(), 1U); + return folly::stringPrintf("STOP JOB %s", paras_[0].c_str()); + case meta::cpp2::AdminJobOp::RECOVER: + return "RECOVER JOB"; } LOG(FATAL) << "Unknown job operation " << static_cast<uint8_t>(op_); } @@ -204,6 +227,13 @@ void AdminJobSentence::addPara(const std::string& para) { paras_.emplace_back(para); } +void AdminJobSentence::addPara(const NameLabelList& paras) { + const auto& labels = paras.labels(); + std::for_each(labels.begin(), labels.end(), [this](const auto& para) { + paras_.emplace_back(*para); + }); +} + std::string ShowStatsSentence::toString() const { return folly::stringPrintf("SHOW STATS"); } diff --git a/src/parser/AdminSentences.h b/src/parser/AdminSentences.h index 70e25f0c3e2e83d698263542217d337db0cfc692..93bf5514f45c38f7a854e530da88de9780cd956e 100644 --- a/src/parser/AdminSentences.h +++ b/src/parser/AdminSentences.h @@ -593,6 +593,7 @@ public: } void addPara(const std::string& para); + void addPara(const NameLabelList& NameLabelList); std::string toString() const override; meta::cpp2::AdminJobOp getOp() const; meta::cpp2::AdminCmd getCmd() const; diff --git a/src/parser/parser.yy b/src/parser/parser.yy index da06ecfe5b11382a9efa03ac12184c95e2260d3f..23e59960f9bd9e895c7d83f05ed3c0ac46b03aae 100644 --- a/src/parser/parser.yy +++ b/src/parser/parser.yy @@ -2184,23 +2184,31 @@ describe_edge_index_sentence ; rebuild_tag_index_sentence - : KW_REBUILD KW_TAG KW_INDEX name_label { + : KW_REBUILD KW_TAG KW_INDEX name_label_list { auto sentence = new AdminJobSentence(meta::cpp2::AdminJobOp::ADD, meta::cpp2::AdminCmd::REBUILD_TAG_INDEX); sentence->addPara(*$4); delete $4; $$ = sentence; } + | KW_REBUILD KW_TAG KW_INDEX { + $$ = new AdminJobSentence(meta::cpp2::AdminJobOp::ADD, + meta::cpp2::AdminCmd::REBUILD_TAG_INDEX); + } ; rebuild_edge_index_sentence - : KW_REBUILD KW_EDGE KW_INDEX name_label { + : KW_REBUILD KW_EDGE KW_INDEX name_label_list { auto sentence = new AdminJobSentence(meta::cpp2::AdminJobOp::ADD, meta::cpp2::AdminCmd::REBUILD_EDGE_INDEX); sentence->addPara(*$4); delete $4; $$ = sentence; } + | KW_REBUILD KW_EDGE KW_INDEX { + $$ = new AdminJobSentence(meta::cpp2::AdminJobOp::ADD, + meta::cpp2::AdminCmd::REBUILD_EDGE_INDEX); + } ; add_group_sentence diff --git a/src/parser/test/ParserTest.cpp b/src/parser/test/ParserTest.cpp index a77b4dab4b156dbcd066ca2b3a8e3f01733b0979..fe128a4977167ba13d7bc9f901188f0b3c2162dc 100644 --- a/src/parser/test/ParserTest.cpp +++ b/src/parser/test/ParserTest.cpp @@ -3090,4 +3090,31 @@ TEST(Parser, FullTextServiceTest) { ASSERT_FALSE(result.ok()); } } + +TEST(Parser, JobTest) { + GQLParser parser; + auto checkTest = [&parser] (const std::string& query, const std::string expectedStr) { + auto result = parser.parse(query); + ASSERT_TRUE(result.ok()) << query << ":" << result.status(); + ASSERT_EQ(result.value()->toString(), expectedStr); + }; + checkTest("SUBMIT JOB COMPACT", "SUBMIT JOB COMPACT"); + checkTest("SUBMIT JOB COMPACT 111", "SUBMIT JOB COMPACT 111"); + checkTest("SUBMIT JOB FLUSH", "SUBMIT JOB FLUSH"); + checkTest("SUBMIT JOB FLUSH 111", "SUBMIT JOB FLUSH 111"); + checkTest("SUBMIT JOB STATS", "SUBMIT JOB STATS"); + checkTest("SUBMIT JOB STATS 111", "SUBMIT JOB STATS 111"); + checkTest("SHOW JOBS", "SHOW JOBS"); + checkTest("SHOW JOB 111", "SHOW JOB 111"); + checkTest("STOP JOB 111", "STOP JOB 111"); + checkTest("RECOVER JOB", "RECOVER JOB"); + checkTest("REBUILD TAG INDEX name_index", "REBUILD TAG INDEX name_index"); + checkTest("REBUILD EDGE INDEX name_index", "REBUILD EDGE INDEX name_index"); + checkTest("REBUILD TAG INDEX", "REBUILD TAG INDEX "); + checkTest("REBUILD EDGE INDEX", "REBUILD EDGE INDEX "); + checkTest("REBUILD TAG INDEX name_index, age_index", + "REBUILD TAG INDEX name_index,age_index"); + checkTest("REBUILD EDGE INDEX name_index, age_index", + "REBUILD EDGE INDEX name_index,age_index"); +} } // namespace nebula diff --git a/src/validator/AdminJobValidator.cpp b/src/validator/AdminJobValidator.cpp index 97d9229e9507ea88131108d9a3e8cc0cce66e67e..20dd7741aa3ff557db368db6902d25a02d68fe83 100644 --- a/src/validator/AdminJobValidator.cpp +++ b/src/validator/AdminJobValidator.cpp @@ -21,25 +21,29 @@ Status AdminJobValidator::validateImpl() { if (cmd == meta::cpp2::AdminCmd::REBUILD_TAG_INDEX || cmd == meta::cpp2::AdminCmd::REBUILD_EDGE_INDEX) { - DCHECK_EQ(sentence_->getParas().size(), 2); - - const auto &indexName = sentence_->getParas()[0]; auto ret = cmd == meta::cpp2::AdminCmd::REBUILD_TAG_INDEX - ? qctx()->getMetaClient()->getTagIndexesFromCache(spaceId) - : qctx()->getMetaClient()->getEdgeIndexesFromCache(spaceId); + ? qctx()->indexMng()->getTagIndexes(spaceId) + : qctx()->indexMng()->getEdgeIndexes(spaceId); if (!ret.ok()) { - return Status::SemanticError( - "Index %s not found in space %s", indexName.c_str(), spaceName.c_str()); + return Status::SemanticError("Get index failed in space `%s': %s", + spaceName.c_str(), ret.status().toString().c_str()); } auto indexes = std::move(ret).value(); - auto it = std::find_if(indexes.begin(), - indexes.end(), - [&indexName](std::shared_ptr<meta::cpp2::IndexItem>& item) { - return item->get_index_name() == indexName; - }); - if (it == indexes.end()) { - return Status::SemanticError( - "Index %s not found in space %s", indexName.c_str(), spaceName.c_str()); + const auto ¶s = sentence_->getParas(); + if (paras.size() == 1 && indexes.empty()) { + return Status::SemanticError("Space `%s' without indexes", spaceName.c_str()); + } + for (auto i = 0u; i < paras.size() - 1; i++) { + const auto &indexName = paras[i]; + auto it = std::find_if(indexes.begin(), indexes.end(), + [&indexName](std::shared_ptr<meta::cpp2::IndexItem>& item) { + return item->get_index_name() == indexName; + }); + if (it == indexes.end()) { + return Status::SemanticError( + "Index %s not found in space %s", + indexName.c_str(), spaceName.c_str()); + } } } } diff --git a/tests/tck/features/index/Index.feature b/tests/tck/features/index/Index.feature index b442776793b11bcb464c88337db7fd404f303b5f..d64df1ba912eecd7a1ead92f6e1f4c0e94ab41f9 100644 --- a/tests/tck/features/index/Index.feature +++ b/tests/tck/features/index/Index.feature @@ -646,7 +646,7 @@ Feature: IndexTest_Vid_String """ SHOW EDGE INDEX STATUS; """ - Then the result should be, in any order: + Then the result should include: | Name | Index Status | | "edge_index_status" | "FINISHED" | Then drop the used space @@ -688,3 +688,235 @@ Feature: IndexTest_Vid_String """ Then the execution should be successful Then drop the used space + + Scenario: IndexTest rebuild all tag indexes by empty input + Given an empty graph + And create a space with following options: + | name | rebuild_tag_space | + | vid_type | FIXED_STRING(10) | + And having executed: + """ + CREATE TAG id_tag(id int); + CREATE TAG name_tag(name string); + """ + And wait 6 seconds + When executing query: + """ + INSERT VERTEX id_tag(id) VALUES "100":(100), "200":(100); + INSERT VERTEX name_tag(name) VALUES "300":("100"), "400":("100"); + """ + Then the execution should be successful + When executing query: + """ + CREATE TAG INDEX id_tag_index ON id_tag(id); + CREATE TAG INDEX name_tag_index ON name_tag(name(10)); + """ + Then the execution should be successful + And wait 6 seconds + When executing query: + """ + REBUILD TAG INDEX; + """ + Then the execution should be successful + And wait 6 seconds + When executing query: + """ + SHOW TAG INDEX STATUS; + """ + Then the result should include: + | Name | Index Status | + | "rebuild_tag_space_all_tag_indexes" | "FINISHED" | + When executing query: + """ + LOOKUP ON id_tag WHERE id_tag.id == 100 + """ + Then the result should be, in any order: + | VertexID | + | "100" | + | "200" | + When executing query: + """ + LOOKUP ON name_tag WHERE name_tag.name == "100" + """ + Then the result should be, in any order: + | VertexID | + | "300" | + | "400" | + Then drop the used space + + Scenario: IndexTest rebuild all tag indexes by multi input + Given an empty graph + And create a space with following options: + | vid_type | FIXED_STRING(10) | + And having executed: + """ + CREATE TAG id_tag(id int); + CREATE TAG name_tag(name string); + CREATE TAG age_tag(age int); + """ + And wait 6 seconds + When executing query: + """ + INSERT VERTEX id_tag(id) VALUES "100":(100), "200":(100); + INSERT VERTEX name_tag(name) VALUES "300":("100"), "400":("100"); + INSERT VERTEX age_tag(age) VALUES "500":(8), "600":(8); + """ + Then the execution should be successful + When executing query: + """ + CREATE TAG INDEX id_tag_index ON id_tag(id); + CREATE TAG INDEX name_tag_index ON name_tag(name(10)); + CREATE TAG INDEX age_tag_index ON age_tag(age); + """ + Then the execution should be successful + And wait 6 seconds + When executing query: + """ + REBUILD TAG INDEX id_tag_index, name_tag_index; + """ + Then the execution should be successful + And wait 6 seconds + When executing query: + """ + SHOW TAG INDEX STATUS; + """ + Then the result should include: + | Name | Index Status | + | "id_tag_index,name_tag_index" | "FINISHED" | + When executing query: + """ + LOOKUP ON id_tag WHERE id_tag.id == 100 + """ + Then the result should be, in any order: + | VertexID | + | "100" | + | "200" | + When executing query: + """ + LOOKUP ON name_tag WHERE name_tag.name == "100" + """ + Then the result should be, in any order: + | VertexID | + | "300" | + | "400" | + When executing query: + """ + LOOKUP ON age_tag WHERE age_tag.age == 8 + """ + Then the result should be, in any order: + | VertexID | + Then drop the used space + + Scenario: IndexTest rebuild all edge indexes by empty input + Given an empty graph + And create a space with following options: + | name | rebuild_edge_space | + | vid_type | FIXED_STRING(10) | + And having executed: + """ + CREATE EDGE id_edge(id int); + CREATE EDGE name_edge(name string); + """ + And wait 6 seconds + When executing query: + """ + INSERT EDGE id_edge(id) VALUES "100"->"200":(100); + INSERT EDGE name_edge(name) VALUES "300"->"400":("100"); + """ + Then the execution should be successful + When executing query: + """ + CREATE EDGE INDEX id_edge_index ON id_edge(id); + CREATE EDGE INDEX name_edge_index ON name_edge(name(10)); + """ + Then the execution should be successful + And wait 6 seconds + When executing query: + """ + REBUILD EDGE INDEX; + """ + Then the execution should be successful + And wait 6 seconds + When executing query: + """ + SHOW EDGE INDEX STATUS; + """ + Then the result should include: + | Name | Index Status | + | "rebuild_edge_space_all_edge_indexes" | "FINISHED" | + When executing query: + """ + LOOKUP ON id_edge WHERE id_edge.id == 100 + """ + Then the result should be, in any order: + | SrcVID | DstVID | Ranking | + | "100" | "200" | 0 | + When executing query: + """ + LOOKUP ON name_edge WHERE name_edge.name == "100" + """ + Then the result should be, in any order: + | SrcVID | DstVID | Ranking | + | "300" | "400" | 0 | + Then drop the used space + + Scenario: IndexTest rebuild all edge indexes by multi input + Given an empty graph + And create a space with following options: + | vid_type | FIXED_STRING(20) | + And having executed: + """ + CREATE EDGE id_edge(id int); + CREATE EDGE name_edge(name string); + CREATE EDGE age_edge(age int); + """ + And wait 6 seconds + When executing query: + """ + INSERT EDGE id_edge(id) VALUES "100"->"200":(100); + INSERT EDGE name_edge(name) VALUES "300"->"400":("100"); + INSERT EDGE age_edge(age) VALUES "500"->"600":(8); + """ + Then the execution should be successful + When executing query: + """ + CREATE EDGE INDEX id_edge_index ON id_edge(id); + CREATE EDGE INDEX name_edge_index ON name_edge(name(10)); + CREATE EDGE INDEX age_edge_index ON age_edge(age); + """ + Then the execution should be successful + And wait 6 seconds + When executing query: + """ + REBUILD EDGE INDEX id_edge_index,name_edge_index; + """ + Then the execution should be successful + And wait 6 seconds + When executing query: + """ + SHOW EDGE INDEX STATUS; + """ + Then the result should include: + | Name | Index Status | + | "id_edge_index,name_edge_index" | "FINISHED" | + When executing query: + """ + LOOKUP ON id_edge WHERE id_edge.id == 100 + """ + Then the result should be, in any order: + | SrcVID | DstVID | Ranking | + | "100" | "200" | 0 | + When executing query: + """ + LOOKUP ON name_edge WHERE name_edge.name == "100" + """ + Then the result should be, in any order: + | SrcVID | DstVID | Ranking | + | "300" | "400" | 0 | + When executing query: + """ + LOOKUP ON age_edge WHERE age_edge.age == 8 + """ + Then the result should be, in any order: + | SrcVID | DstVID | Ranking | + Then drop the used space