Skip to content

Commit

Permalink
Correc the alter default value dont't affected. (#2003)
Browse files Browse the repository at this point in the history
* Correc the alter default value dont't affected.

* Treat bitint as unkown error.

* Fix one alignment.

* Correct the error message.

* Fix one alignment.

* Fix one alignment.

* Fix one alignment.

* Correct the default value remove logical.

* Return error when unknown type.

* Fix one code alignment.

* Remove the useless code.

* Update to master.

* Merge the default value handle code.

Co-authored-by: dutor <440396+dutor@users.noreply.github.com>
  • Loading branch information
Shylock-Hg and dutor committed May 20, 2020
1 parent 8aa3ea6 commit e8a0030
Show file tree
Hide file tree
Showing 11 changed files with 382 additions and 107 deletions.
158 changes: 87 additions & 71 deletions src/graph/SchemaHelper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,81 @@ nebula::cpp2::SupportedType SchemaHelper::columnTypeToSupportedType(nebula::Colu
}
}

StatusOr<nebula::cpp2::Value> SchemaHelper::toDefaultValue(ColumnSpecification* spec) {
nebula::cpp2::Value v;
Getters getter;
CHECK(spec->hasDefault());
auto s = spec->prepare();
if (!s.ok()) {
return s;
}
auto valStatus = spec->getDefault(getter);
if (!valStatus.ok()) {
return std::move(valStatus).status();
}
auto value = std::move(valStatus).value();
auto type = spec->type();
switch (type) {
case nebula::ColumnType::BOOL: {
if (value.which() != VAR_BOOL) {
LOG(ERROR) << "ValueType is wrong, input type "
<< static_cast<int32_t>(type)
<< ", value type " << value.which();
return Status::Error("Wrong type");
}
v.set_bool_value(boost::get<bool>(value));
return v;
}
case nebula::ColumnType::INT: {
if (value.which() != VAR_INT64) {
LOG(ERROR) << "ValueType is wrong, input type "
<< static_cast<int32_t>(type)
<< ", value type " << value.which();
return Status::Error("Wrong type");
}
v.set_int_value(boost::get<int64_t>(value));
return v;
}
case nebula::ColumnType::DOUBLE: {
if (value.which() != VAR_DOUBLE) {
LOG(ERROR) << "ValueType is wrong, input type "
<< static_cast<int32_t>(type)
<< ", value type " << value.which();
return Status::Error("Wrong type");
}
v.set_double_value(boost::get<double>(value));
return v;
}
case nebula::ColumnType::STRING: {
if (value.which() != VAR_STR) {
LOG(ERROR) << "ValueType is wrong, input type "
<< static_cast<int32_t>(type)
<< ", value type " << value.which();
return Status::Error("Wrong type");
}
v.set_string_value(boost::get<std::string>(value));
return v;
}
case nebula::ColumnType::TIMESTAMP: {
if (value.which() != VAR_INT64 && value.which() != VAR_STR) {
LOG(ERROR) << "ValueType is wrong, input type "
<< static_cast<int32_t>(type)
<< ", value type " << value.which();
return Status::Error("Wrong type");
}
auto timestamp = toTimestamp(value);
if (!timestamp.ok()) {
return timestamp.status();
}
v.set_timestamp(timestamp.value());
return v;
}
default:
LOG(ERROR) << "Unsupported Type";
return Status::Error("Unsupported type");
}
}

