diff --git a/src/graph/AlterTagExecutor.cpp b/src/graph/AlterTagExecutor.cpp index 020bd984e49..76cf4de7aad 100644 --- a/src/graph/AlterTagExecutor.cpp +++ b/src/graph/AlterTagExecutor.cpp @@ -27,9 +27,9 @@ void AlterTagExecutor::execute() { const auto& tagOpts = sentence_->tagOptList(); auto spaceId = ectx()->rctx()->session()->space(); - std::vector tagItems; + std::vector tagItems; for (auto& tagOpt : tagOpts) { - nebula::meta::cpp2::AlterTagItem tagItem; + nebula::meta::cpp2::AlterSchemaItem tagItem; auto opType = getTagOpType(tagOpt->getOptType()); tagItem.set_op(std::move(opType)); const auto& specs = tagOpt->columnSpecs(); @@ -65,17 +65,17 @@ void AlterTagExecutor::execute() { std::move(future).via(runner).thenValue(cb).thenError(error); } -nebula::meta::cpp2::AlterTagOp +nebula::meta::cpp2::AlterSchemaOp AlterTagExecutor::getTagOpType(const AlterTagOptItem::OptionType type) { switch (type) { case AlterTagOptItem::OptionType::ADD : - return nebula::meta::cpp2::AlterTagOp::ADD; - case AlterTagOptItem::OptionType::SET : - return nebula::meta::cpp2::AlterTagOp::SET; + return nebula::meta::cpp2::AlterSchemaOp::ADD; + case AlterTagOptItem::OptionType::CHANGE : + return nebula::meta::cpp2::AlterSchemaOp::CHANGE; case AlterTagOptItem::OptionType::DROP : - return nebula::meta::cpp2::AlterTagOp::DROP; + return nebula::meta::cpp2::AlterSchemaOp::DROP; default: - return nebula::meta::cpp2::AlterTagOp::UNKNOWN; + return nebula::meta::cpp2::AlterSchemaOp::UNKNOWN; } } } // namespace graph diff --git a/src/graph/AlterTagExecutor.h b/src/graph/AlterTagExecutor.h index 9906978e16f..f7b019ca0c5 100644 --- a/src/graph/AlterTagExecutor.h +++ b/src/graph/AlterTagExecutor.h @@ -27,7 +27,7 @@ class AlterTagExecutor final : public Executor { private: AlterTagSentence *sentence_{nullptr}; - nebula::meta::cpp2::AlterTagOp + nebula::meta::cpp2::AlterSchemaOp getTagOpType(const AlterTagOptItem::OptionType type); }; diff --git a/src/graph/test/SchemaTest.cpp b/src/graph/test/SchemaTest.cpp index c2fc058b44f..083408144de 100644 --- a/src/graph/test/SchemaTest.cpp +++ b/src/graph/test/SchemaTest.cpp @@ -116,7 +116,7 @@ TEST_F(SchemaTest, metaCommunication) { cpp2::ExecutionResponse resp; std::string query = "ALTER TAG account " "ADD (col1 int TTL = 200, col2 string), " - "SET (balance string), " + "CHANGE (balance string), " "DROP (id)"; auto code = client->execute(query, resp); ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); @@ -208,13 +208,10 @@ TEST_F(SchemaTest, metaCommunication) { }; ASSERT_TRUE(verifyResult(resp, expected)); } - /* test the same tag in diff space, but now meta server not supported, - * will add a issue(#292) to resolve it */ { cpp2::ExecutionResponse resp; std::string query = "CREATE TAG person(name string, interest string)"; auto code = client->execute(query, resp); - sleep(FLAGS_load_data_interval_second + 1); ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); } { diff --git a/src/interface/meta.thrift b/src/interface/meta.thrift index 9cbd9f475e2..e8ba51864eb 100644 --- a/src/interface/meta.thrift +++ b/src/interface/meta.thrift @@ -34,9 +34,9 @@ enum ErrorCode { } (cpp.enum_strict) -enum AlterTagOp { +enum AlterSchemaOp { ADD = 0x01, - SET = 0x02, + CHANGE = 0x02, DROP = 0x03, UNKNOWN = 0x04, } (cpp.enum_strict) @@ -65,8 +65,8 @@ struct TagItem { 4: common.Schema schema, } -struct AlterTagItem { - 1: AlterTagOp op, +struct AlterSchemaItem { + 1: AlterSchemaOp op, 2: common.Schema schema, } @@ -124,9 +124,9 @@ struct CreateTagReq { } struct AlterTagReq { - 1: common.GraphSpaceID space_id, - 2: string tag_name, - 3: list tag_items, + 1: common.GraphSpaceID space_id, + 2: string tag_name, + 3: list tag_items, } struct RemoveTagReq { @@ -156,6 +156,23 @@ struct GetTagResp { 2: common.Schema schema, } +struct GetEdgeReq { + 1: common.GraphSpaceID space_id, + 2: common.EdgeType edge_type, + 3: common.SchemaVer version, +} + +struct AlterEdgeReq { + 1: common.GraphSpaceID space_id, + 2: string edge_name, + 3: list edge_items, +} + +struct GetEdgeResp { + 1: ErrorCode code, + 2: common.Schema schema, +} + // Edge related operations. struct CreateEdgeReq { 1: common.GraphSpaceID space_id, @@ -165,7 +182,7 @@ struct CreateEdgeReq { struct RemoveEdgeReq { 1: common.GraphSpaceID space_id, - 2: common.EdgeType edge_type, + 2: string edge_name, } struct ListEdgesReq { @@ -179,16 +196,6 @@ struct ListEdgesResp { 3: list edges, } -struct GetEdgeReq { - 1: common.GraphSpaceID space_id, - 2: common.EdgeType edge_type, - 3: common.SchemaVer version, -} - -struct GetEdgeResp { - 1: common.Schema schema, -} - // Host related operations. struct AddHostsReq { 1: list hosts; diff --git a/src/meta/CMakeLists.txt b/src/meta/CMakeLists.txt index 07fa18448e1..b0af0f98b57 100644 --- a/src/meta/CMakeLists.txt +++ b/src/meta/CMakeLists.txt @@ -21,12 +21,15 @@ add_library( processors/DropSpaceProcessor.cpp processors/GetPartsAllocProcessor.cpp processors/CreateTagProcessor.cpp - processors/AlterTagProcessor.cpp processors/CreateEdgeProcessor.cpp + processors/AlterTagProcessor.cpp + processors/AlterEdgeProcessor.cpp processors/GetTagProcessor.cpp + processors/GetEdgeProcessor.cpp processors/ListTagsProcessor.cpp - processors/RemoveTagProcessor.cpp processors/ListEdgesProcessor.cpp + processors/RemoveTagProcessor.cpp + processors/RemoveEdgeProcessor.cpp processors/GetProcessor.cpp processors/MultiGetProcessor.cpp processors/MultiPutProcessor.cpp diff --git a/src/meta/MetaServiceUtils.cpp b/src/meta/MetaServiceUtils.cpp index c292666b2fb..90087a3b5ca 100644 --- a/src/meta/MetaServiceUtils.cpp +++ b/src/meta/MetaServiceUtils.cpp @@ -116,6 +116,15 @@ nebula::cpp2::HostAddr MetaServiceUtils::parseHostKey(folly::StringPiece key) { return host; } +std::string MetaServiceUtils::schemaEdgePrefix(GraphSpaceID spaceId, EdgeType edgeType) { + std::string key; + key.reserve(128); + key.append(kEdgesTable.data(), kEdgesTable.size()); + key.append(reinterpret_cast(&spaceId), sizeof(spaceId)); + key.append(reinterpret_cast(&edgeType), sizeof(edgeType)); + return key; +} + std::string MetaServiceUtils::schemaEdgesPrefix(GraphSpaceID spaceId) { std::string key; key.reserve(kEdgesTable.size() + sizeof(GraphSpaceID)); @@ -250,5 +259,47 @@ std::string MetaServiceUtils::assembleSegmentKey(const std::string& segment, return segmentKey; } +cpp2::ErrorCode MetaServiceUtils::alterColumnDefs(std::vector& cols, + const nebula::cpp2::ColumnDef col, + const cpp2::AlterSchemaOp op) { + switch (op) { + case cpp2::AlterSchemaOp::ADD : + { + for (auto it = cols.begin(); it != cols.end(); ++it) { + if (it->get_name() == col.get_name()) { + LOG(WARNING) << "Column existing : " << col.get_name(); + return cpp2::ErrorCode::E_EXISTED; + } + } + cols.emplace_back(std::move(col)); + return cpp2::ErrorCode::SUCCEEDED; + } + case cpp2::AlterSchemaOp::CHANGE : + { + for (auto it = cols.begin(); it != cols.end(); ++it) { + if (col.get_name() == it->get_name()) { + *it = col; + return cpp2::ErrorCode::SUCCEEDED; + } + } + break; + } + case cpp2::AlterSchemaOp::DROP : + { + for (auto it = cols.begin(); it != cols.end(); ++it) { + if (col.get_name() == it->get_name()) { + cols.erase(it); + return cpp2::ErrorCode::SUCCEEDED; + } + } + break; + } + default : + return cpp2::ErrorCode::E_UNKNOWN; + } + LOG(WARNING) << "Column not found : " << col.get_name(); + return cpp2::ErrorCode::E_NOT_FOUND; +} + } // namespace meta } // namespace nebula diff --git a/src/meta/MetaServiceUtils.h b/src/meta/MetaServiceUtils.h index bb7165c4d06..11697075682 100644 --- a/src/meta/MetaServiceUtils.h +++ b/src/meta/MetaServiceUtils.h @@ -8,7 +8,7 @@ #define META_METAUTILS_H_ #include "base/Base.h" -#include "interface/gen-cpp2/common_types.h" +#include "interface/gen-cpp2/meta_types.h" namespace nebula { namespace meta { @@ -52,6 +52,8 @@ class MetaServiceUtils final { static nebula::cpp2::HostAddr parseHostKey(folly::StringPiece key); + static std::string schemaEdgePrefix(GraphSpaceID spaceId, EdgeType edgeType); + static std::string schemaEdgesPrefix(GraphSpaceID spaceId); static std::string schemaEdgeKey(GraphSpaceID spaceId, EdgeType edgeType, SchemaVer version); @@ -79,6 +81,10 @@ class MetaServiceUtils final { static std::string indexEdgeKey(GraphSpaceID spaceId, const std::string& name); static std::string assembleSegmentKey(const std::string& segment, const std::string& key); + + static cpp2::ErrorCode alterColumnDefs(std::vector& cols, + const nebula::cpp2::ColumnDef col, + const cpp2::AlterSchemaOp op); }; } // namespace meta diff --git a/src/meta/client/MetaClient.cpp b/src/meta/client/MetaClient.cpp index 49195567870..944de4aea90 100644 --- a/src/meta/client/MetaClient.cpp +++ b/src/meta/client/MetaClient.cpp @@ -643,7 +643,7 @@ MetaClient::createTagSchema(GraphSpaceID spaceId, std::string name, nebula::cpp2 folly::Future> MetaClient::alterTagSchema(GraphSpaceID spaceId, std::string name, - std::vector tagItems) { + std::vector tagItems) { cpp2::AlterTagReq req; req.set_space_id(std::move(spaceId)); req.set_tag_name(std::move(name)); diff --git a/src/meta/client/MetaClient.h b/src/meta/client/MetaClient.h index a178f3a5822..dc4b7879bfe 100644 --- a/src/meta/client/MetaClient.h +++ b/src/meta/client/MetaClient.h @@ -99,8 +99,9 @@ class MetaClient { createTagSchema(GraphSpaceID spaceId, std::string name, nebula::cpp2::Schema schema); // TODO(boshengchen) need refresh tagNameIdMap and newestTagVerMap - folly::Future> - alterTagSchema(GraphSpaceID spaceId, std::string name, std::vector items); + folly::Future> alterTagSchema(GraphSpaceID spaceId, + std::string name, + std::vector items); folly::Future>> listTagSchemas(GraphSpaceID spaceId); diff --git a/src/meta/processors/AlterEdgeProcessor.cpp b/src/meta/processors/AlterEdgeProcessor.cpp new file mode 100644 index 00000000000..fba3554e1be --- /dev/null +++ b/src/meta/processors/AlterEdgeProcessor.cpp @@ -0,0 +1,69 @@ +/* Copyright (c) 2018 - present, VE Software Inc. All rights reserved + * + * This source code is licensed under Apache 2.0 License + * (found in the LICENSE.Apache file in the root directory) + */ + +#include "meta/processors/AlterEdgeProcessor.h" +#include "time/TimeUtils.h" + +namespace nebula { +namespace meta { + +void AlterEdgeProcessor::process(const cpp2::AlterEdgeReq& req) { + if (spaceExist(req.get_space_id()) == Status::SpaceNotFound()) { + resp_.set_code(cpp2::ErrorCode::E_NOT_FOUND); + onFinished(); + return; + } + folly::SharedMutex::WriteHolder wHolder(LockUtils::edgeLock()); + auto ret = getEdgeType(req.get_space_id(), req.get_edge_name()); + if (!ret.ok()) { + resp_.set_code(to(ret.status())); + onFinished(); + return; + } + auto edgeType = ret.value(); + + // Check the edge belongs to the space + std::unique_ptr iter; + auto edgePrefix = MetaServiceUtils::schemaEdgePrefix(req.get_space_id(), edgeType); + auto code = kvstore_->prefix(kDefaultSpaceId_, kDefaultPartId_, edgePrefix, &iter); + if (code != kvstore::ResultCode::SUCCEEDED || !iter->valid()) { + LOG(WARNING) << "Edge could not be found " << req.get_edge_name() + << ", spaceId " << req.get_space_id() << ", edgeType " << edgeType; + resp_.set_code(cpp2::ErrorCode::E_NOT_FOUND); + onFinished(); + return; + } + + // Get lasted version of edge + auto version = MetaServiceUtils::parseEdgeVersion(iter->key()) + 1; + auto schema = MetaServiceUtils::parseSchema(iter->val()); + auto columns = schema.get_columns(); + auto& edgeItems = req.get_edge_items(); + for (auto& edgeItem : edgeItems) { + auto& cols = edgeItem.get_schema().get_columns(); + for (auto& col : cols) { + auto retCode = MetaServiceUtils::alterColumnDefs(columns, col, edgeItem.op); + if (retCode != cpp2::ErrorCode::SUCCEEDED) { + LOG(WARNING) << "Alter edge error " << static_cast(retCode); + resp_.set_code(retCode); + onFinished(); + return; + } + } + } + schema.set_columns(std::move(columns)); + std::vector data; + LOG(INFO) << "Alter edge " << req.get_edge_name() << ", edgeTye " << edgeType; + data.emplace_back(MetaServiceUtils::schemaEdgeKey(req.get_space_id(), edgeType, version), + MetaServiceUtils::schemaEdgeVal(req.get_edge_name(), schema)); + resp_.set_code(cpp2::ErrorCode::SUCCEEDED); + resp_.set_id(to(edgeType, EntryType::EDGE)); + doPut(std::move(data)); +} + +} // namespace meta +} // namespace nebula + diff --git a/src/meta/processors/AlterEdgeProcessor.h b/src/meta/processors/AlterEdgeProcessor.h new file mode 100644 index 00000000000..00bdd80739a --- /dev/null +++ b/src/meta/processors/AlterEdgeProcessor.h @@ -0,0 +1,31 @@ +/* Copyright (c) 2018 - present, VE Software Inc. All rights reserved + * + * This source code is licensed under Apache 2.0 License + * (found in the LICENSE.Apache file in the root directory) + */ + +#ifndef META_ALTEREDGEPROCESSOR_H_ +#define META_ALTEREDGEPROCESSOR_H_ + +#include "meta/processors/BaseProcessor.h" + +namespace nebula { +namespace meta { + +class AlterEdgeProcessor : public BaseProcessor { +public: + static AlterEdgeProcessor* instance(kvstore::KVStore* kvstore) { + return new AlterEdgeProcessor(kvstore); + } + + void process(const cpp2::AlterEdgeReq& req); + +private: + explicit AlterEdgeProcessor(kvstore::KVStore* kvstore) + : BaseProcessor(kvstore) {} +}; + +} // namespace meta +} // namespace nebula +#endif // META_ALTEREDGEPROCESSOR_H_ + diff --git a/src/meta/processors/AlterTagProcessor.cpp b/src/meta/processors/AlterTagProcessor.cpp index 1422a915877..dd9dbdd9605 100644 --- a/src/meta/processors/AlterTagProcessor.cpp +++ b/src/meta/processors/AlterTagProcessor.cpp @@ -31,7 +31,7 @@ void AlterTagProcessor::process(const cpp2::AlterTagReq& req) { auto code = kvstore_->prefix(kDefaultSpaceId_, kDefaultPartId_, tagPrefix, &iter); if (code != kvstore::ResultCode::SUCCEEDED || !iter->valid()) { LOG(WARNING) << "Tag could not be found " << req.get_tag_name() - << ", spaceId " << req.get_space_id() << ", tagId " << tagId; + << ", spaceId " << req.get_space_id() << ", tagId " << tagId; resp_.set_code(cpp2::ErrorCode::E_NOT_FOUND); onFinished(); return; @@ -45,9 +45,9 @@ void AlterTagProcessor::process(const cpp2::AlterTagReq& req) { for (auto& tagItem : tagItems) { auto& cols = tagItem.get_schema().get_columns(); for (auto& col : cols) { - auto retCode = alterColumnDefs(columns, col, tagItem.op); + auto retCode = MetaServiceUtils::alterColumnDefs(columns, col, tagItem.op); if (retCode != cpp2::ErrorCode::SUCCEEDED) { - LOG(WARNING) << "Alter tag error"; + LOG(WARNING) << "Alter tag error " << static_cast(retCode); resp_.set_code(retCode); onFinished(); return; @@ -64,48 +64,6 @@ void AlterTagProcessor::process(const cpp2::AlterTagReq& req) { doPut(std::move(data)); } -cpp2::ErrorCode AlterTagProcessor::alterColumnDefs(std::vector& cols, - const nebula::cpp2::ColumnDef col, - const cpp2::AlterTagOp op) { - switch (op) { - case cpp2::AlterTagOp::ADD : - { - for (auto it = cols.begin(); it != cols.end(); ++it) { - if (it->get_name() == col.get_name()) { - LOG(WARNING) << "Tag column existing : " << col.get_name(); - return cpp2::ErrorCode::E_EXISTED; - } - } - cols.push_back(std::move(col)); - return cpp2::ErrorCode::SUCCEEDED; - } - case cpp2::AlterTagOp::SET : - { - for (auto it = cols.begin(); it != cols.end(); ++it) { - if (col.get_name() == it->get_name()) { - *it = col; - return cpp2::ErrorCode::SUCCEEDED; - } - } - break; - } - case cpp2::AlterTagOp::DROP : - { - for (auto it = cols.begin(); it != cols.end(); ++it) { - if (col.get_name() == it->get_name()) { - cols.erase(it); - return cpp2::ErrorCode::SUCCEEDED; - } - } - break; - } - default : - return cpp2::ErrorCode::E_UNKNOWN; - } - LOG(WARNING) << "Tag column not found : " << col.get_name(); - return cpp2::ErrorCode::E_NOT_FOUND; -} - } // namespace meta } // namespace nebula diff --git a/src/meta/processors/AlterTagProcessor.h b/src/meta/processors/AlterTagProcessor.h index ef8a245167e..0569c176b04 100644 --- a/src/meta/processors/AlterTagProcessor.h +++ b/src/meta/processors/AlterTagProcessor.h @@ -23,10 +23,6 @@ class AlterTagProcessor : public BaseProcessor { private: explicit AlterTagProcessor(kvstore::KVStore* kvstore) : BaseProcessor(kvstore) {} - - cpp2::ErrorCode alterColumnDefs(std::vector& cols, - const nebula::cpp2::ColumnDef col, - const cpp2::AlterTagOp op); }; } // namespace meta diff --git a/src/meta/processors/BaseProcessor.h b/src/meta/processors/BaseProcessor.h index e9532172b44..f7367d8059b 100644 --- a/src/meta/processors/BaseProcessor.h +++ b/src/meta/processors/BaseProcessor.h @@ -11,7 +11,6 @@ #include #include #include -#include "interface/gen-cpp2/meta_types.h" #include "base/StatusOr.h" #include "time/Duration.h" #include "kvstore/KVStore.h" diff --git a/src/meta/processors/GetEdgeProcessor.cpp b/src/meta/processors/GetEdgeProcessor.cpp new file mode 100644 index 00000000000..64593eacdca --- /dev/null +++ b/src/meta/processors/GetEdgeProcessor.cpp @@ -0,0 +1,29 @@ +/* Copyright (c) 2018 - present, VE Software Inc. All rights reserved + * + * This source code is licensed under Apache 2.0 License + * (found in the LICENSE.Apache file in the root directory) + */ + +#include "meta/processors/GetEdgeProcessor.h" + +namespace nebula { +namespace meta { + +void GetEdgeProcessor::process(const cpp2::GetEdgeReq& req) { + folly::SharedMutex::ReadHolder rHolder(LockUtils::edgeLock()); + std::string val; + std::string edgeKey = MetaServiceUtils::schemaEdgeKey(req.get_space_id(), + req.get_edge_type(), + req.get_version()); + auto ret = kvstore_->get(kDefaultSpaceId_, kDefaultPartId_, std::move(edgeKey), &val); + if (ret != kvstore::ResultCode::SUCCEEDED) { + resp_.set_code(cpp2::ErrorCode::E_NOT_FOUND); + onFinished(); + return; + } + resp_.set_schema(MetaServiceUtils::parseSchema(val)); + onFinished(); +} +} // namespace meta +} // namespace nebula + diff --git a/src/meta/processors/GetEdgeProcessor.h b/src/meta/processors/GetEdgeProcessor.h new file mode 100644 index 00000000000..6793bacf383 --- /dev/null +++ b/src/meta/processors/GetEdgeProcessor.h @@ -0,0 +1,30 @@ +/* Copyright (c) 2018 - present, VE Software Inc. All rights reserved + * + * This source code is licensed under Apache 2.0 License + * (found in the LICENSE.Apache file in the root directory) + */ + +#ifndef META_GETEDGEPROCESSOR_H_ +#define META_GETEDGEPROCESSOR_H_ + +#include "meta/processors/BaseProcessor.h" + +namespace nebula { +namespace meta { + +class GetEdgeProcessor : public BaseProcessor { +public: + static GetEdgeProcessor* instance(kvstore::KVStore* kvstore) { + return new GetEdgeProcessor(kvstore); + } + + void process(const cpp2::GetEdgeReq& req); + +private: + explicit GetEdgeProcessor(kvstore::KVStore* kvstore) + : BaseProcessor(kvstore) {} +}; + +} // namespace meta +} // namespace nebula +#endif // META_GETEDGEPROCESSOR_H_ diff --git a/src/meta/processors/RemoveEdgeProcessor.cpp b/src/meta/processors/RemoveEdgeProcessor.cpp new file mode 100644 index 00000000000..803f0a9530e --- /dev/null +++ b/src/meta/processors/RemoveEdgeProcessor.cpp @@ -0,0 +1,61 @@ +/* Copyright (c) 2018 - present, VE Software Inc. All rights reserved + * + * This source code is licensed under Apache 2.0 License + * (found in the LICENSE.Apache file in the root directory) + */ + +#include "meta/processors/RemoveEdgeProcessor.h" + +namespace nebula { +namespace meta { + +void RemoveEdgeProcessor::process(const cpp2::RemoveEdgeReq& req) { + if (spaceExist(req.get_space_id()) == Status::SpaceNotFound()) { + resp_.set_code(cpp2::ErrorCode::E_NOT_FOUND); + onFinished(); + return; + } + folly::SharedMutex::WriteHolder wHolder(LockUtils::edgeLock()); + auto ret = getEdgeKeys(req.get_space_id(), req.get_edge_name()); + if (!ret.ok()) { + resp_.set_code(cpp2::ErrorCode::E_NOT_FOUND); + onFinished(); + return; + } + resp_.set_code(cpp2::ErrorCode::SUCCEEDED); + LOG(INFO) << "Remove Edge " << req.get_edge_name(); + doMultiRemove(std::move(ret.value())); +} + +StatusOr> RemoveEdgeProcessor::getEdgeKeys(GraphSpaceID id, + const std::string& edgeName) { + auto indexKey = MetaServiceUtils::indexEdgeKey(id, edgeName); + std::vector keys; + std::string edgeVal; + EdgeType edgeType; + auto ret = kvstore_->get(kDefaultSpaceId_, kDefaultPartId_, indexKey, &edgeVal); + if (ret == kvstore::ResultCode::SUCCEEDED) { + edgeType = *reinterpret_cast(edgeVal.data()); + resp_.set_id(to(edgeType, EntryType::EDGE)); + keys.emplace_back(indexKey); + } else { + return Status::Error("No Edge!"); + } + + std::unique_ptr iter; + auto key = MetaServiceUtils::schemaEdgePrefix(id, edgeType); + ret = kvstore_->prefix(kDefaultSpaceId_, kDefaultPartId_, key, &iter); + if (ret != kvstore::ResultCode::SUCCEEDED) { + return Status::Error("Edge get error by id : %d !", edgeType); + } + + while (iter->valid()) { + keys.emplace_back(iter->key()); + iter->next(); + } + return keys; +} + +} // namespace meta +} // namespace nebula + diff --git a/src/meta/processors/RemoveEdgeProcessor.h b/src/meta/processors/RemoveEdgeProcessor.h new file mode 100644 index 00000000000..8163ea71a00 --- /dev/null +++ b/src/meta/processors/RemoveEdgeProcessor.h @@ -0,0 +1,32 @@ +/* Copyright (c) 2018 - present, VE Software Inc. All rights reserved + * + * This source code is licensed under Apache 2.0 License + * (found in the LICENSE.Apache file in the root directory) + */ + +#ifndef NEBULA_GRAPH_REMOVEEDGEPROCESSOR_H +#define NEBULA_GRAPH_REMOVEEDGEPROCESSOR_H + +#include "meta/processors/BaseProcessor.h" + +namespace nebula { +namespace meta { + +class RemoveEdgeProcessor : public BaseProcessor { +public: + static RemoveEdgeProcessor* instance(kvstore::KVStore* kvstore) { + return new RemoveEdgeProcessor(kvstore); + } + + void process(const cpp2::RemoveEdgeReq& req); + +private: + explicit RemoveEdgeProcessor(kvstore::KVStore* kvstore) + : BaseProcessor(kvstore) {} + + StatusOr> getEdgeKeys(GraphSpaceID id, const std::string& edgeName); +}; + +} // namespace meta +} // namespace nebula +#endif // NEBULA_GRAPH_REMOVEEDGEPROCESSOR_H diff --git a/src/meta/test/MetaClientTest.cpp b/src/meta/test/MetaClientTest.cpp index 9645855b8fd..14077a714c0 100644 --- a/src/meta/test/MetaClientTest.cpp +++ b/src/meta/test/MetaClientTest.cpp @@ -120,6 +120,7 @@ TEST(MetaClientTest, InterfacesTest) { ASSERT_EQ(5, outSchema->getNumFields()); ASSERT_STREQ("tagItem0", outSchema->getFieldName(0)); auto version = schemaMan->getNewestTagSchemaVer(spaceId, tagId); + ASSERT_EQ(0, version); auto outSchema1 = schemaMan->getTagSchema(spaceId, tagId, version); ASSERT_TRUE(outSchema1 != nullptr); ASSERT_EQ(5, outSchema1->getNumFields()); @@ -147,6 +148,7 @@ TEST(MetaClientTest, InterfacesTest) { ASSERT_EQ(5, outSchema->getNumFields()); ASSERT_STREQ("edgeItem0", outSchema->getFieldName(0)); auto version = schemaMan->getNewestEdgeSchemaVer(spaceId, edgeType); + ASSERT_EQ(0, version); auto outSchema1 = schemaMan->getEdgeSchema(spaceId, edgeType, version); ASSERT_TRUE(outSchema1 != nullptr); ASSERT_EQ(5, outSchema1->getNumFields()); diff --git a/src/meta/test/MetaServiceUtilsTest.cpp b/src/meta/test/MetaServiceUtilsTest.cpp index 7e40de2eb2f..2b1308ab1a2 100644 --- a/src/meta/test/MetaServiceUtilsTest.cpp +++ b/src/meta/test/MetaServiceUtilsTest.cpp @@ -34,9 +34,9 @@ TEST(MetaServiceUtilsTest, PartKeyTest) { ASSERT_EQ(prefix, partKey.substr(0, partKey.size() - sizeof(PartitionID))); ASSERT_EQ(1, *reinterpret_cast(partKey.c_str() + prefix.size())); - std::vector hosts; + std::vector hosts; for (int i = 0; i < 10; i++) { - cpp2::HostAddr host; + nebula::cpp2::HostAddr host; host.set_ip(i * 20 + 1); host.set_port(i * 20 + 2); hosts.emplace_back(std::move(host)); @@ -65,13 +65,13 @@ TEST(MetaServiceUtilsTest, HostKeyTest) { } TEST(MetaServiceUtilsTest, TagTest) { - cpp2::Schema schema; + nebula::cpp2::Schema schema; decltype(schema.columns) cols; for (auto i = 1; i <= 3; i++) { nebula::cpp2::ColumnDef column; column.set_name(folly::stringPrintf("col_%d", i)); nebula::cpp2::ValueType vType; - vType.set_type(cpp2::SupportedType::INT); + vType.set_type(nebula::cpp2::SupportedType::INT); column.set_type(std::move(vType)); cols.emplace_back(std::move(column)); } @@ -79,7 +79,7 @@ TEST(MetaServiceUtilsTest, TagTest) { nebula::cpp2::ColumnDef column; column.set_name(folly::stringPrintf("col_%d", i)); nebula::cpp2::ValueType vType; - vType.set_type(cpp2::SupportedType::FLOAT); + vType.set_type(nebula::cpp2::SupportedType::FLOAT); column.set_type(std::move(vType)); cols.emplace_back(std::move(column)); } @@ -87,7 +87,7 @@ TEST(MetaServiceUtilsTest, TagTest) { nebula::cpp2::ColumnDef column; column.set_name(folly::stringPrintf("col_%d", i)); nebula::cpp2::ValueType vType; - vType.set_type(cpp2::SupportedType::STRING); + vType.set_type(nebula::cpp2::SupportedType::STRING); column.set_type(std::move(vType)); cols.emplace_back(std::move(column)); } diff --git a/src/meta/test/ProcessorTest.cpp b/src/meta/test/ProcessorTest.cpp index d29a4621432..1032e5dcbc2 100644 --- a/src/meta/test/ProcessorTest.cpp +++ b/src/meta/test/ProcessorTest.cpp @@ -13,13 +13,18 @@ #include #include "meta/processors/CreateSpaceProcessor.h" #include "meta/processors/ListSpacesProcessor.h" +#include "meta/processors/ListSpacesProcessor.h" #include "meta/processors/DropSpaceProcessor.h" #include "meta/processors/RemoveHostsProcessor.h" #include "meta/processors/GetPartsAllocProcessor.h" #include "meta/processors/CreateTagProcessor.h" +#include "meta/processors/CreateEdgeProcessor.h" #include "meta/processors/RemoveTagProcessor.h" +#include "meta/processors/RemoveEdgeProcessor.h" #include "meta/processors/GetTagProcessor.h" +#include "meta/processors/GetEdgeProcessor.h" #include "meta/processors/ListTagsProcessor.h" +#include "meta/processors/ListEdgesProcessor.h" #include "meta/processors/MultiPutProcessor.h" #include "meta/processors/GetProcessor.h" #include "meta/processors/MultiGetProcessor.h" @@ -27,6 +32,7 @@ #include "meta/processors/RemoveRangeProcessor.h" #include "meta/processors/ScanProcessor.h" #include "meta/processors/AlterTagProcessor.h" +#include "meta/processors/AlterEdgeProcessor.h" namespace nebula { namespace meta { @@ -176,8 +182,8 @@ TEST(ProcessorTest, CreateSpaceTest) { } } -TEST(ProcessorTest, CreateTagsTest) { - fs::TempDir rootPath("/tmp/CreateSpaceTest.XXXXXX"); +TEST(ProcessorTest, CreateTagTest) { + fs::TempDir rootPath("/tmp/CreateTagTest.XXXXXX"); std::unique_ptr kv(TestUtils::initKV(rootPath.path())); TestUtils::createSomeHosts(kv.get()); { @@ -192,6 +198,7 @@ TEST(ProcessorTest, CreateTagsTest) { ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, resp.code); ASSERT_EQ(1, resp.get_id().get_space_id()); } + nebula::cpp2::Schema schema; decltype(schema.columns) cols; cols.emplace_back(TestUtils::columnDef(0, SupportedType::INT)); @@ -223,6 +230,93 @@ TEST(ProcessorTest, CreateTagsTest) { } } +TEST(ProcessorTest, CreateEdgeTest) { + fs::TempDir rootPath("/tmp/CreateEdgeTest.XXXXXX"); + std::unique_ptr kv(TestUtils::initKV(rootPath.path())); + TestUtils::createSomeHosts(kv.get()); + { + cpp2::CreateSpaceReq req; + req.set_space_name("first_space"); + req.set_parts_num(9); + req.set_replica_factor(1); + auto* processor = CreateSpaceProcessor::instance(kv.get()); + auto f = processor->getFuture(); + processor->process(req); + auto resp = std::move(f).get(); + ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, resp.code); + ASSERT_EQ(1, resp.get_id().get_space_id()); + } + { + // create second space + cpp2::CreateSpaceReq req; + req.set_space_name("second_space"); + req.set_parts_num(9); + req.set_replica_factor(1); + auto* processor = CreateSpaceProcessor::instance(kv.get()); + auto f = processor->getFuture(); + processor->process(req); + auto resp = std::move(f).get(); + ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, resp.code); + ASSERT_EQ(2, resp.get_id().get_space_id()); + } + + nebula::cpp2::Schema schema; + decltype(schema.columns) cols; + cols.emplace_back(TestUtils::columnDef(0, SupportedType::INT)); + cols.emplace_back(TestUtils::columnDef(1, SupportedType::FLOAT)); + cols.emplace_back(TestUtils::columnDef(2, SupportedType::STRING)); + schema.set_columns(std::move(cols)); + { + cpp2::CreateEdgeReq req; + req.set_space_id(0); + req.set_edge_name("default_edge"); + req.set_schema(schema); + auto* processor = CreateEdgeProcessor::instance(kv.get()); + auto f = processor->getFuture(); + processor->process(req); + auto resp = std::move(f).get(); + ASSERT_EQ(cpp2::ErrorCode::E_NOT_FOUND, resp.code); + } + { + // succeeded + cpp2::CreateEdgeReq req; + req.set_space_id(1); + req.set_edge_name("default_edge"); + req.set_schema(schema); + auto* processor = CreateEdgeProcessor::instance(kv.get()); + auto f = processor->getFuture(); + processor->process(req); + auto resp = std::move(f).get(); + ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, resp.code); + ASSERT_NE(0, resp.get_id().get_edge_type()); + } + { + // existed + cpp2::CreateEdgeReq req; + req.set_space_id(1); + req.set_edge_name("default_edge"); + req.set_schema(schema); + auto* processor = CreateEdgeProcessor::instance(kv.get()); + auto f = processor->getFuture(); + processor->process(req); + auto resp = std::move(f).get(); + ASSERT_EQ(cpp2::ErrorCode::E_EXISTED, resp.code); + } + { + // create same name edge in diff spaces + cpp2::CreateEdgeReq req; + req.set_space_id(2); + req.set_edge_name("default_edge"); + req.set_schema(schema); + auto* processor = CreateEdgeProcessor::instance(kv.get()); + auto f = processor->getFuture(); + processor->process(req); + auto resp = std::move(f).get(); + ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, resp.code); + ASSERT_NE(0, resp.get_id().get_edge_type()); + } +} + TEST(ProcessorTest, KVOperationTest) { fs::TempDir rootPath("/tmp/KVOperationTest.XXXXXX"); std::unique_ptr kv(TestUtils::initKV(rootPath.path())); @@ -381,7 +475,9 @@ TEST(ProcessorTest, ListOrGetTagsTest) { for (auto t = 0; t < 10; t++) { auto tag = tags[t]; ASSERT_EQ(t, tag.get_tag_id()); + ASSERT_EQ(t, tag.get_version()); ASSERT_EQ(folly::stringPrintf("tag_%d", t), tag.get_tag_name()); + ASSERT_EQ(2, tag.get_schema().columns.size()); } } @@ -408,6 +504,58 @@ TEST(ProcessorTest, ListOrGetTagsTest) { } } +TEST(ProcessorTest, ListOrGetEdgesTest) { + fs::TempDir rootPath("/tmp/ListEdgesTest.XXXXXX"); + std::unique_ptr kv(TestUtils::initKV(rootPath.path())); + TestUtils::mockEdge(kv.get(), 10); + + // test ListEdgesProcessor + { + cpp2::ListEdgesReq req; + req.set_space_id(1); + auto* processor = ListEdgesProcessor::instance(kv.get()); + auto f = processor->getFuture(); + processor->process(req); + auto resp = std::move(f).get(); + decltype(resp.edges) edges; + edges = resp.get_edges(); + ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, resp.get_code()); + ASSERT_EQ(10, edges.size()); + + for (auto t = 0; t < 10; t++) { + auto edge = edges[t]; + ASSERT_EQ(t, edge.get_edge_type()); + ASSERT_EQ(t, edge.get_version()); + ASSERT_EQ(folly::stringPrintf("edge_%d", t), edge.get_edge_name()); + ASSERT_EQ(2, edge.get_schema().columns.size()); + } + } + + // test GetEdgeProcessor + { + for (auto t = 0; t < 10; t++) { + cpp2::GetEdgeReq req; + req.set_space_id(1); + req.set_edge_type(t); + req.set_version(t); + + auto* processor = GetEdgeProcessor::instance(kv.get()); + auto f = processor->getFuture(); + processor->process(req); + auto resp = std::move(f).get(); + auto schema = resp.get_schema(); + + std::vector cols = schema.get_columns(); + ASSERT_EQ(cols.size(), 2); + for (auto i = 0; i < 2; i++) { + ASSERT_EQ(folly::stringPrintf("edge_%d_col_%d", t, i), cols[i].get_name()); + ASSERT_EQ((i < 1 ? SupportedType::INT : SupportedType::STRING), + cols[i].get_type().get_type()); + } + } + } +} + TEST(ProcessorTest, RemoveTagTest) { fs::TempDir rootPath("/tmp/RemoveTagTest.XXXXXX"); std::unique_ptr kv(TestUtils::initKV(rootPath.path())); @@ -440,6 +588,60 @@ TEST(ProcessorTest, RemoveTagTest) { } } +TEST(ProcessorTest, RemoveEdgeTest) { + fs::TempDir rootPath("/tmp/RemoveEdgeTest.XXXXXX"); + std::unique_ptr kv(TestUtils::initKV(rootPath.path())); + ASSERT_TRUE(TestUtils::assembleSpace(kv.get(), 1)); + TestUtils::mockEdge(kv.get(), 1); + // Space not exist + { + cpp2::RemoveEdgeReq req; + req.set_space_id(0); + req.set_edge_name("edge_0"); + auto* processor = RemoveEdgeProcessor::instance(kv.get()); + auto f = processor->getFuture(); + processor->process(req); + auto resp = std::move(f).get(); + ASSERT_EQ(cpp2::ErrorCode::E_NOT_FOUND, resp.get_code()); + } + // Edge not exist + { + cpp2::RemoveEdgeReq req; + req.set_space_id(1); + req.set_edge_name("edge_no"); + auto* processor = RemoveEdgeProcessor::instance(kv.get()); + auto f = processor->getFuture(); + processor->process(req); + auto resp = std::move(f).get(); + ASSERT_EQ(cpp2::ErrorCode::E_NOT_FOUND, resp.get_code()); + } + // Succeeded + { + cpp2::RemoveEdgeReq req; + req.set_space_id(1); + req.set_edge_name("edge_0"); + auto* processor = RemoveEdgeProcessor::instance(kv.get()); + auto f = processor->getFuture(); + processor->process(req); + auto resp = std::move(f).get(); + ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, resp.get_code()); + } + + // Check edge data has been deleted. + { + std::string edgeVal; + kvstore::ResultCode ret; + std::unique_ptr iter; + ret = kv.get()->get(0, 0, std::move(MetaServiceUtils::indexEdgeKey(1, "edge_1")), + &edgeVal); + ASSERT_EQ(kvstore::ResultCode::ERR_KEY_NOT_FOUND, ret); + std::string edgePrefix = "__edges__"; + ret = kv.get()->prefix(0, 0, edgePrefix, &iter); + ASSERT_EQ(kvstore::ResultCode::SUCCEEDED, ret); + ASSERT_FALSE(iter->valid()); + } +} + TEST(ProcessorTest, AlterTagTest) { fs::TempDir rootPath("/tmp/AlterTagTest.XXXXXX"); std::unique_ptr kv(TestUtils::initKV(rootPath.path())); @@ -448,7 +650,7 @@ TEST(ProcessorTest, AlterTagTest) { // Alter tag processor test { cpp2::AlterTagReq req; - std::vector items; + std::vector items; nebula::cpp2::Schema addSch; for (auto i = 0; i < 2; i++) { nebula::cpp2::ColumnDef column; @@ -468,18 +670,18 @@ TEST(ProcessorTest, AlterTagTest) { column.name = folly::stringPrintf("tag_%d_col_%d", 0, 0); dropSch.columns.emplace_back(std::move(column)); - auto addItem = cpp2::AlterTagItem(FRAGILE, - cpp2::AlterTagOp::ADD, - std::move(addSch)); - auto setItem = cpp2::AlterTagItem(FRAGILE, - cpp2::AlterTagOp::SET, - std::move(setSch)); - auto dropItem = cpp2::AlterTagItem(FRAGILE, - cpp2::AlterTagOp::DROP, - std::move(dropSch)); - items.push_back(std::move(addItem)); - items.push_back(std::move(setItem)); - items.push_back(std::move(dropItem)); + auto addItem = cpp2::AlterSchemaItem(FRAGILE, + cpp2::AlterSchemaOp::ADD, + std::move(addSch)); + auto setItem = cpp2::AlterSchemaItem(FRAGILE, + cpp2::AlterSchemaOp::CHANGE, + std::move(setSch)); + auto dropItem = cpp2::AlterSchemaItem(FRAGILE, + cpp2::AlterSchemaOp::DROP, + std::move(dropSch)); + items.emplace_back(std::move(addItem)); + items.emplace_back(std::move(setItem)); + items.emplace_back(std::move(dropItem)); req.set_space_id(1); req.set_tag_name("tag_0"); req.set_tag_items(items); @@ -527,15 +729,15 @@ TEST(ProcessorTest, AlterTagTest) { // verify ErrorCode of add { cpp2::AlterTagReq req; - std::vector items; + std::vector items; nebula::cpp2::Schema addSch; nebula::cpp2::ColumnDef column; column.name = "tag_0_col_1"; column.type.type = SupportedType::INT; addSch.columns.emplace_back(std::move(column)); - auto addItem = cpp2::AlterTagItem(FRAGILE, - cpp2::AlterTagOp::ADD, - std::move(addSch)); + auto addItem = cpp2::AlterSchemaItem(FRAGILE, + cpp2::AlterSchemaOp::ADD, + std::move(addSch)); items.push_back(std::move(addItem)); req.set_space_id(1); req.set_tag_name("tag_0"); @@ -549,15 +751,15 @@ TEST(ProcessorTest, AlterTagTest) { // verify ErrorCode of set { cpp2::AlterTagReq req; - std::vector items; + std::vector items; nebula::cpp2::Schema addSch; nebula::cpp2::ColumnDef column; column.name = "tag_0_col_2"; column.type.type = SupportedType::INT; addSch.columns.emplace_back(std::move(column)); - auto addItem = cpp2::AlterTagItem(FRAGILE, - cpp2::AlterTagOp::SET, - std::move(addSch)); + auto addItem = cpp2::AlterSchemaItem(FRAGILE, + cpp2::AlterSchemaOp::CHANGE, + std::move(addSch)); items.push_back(std::move(addItem)); req.set_space_id(1); req.set_tag_name("tag_0"); @@ -571,13 +773,13 @@ TEST(ProcessorTest, AlterTagTest) { // verify ErrorCode of drop { cpp2::AlterTagReq req; - std::vector items; + std::vector items; nebula::cpp2::Schema addSch; nebula::cpp2::ColumnDef column; column.name = "tag_0_col_2"; column.type.type = SupportedType::INT; addSch.columns.emplace_back(std::move(column)); - auto addItem = cpp2::AlterTagItem(FRAGILE, cpp2::AlterTagOp::DROP, std::move(addSch)); + auto addItem = cpp2::AlterSchemaItem(FRAGILE, cpp2::AlterSchemaOp::DROP, std::move(addSch)); items.push_back(addItem); req.set_space_id(1); req.set_tag_name("tag_0"); @@ -590,6 +792,218 @@ TEST(ProcessorTest, AlterTagTest) { } } +TEST(ProcessorTest, AlterEdgeTest) { + fs::TempDir rootPath("/tmp/AlterEdgeTest.XXXXXX"); + std::unique_ptr kv(TestUtils::initKV(rootPath.path())); + ASSERT_TRUE(TestUtils::assembleSpace(kv.get(), 1)); + TestUtils::mockEdge(kv.get(), 1); + // Drop all, then add + { + cpp2::AlterEdgeReq req; + nebula::cpp2::Schema dropSch; + nebula::cpp2::ColumnDef column; + std::vector items; + column.name = folly::stringPrintf("edge_%d_col_%d", 0, 0); + dropSch.columns.emplace_back(std::move(column)); + column.name = folly::stringPrintf("edge_%d_col_%d", 0, 1); + dropSch.columns.emplace_back(std::move(column)); + + auto dropItem = cpp2::AlterSchemaItem(FRAGILE, + cpp2::AlterSchemaOp::DROP, + std::move(dropSch)); + items.emplace_back(std::move(dropItem)); + req.set_space_id(1); + req.set_edge_name("edge_0"); + req.set_edge_items(items); + auto* processor = AlterEdgeProcessor::instance(kv.get()); + auto f = processor->getFuture(); + processor->process(req); + auto resp = std::move(f).get(); + ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, resp.get_code()); + } + { + cpp2::ListEdgesReq req; + req.set_space_id(1); + auto* processor = ListEdgesProcessor::instance(kv.get()); + auto f = processor->getFuture(); + processor->process(req); + auto resp = std::move(f).get(); + ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, resp.get_code()); + auto edges = resp.get_edges(); + ASSERT_EQ(2, edges.size()); + auto edge = edges[0].version > 0 ? edges[0] : edges[1]; + EXPECT_EQ(0, edge.get_edge_type()); + EXPECT_EQ(folly::stringPrintf("edge_%d", 0), edge.get_edge_name()); + EXPECT_EQ(1, edge.version); + EXPECT_EQ(0, edge.get_schema().columns.size()); + } + { + cpp2::AlterEdgeReq req; + nebula::cpp2::Schema addSch; + nebula::cpp2::ColumnDef column; + std::vector items; + column.name = folly::stringPrintf("edge_%d_col_%d", 0, 0); + addSch.columns.emplace_back(std::move(column)); + column.name = folly::stringPrintf("edge_%d_col_%d", 0, 1); + addSch.columns.emplace_back(std::move(column)); + + auto dropItem = cpp2::AlterSchemaItem(FRAGILE, + cpp2::AlterSchemaOp::ADD, + std::move(addSch)); + items.emplace_back(std::move(dropItem)); + req.set_space_id(1); + req.set_edge_name("edge_0"); + req.set_edge_items(items); + auto* processor = AlterEdgeProcessor::instance(kv.get()); + auto f = processor->getFuture(); + processor->process(req); + auto resp = std::move(f).get(); + ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, resp.get_code()); + } + { + cpp2::AlterEdgeReq req; + std::vector items; + nebula::cpp2::Schema addSch; + for (auto i = 0; i < 2; i++) { + nebula::cpp2::ColumnDef column; + column.name = folly::stringPrintf("edge_%d_col_%d", 0, i + 10); + column.type.type = i < 1 ? SupportedType::INT : SupportedType::STRING; + addSch.columns.emplace_back(std::move(column)); + } + nebula::cpp2::Schema setSch; + for (auto i = 0; i < 2; i++) { + nebula::cpp2::ColumnDef column; + column.name = folly::stringPrintf("edge_%d_col_%d", 0, i); + column.type.type = i < 1 ? SupportedType::BOOL : SupportedType::DOUBLE; + setSch.columns.emplace_back(std::move(column)); + } + nebula::cpp2::Schema dropSch; + nebula::cpp2::ColumnDef column; + column.name = folly::stringPrintf("edge_%d_col_%d", 0, 0); + dropSch.columns.emplace_back(std::move(column)); + + auto addItem = cpp2::AlterSchemaItem(FRAGILE, + cpp2::AlterSchemaOp::ADD, + std::move(addSch)); + auto setItem = cpp2::AlterSchemaItem(FRAGILE, + cpp2::AlterSchemaOp::CHANGE, + std::move(setSch)); + auto dropItem = cpp2::AlterSchemaItem(FRAGILE, + cpp2::AlterSchemaOp::DROP, + std::move(dropSch)); + items.emplace_back(std::move(addItem)); + items.emplace_back(std::move(setItem)); + items.emplace_back(std::move(dropItem)); + req.set_space_id(1); + req.set_edge_name("edge_0"); + req.set_edge_items(items); + auto* processor = AlterEdgeProcessor::instance(kv.get()); + auto f = processor->getFuture(); + processor->process(req); + auto resp = std::move(f).get(); + ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, resp.get_code()); + } + // Verify alter result. + { + cpp2::ListEdgesReq req; + req.set_space_id(1); + auto* processor = ListEdgesProcessor::instance(kv.get()); + auto f = processor->getFuture(); + processor->process(req); + auto resp = std::move(f).get(); + ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, resp.get_code()); + auto edges = resp.get_edges(); + ASSERT_EQ(4, edges.size()); + // Get the latest one by comparing the versions. + auto edge = edges[0].version > 0 ? edges[0] : edges[1]; + EXPECT_EQ(0, edge.get_edge_type()); + EXPECT_EQ(folly::stringPrintf("edge_%d", 0), edge.get_edge_name()); + EXPECT_EQ(3, edge.version); + + nebula::cpp2::Schema schema; + decltype(schema.columns) cols; + + nebula::cpp2::ColumnDef column; + column.name = "edge_0_col_1"; + column.type.type = SupportedType::DOUBLE; + cols.emplace_back(std::move(column)); + + column.name = "edge_0_col_10"; + column.type.type = SupportedType::INT; + cols.emplace_back(std::move(column)); + + column.name = "edge_0_col_11"; + column.type.type = SupportedType::STRING; + cols.emplace_back(std::move(column)); + schema.set_columns(std::move(cols)); + EXPECT_EQ(schema, edge.get_schema()); + } + // verify ErrorCode of add + { + cpp2::AlterEdgeReq req; + std::vector items; + nebula::cpp2::Schema addSch; + nebula::cpp2::ColumnDef column; + column.name = "edge_0_col_1"; + column.type.type = SupportedType::INT; + addSch.columns.emplace_back(std::move(column)); + auto addItem = cpp2::AlterSchemaItem(FRAGILE, + cpp2::AlterSchemaOp::ADD, + std::move(addSch)); + items.emplace_back(std::move(addItem)); + req.set_space_id(1); + req.set_edge_name("edge_0"); + req.set_edge_items(items); + auto* processor = AlterEdgeProcessor::instance(kv.get()); + auto f = processor->getFuture(); + processor->process(req); + auto resp = std::move(f).get(); + ASSERT_EQ(cpp2::ErrorCode::E_EXISTED, resp.get_code()); + } + // verify ErrorCode of set + { + cpp2::AlterEdgeReq req; + std::vector items; + nebula::cpp2::Schema addSch; + nebula::cpp2::ColumnDef column; + column.name = "edge_0_col_2"; + column.type.type = SupportedType::INT; + addSch.columns.emplace_back(std::move(column)); + auto addItem = cpp2::AlterSchemaItem(FRAGILE, + cpp2::AlterSchemaOp::CHANGE, + std::move(addSch)); + items.emplace_back(std::move(addItem)); + req.set_space_id(1); + req.set_edge_name("edge_0"); + req.set_edge_items(items); + auto* processor = AlterEdgeProcessor::instance(kv.get()); + auto f = processor->getFuture(); + processor->process(req); + auto resp = std::move(f).get(); + ASSERT_EQ(cpp2::ErrorCode::E_NOT_FOUND, resp.get_code()); + } + // verify ErrorCode of drop + { + cpp2::AlterEdgeReq req; + std::vector items; + nebula::cpp2::Schema addSch; + nebula::cpp2::ColumnDef column; + column.name = "edge_0_col_2"; + column.type.type = SupportedType::INT; + addSch.columns.emplace_back(std::move(column)); + auto addItem = cpp2::AlterSchemaItem(FRAGILE, cpp2::AlterSchemaOp::DROP, std::move(addSch)); + items.emplace_back(addItem); + req.set_space_id(1); + req.set_edge_name("edge_0"); + req.set_edge_items(items); + auto* processor = AlterEdgeProcessor::instance(kv.get()); + auto f = processor->getFuture(); + processor->process(req); + auto resp = std::move(f).get(); + ASSERT_EQ(cpp2::ErrorCode::E_NOT_FOUND, resp.get_code()); + } +} + TEST(ProcessorTest, SameNameTagsTest) { fs::TempDir rootPath("/tmp/CreateSpaceTest.XXXXXX"); std::unique_ptr kv(TestUtils::initKV(rootPath.path())); diff --git a/src/meta/test/TestUtils.h b/src/meta/test/TestUtils.h index 4ddb0b07d29..d336ad0e4ea 100644 --- a/src/meta/test/TestUtils.h +++ b/src/meta/test/TestUtils.h @@ -125,6 +125,33 @@ class TestUtils { }); } + static void mockEdge(kvstore::KVStore* kv, int32_t edgeNum, SchemaVer version = 0) { + std::vector edges; + SchemaVer ver = version; + for (auto t = 0; t < edgeNum; t++) { + EdgeType edgeType = t; + nebula::cpp2::Schema srcsch; + for (auto i = 0; i < 2; i++) { + nebula::cpp2::ColumnDef column; + column.name = folly::stringPrintf("edge_%d_col_%d", edgeType, i); + column.type.type = i < 1 ? SupportedType::INT : SupportedType::STRING; + srcsch.columns.emplace_back(std::move(column)); + } + auto edgeName = folly::stringPrintf("edge_%d", edgeType); + auto edgeTypeVal = std::string(reinterpret_cast(&edgeType), + sizeof(edgeType)); + edges.emplace_back(MetaServiceUtils::indexEdgeKey(1, edgeName), edgeTypeVal); + edges.emplace_back(MetaServiceUtils::schemaEdgeKey(1, edgeType, ver++), + MetaServiceUtils::schemaEdgeVal(edgeName, srcsch)); + } + + kv->asyncMultiPut(0, 0, std::move(edges), + [] (kvstore::ResultCode code, HostAddr leader) { + ASSERT_EQ(kvstore::ResultCode::SUCCEEDED, code); + UNUSED(leader); + }); + } + struct ServerContext { ~ServerContext() { server_->stop(); diff --git a/src/parser/MaintainSentences.h b/src/parser/MaintainSentences.h index 5fdf3928a90..c9dcf989028 100644 --- a/src/parser/MaintainSentences.h +++ b/src/parser/MaintainSentences.h @@ -128,7 +128,7 @@ class AlterTagOptItem final { public: enum OptionType : uint8_t { ADD = 0x01, - SET = 0x02, + CHANGE = 0x02, DROP = 0x03 }; diff --git a/src/parser/parser.yy b/src/parser/parser.yy index ab09fe863c0..c04ef5447c0 100644 --- a/src/parser/parser.yy +++ b/src/parser/parser.yy @@ -518,8 +518,8 @@ alter_tag_opt_item : KW_ADD L_PAREN column_spec_list R_PAREN { $$ = new AlterTagOptItem(AlterTagOptItem::ADD, $3); } - | KW_SET L_PAREN column_spec_list R_PAREN { - $$ = new AlterTagOptItem(AlterTagOptItem::SET, $3); + | KW_CHANGE L_PAREN column_spec_list R_PAREN { + $$ = new AlterTagOptItem(AlterTagOptItem::CHANGE, $3); } | KW_DROP L_PAREN column_spec_list R_PAREN { $$ = new AlterTagOptItem(AlterTagOptItem::DROP, $3); diff --git a/src/parser/test/ParserTest.cpp b/src/parser/test/ParserTest.cpp index 43510eeb5e8..7cf1bb34b4a 100644 --- a/src/parser/test/ParserTest.cpp +++ b/src/parser/test/ParserTest.cpp @@ -117,7 +117,7 @@ TEST(Parser, AlterTag) { { GQLParser parser; std::string query = "ALTER TAG person ADD (col1 int TTL = 200, col2 string), " - "SET (col3 int TTL = 200, col4 string), " + "CHANGE (col3 int TTL = 200, col4 string), " "DROP (col5, col6)"; auto result = parser.parse(query); ASSERT_TRUE(result.ok()) << result.status();