Add support for vertex properties to storage v2
Reviewers: mtomic, teon.banek Reviewed By: mtomic Subscribers: pullbot Differential Revision: https://phabricator.memgraph.io/D2163
This commit is contained in:
parent
542d65544b
commit
db72ef05f8
@ -2,6 +2,8 @@
|
||||
|
||||
#include <atomic>
|
||||
|
||||
#include "storage/v2/property_value.hpp"
|
||||
|
||||
namespace storage {
|
||||
|
||||
struct Delta {
|
||||
@ -10,11 +12,13 @@ struct Delta {
|
||||
RECREATE_OBJECT,
|
||||
ADD_LABEL,
|
||||
REMOVE_LABEL,
|
||||
SET_PROPERTY,
|
||||
};
|
||||
|
||||
Delta(Action action, uint64_t value, std::atomic<uint64_t> *timestamp,
|
||||
uint64_t command_id)
|
||||
Delta(Action action, uint64_t key, const PropertyValue &value,
|
||||
std::atomic<uint64_t> *timestamp, uint64_t command_id)
|
||||
: action(action),
|
||||
key(key),
|
||||
value(value),
|
||||
timestamp(timestamp),
|
||||
command_id(command_id),
|
||||
@ -23,7 +27,8 @@ struct Delta {
|
||||
|
||||
Delta(Delta &&other) noexcept
|
||||
: action(other.action),
|
||||
value(other.value),
|
||||
key(other.key),
|
||||
value(std::move(other.value)),
|
||||
timestamp(other.timestamp),
|
||||
command_id(other.command_id),
|
||||
prev(other.prev),
|
||||
@ -36,7 +41,9 @@ struct Delta {
|
||||
~Delta() {}
|
||||
|
||||
Action action;
|
||||
uint64_t value;
|
||||
|
||||
uint64_t key; // Used as the label id or the property id.
|
||||
PropertyValue value; // Used as the property value (only for SET_PROPERTY).
|
||||
|
||||
// TODO: optimize with in-place copy
|
||||
std::atomic<uint64_t> *timestamp;
|
||||
|
@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "storage/v2/delta.hpp"
|
||||
#include "storage/v2/property_value.hpp"
|
||||
#include "storage/v2/transaction.hpp"
|
||||
#include "storage/v2/view.hpp"
|
||||
|
||||
@ -67,18 +68,21 @@ inline bool PrepareForWrite(Transaction *transaction, Vertex *vertex) {
|
||||
/// the created delta. It doesn't perform any linking of the delta and is
|
||||
/// primarily used to create the first delta for an object.
|
||||
inline Delta *CreateDelta(Transaction *transaction, Delta::Action action,
|
||||
uint64_t value) {
|
||||
return &transaction->deltas.emplace_back(
|
||||
action, value, &transaction->commit_timestamp, transaction->command_id);
|
||||
uint64_t key) {
|
||||
return &transaction->deltas.emplace_back(action, key, PropertyValue(),
|
||||
&transaction->commit_timestamp,
|
||||
transaction->command_id);
|
||||
}
|
||||
|
||||
/// This function creates a delta in the transaction for the Vertex object and
|
||||
/// links the delta into the Vertex's delta list. It also adds the Vertex to the
|
||||
/// transaction's modified vertices list.
|
||||
inline void CreateAndLinkDelta(Transaction *transaction, Vertex *vertex,
|
||||
Delta::Action action, uint64_t value) {
|
||||
auto delta = &transaction->deltas.emplace_back(
|
||||
action, value, &transaction->commit_timestamp, transaction->command_id);
|
||||
Delta::Action action, uint64_t key,
|
||||
const PropertyValue &value = PropertyValue()) {
|
||||
auto delta = &transaction->deltas.emplace_back(action, key, value,
|
||||
&transaction->commit_timestamp,
|
||||
transaction->command_id);
|
||||
|
||||
if (vertex->delta) {
|
||||
vertex->delta->prev = delta;
|
||||
|
@ -128,7 +128,7 @@ class Storage final {
|
||||
switch (current->action) {
|
||||
case Delta::Action::REMOVE_LABEL: {
|
||||
auto it = std::find(vertex->labels.begin(), vertex->labels.end(),
|
||||
current->value);
|
||||
current->key);
|
||||
CHECK(it != vertex->labels.end()) << "Invalid database state!";
|
||||
std::swap(*it, *vertex->labels.rbegin());
|
||||
vertex->labels.pop_back();
|
||||
@ -136,9 +136,24 @@ class Storage final {
|
||||
}
|
||||
case Delta::Action::ADD_LABEL: {
|
||||
auto it = std::find(vertex->labels.begin(), vertex->labels.end(),
|
||||
current->value);
|
||||
current->key);
|
||||
CHECK(it == vertex->labels.end()) << "Invalid database state!";
|
||||
vertex->labels.push_back(current->value);
|
||||
vertex->labels.push_back(current->key);
|
||||
break;
|
||||
}
|
||||
case Delta::Action::SET_PROPERTY: {
|
||||
auto it = vertex->properties.find(current->key);
|
||||
if (it != vertex->properties.end()) {
|
||||
if (current->value.IsNull()) {
|
||||
// remove the property
|
||||
vertex->properties.erase(it);
|
||||
} else {
|
||||
// set the value
|
||||
it->second = current->value;
|
||||
}
|
||||
} else if (!current->value.IsNull()) {
|
||||
vertex->properties.emplace(current->key, current->value);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Delta::Action::DELETE_OBJECT: {
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include "utils/skip_list.hpp"
|
||||
|
||||
#include "storage/v2/delta.hpp"
|
||||
#include "storage/v2/property_value.hpp"
|
||||
#include "storage/v2/vertex.hpp"
|
||||
#include "storage/v2/view.hpp"
|
||||
|
||||
|
@ -19,9 +19,7 @@ struct Vertex {
|
||||
|
||||
Gid gid;
|
||||
std::vector<uint64_t> labels;
|
||||
|
||||
// TODO: add
|
||||
// std::unordered_map<uint64_t, storage::PropertyValue> properties;
|
||||
std::unordered_map<uint64_t, storage::PropertyValue> properties;
|
||||
|
||||
utils::SpinLock lock;
|
||||
bool deleted;
|
||||
|
@ -33,6 +33,7 @@ class VertexAccessor final {
|
||||
switch (delta.action) {
|
||||
case Delta::Action::ADD_LABEL:
|
||||
case Delta::Action::REMOVE_LABEL:
|
||||
case Delta::Action::SET_PROPERTY:
|
||||
break;
|
||||
case Delta::Action::RECREATE_OBJECT: {
|
||||
is_visible = true;
|
||||
@ -116,14 +117,14 @@ class VertexAccessor final {
|
||||
[&deleted, &has_label, label](const Delta &delta) {
|
||||
switch (delta.action) {
|
||||
case Delta::Action::REMOVE_LABEL: {
|
||||
if (delta.value == label) {
|
||||
if (delta.key == label) {
|
||||
CHECK(has_label) << "Invalid database state!";
|
||||
has_label = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Delta::Action::ADD_LABEL: {
|
||||
if (delta.value == label) {
|
||||
if (delta.key == label) {
|
||||
CHECK(!has_label) << "Invalid database state!";
|
||||
has_label = true;
|
||||
}
|
||||
@ -137,6 +138,8 @@ class VertexAccessor final {
|
||||
deleted = false;
|
||||
break;
|
||||
}
|
||||
case Delta::Action::SET_PROPERTY:
|
||||
break;
|
||||
}
|
||||
});
|
||||
if (deleted) return Result<bool>{Error::DELETED_OBJECT};
|
||||
@ -158,7 +161,7 @@ class VertexAccessor final {
|
||||
switch (delta.action) {
|
||||
case Delta::Action::REMOVE_LABEL: {
|
||||
// Remove the label because we don't see the addition.
|
||||
auto it = std::find(labels.begin(), labels.end(), delta.value);
|
||||
auto it = std::find(labels.begin(), labels.end(), delta.key);
|
||||
CHECK(it != labels.end()) << "Invalid database state!";
|
||||
std::swap(*it, *labels.rbegin());
|
||||
labels.pop_back();
|
||||
@ -166,9 +169,9 @@ class VertexAccessor final {
|
||||
}
|
||||
case Delta::Action::ADD_LABEL: {
|
||||
// Add the label because we don't see the removal.
|
||||
auto it = std::find(labels.begin(), labels.end(), delta.value);
|
||||
auto it = std::find(labels.begin(), labels.end(), delta.key);
|
||||
CHECK(it == labels.end()) << "Invalid database state!";
|
||||
labels.push_back(delta.value);
|
||||
labels.push_back(delta.key);
|
||||
break;
|
||||
}
|
||||
case Delta::Action::DELETE_OBJECT: {
|
||||
@ -179,12 +182,133 @@ class VertexAccessor final {
|
||||
deleted = false;
|
||||
break;
|
||||
}
|
||||
case Delta::Action::SET_PROPERTY:
|
||||
break;
|
||||
}
|
||||
});
|
||||
if (deleted) return Result<std::vector<uint64_t>>{Error::DELETED_OBJECT};
|
||||
return Result<std::vector<uint64_t>>{std::move(labels)};
|
||||
}
|
||||
|
||||
Result<bool> SetProperty(uint64_t property, const PropertyValue &value) {
|
||||
std::lock_guard<utils::SpinLock> guard(vertex_->lock);
|
||||
|
||||
if (!PrepareForWrite(transaction_, vertex_))
|
||||
return Result<bool>{Error::SERIALIZATION_ERROR};
|
||||
|
||||
if (vertex_->deleted) return Result<bool>{Error::DELETED_OBJECT};
|
||||
|
||||
auto it = vertex_->properties.find(property);
|
||||
bool existed = it != vertex_->properties.end();
|
||||
if (it != vertex_->properties.end()) {
|
||||
CreateAndLinkDelta(transaction_, vertex_, Delta::Action::SET_PROPERTY,
|
||||
property, it->second);
|
||||
if (value.IsNull()) {
|
||||
// remove the property
|
||||
vertex_->properties.erase(it);
|
||||
} else {
|
||||
// set the value
|
||||
it->second = value;
|
||||
}
|
||||
} else {
|
||||
CreateAndLinkDelta(transaction_, vertex_, Delta::Action::SET_PROPERTY,
|
||||
property, PropertyValue());
|
||||
if (!value.IsNull()) {
|
||||
vertex_->properties.emplace(property, value);
|
||||
}
|
||||
}
|
||||
|
||||
return Result<bool>{existed};
|
||||
}
|
||||
|
||||
Result<PropertyValue> GetProperty(uint64_t property, View view) {
|
||||
bool deleted = false;
|
||||
PropertyValue value;
|
||||
Delta *delta = nullptr;
|
||||
{
|
||||
std::lock_guard<utils::SpinLock> guard(vertex_->lock);
|
||||
deleted = vertex_->deleted;
|
||||
auto it = vertex_->properties.find(property);
|
||||
if (it != vertex_->properties.end()) {
|
||||
value = it->second;
|
||||
}
|
||||
delta = vertex_->delta;
|
||||
}
|
||||
ApplyDeltasForRead(transaction_, delta, view,
|
||||
[&deleted, &value, property](const Delta &delta) {
|
||||
switch (delta.action) {
|
||||
case Delta::Action::SET_PROPERTY: {
|
||||
if (delta.key == property) {
|
||||
value = delta.value;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Delta::Action::DELETE_OBJECT: {
|
||||
LOG(FATAL) << "Invalid accessor!";
|
||||
break;
|
||||
}
|
||||
case Delta::Action::RECREATE_OBJECT: {
|
||||
deleted = false;
|
||||
break;
|
||||
}
|
||||
case Delta::Action::ADD_LABEL:
|
||||
case Delta::Action::REMOVE_LABEL:
|
||||
break;
|
||||
}
|
||||
});
|
||||
if (deleted) return Result<PropertyValue>{Error::DELETED_OBJECT};
|
||||
return Result<PropertyValue>{std::move(value)};
|
||||
}
|
||||
|
||||
Result<std::unordered_map<uint64_t, PropertyValue>> Properties(View view) {
|
||||
std::unordered_map<uint64_t, PropertyValue> properties;
|
||||
bool deleted = false;
|
||||
Delta *delta = nullptr;
|
||||
{
|
||||
std::lock_guard<utils::SpinLock> guard(vertex_->lock);
|
||||
deleted = vertex_->deleted;
|
||||
properties = vertex_->properties;
|
||||
delta = vertex_->delta;
|
||||
}
|
||||
ApplyDeltasForRead(transaction_, delta, view,
|
||||
[&deleted, &properties](const Delta &delta) {
|
||||
switch (delta.action) {
|
||||
case Delta::Action::SET_PROPERTY: {
|
||||
auto it = properties.find(delta.key);
|
||||
if (it != properties.end()) {
|
||||
if (delta.value.IsNull()) {
|
||||
// remove the property
|
||||
properties.erase(it);
|
||||
} else {
|
||||
// set the value
|
||||
it->second = delta.value;
|
||||
}
|
||||
} else if (!delta.value.IsNull()) {
|
||||
properties.emplace(delta.key, delta.value);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Delta::Action::DELETE_OBJECT: {
|
||||
LOG(FATAL) << "Invalid accessor!";
|
||||
break;
|
||||
}
|
||||
case Delta::Action::RECREATE_OBJECT: {
|
||||
deleted = false;
|
||||
break;
|
||||
}
|
||||
case Delta::Action::ADD_LABEL:
|
||||
case Delta::Action::REMOVE_LABEL:
|
||||
break;
|
||||
}
|
||||
});
|
||||
if (deleted) {
|
||||
return Result<std::unordered_map<uint64_t, PropertyValue>>{
|
||||
Error::DELETED_OBJECT};
|
||||
}
|
||||
return Result<std::unordered_map<uint64_t, PropertyValue>>{
|
||||
std::move(properties)};
|
||||
}
|
||||
|
||||
Gid Gid() const { return vertex_->gid; }
|
||||
|
||||
private:
|
||||
|
@ -596,6 +596,169 @@ TEST(StorageV2, VertexDeleteLabel) {
|
||||
}
|
||||
}
|
||||
|
||||
// NOLINTNEXTLINE(hicpp-special-member-functions)
|
||||
TEST(StorageV2, VertexDeleteProperty) {
|
||||
storage::Storage store;
|
||||
storage::Gid gid =
|
||||
storage::Gid::FromUint(std::numeric_limits<uint64_t>::max());
|
||||
|
||||
// Create the vertex
|
||||
{
|
||||
auto acc = store.Access();
|
||||
auto vertex = acc.CreateVertex();
|
||||
gid = vertex.Gid();
|
||||
ASSERT_FALSE(acc.FindVertex(gid, storage::View::OLD).has_value());
|
||||
ASSERT_TRUE(acc.FindVertex(gid, storage::View::NEW).has_value());
|
||||
acc.Commit();
|
||||
}
|
||||
|
||||
// Set property, delete the vertex and check the property API (same command)
|
||||
{
|
||||
auto acc = store.Access();
|
||||
auto vertex = acc.FindVertex(gid, storage::View::NEW);
|
||||
ASSERT_TRUE(vertex);
|
||||
|
||||
// Check whether property 5 exists
|
||||
ASSERT_TRUE(
|
||||
vertex->GetProperty(5, storage::View::OLD).GetReturn().IsNull());
|
||||
ASSERT_TRUE(
|
||||
vertex->GetProperty(5, storage::View::NEW).GetReturn().IsNull());
|
||||
ASSERT_EQ(vertex->Properties(storage::View::OLD).GetReturn().size(), 0);
|
||||
ASSERT_EQ(vertex->Properties(storage::View::NEW).GetReturn().size(), 0);
|
||||
|
||||
// Set property 5 to "nandare"
|
||||
ASSERT_FALSE(
|
||||
vertex->SetProperty(5, storage::PropertyValue("nandare")).GetReturn());
|
||||
|
||||
// Check whether property 5 exists
|
||||
ASSERT_TRUE(
|
||||
vertex->GetProperty(5, storage::View::OLD).GetReturn().IsNull());
|
||||
ASSERT_EQ(
|
||||
vertex->GetProperty(5, storage::View::NEW).GetReturn().ValueString(),
|
||||
"nandare");
|
||||
ASSERT_EQ(vertex->Properties(storage::View::OLD).GetReturn().size(), 0);
|
||||
{
|
||||
auto properties = vertex->Properties(storage::View::NEW).GetReturn();
|
||||
ASSERT_EQ(properties.size(), 1);
|
||||
ASSERT_EQ(properties[5].ValueString(), "nandare");
|
||||
}
|
||||
|
||||
// Delete the vertex
|
||||
ASSERT_TRUE(vertex->Delete().GetReturn());
|
||||
|
||||
// Check whether label 5 exists
|
||||
ASSERT_TRUE(
|
||||
vertex->GetProperty(5, storage::View::OLD).GetReturn().IsNull());
|
||||
ASSERT_EQ(vertex->GetProperty(5, storage::View::NEW).GetError(),
|
||||
storage::Error::DELETED_OBJECT);
|
||||
ASSERT_EQ(vertex->Properties(storage::View::OLD).GetReturn().size(), 0);
|
||||
ASSERT_EQ(vertex->Properties(storage::View::NEW).GetError(),
|
||||
storage::Error::DELETED_OBJECT);
|
||||
|
||||
// Try to set the property
|
||||
{
|
||||
auto ret = vertex->SetProperty(5, storage::PropertyValue("haihai"));
|
||||
ASSERT_TRUE(ret.IsError());
|
||||
ASSERT_EQ(ret.GetError(), storage::Error::DELETED_OBJECT);
|
||||
}
|
||||
|
||||
acc.Abort();
|
||||
}
|
||||
|
||||
// Set property, delete the vertex and check the property API (different
|
||||
// command)
|
||||
{
|
||||
auto acc = store.Access();
|
||||
auto vertex = acc.FindVertex(gid, storage::View::NEW);
|
||||
ASSERT_TRUE(vertex);
|
||||
|
||||
// Check whether property 5 exists
|
||||
ASSERT_TRUE(
|
||||
vertex->GetProperty(5, storage::View::OLD).GetReturn().IsNull());
|
||||
ASSERT_TRUE(
|
||||
vertex->GetProperty(5, storage::View::NEW).GetReturn().IsNull());
|
||||
ASSERT_EQ(vertex->Properties(storage::View::OLD).GetReturn().size(), 0);
|
||||
ASSERT_EQ(vertex->Properties(storage::View::NEW).GetReturn().size(), 0);
|
||||
|
||||
// Set property 5 to "nandare"
|
||||
ASSERT_FALSE(
|
||||
vertex->SetProperty(5, storage::PropertyValue("nandare")).GetReturn());
|
||||
|
||||
// Check whether property 5 exists
|
||||
ASSERT_TRUE(
|
||||
vertex->GetProperty(5, storage::View::OLD).GetReturn().IsNull());
|
||||
ASSERT_EQ(
|
||||
vertex->GetProperty(5, storage::View::NEW).GetReturn().ValueString(),
|
||||
"nandare");
|
||||
ASSERT_EQ(vertex->Properties(storage::View::OLD).GetReturn().size(), 0);
|
||||
{
|
||||
auto properties = vertex->Properties(storage::View::NEW).GetReturn();
|
||||
ASSERT_EQ(properties.size(), 1);
|
||||
ASSERT_EQ(properties[5].ValueString(), "nandare");
|
||||
}
|
||||
|
||||
// Advance command
|
||||
acc.AdvanceCommand();
|
||||
|
||||
// Check whether property 5 exists
|
||||
ASSERT_EQ(
|
||||
vertex->GetProperty(5, storage::View::OLD).GetReturn().ValueString(),
|
||||
"nandare");
|
||||
ASSERT_EQ(
|
||||
vertex->GetProperty(5, storage::View::NEW).GetReturn().ValueString(),
|
||||
"nandare");
|
||||
{
|
||||
auto properties = vertex->Properties(storage::View::OLD).GetReturn();
|
||||
ASSERT_EQ(properties.size(), 1);
|
||||
ASSERT_EQ(properties[5].ValueString(), "nandare");
|
||||
}
|
||||
{
|
||||
auto properties = vertex->Properties(storage::View::NEW).GetReturn();
|
||||
ASSERT_EQ(properties.size(), 1);
|
||||
ASSERT_EQ(properties[5].ValueString(), "nandare");
|
||||
}
|
||||
|
||||
// Delete the vertex
|
||||
ASSERT_TRUE(vertex->Delete().GetReturn());
|
||||
|
||||
// Check whether property 5 exists
|
||||
ASSERT_EQ(
|
||||
vertex->GetProperty(5, storage::View::OLD).GetReturn().ValueString(),
|
||||
"nandare");
|
||||
ASSERT_EQ(vertex->GetProperty(5, storage::View::NEW).GetError(),
|
||||
storage::Error::DELETED_OBJECT);
|
||||
{
|
||||
auto properties = vertex->Properties(storage::View::OLD).GetReturn();
|
||||
ASSERT_EQ(properties.size(), 1);
|
||||
ASSERT_EQ(properties[5].ValueString(), "nandare");
|
||||
}
|
||||
ASSERT_EQ(vertex->Properties(storage::View::NEW).GetError(),
|
||||
storage::Error::DELETED_OBJECT);
|
||||
|
||||
// Advance command
|
||||
acc.AdvanceCommand();
|
||||
|
||||
// Check whether property 5 exists
|
||||
ASSERT_EQ(vertex->GetProperty(5, storage::View::OLD).GetError(),
|
||||
storage::Error::DELETED_OBJECT);
|
||||
ASSERT_EQ(vertex->GetProperty(5, storage::View::NEW).GetError(),
|
||||
storage::Error::DELETED_OBJECT);
|
||||
ASSERT_EQ(vertex->Properties(storage::View::OLD).GetError(),
|
||||
storage::Error::DELETED_OBJECT);
|
||||
ASSERT_EQ(vertex->Properties(storage::View::NEW).GetError(),
|
||||
storage::Error::DELETED_OBJECT);
|
||||
|
||||
// Try to set the property
|
||||
{
|
||||
auto ret = vertex->SetProperty(5, storage::PropertyValue("haihai"));
|
||||
ASSERT_TRUE(ret.IsError());
|
||||
ASSERT_EQ(ret.GetError(), storage::Error::DELETED_OBJECT);
|
||||
}
|
||||
|
||||
acc.Abort();
|
||||
}
|
||||
}
|
||||
|
||||
// NOLINTNEXTLINE(hicpp-special-member-functions)
|
||||
TEST(StorageV2, VertexLabelCommit) {
|
||||
storage::Storage store;
|
||||
@ -940,7 +1103,7 @@ TEST(StorageV2, VertexLabelSerializationError) {
|
||||
auto acc1 = store.Access();
|
||||
auto acc2 = store.Access();
|
||||
|
||||
// Add label 10 in accessor 1.
|
||||
// Add label 1 in accessor 1.
|
||||
{
|
||||
auto vertex = acc1.FindVertex(gid, storage::View::OLD);
|
||||
ASSERT_TRUE(vertex);
|
||||
@ -1024,3 +1187,791 @@ TEST(StorageV2, VertexLabelSerializationError) {
|
||||
acc.Abort();
|
||||
}
|
||||
}
|
||||
|
||||
// NOLINTNEXTLINE(hicpp-special-member-functions)
|
||||
TEST(StorageV2, VertexPropertyCommit) {
|
||||
storage::Storage store;
|
||||
storage::Gid gid =
|
||||
storage::Gid::FromUint(std::numeric_limits<uint64_t>::max());
|
||||
{
|
||||
auto acc = store.Access();
|
||||
auto vertex = acc.CreateVertex();
|
||||
gid = vertex.Gid();
|
||||
|
||||
ASSERT_TRUE(vertex.GetProperty(5, storage::View::NEW).GetReturn().IsNull());
|
||||
ASSERT_EQ(vertex.Properties(storage::View::NEW).GetReturn().size(), 0);
|
||||
|
||||
{
|
||||
auto res = vertex.SetProperty(5, storage::PropertyValue("temporary"));
|
||||
ASSERT_TRUE(res.IsReturn());
|
||||
ASSERT_FALSE(res.GetReturn());
|
||||
}
|
||||
|
||||
ASSERT_EQ(
|
||||
vertex.GetProperty(5, storage::View::NEW).GetReturn().ValueString(),
|
||||
"temporary");
|
||||
{
|
||||
auto properties = vertex.Properties(storage::View::NEW).GetReturn();
|
||||
ASSERT_EQ(properties.size(), 1);
|
||||
ASSERT_EQ(properties[5].ValueString(), "temporary");
|
||||
}
|
||||
|
||||
{
|
||||
auto res = vertex.SetProperty(5, storage::PropertyValue("nandare"));
|
||||
ASSERT_TRUE(res.IsReturn());
|
||||
ASSERT_TRUE(res.GetReturn());
|
||||
}
|
||||
|
||||
ASSERT_EQ(
|
||||
vertex.GetProperty(5, storage::View::NEW).GetReturn().ValueString(),
|
||||
"nandare");
|
||||
{
|
||||
auto properties = vertex.Properties(storage::View::NEW).GetReturn();
|
||||
ASSERT_EQ(properties.size(), 1);
|
||||
ASSERT_EQ(properties[5].ValueString(), "nandare");
|
||||
}
|
||||
|
||||
acc.Commit();
|
||||
}
|
||||
{
|
||||
auto acc = store.Access();
|
||||
auto vertex = acc.FindVertex(gid, storage::View::OLD);
|
||||
ASSERT_TRUE(vertex);
|
||||
|
||||
ASSERT_EQ(
|
||||
vertex->GetProperty(5, storage::View::OLD).GetReturn().ValueString(),
|
||||
"nandare");
|
||||
{
|
||||
auto properties = vertex->Properties(storage::View::OLD).GetReturn();
|
||||
ASSERT_EQ(properties.size(), 1);
|
||||
ASSERT_EQ(properties[5].ValueString(), "nandare");
|
||||
}
|
||||
|
||||
ASSERT_EQ(
|
||||
vertex->GetProperty(5, storage::View::NEW).GetReturn().ValueString(),
|
||||
"nandare");
|
||||
{
|
||||
auto properties = vertex->Properties(storage::View::NEW).GetReturn();
|
||||
ASSERT_EQ(properties.size(), 1);
|
||||
ASSERT_EQ(properties[5].ValueString(), "nandare");
|
||||
}
|
||||
|
||||
ASSERT_TRUE(
|
||||
vertex->GetProperty(10, storage::View::OLD).GetReturn().IsNull());
|
||||
ASSERT_TRUE(
|
||||
vertex->GetProperty(10, storage::View::NEW).GetReturn().IsNull());
|
||||
|
||||
acc.Abort();
|
||||
}
|
||||
{
|
||||
auto acc = store.Access();
|
||||
auto vertex = acc.FindVertex(gid, storage::View::OLD);
|
||||
ASSERT_TRUE(vertex);
|
||||
|
||||
{
|
||||
auto res = vertex->SetProperty(5, storage::PropertyValue());
|
||||
ASSERT_TRUE(res.IsReturn());
|
||||
ASSERT_TRUE(res.GetReturn());
|
||||
}
|
||||
|
||||
ASSERT_EQ(
|
||||
vertex->GetProperty(5, storage::View::OLD).GetReturn().ValueString(),
|
||||
"nandare");
|
||||
{
|
||||
auto properties = vertex->Properties(storage::View::OLD).GetReturn();
|
||||
ASSERT_EQ(properties.size(), 1);
|
||||
ASSERT_EQ(properties[5].ValueString(), "nandare");
|
||||
}
|
||||
|
||||
ASSERT_TRUE(
|
||||
vertex->GetProperty(5, storage::View::NEW).GetReturn().IsNull());
|
||||
ASSERT_EQ(vertex->Properties(storage::View::NEW).GetReturn().size(), 0);
|
||||
|
||||
{
|
||||
auto res = vertex->SetProperty(5, storage::PropertyValue());
|
||||
ASSERT_TRUE(res.IsReturn());
|
||||
ASSERT_FALSE(res.GetReturn());
|
||||
}
|
||||
|
||||
acc.Commit();
|
||||
}
|
||||
{
|
||||
auto acc = store.Access();
|
||||
auto vertex = acc.FindVertex(gid, storage::View::OLD);
|
||||
ASSERT_TRUE(vertex);
|
||||
|
||||
ASSERT_TRUE(
|
||||
vertex->GetProperty(5, storage::View::OLD).GetReturn().IsNull());
|
||||
ASSERT_TRUE(
|
||||
vertex->GetProperty(5, storage::View::NEW).GetReturn().IsNull());
|
||||
ASSERT_EQ(vertex->Properties(storage::View::OLD).GetReturn().size(), 0);
|
||||
ASSERT_EQ(vertex->Properties(storage::View::NEW).GetReturn().size(), 0);
|
||||
|
||||
ASSERT_TRUE(
|
||||
vertex->GetProperty(10, storage::View::OLD).GetReturn().IsNull());
|
||||
ASSERT_TRUE(
|
||||
vertex->GetProperty(10, storage::View::NEW).GetReturn().IsNull());
|
||||
|
||||
acc.Abort();
|
||||
}
|
||||
}
|
||||
|
||||
// NOLINTNEXTLINE(hicpp-special-member-functions)
|
||||
TEST(StorageV2, VertexPropertyAbort) {
|
||||
storage::Storage store;
|
||||
storage::Gid gid =
|
||||
storage::Gid::FromUint(std::numeric_limits<uint64_t>::max());
|
||||
|
||||
// Create the vertex.
|
||||
{
|
||||
auto acc = store.Access();
|
||||
auto vertex = acc.CreateVertex();
|
||||
gid = vertex.Gid();
|
||||
acc.Commit();
|
||||
}
|
||||
|
||||
// Set property 5 to "nandare", but abort the transaction.
|
||||
{
|
||||
auto acc = store.Access();
|
||||
auto vertex = acc.FindVertex(gid, storage::View::OLD);
|
||||
ASSERT_TRUE(vertex);
|
||||
|
||||
ASSERT_TRUE(
|
||||
vertex->GetProperty(5, storage::View::NEW).GetReturn().IsNull());
|
||||
ASSERT_EQ(vertex->Properties(storage::View::NEW).GetReturn().size(), 0);
|
||||
|
||||
{
|
||||
auto res = vertex->SetProperty(5, storage::PropertyValue("temporary"));
|
||||
ASSERT_TRUE(res.IsReturn());
|
||||
ASSERT_FALSE(res.GetReturn());
|
||||
}
|
||||
|
||||
ASSERT_EQ(
|
||||
vertex->GetProperty(5, storage::View::NEW).GetReturn().ValueString(),
|
||||
"temporary");
|
||||
{
|
||||
auto properties = vertex->Properties(storage::View::NEW).GetReturn();
|
||||
ASSERT_EQ(properties.size(), 1);
|
||||
ASSERT_EQ(properties[5].ValueString(), "temporary");
|
||||
}
|
||||
|
||||
{
|
||||
auto res = vertex->SetProperty(5, storage::PropertyValue("nandare"));
|
||||
ASSERT_TRUE(res.IsReturn());
|
||||
ASSERT_TRUE(res.GetReturn());
|
||||
}
|
||||
|
||||
ASSERT_EQ(
|
||||
vertex->GetProperty(5, storage::View::NEW).GetReturn().ValueString(),
|
||||
"nandare");
|
||||
{
|
||||
auto properties = vertex->Properties(storage::View::NEW).GetReturn();
|
||||
ASSERT_EQ(properties.size(), 1);
|
||||
ASSERT_EQ(properties[5].ValueString(), "nandare");
|
||||
}
|
||||
|
||||
acc.Abort();
|
||||
}
|
||||
|
||||
// Check that property 5 is null.
|
||||
{
|
||||
auto acc = store.Access();
|
||||
auto vertex = acc.FindVertex(gid, storage::View::OLD);
|
||||
ASSERT_TRUE(vertex);
|
||||
|
||||
ASSERT_TRUE(
|
||||
vertex->GetProperty(5, storage::View::OLD).GetReturn().IsNull());
|
||||
ASSERT_TRUE(
|
||||
vertex->GetProperty(5, storage::View::NEW).GetReturn().IsNull());
|
||||
ASSERT_EQ(vertex->Properties(storage::View::OLD).GetReturn().size(), 0);
|
||||
ASSERT_EQ(vertex->Properties(storage::View::NEW).GetReturn().size(), 0);
|
||||
|
||||
ASSERT_TRUE(
|
||||
vertex->GetProperty(10, storage::View::OLD).GetReturn().IsNull());
|
||||
ASSERT_TRUE(
|
||||
vertex->GetProperty(10, storage::View::NEW).GetReturn().IsNull());
|
||||
|
||||
acc.Abort();
|
||||
}
|
||||
|
||||
// Set property 5 to "nandare".
|
||||
{
|
||||
auto acc = store.Access();
|
||||
auto vertex = acc.FindVertex(gid, storage::View::OLD);
|
||||
ASSERT_TRUE(vertex);
|
||||
|
||||
ASSERT_TRUE(
|
||||
vertex->GetProperty(5, storage::View::NEW).GetReturn().IsNull());
|
||||
ASSERT_EQ(vertex->Properties(storage::View::NEW).GetReturn().size(), 0);
|
||||
|
||||
{
|
||||
auto res = vertex->SetProperty(5, storage::PropertyValue("temporary"));
|
||||
ASSERT_TRUE(res.IsReturn());
|
||||
ASSERT_FALSE(res.GetReturn());
|
||||
}
|
||||
|
||||
ASSERT_EQ(
|
||||
vertex->GetProperty(5, storage::View::NEW).GetReturn().ValueString(),
|
||||
"temporary");
|
||||
{
|
||||
auto properties = vertex->Properties(storage::View::NEW).GetReturn();
|
||||
ASSERT_EQ(properties.size(), 1);
|
||||
ASSERT_EQ(properties[5].ValueString(), "temporary");
|
||||
}
|
||||
|
||||
{
|
||||
auto res = vertex->SetProperty(5, storage::PropertyValue("nandare"));
|
||||
ASSERT_TRUE(res.IsReturn());
|
||||
ASSERT_TRUE(res.GetReturn());
|
||||
}
|
||||
|
||||
ASSERT_EQ(
|
||||
vertex->GetProperty(5, storage::View::NEW).GetReturn().ValueString(),
|
||||
"nandare");
|
||||
{
|
||||
auto properties = vertex->Properties(storage::View::NEW).GetReturn();
|
||||
ASSERT_EQ(properties.size(), 1);
|
||||
ASSERT_EQ(properties[5].ValueString(), "nandare");
|
||||
}
|
||||
|
||||
acc.Commit();
|
||||
}
|
||||
|
||||
// Check that property 5 is "nandare".
|
||||
{
|
||||
auto acc = store.Access();
|
||||
auto vertex = acc.FindVertex(gid, storage::View::OLD);
|
||||
ASSERT_TRUE(vertex);
|
||||
|
||||
ASSERT_EQ(
|
||||
vertex->GetProperty(5, storage::View::OLD).GetReturn().ValueString(),
|
||||
"nandare");
|
||||
{
|
||||
auto properties = vertex->Properties(storage::View::OLD).GetReturn();
|
||||
ASSERT_EQ(properties.size(), 1);
|
||||
ASSERT_EQ(properties[5].ValueString(), "nandare");
|
||||
}
|
||||
|
||||
ASSERT_EQ(
|
||||
vertex->GetProperty(5, storage::View::NEW).GetReturn().ValueString(),
|
||||
"nandare");
|
||||
{
|
||||
auto properties = vertex->Properties(storage::View::NEW).GetReturn();
|
||||
ASSERT_EQ(properties.size(), 1);
|
||||
ASSERT_EQ(properties[5].ValueString(), "nandare");
|
||||
}
|
||||
|
||||
ASSERT_TRUE(
|
||||
vertex->GetProperty(10, storage::View::OLD).GetReturn().IsNull());
|
||||
ASSERT_TRUE(
|
||||
vertex->GetProperty(10, storage::View::NEW).GetReturn().IsNull());
|
||||
|
||||
acc.Abort();
|
||||
}
|
||||
|
||||
// Set property 5 to null, but abort the transaction.
|
||||
{
|
||||
auto acc = store.Access();
|
||||
auto vertex = acc.FindVertex(gid, storage::View::OLD);
|
||||
ASSERT_TRUE(vertex);
|
||||
|
||||
ASSERT_EQ(
|
||||
vertex->GetProperty(5, storage::View::OLD).GetReturn().ValueString(),
|
||||
"nandare");
|
||||
{
|
||||
auto properties = vertex->Properties(storage::View::OLD).GetReturn();
|
||||
ASSERT_EQ(properties.size(), 1);
|
||||
ASSERT_EQ(properties[5].ValueString(), "nandare");
|
||||
}
|
||||
|
||||
ASSERT_EQ(
|
||||
vertex->GetProperty(5, storage::View::NEW).GetReturn().ValueString(),
|
||||
"nandare");
|
||||
{
|
||||
auto properties = vertex->Properties(storage::View::NEW).GetReturn();
|
||||
ASSERT_EQ(properties.size(), 1);
|
||||
ASSERT_EQ(properties[5].ValueString(), "nandare");
|
||||
}
|
||||
|
||||
{
|
||||
auto res = vertex->SetProperty(5, storage::PropertyValue());
|
||||
ASSERT_TRUE(res.IsReturn());
|
||||
ASSERT_TRUE(res.GetReturn());
|
||||
}
|
||||
|
||||
ASSERT_EQ(
|
||||
vertex->GetProperty(5, storage::View::OLD).GetReturn().ValueString(),
|
||||
"nandare");
|
||||
{
|
||||
auto properties = vertex->Properties(storage::View::OLD).GetReturn();
|
||||
ASSERT_EQ(properties.size(), 1);
|
||||
ASSERT_EQ(properties[5].ValueString(), "nandare");
|
||||
}
|
||||
|
||||
ASSERT_TRUE(
|
||||
vertex->GetProperty(5, storage::View::NEW).GetReturn().IsNull());
|
||||
ASSERT_EQ(vertex->Properties(storage::View::NEW).GetReturn().size(), 0);
|
||||
|
||||
acc.Abort();
|
||||
}
|
||||
|
||||
// Check that property 5 is "nandare".
|
||||
{
|
||||
auto acc = store.Access();
|
||||
auto vertex = acc.FindVertex(gid, storage::View::OLD);
|
||||
ASSERT_TRUE(vertex);
|
||||
|
||||
ASSERT_EQ(
|
||||
vertex->GetProperty(5, storage::View::OLD).GetReturn().ValueString(),
|
||||
"nandare");
|
||||
{
|
||||
auto properties = vertex->Properties(storage::View::OLD).GetReturn();
|
||||
ASSERT_EQ(properties.size(), 1);
|
||||
ASSERT_EQ(properties[5].ValueString(), "nandare");
|
||||
}
|
||||
|
||||
ASSERT_EQ(
|
||||
vertex->GetProperty(5, storage::View::NEW).GetReturn().ValueString(),
|
||||
"nandare");
|
||||
{
|
||||
auto properties = vertex->Properties(storage::View::NEW).GetReturn();
|
||||
ASSERT_EQ(properties.size(), 1);
|
||||
ASSERT_EQ(properties[5].ValueString(), "nandare");
|
||||
}
|
||||
|
||||
ASSERT_TRUE(
|
||||
vertex->GetProperty(10, storage::View::OLD).GetReturn().IsNull());
|
||||
ASSERT_TRUE(
|
||||
vertex->GetProperty(10, storage::View::NEW).GetReturn().IsNull());
|
||||
|
||||
acc.Abort();
|
||||
}
|
||||
|
||||
// Set property 5 to null.
|
||||
{
|
||||
auto acc = store.Access();
|
||||
auto vertex = acc.FindVertex(gid, storage::View::OLD);
|
||||
ASSERT_TRUE(vertex);
|
||||
|
||||
ASSERT_EQ(
|
||||
vertex->GetProperty(5, storage::View::OLD).GetReturn().ValueString(),
|
||||
"nandare");
|
||||
{
|
||||
auto properties = vertex->Properties(storage::View::OLD).GetReturn();
|
||||
ASSERT_EQ(properties.size(), 1);
|
||||
ASSERT_EQ(properties[5].ValueString(), "nandare");
|
||||
}
|
||||
|
||||
ASSERT_EQ(
|
||||
vertex->GetProperty(5, storage::View::NEW).GetReturn().ValueString(),
|
||||
"nandare");
|
||||
{
|
||||
auto properties = vertex->Properties(storage::View::NEW).GetReturn();
|
||||
ASSERT_EQ(properties.size(), 1);
|
||||
ASSERT_EQ(properties[5].ValueString(), "nandare");
|
||||
}
|
||||
|
||||
{
|
||||
auto res = vertex->SetProperty(5, storage::PropertyValue());
|
||||
ASSERT_TRUE(res.IsReturn());
|
||||
ASSERT_TRUE(res.GetReturn());
|
||||
}
|
||||
|
||||
ASSERT_EQ(
|
||||
vertex->GetProperty(5, storage::View::OLD).GetReturn().ValueString(),
|
||||
"nandare");
|
||||
{
|
||||
auto properties = vertex->Properties(storage::View::OLD).GetReturn();
|
||||
ASSERT_EQ(properties.size(), 1);
|
||||
ASSERT_EQ(properties[5].ValueString(), "nandare");
|
||||
}
|
||||
|
||||
ASSERT_TRUE(
|
||||
vertex->GetProperty(5, storage::View::NEW).GetReturn().IsNull());
|
||||
ASSERT_EQ(vertex->Properties(storage::View::NEW).GetReturn().size(), 0);
|
||||
|
||||
acc.Commit();
|
||||
}
|
||||
|
||||
// Check that property 5 is null.
|
||||
{
|
||||
auto acc = store.Access();
|
||||
auto vertex = acc.FindVertex(gid, storage::View::OLD);
|
||||
ASSERT_TRUE(vertex);
|
||||
|
||||
ASSERT_TRUE(
|
||||
vertex->GetProperty(5, storage::View::OLD).GetReturn().IsNull());
|
||||
ASSERT_TRUE(
|
||||
vertex->GetProperty(5, storage::View::NEW).GetReturn().IsNull());
|
||||
ASSERT_EQ(vertex->Properties(storage::View::OLD).GetReturn().size(), 0);
|
||||
ASSERT_EQ(vertex->Properties(storage::View::NEW).GetReturn().size(), 0);
|
||||
|
||||
ASSERT_TRUE(
|
||||
vertex->GetProperty(10, storage::View::OLD).GetReturn().IsNull());
|
||||
ASSERT_TRUE(
|
||||
vertex->GetProperty(10, storage::View::NEW).GetReturn().IsNull());
|
||||
|
||||
acc.Abort();
|
||||
}
|
||||
}
|
||||
|
||||
// NOLINTNEXTLINE(hicpp-special-member-functions)
|
||||
TEST(StorageV2, VertexPropertySerializationError) {
|
||||
storage::Storage store;
|
||||
storage::Gid gid =
|
||||
storage::Gid::FromUint(std::numeric_limits<uint64_t>::max());
|
||||
{
|
||||
auto acc = store.Access();
|
||||
auto vertex = acc.CreateVertex();
|
||||
gid = vertex.Gid();
|
||||
acc.Commit();
|
||||
}
|
||||
|
||||
auto acc1 = store.Access();
|
||||
auto acc2 = store.Access();
|
||||
|
||||
// Set property 1 to 123 in accessor 1.
|
||||
{
|
||||
auto vertex = acc1.FindVertex(gid, storage::View::OLD);
|
||||
ASSERT_TRUE(vertex);
|
||||
|
||||
ASSERT_TRUE(
|
||||
vertex->GetProperty(1, storage::View::OLD).GetReturn().IsNull());
|
||||
ASSERT_TRUE(
|
||||
vertex->GetProperty(1, storage::View::NEW).GetReturn().IsNull());
|
||||
ASSERT_TRUE(
|
||||
vertex->GetProperty(2, storage::View::OLD).GetReturn().IsNull());
|
||||
ASSERT_TRUE(
|
||||
vertex->GetProperty(2, storage::View::NEW).GetReturn().IsNull());
|
||||
ASSERT_EQ(vertex->Properties(storage::View::OLD).GetReturn().size(), 0);
|
||||
ASSERT_EQ(vertex->Properties(storage::View::NEW).GetReturn().size(), 0);
|
||||
|
||||
{
|
||||
auto res = vertex->SetProperty(1, storage::PropertyValue(123));
|
||||
ASSERT_TRUE(res.IsReturn());
|
||||
ASSERT_FALSE(res.GetReturn());
|
||||
}
|
||||
|
||||
ASSERT_TRUE(
|
||||
vertex->GetProperty(1, storage::View::OLD).GetReturn().IsNull());
|
||||
ASSERT_EQ(vertex->GetProperty(1, storage::View::NEW).GetReturn().ValueInt(),
|
||||
123);
|
||||
ASSERT_TRUE(
|
||||
vertex->GetProperty(2, storage::View::OLD).GetReturn().IsNull());
|
||||
ASSERT_TRUE(
|
||||
vertex->GetProperty(2, storage::View::NEW).GetReturn().IsNull());
|
||||
ASSERT_EQ(vertex->Properties(storage::View::OLD).GetReturn().size(), 0);
|
||||
{
|
||||
auto properties = vertex->Properties(storage::View::NEW).GetReturn();
|
||||
ASSERT_EQ(properties.size(), 1);
|
||||
ASSERT_EQ(properties[1].ValueInt(), 123);
|
||||
}
|
||||
}
|
||||
|
||||
// Set property 2 to "nandare" in accessor 2.
|
||||
{
|
||||
auto vertex = acc2.FindVertex(gid, storage::View::OLD);
|
||||
ASSERT_TRUE(vertex);
|
||||
|
||||
ASSERT_TRUE(
|
||||
vertex->GetProperty(1, storage::View::OLD).GetReturn().IsNull());
|
||||
ASSERT_TRUE(
|
||||
vertex->GetProperty(1, storage::View::NEW).GetReturn().IsNull());
|
||||
ASSERT_TRUE(
|
||||
vertex->GetProperty(2, storage::View::OLD).GetReturn().IsNull());
|
||||
ASSERT_TRUE(
|
||||
vertex->GetProperty(2, storage::View::NEW).GetReturn().IsNull());
|
||||
ASSERT_EQ(vertex->Properties(storage::View::OLD).GetReturn().size(), 0);
|
||||
ASSERT_EQ(vertex->Properties(storage::View::NEW).GetReturn().size(), 0);
|
||||
|
||||
{
|
||||
auto res = vertex->SetProperty(2, storage::PropertyValue("nandare"));
|
||||
ASSERT_TRUE(res.IsError());
|
||||
ASSERT_EQ(res.GetError(), storage::Error::SERIALIZATION_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
// Finalize both accessors.
|
||||
acc1.Commit();
|
||||
acc2.Abort();
|
||||
|
||||
// Check which properties exist.
|
||||
{
|
||||
auto acc = store.Access();
|
||||
auto vertex = acc.FindVertex(gid, storage::View::OLD);
|
||||
ASSERT_TRUE(vertex);
|
||||
|
||||
ASSERT_EQ(vertex->GetProperty(1, storage::View::OLD).GetReturn().ValueInt(),
|
||||
123);
|
||||
ASSERT_TRUE(
|
||||
vertex->GetProperty(2, storage::View::OLD).GetReturn().IsNull());
|
||||
{
|
||||
auto properties = vertex->Properties(storage::View::OLD).GetReturn();
|
||||
ASSERT_EQ(properties.size(), 1);
|
||||
ASSERT_EQ(properties[1].ValueInt(), 123);
|
||||
}
|
||||
|
||||
ASSERT_EQ(vertex->GetProperty(1, storage::View::NEW).GetReturn().ValueInt(),
|
||||
123);
|
||||
ASSERT_TRUE(
|
||||
vertex->GetProperty(2, storage::View::NEW).GetReturn().IsNull());
|
||||
{
|
||||
auto properties = vertex->Properties(storage::View::NEW).GetReturn();
|
||||
ASSERT_EQ(properties.size(), 1);
|
||||
ASSERT_EQ(properties[1].ValueInt(), 123);
|
||||
}
|
||||
|
||||
acc.Abort();
|
||||
}
|
||||
}
|
||||
|
||||
// NOLINTNEXTLINE(hicpp-special-member-functions)
|
||||
TEST(StorageV2, VertexLabelPropertyMixed) {
|
||||
storage::Storage store;
|
||||
auto acc = store.Access();
|
||||
auto vertex = acc.CreateVertex();
|
||||
|
||||
// Check whether label 5 and property 5 exist
|
||||
ASSERT_FALSE(vertex.HasLabel(5, storage::View::NEW).GetReturn());
|
||||
ASSERT_EQ(vertex.Labels(storage::View::NEW).GetReturn().size(), 0);
|
||||
ASSERT_TRUE(vertex.GetProperty(5, storage::View::NEW).GetReturn().IsNull());
|
||||
ASSERT_EQ(vertex.Properties(storage::View::NEW).GetReturn().size(), 0);
|
||||
|
||||
// Add label 5
|
||||
ASSERT_TRUE(vertex.AddLabel(5).GetReturn());
|
||||
|
||||
// Check whether label 5 and property 5 exist
|
||||
ASSERT_TRUE(vertex.HasLabel(5, storage::View::NEW).GetReturn());
|
||||
{
|
||||
auto labels = vertex.Labels(storage::View::NEW).GetReturn();
|
||||
ASSERT_EQ(labels.size(), 1);
|
||||
ASSERT_EQ(labels[0], 5);
|
||||
}
|
||||
ASSERT_TRUE(vertex.GetProperty(5, storage::View::NEW).GetReturn().IsNull());
|
||||
ASSERT_EQ(vertex.Properties(storage::View::NEW).GetReturn().size(), 0);
|
||||
|
||||
// Advance command
|
||||
acc.AdvanceCommand();
|
||||
|
||||
// Check whether label 5 and property 5 exist
|
||||
ASSERT_TRUE(vertex.HasLabel(5, storage::View::OLD).GetReturn());
|
||||
ASSERT_TRUE(vertex.HasLabel(5, storage::View::NEW).GetReturn());
|
||||
{
|
||||
auto labels = vertex.Labels(storage::View::OLD).GetReturn();
|
||||
ASSERT_EQ(labels.size(), 1);
|
||||
ASSERT_EQ(labels[0], 5);
|
||||
}
|
||||
{
|
||||
auto labels = vertex.Labels(storage::View::NEW).GetReturn();
|
||||
ASSERT_EQ(labels.size(), 1);
|
||||
ASSERT_EQ(labels[0], 5);
|
||||
}
|
||||
ASSERT_TRUE(vertex.GetProperty(5, storage::View::OLD).GetReturn().IsNull());
|
||||
ASSERT_TRUE(vertex.GetProperty(5, storage::View::NEW).GetReturn().IsNull());
|
||||
ASSERT_EQ(vertex.Properties(storage::View::OLD).GetReturn().size(), 0);
|
||||
ASSERT_EQ(vertex.Properties(storage::View::NEW).GetReturn().size(), 0);
|
||||
|
||||
// Set property 5 to "nandare"
|
||||
ASSERT_FALSE(
|
||||
vertex.SetProperty(5, storage::PropertyValue("nandare")).GetReturn());
|
||||
|
||||
// Check whether label 5 and property 5 exist
|
||||
ASSERT_TRUE(vertex.HasLabel(5, storage::View::OLD).GetReturn());
|
||||
ASSERT_TRUE(vertex.HasLabel(5, storage::View::NEW).GetReturn());
|
||||
{
|
||||
auto labels = vertex.Labels(storage::View::OLD).GetReturn();
|
||||
ASSERT_EQ(labels.size(), 1);
|
||||
ASSERT_EQ(labels[0], 5);
|
||||
}
|
||||
{
|
||||
auto labels = vertex.Labels(storage::View::NEW).GetReturn();
|
||||
ASSERT_EQ(labels.size(), 1);
|
||||
ASSERT_EQ(labels[0], 5);
|
||||
}
|
||||
ASSERT_TRUE(vertex.GetProperty(5, storage::View::OLD).GetReturn().IsNull());
|
||||
ASSERT_EQ(vertex.GetProperty(5, storage::View::NEW).GetReturn().ValueString(),
|
||||
"nandare");
|
||||
ASSERT_EQ(vertex.Properties(storage::View::OLD).GetReturn().size(), 0);
|
||||
{
|
||||
auto properties = vertex.Properties(storage::View::NEW).GetReturn();
|
||||
ASSERT_EQ(properties.size(), 1);
|
||||
ASSERT_EQ(properties[5].ValueString(), "nandare");
|
||||
}
|
||||
|
||||
// Advance command
|
||||
acc.AdvanceCommand();
|
||||
|
||||
// Check whether label 5 and property 5 exist
|
||||
ASSERT_TRUE(vertex.HasLabel(5, storage::View::OLD).GetReturn());
|
||||
ASSERT_TRUE(vertex.HasLabel(5, storage::View::NEW).GetReturn());
|
||||
{
|
||||
auto labels = vertex.Labels(storage::View::OLD).GetReturn();
|
||||
ASSERT_EQ(labels.size(), 1);
|
||||
ASSERT_EQ(labels[0], 5);
|
||||
}
|
||||
{
|
||||
auto labels = vertex.Labels(storage::View::NEW).GetReturn();
|
||||
ASSERT_EQ(labels.size(), 1);
|
||||
ASSERT_EQ(labels[0], 5);
|
||||
}
|
||||
ASSERT_EQ(vertex.GetProperty(5, storage::View::OLD).GetReturn().ValueString(),
|
||||
"nandare");
|
||||
ASSERT_EQ(vertex.GetProperty(5, storage::View::NEW).GetReturn().ValueString(),
|
||||
"nandare");
|
||||
{
|
||||
auto properties = vertex.Properties(storage::View::OLD).GetReturn();
|
||||
ASSERT_EQ(properties.size(), 1);
|
||||
ASSERT_EQ(properties[5].ValueString(), "nandare");
|
||||
}
|
||||
{
|
||||
auto properties = vertex.Properties(storage::View::NEW).GetReturn();
|
||||
ASSERT_EQ(properties.size(), 1);
|
||||
ASSERT_EQ(properties[5].ValueString(), "nandare");
|
||||
}
|
||||
|
||||
// Set property 5 to "haihai"
|
||||
ASSERT_TRUE(
|
||||
vertex.SetProperty(5, storage::PropertyValue("haihai")).GetReturn());
|
||||
|
||||
// Check whether label 5 and property 5 exist
|
||||
ASSERT_TRUE(vertex.HasLabel(5, storage::View::OLD).GetReturn());
|
||||
ASSERT_TRUE(vertex.HasLabel(5, storage::View::NEW).GetReturn());
|
||||
{
|
||||
auto labels = vertex.Labels(storage::View::OLD).GetReturn();
|
||||
ASSERT_EQ(labels.size(), 1);
|
||||
ASSERT_EQ(labels[0], 5);
|
||||
}
|
||||
{
|
||||
auto labels = vertex.Labels(storage::View::NEW).GetReturn();
|
||||
ASSERT_EQ(labels.size(), 1);
|
||||
ASSERT_EQ(labels[0], 5);
|
||||
}
|
||||
ASSERT_EQ(vertex.GetProperty(5, storage::View::OLD).GetReturn().ValueString(),
|
||||
"nandare");
|
||||
ASSERT_EQ(vertex.GetProperty(5, storage::View::NEW).GetReturn().ValueString(),
|
||||
"haihai");
|
||||
{
|
||||
auto properties = vertex.Properties(storage::View::OLD).GetReturn();
|
||||
ASSERT_EQ(properties.size(), 1);
|
||||
ASSERT_EQ(properties[5].ValueString(), "nandare");
|
||||
}
|
||||
{
|
||||
auto properties = vertex.Properties(storage::View::NEW).GetReturn();
|
||||
ASSERT_EQ(properties.size(), 1);
|
||||
ASSERT_EQ(properties[5].ValueString(), "haihai");
|
||||
}
|
||||
|
||||
// Advance command
|
||||
acc.AdvanceCommand();
|
||||
|
||||
// Check whether label 5 and property 5 exist
|
||||
ASSERT_TRUE(vertex.HasLabel(5, storage::View::OLD).GetReturn());
|
||||
ASSERT_TRUE(vertex.HasLabel(5, storage::View::NEW).GetReturn());
|
||||
{
|
||||
auto labels = vertex.Labels(storage::View::OLD).GetReturn();
|
||||
ASSERT_EQ(labels.size(), 1);
|
||||
ASSERT_EQ(labels[0], 5);
|
||||
}
|
||||
{
|
||||
auto labels = vertex.Labels(storage::View::NEW).GetReturn();
|
||||
ASSERT_EQ(labels.size(), 1);
|
||||
ASSERT_EQ(labels[0], 5);
|
||||
}
|
||||
ASSERT_EQ(vertex.GetProperty(5, storage::View::OLD).GetReturn().ValueString(),
|
||||
"haihai");
|
||||
ASSERT_EQ(vertex.GetProperty(5, storage::View::NEW).GetReturn().ValueString(),
|
||||
"haihai");
|
||||
{
|
||||
auto properties = vertex.Properties(storage::View::OLD).GetReturn();
|
||||
ASSERT_EQ(properties.size(), 1);
|
||||
ASSERT_EQ(properties[5].ValueString(), "haihai");
|
||||
}
|
||||
{
|
||||
auto properties = vertex.Properties(storage::View::NEW).GetReturn();
|
||||
ASSERT_EQ(properties.size(), 1);
|
||||
ASSERT_EQ(properties[5].ValueString(), "haihai");
|
||||
}
|
||||
|
||||
// Remove label 5
|
||||
ASSERT_TRUE(vertex.RemoveLabel(5).GetReturn());
|
||||
|
||||
// Check whether label 5 and property 5 exist
|
||||
ASSERT_TRUE(vertex.HasLabel(5, storage::View::OLD).GetReturn());
|
||||
ASSERT_FALSE(vertex.HasLabel(5, storage::View::NEW).GetReturn());
|
||||
{
|
||||
auto labels = vertex.Labels(storage::View::OLD).GetReturn();
|
||||
ASSERT_EQ(labels.size(), 1);
|
||||
ASSERT_EQ(labels[0], 5);
|
||||
}
|
||||
ASSERT_EQ(vertex.Labels(storage::View::NEW).GetReturn().size(), 0);
|
||||
ASSERT_EQ(vertex.GetProperty(5, storage::View::OLD).GetReturn().ValueString(),
|
||||
"haihai");
|
||||
ASSERT_EQ(vertex.GetProperty(5, storage::View::NEW).GetReturn().ValueString(),
|
||||
"haihai");
|
||||
{
|
||||
auto properties = vertex.Properties(storage::View::OLD).GetReturn();
|
||||
ASSERT_EQ(properties.size(), 1);
|
||||
ASSERT_EQ(properties[5].ValueString(), "haihai");
|
||||
}
|
||||
{
|
||||
auto properties = vertex.Properties(storage::View::NEW).GetReturn();
|
||||
ASSERT_EQ(properties.size(), 1);
|
||||
ASSERT_EQ(properties[5].ValueString(), "haihai");
|
||||
}
|
||||
|
||||
// Advance command
|
||||
acc.AdvanceCommand();
|
||||
|
||||
// Check whether label 5 and property 5 exist
|
||||
ASSERT_FALSE(vertex.HasLabel(5, storage::View::OLD).GetReturn());
|
||||
ASSERT_FALSE(vertex.HasLabel(5, storage::View::NEW).GetReturn());
|
||||
ASSERT_EQ(vertex.Labels(storage::View::OLD).GetReturn().size(), 0);
|
||||
ASSERT_EQ(vertex.Labels(storage::View::NEW).GetReturn().size(), 0);
|
||||
ASSERT_EQ(vertex.GetProperty(5, storage::View::OLD).GetReturn().ValueString(),
|
||||
"haihai");
|
||||
ASSERT_EQ(vertex.GetProperty(5, storage::View::NEW).GetReturn().ValueString(),
|
||||
"haihai");
|
||||
{
|
||||
auto properties = vertex.Properties(storage::View::OLD).GetReturn();
|
||||
ASSERT_EQ(properties.size(), 1);
|
||||
ASSERT_EQ(properties[5].ValueString(), "haihai");
|
||||
}
|
||||
{
|
||||
auto properties = vertex.Properties(storage::View::NEW).GetReturn();
|
||||
ASSERT_EQ(properties.size(), 1);
|
||||
ASSERT_EQ(properties[5].ValueString(), "haihai");
|
||||
}
|
||||
|
||||
// Set property 5 to null
|
||||
ASSERT_TRUE(vertex.SetProperty(5, storage::PropertyValue()).GetReturn());
|
||||
|
||||
// Check whether label 5 and property 5 exist
|
||||
ASSERT_FALSE(vertex.HasLabel(5, storage::View::OLD).GetReturn());
|
||||
ASSERT_FALSE(vertex.HasLabel(5, storage::View::NEW).GetReturn());
|
||||
ASSERT_EQ(vertex.Labels(storage::View::OLD).GetReturn().size(), 0);
|
||||
ASSERT_EQ(vertex.Labels(storage::View::NEW).GetReturn().size(), 0);
|
||||
ASSERT_EQ(vertex.GetProperty(5, storage::View::OLD).GetReturn().ValueString(),
|
||||
"haihai");
|
||||
ASSERT_TRUE(vertex.GetProperty(5, storage::View::NEW).GetReturn().IsNull());
|
||||
{
|
||||
auto properties = vertex.Properties(storage::View::OLD).GetReturn();
|
||||
ASSERT_EQ(properties.size(), 1);
|
||||
ASSERT_EQ(properties[5].ValueString(), "haihai");
|
||||
}
|
||||
ASSERT_EQ(vertex.Properties(storage::View::NEW).GetReturn().size(), 0);
|
||||
|
||||
// Advance command
|
||||
acc.AdvanceCommand();
|
||||
|
||||
// Check whether label 5 and property 5 exist
|
||||
ASSERT_FALSE(vertex.HasLabel(5, storage::View::OLD).GetReturn());
|
||||
ASSERT_FALSE(vertex.HasLabel(5, storage::View::NEW).GetReturn());
|
||||
ASSERT_EQ(vertex.Labels(storage::View::OLD).GetReturn().size(), 0);
|
||||
ASSERT_EQ(vertex.Labels(storage::View::NEW).GetReturn().size(), 0);
|
||||
ASSERT_TRUE(vertex.GetProperty(5, storage::View::NEW).GetReturn().IsNull());
|
||||
ASSERT_TRUE(vertex.GetProperty(5, storage::View::NEW).GetReturn().IsNull());
|
||||
ASSERT_EQ(vertex.Properties(storage::View::OLD).GetReturn().size(), 0);
|
||||
ASSERT_EQ(vertex.Properties(storage::View::NEW).GetReturn().size(), 0);
|
||||
|
||||
acc.Commit();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user