diff --git a/src/clients/meta/MetaClient.cpp b/src/clients/meta/MetaClient.cpp index 98504ab0782..52d6e94e9e8 100644 --- a/src/clients/meta/MetaClient.cpp +++ b/src/clients/meta/MetaClient.cpp @@ -1204,6 +1204,25 @@ folly::Future>> MetaClient::listHosts(cpp2: return future; } +folly::Future> MetaClient::alterSpace(const std::string& spaceName, + meta::cpp2::AlterSpaceOp op, + const std::vector& paras) { + cpp2::AlterSpaceReq req; + req.set_op(op); + req.set_space_name(spaceName); + req.set_paras(paras); + folly::Promise> promise; + auto future = promise.getFuture(); + getResponse( + std::move(req), + [](auto client, auto request) { return client->future_alterSpace(request); }, + [](cpp2::ExecResp&& resp) -> bool { + return resp.get_code() == nebula::cpp2::ErrorCode::SUCCEEDED; + }, + std::move(promise)); + return future; +} + folly::Future>> MetaClient::listParts( GraphSpaceID spaceId, std::vector partIds) { cpp2::ListPartsReq req; diff --git a/src/clients/meta/MetaClient.h b/src/clients/meta/MetaClient.h index 80f975e0181..abaa817cb85 100644 --- a/src/clients/meta/MetaClient.h +++ b/src/clients/meta/MetaClient.h @@ -260,6 +260,10 @@ class MetaClient { folly::Future>> listHosts( cpp2::ListHostType type = cpp2::ListHostType::ALLOC); + folly::Future> alterSpace(const std::string& spaceName, + meta::cpp2::AlterSpaceOp op, + const std::vector& paras); + folly::Future>> listParts(GraphSpaceID spaceId, std::vector partIds); diff --git a/src/graph/executor/Executor.cpp b/src/graph/executor/Executor.cpp index d52e9bd60ca..c0be563a5d3 100644 --- a/src/graph/executor/Executor.cpp +++ b/src/graph/executor/Executor.cpp @@ -519,6 +519,9 @@ Executor *Executor::makeExecutor(QueryContext *qctx, const PlanNode *node) { case PlanNode::Kind::kAppendVertices: { return pool->add(new AppendVerticesExecutor(node, qctx)); } + case PlanNode::Kind::kAlterSpace: { + return pool->add(new AlterSpaceExecutor(node, qctx)); + } case PlanNode::Kind::kUnknown: { LOG(FATAL) << "Unknown plan node kind " << static_cast(node->kind()); break; diff --git a/src/graph/executor/admin/SpaceExecutor.cpp b/src/graph/executor/admin/SpaceExecutor.cpp index f2a452482fc..0a4cf763830 100644 --- a/src/graph/executor/admin/SpaceExecutor.cpp +++ b/src/graph/executor/admin/SpaceExecutor.cpp @@ -257,5 +257,22 @@ folly::Future ShowCreateSpaceExecutor::execute() { .build()); }); } + +folly::Future AlterSpaceExecutor::execute() { + SCOPED_TIMER(&execTime_); + auto *asnode = asNode(node()); + return qctx() + ->getMetaClient() + ->alterSpace(asnode->getSpaceName(), asnode->getAlterSpaceOp(), asnode->getParas()) + .via(runner()) + .thenValue([this](StatusOr &&resp) { + SCOPED_TIMER(&execTime_); + if (!resp.ok()) { + LOG(ERROR) << resp.status().toString(); + return std::move(resp).status(); + } + return Status::OK(); + }); +} } // namespace graph } // namespace nebula diff --git a/src/graph/executor/admin/SpaceExecutor.h b/src/graph/executor/admin/SpaceExecutor.h index e0c917d93f0..d3b338af1dd 100644 --- a/src/graph/executor/admin/SpaceExecutor.h +++ b/src/graph/executor/admin/SpaceExecutor.h @@ -58,6 +58,14 @@ class ShowCreateSpaceExecutor final : public Executor { folly::Future execute() override; }; + +class AlterSpaceExecutor final : public Executor { + public: + AlterSpaceExecutor(const PlanNode *node, QueryContext *qctx) + : Executor("AlterSpaceExecutor", node, qctx) {} + + folly::Future execute() override; +}; } // namespace graph } // namespace nebula diff --git a/src/graph/planner/plan/Admin.h b/src/graph/planner/plan/Admin.h index c95ecfadf2f..74cac7b0a7b 100644 --- a/src/graph/planner/plan/Admin.h +++ b/src/graph/planner/plan/Admin.h @@ -194,6 +194,38 @@ class DropSpace final : public SingleDependencyNode { bool ifExists_; }; +class AlterSpace final : public SingleDependencyNode { + public: + static AlterSpace* make(QueryContext* qctx, + PlanNode* input, + const std::string& spaceName, + meta::cpp2::AlterSpaceOp op, + const std::vector& paras) { + return qctx->objPool()->add(new AlterSpace(qctx, input, spaceName, op, paras)); + } + const std::string& getSpaceName() const { return spaceName_; } + + meta::cpp2::AlterSpaceOp getAlterSpaceOp() const { return op_; } + + const std::vector& getParas() const { return paras_; } + + private: + AlterSpace(QueryContext* qctx, + PlanNode* input, + const std::string& spaceName, + meta::cpp2::AlterSpaceOp op, + const std::vector& paras) + : SingleDependencyNode(qctx, Kind::kAlterSpace, input), + spaceName_(spaceName), + op_(op), + paras_(paras) {} + + private: + std::string spaceName_; + meta::cpp2::AlterSpaceOp op_; + std::vector paras_; +}; + class DescSpace final : public SingleDependencyNode { public: static DescSpace* make(QueryContext* qctx, PlanNode* input, std::string spaceName) { diff --git a/src/graph/planner/plan/PlanNode.cpp b/src/graph/planner/plan/PlanNode.cpp index 6ac02659611..1a2c210da76 100644 --- a/src/graph/planner/plan/PlanNode.cpp +++ b/src/graph/planner/plan/PlanNode.cpp @@ -174,6 +174,8 @@ const char* PlanNode::toString(PlanNode::Kind kind) { return "DropEdge"; case Kind::kShowSpaces: return "ShowSpaces"; + case Kind::kAlterSpace: + return "AlterSpaces"; case Kind::kShowTags: return "ShowTags"; case Kind::kShowEdges: diff --git a/src/graph/planner/plan/PlanNode.h b/src/graph/planner/plan/PlanNode.h index 08ab4ae0466..c12fe92d909 100644 --- a/src/graph/planner/plan/PlanNode.h +++ b/src/graph/planner/plan/PlanNode.h @@ -92,6 +92,7 @@ class PlanNode { kDropSpace, kDropTag, kDropEdge, + kAlterSpace, // index related kCreateTagIndex, diff --git a/src/graph/service/PermissionCheck.cpp b/src/graph/service/PermissionCheck.cpp index 13b5859fbc7..517e6373790 100644 --- a/src/graph/service/PermissionCheck.cpp +++ b/src/graph/service/PermissionCheck.cpp @@ -51,6 +51,7 @@ Status PermissionCheck::permissionCheck(ClientSession *session, return Status::OK(); } case Sentence::Kind::kCreateSpace: + case Sentence::Kind::kAlterSpace: case Sentence::Kind::kCreateSpaceAs: case Sentence::Kind::kDropSpace: case Sentence::Kind::kCreateSnapshot: diff --git a/src/graph/validator/AdminValidator.cpp b/src/graph/validator/AdminValidator.cpp index fb32c5d21ad..fe6d72073a6 100644 --- a/src/graph/validator/AdminValidator.cpp +++ b/src/graph/validator/AdminValidator.cpp @@ -163,6 +163,17 @@ Status CreateSpaceAsValidator::toPlan() { return Status::OK(); } +Status AlterSpaceValidator::validateImpl() { return Status::OK(); } + +Status AlterSpaceValidator::toPlan() { + auto sentence = static_cast(sentence_); + auto *doNode = AlterSpace::make( + qctx_, nullptr, sentence->spaceName(), sentence->alterSpaceOp(), sentence->paras()); + root_ = doNode; + tail_ = root_; + return Status::OK(); +} + Status DescSpaceValidator::validateImpl() { return Status::OK(); } Status DescSpaceValidator::toPlan() { diff --git a/src/graph/validator/AdminValidator.h b/src/graph/validator/AdminValidator.h index 0ae1864b9f3..f0a03ac9bf1 100644 --- a/src/graph/validator/AdminValidator.h +++ b/src/graph/validator/AdminValidator.h @@ -48,6 +48,18 @@ class CreateSpaceAsValidator final : public Validator { std::string newSpaceName_; }; +class AlterSpaceValidator final : public Validator { + public: + AlterSpaceValidator(Sentence* sentence, QueryContext* context) : Validator(sentence, context) { + noSpaceRequired_ = true; + } + + private: + Status validateImpl() override; + + Status toPlan() override; +}; + class DescSpaceValidator final : public Validator { public: DescSpaceValidator(Sentence* sentence, QueryContext* context) : Validator(sentence, context) { diff --git a/src/graph/validator/Validator.cpp b/src/graph/validator/Validator.cpp index 022e60a023c..355f6217dcd 100644 --- a/src/graph/validator/Validator.cpp +++ b/src/graph/validator/Validator.cpp @@ -252,6 +252,8 @@ std::unique_ptr Validator::makeValidator(Sentence* sentence, QueryCon return std::make_unique(sentence, context); case Sentence::Kind::kKillQuery: return std::make_unique(sentence, context); + case Sentence::Kind::kAlterSpace: + return std::make_unique(sentence, context); case Sentence::Kind::kUnknown: case Sentence::Kind::kReturn: { // nothing diff --git a/src/interface/meta.thrift b/src/interface/meta.thrift index d870f0ef8e2..1107f7be59b 100644 --- a/src/interface/meta.thrift +++ b/src/interface/meta.thrift @@ -203,6 +203,16 @@ struct ExecResp { 3: common.HostAddr leader, } +enum AlterSpaceOp { + ADD_ZONE = 0x01, +} (cpp.enum_strict) + +struct AlterSpaceReq { + 1: binary space_name, + 2: AlterSpaceOp op, + 3: list paras, +} + // Job related data structures enum AdminJobOp { ADD = 0x01, @@ -1133,6 +1143,7 @@ service MetaService { ExecResp dropSpace(1: DropSpaceReq req); GetSpaceResp getSpace(1: GetSpaceReq req); ListSpacesResp listSpaces(1: ListSpacesReq req); + ExecResp alterSpace(1: AlterSpaceReq req); ExecResp createSpaceAs(1: CreateSpaceAsReq req); diff --git a/src/meta/CMakeLists.txt b/src/meta/CMakeLists.txt index 0858850fdac..7186067dde4 100644 --- a/src/meta/CMakeLists.txt +++ b/src/meta/CMakeLists.txt @@ -15,6 +15,7 @@ nebula_add_library( processors/parts/ListSpacesProcessor.cpp processors/parts/DropSpaceProcessor.cpp processors/parts/GetPartsAllocProcessor.cpp + processors/parts/AlterSpaceProcessor.cpp processors/schema/CreateTagProcessor.cpp processors/schema/AlterTagProcessor.cpp processors/schema/GetTagProcessor.cpp diff --git a/src/meta/MetaServiceHandler.cpp b/src/meta/MetaServiceHandler.cpp index cc78fcbf2c6..729d9dedf51 100644 --- a/src/meta/MetaServiceHandler.cpp +++ b/src/meta/MetaServiceHandler.cpp @@ -41,6 +41,7 @@ #include "meta/processors/kv/RemoveRangeProcessor.h" #include "meta/processors/kv/ScanProcessor.h" #include "meta/processors/listener/ListenerProcessor.h" +#include "meta/processors/parts/AlterSpaceProcessor.h" #include "meta/processors/parts/CreateSpaceAsProcessor.h" #include "meta/processors/parts/CreateSpaceProcessor.h" #include "meta/processors/parts/DropSpaceProcessor.h" @@ -85,6 +86,12 @@ folly::Future MetaServiceHandler::future_createSpace( RETURN_FUTURE(processor); } +folly::Future MetaServiceHandler::future_alterSpace( + const cpp2::AlterSpaceReq& req) { + auto* processor = AlterSpaceProcessor::instance(kvstore_); + RETURN_FUTURE(processor); +} + folly::Future MetaServiceHandler::future_createSpaceAs( const cpp2::CreateSpaceAsReq& req) { auto* processor = CreateSpaceAsProcessor::instance(kvstore_); diff --git a/src/meta/MetaServiceHandler.h b/src/meta/MetaServiceHandler.h index a1d7332fbf8..1bc7bf34f3f 100644 --- a/src/meta/MetaServiceHandler.h +++ b/src/meta/MetaServiceHandler.h @@ -30,6 +30,8 @@ class MetaServiceHandler final : public cpp2::MetaServiceSvIf { * */ folly::Future future_createSpace(const cpp2::CreateSpaceReq& req) override; + folly::Future future_alterSpace(const cpp2::AlterSpaceReq& req) override; + folly::Future future_createSpaceAs(const cpp2::CreateSpaceAsReq& req) override; folly::Future future_dropSpace(const cpp2::DropSpaceReq& req) override; diff --git a/src/meta/processors/parts/AlterSpaceProcessor.cpp b/src/meta/processors/parts/AlterSpaceProcessor.cpp new file mode 100644 index 00000000000..d0a9bbfe7e8 --- /dev/null +++ b/src/meta/processors/parts/AlterSpaceProcessor.cpp @@ -0,0 +1,92 @@ +/* Copyright (c) 2018 vesoft inc. All rights reserved. + * + * This source code is licensed under Apache 2.0 License. + */ + +#include "meta/processors/parts/AlterSpaceProcessor.h" + +namespace nebula { +namespace meta { +void AlterSpaceProcessor::process(const cpp2::AlterSpaceReq& req) { + const std::vector& zones = req.get_paras(); + const std::string& spaceName = req.get_space_name(); + cpp2::AlterSpaceOp op = req.get_op(); + switch (op) { + case cpp2::AlterSpaceOp::ADD_ZONE: { + nebula::cpp2::ErrorCode ret = addZones(spaceName, zones); + if (ret != nebula::cpp2::ErrorCode::SUCCEEDED) { + handleErrorCode(ret); + onFinished(); + return; + } + break; + } + default: + break; + } + handleErrorCode(nebula::cpp2::ErrorCode::SUCCEEDED); + onFinished(); +} + +nebula::cpp2::ErrorCode AlterSpaceProcessor::addZones(const std::string& spaceName, + const std::vector& zones) { + auto spaceRet = getSpaceId(spaceName); + if (!nebula::ok(spaceRet)) { + auto retCode = nebula::error(spaceRet); + return retCode; + } + auto spaceId = nebula::value(spaceRet); + std::string spaceKey = MetaKeyUtils::spaceKey(spaceId); + std::string spaceVal; + nebula::cpp2::ErrorCode retCode = + kvstore_->get(kDefaultSpaceId, kDefaultPartId, spaceKey, &spaceVal); + if (retCode != nebula::cpp2::ErrorCode::SUCCEEDED) { + return retCode; + } + meta::cpp2::SpaceDesc properties = MetaKeyUtils::parseSpace(spaceVal); + const std::vector& curZones = properties.get_zone_names(); + std::set zm; + for (const std::string& z : curZones) { + zm.insert(z); + } + std::vector newZones = curZones; + newZones.reserve(curZones.size() + zones.size()); + for (const std::string& z : zones) { + std::string zoneKey = MetaKeyUtils::zoneKey(z); + std::string zoneVal; + nebula::cpp2::ErrorCode zoneRet = + kvstore_->get(kDefaultSpaceId, kDefaultPartId, zoneKey, &zoneVal); + if (zoneRet != nebula::cpp2::ErrorCode::SUCCEEDED) { + return zoneRet == nebula::cpp2::ErrorCode::E_KEY_NOT_FOUND + ? nebula::cpp2::ErrorCode::E_ZONE_NOT_FOUND + : zoneRet; + } + if (zm.count(z)) { + return nebula::cpp2::ErrorCode::E_CONFLICT; + } + newZones.emplace_back(z); + } + properties.set_zone_names(newZones); + std::vector data; + data.emplace_back(MetaKeyUtils::spaceKey(spaceId), MetaKeyUtils::spaceVal(properties)); + folly::Baton baton; + auto ret = nebula::cpp2::ErrorCode::SUCCEEDED; + kvstore_->asyncMultiPut(kDefaultSpaceId, + kDefaultPartId, + std::move(data), + [&ret, &baton](nebula::cpp2::ErrorCode code) { + if (nebula::cpp2::ErrorCode::SUCCEEDED != code) { + ret = code; + LOG(INFO) << "Put data error on meta server"; + } + baton.post(); + }); + baton.wait(); + if (ret != nebula::cpp2::ErrorCode::SUCCEEDED) { + return ret; + } + return nebula::cpp2::ErrorCode::SUCCEEDED; +} + +} // namespace meta +} // namespace nebula diff --git a/src/meta/processors/parts/AlterSpaceProcessor.h b/src/meta/processors/parts/AlterSpaceProcessor.h new file mode 100644 index 00000000000..90c8bb9799b --- /dev/null +++ b/src/meta/processors/parts/AlterSpaceProcessor.h @@ -0,0 +1,33 @@ +/* Copyright (c) 2018 vesoft inc. All rights reserved. + * + * This source code is licensed under Apache 2.0 License. + */ + +#ifndef NEBULA_GRAPH_ALTERSPACEPROCESSOR_H +#define NEBULA_GRAPH_ALTERSPACEPROCESSOR_H + +#include "meta/processors/BaseProcessor.h" + +namespace nebula { +namespace meta { +class AlterSpaceProcessor : public BaseProcessor { + public: + static AlterSpaceProcessor* instance(kvstore::KVStore* kvstore) { + return new AlterSpaceProcessor(kvstore); + } + + void process(const cpp2::AlterSpaceReq& req); + + private: + nebula::cpp2::ErrorCode addZones(const std::string& spaceName, + const std::vector& zones); + + private: + explicit AlterSpaceProcessor(kvstore::KVStore* kvstore) + : BaseProcessor(kvstore) {} +}; + +} // namespace meta +} // namespace nebula + +#endif // NEBULA_GRAPH_ALTERSPACEPROCESSOR_H diff --git a/src/meta/test/ProcessorTest.cpp b/src/meta/test/ProcessorTest.cpp index 417e279f9ea..20b5fef18e9 100644 --- a/src/meta/test/ProcessorTest.cpp +++ b/src/meta/test/ProcessorTest.cpp @@ -13,6 +13,7 @@ #include "meta/processors/kv/RemoveProcessor.h" #include "meta/processors/kv/RemoveRangeProcessor.h" #include "meta/processors/kv/ScanProcessor.h" +#include "meta/processors/parts/AlterSpaceProcessor.h" #include "meta/processors/parts/CreateSpaceProcessor.h" #include "meta/processors/parts/DropSpaceProcessor.h" #include "meta/processors/parts/GetPartsAllocProcessor.h" @@ -3640,6 +3641,68 @@ TEST(ProcessorTest, RenameZoneTest) { } } +TEST(ProcessorTest, AlterSpaceTest) { + fs::TempDir rootPath("/tmp/RenameZoneTest.XXXXXX"); + auto store = MockCluster::initMetaKV(rootPath.path()); + auto* kv = dynamic_cast(store.get()); + TestUtils::assembleSpaceWithZone(kv, 1, 8, 1, 8, 8); + TestUtils::assembleZone(kv, + {{"9", {HostAddr("127.0.0.1", 9)}}, + {"10", {HostAddr("127.0.0.1", 10)}}, + {"11", {HostAddr("127.0.0.1", 11)}}}); + { + AlterSpaceProcessor* processor = AlterSpaceProcessor::instance(kv); + meta::cpp2::AlterSpaceReq req; + req.set_space_name("test_space"); + req.set_op(meta::cpp2::AlterSpaceOp::ADD_ZONE); + req.set_paras({"12"}); + auto f = processor->getFuture(); + processor->process(req); + auto resp = std::move(f).get(); + ASSERT_EQ(nebula::cpp2::ErrorCode::E_ZONE_NOT_FOUND, resp.get_code()); + } + { + AlterSpaceProcessor* processor = AlterSpaceProcessor::instance(kv); + meta::cpp2::AlterSpaceReq req; + req.set_space_name("aaa"); + req.set_op(meta::cpp2::AlterSpaceOp::ADD_ZONE); + req.set_paras({"9"}); + auto f = processor->getFuture(); + processor->process(req); + auto resp = std::move(f).get(); + ASSERT_EQ(nebula::cpp2::ErrorCode::E_SPACE_NOT_FOUND, resp.get_code()); + } + { + AlterSpaceProcessor* processor = AlterSpaceProcessor::instance(kv); + meta::cpp2::AlterSpaceReq req; + req.set_space_name("test_space"); + req.set_op(meta::cpp2::AlterSpaceOp::ADD_ZONE); + req.set_paras({"8"}); + auto f = processor->getFuture(); + processor->process(req); + auto resp = std::move(f).get(); + ASSERT_EQ(nebula::cpp2::ErrorCode::E_CONFLICT, resp.get_code()); + } + { + AlterSpaceProcessor* processor = AlterSpaceProcessor::instance(kv); + meta::cpp2::AlterSpaceReq req; + req.set_space_name("test_space"); + req.set_op(meta::cpp2::AlterSpaceOp::ADD_ZONE); + req.set_paras({"9", "10", "11"}); + auto f = processor->getFuture(); + processor->process(req); + auto resp = std::move(f).get(); + ASSERT_EQ(nebula::cpp2::ErrorCode::SUCCEEDED, resp.get_code()); + std::string spaceKey = MetaKeyUtils::spaceKey(1); + std::string spaceVal; + kv->get(kDefaultSpaceId, kDefaultPartId, spaceKey, &spaceVal); + meta::cpp2::SpaceDesc properties = MetaKeyUtils::parseSpace(spaceVal); + const std::vector& zones = properties.get_zone_names(); + const std::vector& res = {"1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11"}; + ASSERT_EQ(res, zones); + } +} + } // namespace meta } // namespace nebula diff --git a/src/parser/AdminSentences.cpp b/src/parser/AdminSentences.cpp index cd774e27894..2d9b0319847 100644 --- a/src/parser/AdminSentences.cpp +++ b/src/parser/AdminSentences.cpp @@ -112,6 +112,15 @@ std::string DropSpaceSentence::toString() const { return folly::stringPrintf("DROP SPACE %s", spaceName_.get()->c_str()); } +std::string AlterSpaceSentence::toString() const { + std::string zones = paras_.front(); + for (size_t i = 1; i < paras_.size(); i++) { + zones += "," + paras_[i]; + } + return folly::stringPrintf( + "ALTER SPACE %s ADD ZONE %s", spaceName_.get()->c_str(), zones.c_str()); +} + std::string DescribeSpaceSentence::toString() const { return folly::stringPrintf("DESCRIBE SPACE %s", spaceName_.get()->c_str()); } diff --git a/src/parser/AdminSentences.h b/src/parser/AdminSentences.h index b654700066c..93638e89de7 100644 --- a/src/parser/AdminSentences.h +++ b/src/parser/AdminSentences.h @@ -369,6 +369,28 @@ class DropSpaceSentence final : public DropSentence { std::unique_ptr clusterName_; }; +class AlterSpaceSentence final : public Sentence { + public: + AlterSpaceSentence(std::string* spaceName, meta::cpp2::AlterSpaceOp op) + : op_(op), spaceName_(spaceName) { + kind_ = Kind::kAlterSpace; + } + void addPara(const std::string& para) { paras_.push_back(para); } + + std::string spaceName() const { return *spaceName_; } + + const std::vector& paras() const { return paras_; } + + meta::cpp2::AlterSpaceOp alterSpaceOp() const { return op_; } + + std::string toString() const override; + + private: + meta::cpp2::AlterSpaceOp op_; + std::unique_ptr spaceName_; + std::vector paras_; +}; + class DescribeSpaceSentence final : public Sentence { public: explicit DescribeSpaceSentence(std::string* spaceName) { diff --git a/src/parser/Sentence.h b/src/parser/Sentence.h index 4e27150d368..b007149bc07 100644 --- a/src/parser/Sentence.h +++ b/src/parser/Sentence.h @@ -132,6 +132,7 @@ class Sentence { kShowQueries, kKillQuery, kShowMetaLeader, + kAlterSpace, }; Kind kind() const { return kind_; } diff --git a/src/parser/parser.yy b/src/parser/parser.yy index 019336ccbb3..c6efbbf4b8e 100644 --- a/src/parser/parser.yy +++ b/src/parser/parser.yy @@ -347,7 +347,7 @@ static constexpr size_t kCommentLengthLimit = 256; %type query_unique_identifier %type maintain_sentence -%type create_space_sentence describe_space_sentence drop_space_sentence +%type create_space_sentence describe_space_sentence drop_space_sentence alter_space_sentence %type create_tag_sentence create_edge_sentence %type alter_tag_sentence alter_edge_sentence %type drop_tag_sentence drop_edge_sentence @@ -3332,6 +3332,18 @@ zone_name_list } ; +alter_space_sentence + : KW_ALTER KW_SPACE name_label KW_ADD KW_ZONE name_label_list { + auto sentence = new AlterSpaceSentence($3, meta::cpp2::AlterSpaceOp::ADD_ZONE); + NameLabelList* nl = $6; + std::vector vec = nl->labels(); + for(const std::string *para:vec) { + sentence->addPara(*para); + } + delete nl; + $$ = sentence; + } + create_space_sentence : KW_CREATE KW_SPACE opt_if_not_exists name_label { auto sentence = new CreateSpaceSentence($4, $3); @@ -3670,6 +3682,7 @@ mutate_sentence maintain_sentence : create_space_sentence { $$ = $1; } | describe_space_sentence { $$ = $1; } + | alter_space_sentence { $$ = $1; } | drop_space_sentence { $$ = $1; } | create_tag_sentence { $$ = $1; } | create_edge_sentence { $$ = $1; }