Skip to content

Commit

Permalink
Added "if not exists" option to create space/tag/edge. (vesoft-inc#1379)
Browse files Browse the repository at this point in the history
* Added "if not exists" option to create space/tag/edge.

This option allows you to check if the space/tag/edge
that you create already exists in the database.

example:

create space if not exists testspace
create tag if not exists testtag()
create edge if not exists edge1()

* address yixinglu's comments.
  • Loading branch information
monadbobo authored and dutor committed Dec 5, 2019
1 parent 7b2dfa5 commit 4b310b8
Show file tree
Hide file tree
Showing 15 changed files with 149 additions and 61 deletions.
2 changes: 1 addition & 1 deletion src/graph/CreateEdgeExecutor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ void CreateEdgeExecutor::execute() {
auto *name = sentence_->name();
auto spaceId = ectx()->rctx()->session()->space();

auto future = mc->createEdgeSchema(spaceId, *name, schema_);
auto future = mc->createEdgeSchema(spaceId, *name, schema_, sentence_->isIfNotExist());
auto *runner = ectx()->rctx()->runner();
auto cb = [this] (auto &&resp) {
if (!resp.ok()) {
Expand Down
3 changes: 2 additions & 1 deletion src/graph/CreateSpaceExecutor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@ Status CreateSpaceExecutor::prepare() {


void CreateSpaceExecutor::execute() {
auto future = ectx()->getMetaClient()->createSpace(*spaceName_, partNum_, replicaFactor_);
auto future = ectx()->getMetaClient()->createSpace(
*spaceName_, partNum_, replicaFactor_, sentence_->isIfNotExist());
auto *runner = ectx()->rctx()->runner();

auto cb = [this] (auto &&resp) {
Expand Down
2 changes: 1 addition & 1 deletion src/graph/CreateTagExecutor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ void CreateTagExecutor::execute() {
auto *name = sentence_->name();
auto spaceId = ectx()->rctx()->session()->space();

auto future = mc->createTagSchema(spaceId, *name, schema_);
auto future = mc->createTagSchema(spaceId, *name, schema_, sentence_->isIfNotExist());
auto *runner = ectx()->rctx()->runner();
auto cb = [this] (auto &&resp) {
if (!resp.ok()) {
Expand Down
18 changes: 18 additions & 0 deletions src/graph/test/SchemaTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,12 @@ TEST_F(SchemaTest, metaCommunication) {
auto code = client->execute(query, resp);
ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code);
}
{
std::string query = "CREATE SPACE IF NOT EXISTS default_space";
cpp2::ExecutionResponse resp;
auto code = client->execute(query, resp);
ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code);
}
// show parts of default_space
{
cpp2::ExecutionResponse resp;
Expand Down Expand Up @@ -172,6 +178,12 @@ TEST_F(SchemaTest, metaCommunication) {
auto code = client->execute(query, resp);
ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code);
}
{
cpp2::ExecutionResponse resp;
std::string query = "CREATE TAG IF NOT EXISTS tag1()";
auto code = client->execute(query, resp);
ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code);
}
{
cpp2::ExecutionResponse resp;
std::string query = "DESCRIBE TAG tag1";
Expand Down Expand Up @@ -376,6 +388,12 @@ TEST_F(SchemaTest, metaCommunication) {
auto code = client->execute(query, resp);
ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code);
}
{
cpp2::ExecutionResponse resp;
std::string query = "CREATE EDGE IF NOT EXISTS edge1()";
auto code = client->execute(query, resp);
ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code);
}
{
cpp2::ExecutionResponse resp;
std::string query = "DESCRIBE EDGE edge1";
Expand Down
3 changes: 3 additions & 0 deletions src/interface/meta.thrift
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,7 @@ struct ExecResp {
// Graph space related operations.
struct CreateSpaceReq {
1: SpaceProperties properties,
2: bool if_not_exists,
}

struct DropSpaceReq {
Expand Down Expand Up @@ -193,6 +194,7 @@ struct CreateTagReq {
1: common.GraphSpaceID space_id,
2: string tag_name,
3: common.Schema schema,
4: bool if_not_exists,
}

struct AlterTagReq {
Expand Down Expand Up @@ -235,6 +237,7 @@ struct CreateEdgeReq {
1: common.GraphSpaceID space_id,
2: string edge_name,
3: common.Schema schema,
4: bool if_not_exists,
}

struct AlterEdgeReq {
Expand Down
37 changes: 22 additions & 15 deletions src/meta/client/MetaClient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -530,14 +530,17 @@ void MetaClient::diff(const LocalCache& oldCache, const LocalCache& newCache) {

/// ================================== public methods =================================

folly::Future<StatusOr<GraphSpaceID>>
MetaClient::createSpace(std::string name, int32_t partsNum, int32_t replicaFactor) {
folly::Future<StatusOr<GraphSpaceID>> MetaClient::createSpace(std::string name,
int32_t partsNum,
int32_t replicaFactor,
bool ifNotExists) {
cpp2::SpaceProperties properties;
properties.set_space_name(std::move(name));
properties.set_partition_num(partsNum);
properties.set_replica_factor(replicaFactor);
cpp2::CreateSpaceReq req;
req.set_properties(std::move(properties));
req.set_if_not_exists(ifNotExists);
folly::Promise<StatusOr<GraphSpaceID>> promise;
auto future = promise.getFuture();
getResponse(std::move(req), [] (auto client, auto request) {
Expand All @@ -548,7 +551,6 @@ MetaClient::createSpace(std::string name, int32_t partsNum, int32_t replicaFacto
return future;
}


folly::Future<StatusOr<std::vector<SpaceIdName>>> MetaClient::listSpaces() {
cpp2::ListSpacesReq req;
folly::Promise<StatusOr<std::vector<SpaceIdName>>> promise;
Expand Down Expand Up @@ -897,12 +899,15 @@ StatusOr<int32_t> MetaClient::partsNum(GraphSpaceID spaceId) {
return it->second->partsAlloc_.size();
}

folly::Future<StatusOr<TagID>>
MetaClient::createTagSchema(GraphSpaceID spaceId, std::string name, nebula::cpp2::Schema schema) {
folly::Future<StatusOr<TagID>> MetaClient::createTagSchema(GraphSpaceID spaceId,
std::string name,
nebula::cpp2::Schema schema,
bool ifNotExists) {
cpp2::CreateTagReq req;
req.set_space_id(std::move(spaceId));
req.set_tag_name(std::move(name));
req.set_schema(std::move(schema));
req.set_if_not_exists(ifNotExists);
folly::Promise<StatusOr<TagID>> promise;
auto future = promise.getFuture();
getResponse(std::move(req), [] (auto client, auto request) {
Expand All @@ -913,7 +918,6 @@ MetaClient::createTagSchema(GraphSpaceID spaceId, std::string name, nebula::cpp2
return future;
}


folly::Future<StatusOr<TagID>>
MetaClient::alterTagSchema(GraphSpaceID spaceId,
std::string name,
Expand Down Expand Up @@ -982,24 +986,27 @@ MetaClient::getTagSchema(int32_t spaceId, std::string name, int64_t version) {
return future;
}


folly::Future<StatusOr<EdgeType>>
MetaClient::createEdgeSchema(GraphSpaceID spaceId, std::string name, nebula::cpp2::Schema schema) {
folly::Future<StatusOr<EdgeType>> MetaClient::createEdgeSchema(GraphSpaceID spaceId,
std::string name,
nebula::cpp2::Schema schema,
bool ifNotExists) {
cpp2::CreateEdgeReq req;
req.set_space_id(std::move(spaceId));
req.set_edge_name(std::move(name));
req.set_schema(schema);
req.set_if_not_exists(ifNotExists);

folly::Promise<StatusOr<EdgeType>> promise;
auto future = promise.getFuture();
getResponse(std::move(req), [] (auto client, auto request) {
return client->future_createEdge(request);
}, [] (cpp2::ExecResp&& resp) -> EdgeType {
return resp.get_id().get_edge_type();
}, std::move(promise), true);
getResponse(
std::move(req),
[](auto client, auto request) { return client->future_createEdge(request); },
[](cpp2::ExecResp&& resp) -> EdgeType { return resp.get_id().get_edge_type(); },
std::move(promise),
true);
return future;
}


folly::Future<StatusOr<bool>>
MetaClient::alterEdgeSchema(GraphSpaceID spaceId,
std::string name,
Expand Down
18 changes: 12 additions & 6 deletions src/meta/client/MetaClient.h
Original file line number Diff line number Diff line change
Expand Up @@ -136,8 +136,10 @@ class MetaClient {
/**
* TODO(dangleptr): Use one struct to represent space description.
* */
folly::Future<StatusOr<GraphSpaceID>>
createSpace(std::string name, int32_t partsNum, int32_t replicaFactor);
folly::Future<StatusOr<GraphSpaceID>> createSpace(std::string name,
int32_t partsNum,
int32_t replicaFactor,
bool ifNotExists = false);

folly::Future<StatusOr<std::vector<SpaceIdName>>>
listSpaces();
Expand All @@ -158,8 +160,10 @@ class MetaClient {
getPartsAlloc(GraphSpaceID spaceId);

// Operations for schema
folly::Future<StatusOr<TagID>>
createTagSchema(GraphSpaceID spaceId, std::string name, nebula::cpp2::Schema schema);
folly::Future<StatusOr<TagID>> createTagSchema(GraphSpaceID spaceId,
std::string name,
nebula::cpp2::Schema schema,
bool ifNotExists = false);

folly::Future<StatusOr<TagID>>
alterTagSchema(GraphSpaceID spaceId,
Expand All @@ -177,8 +181,10 @@ class MetaClient {
folly::Future<StatusOr<nebula::cpp2::Schema>>
getTagSchema(int32_t spaceId, std::string name, SchemaVer version = -1);

folly::Future<StatusOr<EdgeType>>
createEdgeSchema(GraphSpaceID spaceId, std::string name, nebula::cpp2::Schema schema);
folly::Future<StatusOr<EdgeType>> createEdgeSchema(GraphSpaceID spaceId,
std::string name,
nebula::cpp2::Schema schema,
bool ifNotExists = false);

folly::Future<StatusOr<bool>>
alterEdgeSchema(GraphSpaceID spaceId,
Expand Down
13 changes: 10 additions & 3 deletions src/meta/processors/partsMan/CreateSpaceProcessor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,17 @@ void CreateSpaceProcessor::process(const cpp2::CreateSpaceReq& req) {
auto properties = req.get_properties();
auto spaceRet = getSpaceId(properties.get_space_name());
if (spaceRet.ok()) {
LOG(ERROR) << "Create Space Failed : Space " << properties.get_space_name()
<< " have existed!";
cpp2::ErrorCode ret;
if (req.get_if_not_exists()) {
ret = cpp2::ErrorCode::SUCCEEDED;
} else {
LOG(ERROR) << "Create Space Failed : Space " << properties.get_space_name()
<< " have existed!";
ret = cpp2::ErrorCode::E_EXISTED;
}

resp_.set_id(to(spaceRet.value(), EntryType::SPACE));
resp_.set_code(cpp2::ErrorCode::E_EXISTED);
resp_.set_code(ret);
onFinished();
return;
}
Expand Down
8 changes: 7 additions & 1 deletion src/meta/processors/schemaMan/CreateEdgeProcessor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,14 @@ void CreateEdgeProcessor::process(const cpp2::CreateEdgeReq& req) {
folly::SharedMutex::WriteHolder wHolder(LockUtils::edgeLock());
auto ret = getEdgeType(req.get_space_id(), req.get_edge_name());
if (ret.ok()) {
cpp2::ErrorCode ec;
if (req.get_if_not_exists()) {
ec = cpp2::ErrorCode::SUCCEEDED;
} else {
ec = cpp2::ErrorCode::E_EXISTED;
}
resp_.set_id(to(ret.value(), EntryType::EDGE));
resp_.set_code(cpp2::ErrorCode::E_EXISTED);
resp_.set_code(ec);
onFinished();
return;
}
Expand Down
10 changes: 8 additions & 2 deletions src/meta/processors/schemaMan/CreateTagProcessor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,15 @@ void CreateTagProcessor::process(const cpp2::CreateTagReq& req) {
folly::SharedMutex::WriteHolder wHolder(LockUtils::tagLock());
auto ret = getTagId(req.get_space_id(), req.get_tag_name());
if (ret.ok()) {
LOG(ERROR) << "Create Tag Failed :" << req.get_tag_name() << " has existed";
cpp2::ErrorCode ec;
if (req.get_if_not_exists()) {
ec = cpp2::ErrorCode::SUCCEEDED;
} else {
LOG(ERROR) << "Create Tag Failed :" << req.get_tag_name() << " has existed";
ec = cpp2::ErrorCode::E_EXISTED;
}
resp_.set_id(to(ret.value(), EntryType::TAG));
resp_.set_code(cpp2::ErrorCode::E_EXISTED);
resp_.set_code(ec);
onFinished();
return;
}
Expand Down
8 changes: 8 additions & 0 deletions src/meta/test/MetaClientTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,9 @@ TEST(MetaClientTest, InterfacesTest) {
auto ret = client->createSpace("default_space", 8, 3).get();
ASSERT_TRUE(ret.ok()) << ret.status();
spaceId = ret.value();

ret = client->createSpace("default_space", 8, 3, true).get();
ASSERT_TRUE(ret.ok()) << ret.status();
}
{
auto ret = client->listSpaces().get();
Expand Down Expand Up @@ -93,6 +96,9 @@ TEST(MetaClientTest, InterfacesTest) {
}
auto ret = client->createTagSchema(spaceId, "tagName", schema).get();
ASSERT_TRUE(ret.ok()) << ret.status();

ret = client->createTagSchema(spaceId, "tagName", schema, true).get();
ASSERT_TRUE(ret.ok()) << ret.status();
}
{
// Create tag schema with default value
Expand Down Expand Up @@ -120,6 +126,8 @@ TEST(MetaClientTest, InterfacesTest) {
}
auto ret = client->createEdgeSchema(spaceId, "edgeName", schema).get();
ASSERT_TRUE(ret.ok()) << ret.status();
ret = client->createEdgeSchema(spaceId, "edgeName", schema, true).get();
ASSERT_TRUE(ret.ok()) << ret.status();
}
{
// Create edge schema with default value
Expand Down
5 changes: 3 additions & 2 deletions src/parser/AdminSentences.h
Original file line number Diff line number Diff line change
Expand Up @@ -152,9 +152,10 @@ class SpaceOptList final {
};


class CreateSpaceSentence final : public Sentence {
class CreateSpaceSentence final : public CreateSentence {
public:
explicit CreateSpaceSentence(std::string *spaceName) {
explicit CreateSpaceSentence(std::string* spaceName, bool ifNotExist)
: CreateSentence(ifNotExist) {
spaceName_.reset(spaceName);
kind_ = Kind::kCreateSpace;
}
Expand Down
12 changes: 8 additions & 4 deletions src/parser/MaintainSentences.h
Original file line number Diff line number Diff line change
Expand Up @@ -231,11 +231,13 @@ class SchemaPropList final {
};


class CreateTagSentence final : public Sentence {
class CreateTagSentence final : public CreateSentence {
public:
CreateTagSentence(std::string *name,
ColumnSpecificationList *columns,
SchemaPropList *schemaProps) {
SchemaPropList *schemaProps,
bool ifNotExists)
: CreateSentence(ifNotExists) {
name_.reset(name);
columns_.reset(columns);
schemaProps_.reset(schemaProps);
Expand Down Expand Up @@ -263,11 +265,13 @@ class CreateTagSentence final : public Sentence {
};


class CreateEdgeSentence final : public Sentence {
class CreateEdgeSentence final : public CreateSentence {
public:
CreateEdgeSentence(std::string *name,
ColumnSpecificationList *columns,
SchemaPropList *schemaProps) {
SchemaPropList *schemaProps,
bool ifNotExists)
: CreateSentence(ifNotExists) {
name_.reset(name);
columns_.reset(columns);
schemaProps_.reset(schemaProps);
Expand Down
13 changes: 13 additions & 0 deletions src/parser/Sentence.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,19 @@ class Sentence {
Kind kind_{Kind::kUnknown};
};

class CreateSentence : public Sentence {
public:
explicit CreateSentence(bool ifNotExist) : ifNotExist_{ifNotExist} {}
virtual ~CreateSentence() {}

bool isIfNotExist() {
return ifNotExist_;
}

private:
bool ifNotExist_{false};
};

inline std::ostream& operator<<(std::ostream &os, Sentence::Kind kind) {
return os << static_cast<uint32_t>(kind);
}
Expand Down
Loading

0 comments on commit 4b310b8

Please sign in to comment.