// static
Status SchemaHelper::createSchema(const std::vector<ColumnSpecification*>& specs,
const std::vector<SchemaPropItem*>& schemaProps,
Expand All @@ -44,79 +119,12 @@ Status SchemaHelper::createSchema(const std::vector<ColumnSpecification*>& specs
nebula::cpp2::ColumnDef column;
column.name = *spec->name();
column.type.type = columnTypeToSupportedType(spec->type());
nebula::cpp2::Value v;
Getters getter;
if (spec->hasDefault()) {
auto s = spec->prepare();
if (!s.ok()) {
return s;
}
auto valStatus = spec->getDefault(getter);
if (!valStatus.ok()) {
return std::move(valStatus).status();
auto statusV = toDefaultValue(spec);
if (!statusV.ok()) {
return statusV.status();
}
auto value = std::move(valStatus).value();
auto type = spec->type();
switch (type) {
case nebula::ColumnType::BOOL: {
if (value.which() != VAR_BOOL) {
LOG(ERROR) << "ValueType is wrong, input type "
<< static_cast<int32_t>(type)
<< ", value type " << value.which();
return Status::Error("Wrong type");
}
v.set_bool_value(boost::get<bool>(value));
break;
}
case nebula::ColumnType::INT: {
if (value.which() != VAR_INT64) {
LOG(ERROR) << "ValueType is wrong, input type "
<< static_cast<int32_t>(type)
<< ", value type " << value.which();
return Status::Error("Wrong type");
}
v.set_int_value(boost::get<int64_t>(value));
break;
}
case nebula::ColumnType::DOUBLE: {
if (value.which() != VAR_DOUBLE) {
LOG(ERROR) << "ValueType is wrong, input type "
<< static_cast<int32_t>(type)
<< ", value type " << value.which();
return Status::Error("Wrong type");
}
v.set_double_value(boost::get<double>(value));
break;
}
case nebula::ColumnType::STRING: {
if (value.which() != VAR_STR) {
LOG(ERROR) << "ValueType is wrong, input type "
<< static_cast<int32_t>(type)
<< ", value type " << value.which();
return Status::Error("Wrong type");
}
v.set_string_value(boost::get<std::string>(value));
break;
}
case nebula::ColumnType::TIMESTAMP: {
if (value.which() != VAR_INT64 && value.which() != VAR_STR) {
LOG(ERROR) << "ValueType is wrong, input type "
<< static_cast<int32_t>(type)
<< ", value type " << value.which();
return Status::Error("Wrong type");
}
auto timestamp = toTimestamp(value);
if (!timestamp.ok()) {
return timestamp.status();
}
v.set_timestamp(timestamp.value());
break;
}
default:
LOG(ERROR) << "Unsupported Type";
return Status::Error("Unsupported type");
}
column.set_default_value(std::move(v));
column.set_default_value(std::move(statusV).value());
}
schema.columns.emplace_back(std::move(column));
}
Expand Down Expand Up @@ -196,6 +204,7 @@ Status SchemaHelper::alterSchema(const std::vector<AlterSchemaOptItem*>& schemaO
const std::vector<SchemaPropItem*>& schemaProps,
std::vector<nebula::meta::cpp2::AlterSchemaItem>& options,
nebula::cpp2::SchemaProp& prop) {
Getters g;
for (auto& schemaOpt : schemaOpts) {
nebula::meta::cpp2::AlterSchemaItem schemaItem;
auto opType = schemaOpt->toType();
Expand All @@ -214,6 +223,13 @@ Status SchemaHelper::alterSchema(const std::vector<AlterSchemaOptItem*>& schemaO
nebula::cpp2::ColumnDef column;
column.name = *spec->name();
column.type.type = columnTypeToSupportedType(spec->type());
if (spec->hasDefault()) {
auto statusV = toDefaultValue(spec);
if (!statusV.ok()) {
return statusV.status();
}
column.set_default_value(std::move(statusV).value());
}
schema.columns.emplace_back(std::move(column));
}
}
Expand Down
3 changes: 3 additions & 0 deletions src/graph/SchemaHelper.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ class SchemaHelper final {
static nebula::cpp2::SupportedType columnTypeToSupportedType(nebula::ColumnType type);

static StatusOr<int64_t> toTimestamp(const VariantType &value);

private:
static StatusOr<nebula::cpp2::Value> toDefaultValue(ColumnSpecification* spec);
};

} // namespace graph
Expand Down
152 changes: 152 additions & 0 deletions src/graph/test/SchemaTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,43 @@ class SchemaTest : public TestBase {
}
};

class SchemaTestIssue1987 : public TestBase, public ::testing::WithParamInterface<std::string> {
protected:
void SetUp() override {
TestBase::SetUp();
client_ = gEnv->getClient();
ASSERT_NE(nullptr, client_);
setupSchema();
}

void TearDown() override {
{
cpp2::ExecutionResponse resp;
std::string cmd = "DROP SPACE issue1987";
auto code = client_->execute(cmd, resp);
ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code);
}
TestBase::TearDown();
}

void setupSchema() {
{
cpp2::ExecutionResponse resp;
std::string cmd = "CREATE SPACE issue1987";
auto code = client_->execute(cmd, resp);
ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code);
}
{
cpp2::ExecutionResponse resp;
std::string cmd = "USE issue1987";
auto code = client_->execute(cmd, resp);
ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code);
}
}

std::unique_ptr<GraphClient> client_{nullptr};
};

TEST_F(SchemaTest, TestComment) {
auto client = gEnv->getClient();
ASSERT_NE(nullptr, client);
Expand Down Expand Up @@ -1120,6 +1157,121 @@ TEST_F(SchemaTest, TestTagAndEdge) {
LOG(FATAL) << "Space still exists after sleep " << retry << " seconds";
}

TEST_P(SchemaTestIssue1987, issue1987) {
{
cpp2::ExecutionResponse resp;
std::string query = "CREATE " + GetParam()
+ " t(name string default \"N/A\", age int default -1)";
auto code = client_->execute(query, resp);
ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code);
}
// ADD
{
cpp2::ExecutionResponse resp;
std::string query = "ALTER " + GetParam() + " t ADD (description string default \"none\");";
auto code = client_->execute(query, resp);
ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code);
::sleep(FLAGS_heartbeat_interval_secs + 1);
}
std::string ve;
std::string entity;
if (GetParam() == "TAG") {
ve = "VERTEX";
entity = "1";
} else if (GetParam() == "EDGE") {
ve = "EDGE";
entity = "1->2";
} else {
ASSERT_TRUE(false) << "Invalid parameter " << GetParam();
}
{
cpp2::ExecutionResponse resp;
std::string query = "INSERT " + ve + " t() VALUES " + entity + ":()";
auto code = client_->execute(query, resp);
ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code);
}
std::unordered_set<uint16_t> ignore;
if (GetParam() == "TAG") {
ignore.emplace(0);
} else if (GetParam() == "EDGE") {
ignore.emplace(0);
ignore.emplace(1);
ignore.emplace(2);
} else {
ASSERT_TRUE(false) << "Invalid parameter " << GetParam();
}
{
std::vector<std::tuple<std::string, int64_t, std::string>> result {
{"N/A", -1, "none"}
};
cpp2::ExecutionResponse resp;
std::string query = std::string() + "FETCH PROP ON " + "t " + entity;
auto code = client_->execute(query, resp);
ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code);
ASSERT_TRUE(verifyResult(resp, result, true, ignore));
}

// CHANGE
{
cpp2::ExecutionResponse resp;
std::string query = "ALTER " + GetParam()
+ " t CHANGE (description string default \"NONE\")";
auto code = client_->execute(query, resp);
ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code);
::sleep(FLAGS_heartbeat_interval_secs + 1);
}
{
cpp2::ExecutionResponse resp;
std::string query = "INSERT " + ve + " t() VALUES " + entity + ":()";
auto code = client_->execute(query, resp);
ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code);
}
{
std::vector<std::tuple<std::string, int64_t, std::string>> result {
{"N/A", -1, "NONE"}
};
cpp2::ExecutionResponse resp;
std::string query = std::string() + "FETCH PROP ON " + "t " + entity;
auto code = client_->execute(query, resp);
ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code);
ASSERT_TRUE(verifyResult(resp, result, true, ignore));
}

// DROP
{
cpp2::ExecutionResponse resp;
std::string query = "ALTER " + GetParam() + " t CHANGE (description string)";
auto code = client_->execute(query, resp);
ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code);
::sleep(FLAGS_heartbeat_interval_secs + 1);
}
{
cpp2::ExecutionResponse resp;
std::string query = "INSERT " + ve + " t(description) VALUES " + entity + ":(\"some one\")";
auto code = client_->execute(query, resp);
ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code);
}
{
std::vector<std::tuple<std::string, int64_t, std::string>> result {
{"N/A", -1, "some one"}
};
cpp2::ExecutionResponse resp;
std::string query = std::string() + "FETCH PROP ON " + "t " + entity;
auto code = client_->execute(query, resp);
ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code);
ASSERT_TRUE(verifyResult(resp, result, true, ignore));
}
{
cpp2::ExecutionResponse resp;
std::string query = "INSERT " + ve + " t() VALUES " + entity + ":()";
auto code = client_->execute(query, resp);
ASSERT_NE(cpp2::ErrorCode::SUCCEEDED, code);
}
}

INSTANTIATE_TEST_CASE_P(SchemaIssue1987, SchemaTestIssue1987, ::testing::Values("TAG", "EDGE"));


TEST_F(SchemaTest, issue2009) {
auto client = gEnv->getClient();
ASSERT_NE(nullptr, client);
Expand Down
Loading

0 comments on commit e8a0030

Please sign in to comment.