Constraint code cleanup
Summary: Refactor tests, remove some test cases, refactor some methods in `GraphDbAccessor`. Reviewers: msantl Reviewed By: msantl Subscribers: pullbot Differential Revision: https://phabricator.memgraph.io/D1933
This commit is contained in:
parent
dc231fe4e7
commit
2a63e2f12d
18
src/database/single_node/exceptions.hpp
Normal file
18
src/database/single_node/exceptions.hpp
Normal file
@ -0,0 +1,18 @@
|
||||
/// @file
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "utils/exceptions.hpp"
|
||||
|
||||
namespace database {
|
||||
/// Thrown when creating an index which already exists.
|
||||
class IndexExistsException : public utils::BasicException {
|
||||
using utils::BasicException::BasicException;
|
||||
};
|
||||
|
||||
/// Thrown on concurrent index creation when the transaction engine fails to
|
||||
/// start a new transaction.
|
||||
class IndexTransactionException : public utils::BasicException {
|
||||
using utils::BasicException::BasicException;
|
||||
};
|
||||
} // namespace database
|
@ -255,9 +255,9 @@ GraphDbAccessor::ListUniqueLabelPropertyConstraints() const {
|
||||
return db_.storage().unique_label_property_constraints_.ListConstraints();
|
||||
}
|
||||
|
||||
void GraphDbAccessor::UpdateLabelIndices(storage::Label label,
|
||||
const VertexAccessor &vertex_accessor,
|
||||
const Vertex *vertex) {
|
||||
void GraphDbAccessor::UpdateOnAddLabel(storage::Label label,
|
||||
const VertexAccessor &vertex_accessor,
|
||||
const Vertex *vertex) {
|
||||
DCHECK(!commited_ && !aborted_) << "Accessor committed or aborted";
|
||||
auto *vlist_ptr = vertex_accessor.address();
|
||||
|
||||
@ -284,7 +284,7 @@ void GraphDbAccessor::UpdateOnRemoveLabel(
|
||||
label, accessor, transaction());
|
||||
}
|
||||
|
||||
void GraphDbAccessor::UpdatePropertyIndex(
|
||||
void GraphDbAccessor::UpdateOnAddProperty(
|
||||
storage::Property property, const PropertyValue &value,
|
||||
const RecordAccessor<Vertex> &vertex_accessor, const Vertex *vertex) {
|
||||
DCHECK(!commited_ && !aborted_) << "Accessor committed or aborted";
|
||||
@ -299,9 +299,9 @@ void GraphDbAccessor::UpdatePropertyIndex(
|
||||
}
|
||||
}
|
||||
|
||||
void GraphDbAccessor::UpdateOnPropertyRemove(
|
||||
storage::Property property, const Vertex *vertex,
|
||||
const RecordAccessor<Vertex> &accessor) {
|
||||
void GraphDbAccessor::UpdateOnRemoveProperty(
|
||||
storage::Property property, const RecordAccessor<Vertex> &accessor,
|
||||
const Vertex *vertex) {
|
||||
db_.storage().unique_label_property_constraints_.UpdateOnRemoveProperty(
|
||||
property, accessor, transaction());
|
||||
|
||||
@ -316,7 +316,7 @@ void GraphDbAccessor::BuildExistenceConstraint(
|
||||
storage::Label label, const std::vector<storage::Property> &properties) {
|
||||
auto dba =
|
||||
db_.AccessBlocking(std::experimental::make_optional(transaction().id_));
|
||||
ExistenceRule rule{label, properties};
|
||||
storage::constraints::ExistenceRule rule{label, properties};
|
||||
|
||||
for (auto v : dba->Vertices(false)) {
|
||||
if (!CheckIfSatisfiesExistenceRule(v.GetOld(), rule)) {
|
||||
@ -326,7 +326,10 @@ void GraphDbAccessor::BuildExistenceConstraint(
|
||||
}
|
||||
}
|
||||
|
||||
if (!db_.storage().existence_constraints_.AddConstraint(rule)) return;
|
||||
if (!db_.storage().existence_constraints_.AddConstraint(rule)) {
|
||||
// Already exists
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<std::string> property_names(properties.size());
|
||||
std::transform(properties.begin(), properties.end(), property_names.begin(),
|
||||
@ -342,8 +345,11 @@ void GraphDbAccessor::DeleteExistenceConstraint(
|
||||
storage::Label label, const std::vector<storage::Property> &properties) {
|
||||
auto dba =
|
||||
db_.AccessBlocking(std::experimental::make_optional(transaction().id_));
|
||||
ExistenceRule rule{label, properties};
|
||||
if (!db_.storage().existence_constraints_.RemoveConstraint(rule)) return;
|
||||
storage::constraints::ExistenceRule rule{label, properties};
|
||||
if (!db_.storage().existence_constraints_.RemoveConstraint(rule)) {
|
||||
// Nothing was deleted
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<std::string> property_names(properties.size());
|
||||
std::transform(properties.begin(), properties.end(), property_names.begin(),
|
||||
@ -358,12 +364,12 @@ void GraphDbAccessor::DeleteExistenceConstraint(
|
||||
bool GraphDbAccessor::ExistenceConstraintExists(
|
||||
storage::Label label,
|
||||
const std::vector<storage::Property> &properties) const {
|
||||
ExistenceRule rule{label, properties};
|
||||
storage::constraints::ExistenceRule rule{label, properties};
|
||||
return db_.storage().existence_constraints_.Exists(rule);
|
||||
}
|
||||
|
||||
std::vector<ExistenceRule> GraphDbAccessor::ExistenceConstraintsList()
|
||||
const {
|
||||
std::vector<storage::constraints::ExistenceRule>
|
||||
GraphDbAccessor::ListExistenceConstraints() const {
|
||||
return db_.storage().existence_constraints_.ListConstraints();
|
||||
}
|
||||
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include <cppitertools/filter.hpp>
|
||||
#include <cppitertools/imap.hpp>
|
||||
|
||||
#include "database/single_node/exceptions.hpp"
|
||||
#include "database/single_node/graph_db.hpp"
|
||||
#include "storage/common/types/types.hpp"
|
||||
#include "storage/single_node/constraints/exceptions.hpp"
|
||||
@ -19,26 +20,8 @@
|
||||
#include "transactions/transaction.hpp"
|
||||
#include "transactions/type.hpp"
|
||||
#include "utils/bound.hpp"
|
||||
#include "utils/exceptions.hpp"
|
||||
|
||||
namespace database {
|
||||
|
||||
/** Thrown when creating an index which already exists. */
|
||||
class IndexExistsException : public utils::BasicException {
|
||||
using utils::BasicException::BasicException;
|
||||
};
|
||||
|
||||
/** Thrown when creating an index which already exists. */
|
||||
class IndexCreationOnWorkerException : public utils::BasicException {
|
||||
using utils::BasicException::BasicException;
|
||||
};
|
||||
|
||||
/// Thrown on concurrent index creation when the transaction engine fails to
|
||||
/// start a new transaction.
|
||||
class IndexTransactionException : public utils::BasicException {
|
||||
using utils::BasicException::BasicException;
|
||||
};
|
||||
|
||||
/**
|
||||
* Base accessor for the database object: exposes functions for operating on the
|
||||
* database. All the functions in this class should be self-sufficient: for
|
||||
@ -514,7 +497,8 @@ class GraphDbAccessor {
|
||||
/**
|
||||
* Returns the list of existence constraints currently active.
|
||||
*/
|
||||
std::vector<ExistenceRule> ExistenceConstraintsList() const;
|
||||
std::vector<storage::constraints::ExistenceRule> ListExistenceConstraints()
|
||||
const;
|
||||
|
||||
/**
|
||||
* Return approximate number of all vertices in the database.
|
||||
@ -664,18 +648,6 @@ class GraphDbAccessor {
|
||||
**/
|
||||
std::vector<std::pair<std::string, std::string>> StorageInfo() const;
|
||||
|
||||
/**
|
||||
* Insert this vertex into corresponding label and label+property (if it
|
||||
* exists) index.
|
||||
*
|
||||
* @param label - label with which to insert vertex label record
|
||||
* @param vertex_accessor - vertex_accessor to insert
|
||||
* @param vertex - vertex record to insert
|
||||
*/
|
||||
void UpdateLabelIndices(storage::Label label,
|
||||
const VertexAccessor &vertex_accessor,
|
||||
const Vertex *const vertex);
|
||||
|
||||
private:
|
||||
GraphDb &db_;
|
||||
tx::Transaction &transaction_;
|
||||
@ -687,29 +659,46 @@ class GraphDbAccessor {
|
||||
bool aborted_{false};
|
||||
|
||||
/**
|
||||
* Notifies storage about change.
|
||||
* Notifies storage about a change.
|
||||
*
|
||||
* @param label - label that was added
|
||||
* @param vertex_accessor - vertex_accessor that was updated
|
||||
* @param vertex - vertex that was updated
|
||||
*/
|
||||
void UpdateOnRemoveLabel(storage::Label label,
|
||||
void UpdateOnAddLabel(storage::Label label,
|
||||
const VertexAccessor &vertex_accessor,
|
||||
const Vertex *vertex);
|
||||
|
||||
/**
|
||||
* Notifies storage about a change.
|
||||
*
|
||||
* @param label - label that was removed
|
||||
* @param vertex_accessor - vertex_accessor that was updated
|
||||
*/
|
||||
void UpdateOnRemoveLabel(storage::Label label,
|
||||
const RecordAccessor<Vertex> &accessor);
|
||||
|
||||
/**
|
||||
* Notifies storage about change.
|
||||
* Notifies storage about a change.
|
||||
* @param vertex_accessor - vertex_accessor that was updated
|
||||
* @param vertex - vertex that was updated
|
||||
*/
|
||||
void UpdateOnPropertyRemove(storage::Property property,
|
||||
const Vertex *vertex,
|
||||
const RecordAccessor<Vertex> &accessor);
|
||||
void UpdateOnRemoveProperty(storage::Property property,
|
||||
const RecordAccessor<Vertex> &accessor,
|
||||
const Vertex* vertex);
|
||||
|
||||
/**
|
||||
* Insert this vertex into corresponding any label + 'property' index.
|
||||
* @param property - vertex will be inserted into indexes which contain this
|
||||
* property
|
||||
* @param vertex_accessor - vertex accessor to insert
|
||||
* @param vertex - vertex to insert
|
||||
* Notifies storage about a change.
|
||||
*
|
||||
* @param property - property that was added
|
||||
* @param value - corresponding value that was added
|
||||
* @param vertex_accessor - vertex accessor that was updated
|
||||
* @param vertex - vertex that was updated
|
||||
*/
|
||||
void UpdatePropertyIndex(storage::Property property,
|
||||
void UpdateOnAddProperty(storage::Property property,
|
||||
const PropertyValue &value,
|
||||
const RecordAccessor<Vertex> &vertex_accessor,
|
||||
const Vertex *const vertex);
|
||||
const Vertex *vertex);
|
||||
};
|
||||
|
||||
} // namespace database
|
||||
|
@ -58,7 +58,7 @@ bool Encode(const fs::path &snapshot_file, database::GraphDb &db,
|
||||
// Write existence constraints to snapshoot
|
||||
{
|
||||
std::vector<communication::bolt::Value> existence_constraints;
|
||||
for (const auto &rule : dba.ExistenceConstraintsList()) {
|
||||
for (const auto &rule : dba.ListExistenceConstraints()) {
|
||||
existence_constraints.emplace_back(dba.LabelName(rule.label));
|
||||
existence_constraints.emplace_back(
|
||||
static_cast<int64_t>(rule.properties.size()));
|
||||
|
@ -1,6 +1,6 @@
|
||||
#include "storage/single_node/constraints/existence_constraints.hpp"
|
||||
|
||||
namespace database {
|
||||
namespace storage::constraints {
|
||||
bool Contains(const PropertyValueStore &store,
|
||||
const std::vector<storage::Property> &properties) {
|
||||
for (auto &property : properties) {
|
||||
@ -13,7 +13,7 @@ bool Contains(const PropertyValueStore &store,
|
||||
}
|
||||
|
||||
bool CheckIfSatisfiesExistenceRule(const Vertex *vertex,
|
||||
const database::ExistenceRule &rule) {
|
||||
const ExistenceRule &rule) {
|
||||
if (!utils::Contains(vertex->labels_, rule.label)) return true;
|
||||
if (!Contains(vertex->properties_, rule.properties)) return false;
|
||||
|
||||
@ -69,4 +69,4 @@ bool ExistenceConstraints::CheckOnRemoveProperty(
|
||||
const std::vector<ExistenceRule> &ExistenceConstraints::ListConstraints() const {
|
||||
return constraints_;
|
||||
}
|
||||
} // namespace database
|
||||
} // namespace storage::constraints
|
||||
|
@ -10,7 +10,7 @@
|
||||
#include "storage/single_node/vertex.hpp"
|
||||
#include "transactions/type.hpp"
|
||||
|
||||
namespace database {
|
||||
namespace storage::constraints {
|
||||
|
||||
/// Existence rule defines label -> set of properties rule. This means that
|
||||
/// every vertex with that label has to have every property in the set of
|
||||
@ -30,7 +30,7 @@ struct ExistenceRule {
|
||||
};
|
||||
|
||||
bool CheckIfSatisfiesExistenceRule(const Vertex *vertex,
|
||||
const database::ExistenceRule &rule);
|
||||
const ExistenceRule &rule);
|
||||
|
||||
/// ExistenceConstraints contains all active constrains. Existence constraints
|
||||
/// are restriction on the vertices and are defined by ExistenceRule.
|
||||
@ -84,4 +84,4 @@ class ExistenceConstraints {
|
||||
private:
|
||||
std::vector<ExistenceRule> constraints_;
|
||||
};
|
||||
}; // namespace database
|
||||
}; // namespace storage::constraints
|
||||
|
@ -26,7 +26,7 @@ void RecordAccessor<Vertex>::PropsSet(storage::Property key,
|
||||
auto delta = StateDelta::PropsSetVertex(dba.transaction_id(), gid(), key,
|
||||
dba.PropertyName(key), value);
|
||||
update().properties_.set(key, value);
|
||||
dba.UpdatePropertyIndex(key, value, *this, &update());
|
||||
dba.UpdateOnAddProperty(key, value, *this, &update());
|
||||
db_accessor().wal().Emplace(delta);
|
||||
}
|
||||
|
||||
@ -48,7 +48,7 @@ void RecordAccessor<Vertex>::PropsErase(storage::Property key) {
|
||||
StateDelta::PropsSetVertex(dba.transaction_id(), gid(), key,
|
||||
dba.PropertyName(key), PropertyValue::Null);
|
||||
update().properties_.set(key, PropertyValue::Null);
|
||||
dba.UpdateOnPropertyRemove(key, GetNew(), *this);
|
||||
dba.UpdateOnRemoveProperty(key, *this, GetNew());
|
||||
dba.wal().Emplace(delta);
|
||||
}
|
||||
|
||||
|
@ -78,7 +78,7 @@ class Storage {
|
||||
LabelPropertyIndex label_property_index_;
|
||||
|
||||
// existence constraints
|
||||
ExistenceConstraints existence_constraints_;
|
||||
storage::constraints::ExistenceConstraints existence_constraints_;
|
||||
|
||||
// unique constraints
|
||||
storage::constraints::UniqueLabelPropertyConstraint
|
||||
|
@ -25,7 +25,7 @@ void VertexAccessor::add_label(storage::Label label) {
|
||||
if (!utils::Contains(vertex.labels_, label)) {
|
||||
vertex.labels_.emplace_back(label);
|
||||
dba.wal().Emplace(delta);
|
||||
dba.UpdateLabelIndices(label, *this, &vertex);
|
||||
dba.UpdateOnAddLabel(label, *this, &vertex);
|
||||
}
|
||||
}
|
||||
|
||||
@ -40,6 +40,7 @@ void VertexAccessor::remove_label(storage::Label label) {
|
||||
std::swap(*found, labels.back());
|
||||
labels.pop_back();
|
||||
dba.wal().Emplace(delta);
|
||||
dba.UpdateOnRemoveLabel(label, *this);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -168,8 +168,8 @@ class DbGenerator {
|
||||
|
||||
bool CompareExistenceConstraints(const database::GraphDbAccessor &dba1,
|
||||
const database::GraphDbAccessor &dba2) {
|
||||
auto c1 = dba1.ExistenceConstraintsList();
|
||||
auto c2 = dba2.ExistenceConstraintsList();
|
||||
auto c1 = dba1.ListExistenceConstraints();
|
||||
auto c2 = dba2.ListExistenceConstraints();
|
||||
|
||||
auto compare_prop = [](auto &dba1, auto &p1, auto &dba2, auto &p2) {
|
||||
std::vector<std::string> p1_names;
|
||||
|
@ -4,131 +4,132 @@
|
||||
|
||||
#include "database/single_node/graph_db.hpp"
|
||||
#include "database/single_node/graph_db_accessor.hpp"
|
||||
#include "storage/single_node/constraints/existence_constraints.hpp"
|
||||
|
||||
class ExistenceConstraintsTest : public ::testing::Test {
|
||||
public:
|
||||
void SetUp() override {}
|
||||
database::ExistenceConstraints constraints_;
|
||||
void SetUp() override {
|
||||
auto dba = db_.Access();
|
||||
label_ = dba->Label("label");
|
||||
property_ = dba->Property("property");
|
||||
properties_ = {property_};
|
||||
rule_ = {label_, properties_};
|
||||
dba->Commit();
|
||||
}
|
||||
|
||||
storage::constraints::ExistenceConstraints constraints_;
|
||||
database::GraphDb db_;
|
||||
storage::Label label_;
|
||||
storage::Property property_;
|
||||
std::vector<storage::Property> properties_;
|
||||
storage::constraints::ExistenceRule rule_;
|
||||
};
|
||||
|
||||
TEST_F(ExistenceConstraintsTest, MultiBuildDrop) {
|
||||
auto d = db_.Access();
|
||||
auto label = d->Label("label");
|
||||
auto prop = d->Property("property");
|
||||
database::ExistenceRule rule{label, std::vector<storage::Property>{prop}};
|
||||
d->Commit();
|
||||
|
||||
TEST_F(ExistenceConstraintsTest, BuildDrop) {
|
||||
{
|
||||
auto dba = db_.AccessBlocking();
|
||||
constraints_.AddConstraint(rule);
|
||||
EXPECT_TRUE(constraints_.Exists(rule));
|
||||
auto dba = db_.Access();
|
||||
EXPECT_FALSE(dba->ExistenceConstraintExists(label_, properties_));
|
||||
dba->Commit();
|
||||
}
|
||||
{
|
||||
auto dba = db_.AccessBlocking();
|
||||
constraints_.RemoveConstraint(rule);
|
||||
EXPECT_FALSE(constraints_.Exists(rule));
|
||||
auto dba = db_.Access();
|
||||
dba->BuildExistenceConstraint(label_, properties_);
|
||||
EXPECT_TRUE(dba->ExistenceConstraintExists(label_, properties_));
|
||||
dba->Commit();
|
||||
}
|
||||
{
|
||||
auto dba = db_.Access();
|
||||
dba->DeleteExistenceConstraint(label_, properties_);
|
||||
EXPECT_FALSE(dba->ExistenceConstraintExists(label_, properties_));
|
||||
dba->Commit();
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(ExistenceConstraintsTest, InsertTest) {
|
||||
auto d = db_.Access();
|
||||
auto label = d->Label("label");
|
||||
auto prop = d->Property("property");
|
||||
database::ExistenceRule rule{label, std::vector<storage::Property>{prop}};
|
||||
d->Commit();
|
||||
|
||||
TEST_F(ExistenceConstraintsTest, BuildWithViolation) {
|
||||
{
|
||||
auto dba = db_.Access();
|
||||
auto v = dba->InsertVertex();
|
||||
v.add_label(label);
|
||||
EXPECT_TRUE(constraints_.CheckOnAddLabel(v.GetNew(), label));
|
||||
v.add_label(label_);
|
||||
dba->Commit();
|
||||
}
|
||||
{
|
||||
auto dba = db_.Access();
|
||||
bool can_add_constraint = true;
|
||||
for (auto v : dba->Vertices(false)) {
|
||||
if (!database::CheckIfSatisfiesExistenceRule(v.GetOld(), rule)) {
|
||||
can_add_constraint = false;
|
||||
}
|
||||
}
|
||||
EXPECT_THROW(dba->BuildExistenceConstraint(label_, properties_),
|
||||
database::IndexConstraintViolationException);
|
||||
}
|
||||
}
|
||||
|
||||
EXPECT_FALSE(can_add_constraint);
|
||||
dba->Commit();
|
||||
}
|
||||
{
|
||||
auto dba = db_.AccessBlocking();
|
||||
constraints_.AddConstraint(rule);
|
||||
dba->Commit();
|
||||
}
|
||||
TEST_F(ExistenceConstraintsTest, InsertFail) {
|
||||
{
|
||||
auto dba = db_.Access();
|
||||
auto v1 = dba->InsertVertex();
|
||||
v1.add_label(label);
|
||||
EXPECT_FALSE(
|
||||
constraints_.CheckOnAddLabel(v1.GetNew(), label));
|
||||
auto v2 = dba->InsertVertex();
|
||||
v2.PropsSet(prop, PropertyValue(false));
|
||||
v2.add_label(label);
|
||||
EXPECT_TRUE(constraints_.CheckOnAddLabel(v2.GetNew(), label));
|
||||
dba->Commit();
|
||||
}
|
||||
{
|
||||
auto dba = db_.AccessBlocking();
|
||||
constraints_.RemoveConstraint(rule);
|
||||
dba->BuildExistenceConstraint(label_, properties_);
|
||||
dba->Commit();
|
||||
}
|
||||
{
|
||||
auto dba = db_.Access();
|
||||
auto v = dba->InsertVertex();
|
||||
v.add_label(label);
|
||||
EXPECT_TRUE(constraints_.CheckOnAddLabel(v.GetNew(), label));
|
||||
EXPECT_THROW(v.add_label(label_),
|
||||
database::IndexConstraintViolationException);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(ExistenceConstraintsTest, InsertPass) {
|
||||
{
|
||||
auto dba = db_.Access();
|
||||
dba->BuildExistenceConstraint(label_, properties_);
|
||||
dba->Commit();
|
||||
}
|
||||
{
|
||||
auto dba = db_.Access();
|
||||
auto v = dba->InsertVertex();
|
||||
v.PropsSet(property_, PropertyValue("Something"));
|
||||
v.add_label(label_);
|
||||
dba->Commit();
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(ExistenceConstraintsTest, GraphDbAccessor) {
|
||||
auto d = db_.Access();
|
||||
auto label = d->Label("label");
|
||||
auto prop = d->Property("property");
|
||||
auto properties = std::vector<storage::Property>{prop};
|
||||
d->Commit();
|
||||
TEST_F(ExistenceConstraintsTest, RemoveFail) {
|
||||
{
|
||||
auto dba = db_.Access();
|
||||
dba->BuildExistenceConstraint(label_, properties_);
|
||||
dba->Commit();
|
||||
}
|
||||
gid::Gid gid;
|
||||
{
|
||||
auto dba = db_.Access();
|
||||
auto v = dba->InsertVertex();
|
||||
v.PropsSet(property_, PropertyValue("Something"));
|
||||
v.add_label(label_);
|
||||
gid = v.gid();
|
||||
dba->Commit();
|
||||
}
|
||||
{
|
||||
auto dba = db_.Access();
|
||||
auto v = dba->FindVertex(gid, false);
|
||||
EXPECT_THROW(v.PropsErase(property_),
|
||||
database::IndexConstraintViolationException);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(ExistenceConstraintsTest, RemovePass) {
|
||||
{
|
||||
auto dba = db_.Access();
|
||||
dba->BuildExistenceConstraint(label, properties);
|
||||
// Constraint is not visible because transaction creates blocking
|
||||
// transaction with different id;
|
||||
dba->BuildExistenceConstraint(label_, properties_);
|
||||
dba->Commit();
|
||||
}
|
||||
gid::Gid gid;
|
||||
{
|
||||
auto dba = db_.Access();
|
||||
auto v = dba->InsertVertex();
|
||||
v.PropsSet(property_, PropertyValue("Something"));
|
||||
v.add_label(label_);
|
||||
gid = v.gid();
|
||||
dba->Commit();
|
||||
}
|
||||
{
|
||||
auto dba = db_.Access();
|
||||
EXPECT_TRUE(dba->ExistenceConstraintExists(label, properties));
|
||||
auto v1 = dba->InsertVertex();
|
||||
EXPECT_THROW(v1.add_label(label),
|
||||
database::IndexConstraintViolationException);
|
||||
auto v2 = dba->InsertVertex();
|
||||
v2.PropsSet(prop, PropertyValue(false));
|
||||
v2.add_label(label);
|
||||
EXPECT_THROW(v2.PropsErase(prop),
|
||||
database::IndexConstraintViolationException);
|
||||
v2.remove_label(label);
|
||||
dba->Commit();
|
||||
}
|
||||
{
|
||||
auto dba = db_.Access();
|
||||
dba->DeleteExistenceConstraint(label, properties);
|
||||
dba->Commit();
|
||||
}
|
||||
{
|
||||
auto dba = db_.Access();
|
||||
EXPECT_FALSE(dba->ExistenceConstraintExists(label, properties));
|
||||
auto v1 = dba->InsertVertex();
|
||||
v1.add_label(label);
|
||||
auto v = dba->FindVertex(gid, false);
|
||||
v.remove_label(label_);
|
||||
v.PropsErase(property_);
|
||||
dba->Commit();
|
||||
}
|
||||
}
|
||||
|
@ -4,15 +4,14 @@
|
||||
|
||||
#include "database/single_node/graph_db.hpp"
|
||||
#include "database/single_node/graph_db_accessor.hpp"
|
||||
#include "storage/single_node/constraints/unique_label_property_constraint.hpp"
|
||||
|
||||
class UniqueLabelPropertyTest : public ::testing::Test {
|
||||
public:
|
||||
void SetUp() override {
|
||||
auto dba = db_.AccessBlocking();
|
||||
auto dba = db_.Access();
|
||||
label_ = dba->Label("label");
|
||||
property_ = dba->Property("property");
|
||||
constraint_.AddConstraint(label_, property_, dba->transaction());
|
||||
dba->BuildUniqueConstraint(label_, property_);
|
||||
dba->Commit();
|
||||
}
|
||||
|
||||
@ -20,43 +19,42 @@ class UniqueLabelPropertyTest : public ::testing::Test {
|
||||
storage::Label label_;
|
||||
storage::Property property_;
|
||||
PropertyValue value_{"value"};
|
||||
storage::constraints::UniqueLabelPropertyConstraint constraint_;
|
||||
};
|
||||
|
||||
TEST_F(UniqueLabelPropertyTest, BuildDrop) {
|
||||
{
|
||||
auto dba = db_.Access();
|
||||
EXPECT_TRUE(constraint_.Exists(label_, property_));
|
||||
EXPECT_TRUE(dba->UniqueConstraintExists(label_, property_));
|
||||
dba->Commit();
|
||||
}
|
||||
{
|
||||
auto dba = db_.Access();
|
||||
constraint_.RemoveConstraint(label_, property_);
|
||||
dba->DeleteUniqueConstraint(label_, property_);
|
||||
dba->Commit();
|
||||
}
|
||||
{
|
||||
auto dba = db_.Access();
|
||||
EXPECT_FALSE(constraint_.Exists(label_, property_));
|
||||
EXPECT_FALSE(dba->UniqueConstraintExists(label_, property_));
|
||||
dba->Commit();
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(UniqueLabelPropertyTest, BuildWithViolation) {
|
||||
auto dba1 = db_.Access();
|
||||
auto l1 = dba1->Label("l1");
|
||||
auto p1 = dba1->Property("p1");
|
||||
|
||||
auto v1 = dba1->InsertVertex();
|
||||
v1.add_label(label_);
|
||||
v1.PropsSet(property_, value_);
|
||||
v1.add_label(l1);
|
||||
v1.PropsSet(p1, value_);
|
||||
|
||||
auto v2 = dba1->InsertVertex();
|
||||
v2.add_label(label_);
|
||||
v2.PropsSet(property_, value_);
|
||||
v2.add_label(l1);
|
||||
v2.PropsSet(p1, value_);
|
||||
dba1->Commit();
|
||||
|
||||
auto dba2 = db_.Access();
|
||||
auto v3 = dba2->FindVertex(v1.gid(), false);
|
||||
auto v4 = dba2->FindVertex(v2.gid(), false);
|
||||
constraint_.Update(v3, dba2->transaction());
|
||||
EXPECT_THROW(constraint_.Update(v4, dba2->transaction()),
|
||||
EXPECT_THROW(dba2->BuildUniqueConstraint(l1, p1),
|
||||
database::IndexConstraintViolationException);
|
||||
}
|
||||
|
||||
@ -65,23 +63,15 @@ TEST_F(UniqueLabelPropertyTest, InsertInsert) {
|
||||
auto dba = db_.Access();
|
||||
auto v = dba->InsertVertex();
|
||||
v.add_label(label_);
|
||||
constraint_.UpdateOnAddLabel(label_, v, dba->transaction());
|
||||
v.PropsSet(property_, value_);
|
||||
constraint_.UpdateOnAddProperty(property_, value_, v, dba->transaction());
|
||||
dba->Commit();
|
||||
}
|
||||
{
|
||||
auto dba = db_.Access();
|
||||
auto v = dba->InsertVertex();
|
||||
v.add_label(label_);
|
||||
constraint_.UpdateOnAddLabel(label_, v, dba->transaction());
|
||||
v.PropsSet(property_, value_);
|
||||
EXPECT_THROW(constraint_.UpdateOnAddProperty(property_, value_, v,
|
||||
dba->transaction()),
|
||||
database::IndexConstraintViolationException);
|
||||
EXPECT_THROW(constraint_.UpdateOnAddLabel(label_, v, dba->transaction()),
|
||||
database::IndexConstraintViolationException);
|
||||
dba->Commit();
|
||||
EXPECT_THROW(v.PropsSet(property_, value_),
|
||||
database::IndexConstraintViolationException);
|
||||
}
|
||||
}
|
||||
|
||||
@ -90,9 +80,7 @@ TEST_F(UniqueLabelPropertyTest, InsertInsertDiffValues) {
|
||||
auto dba = db_.Access();
|
||||
auto v = dba->InsertVertex();
|
||||
v.add_label(label_);
|
||||
constraint_.UpdateOnAddLabel(label_, v, dba->transaction());
|
||||
v.PropsSet(property_, value_);
|
||||
constraint_.UpdateOnAddProperty(property_, value_, v, dba->transaction());
|
||||
dba->Commit();
|
||||
}
|
||||
{
|
||||
@ -100,10 +88,7 @@ TEST_F(UniqueLabelPropertyTest, InsertInsertDiffValues) {
|
||||
auto v = dba->InsertVertex();
|
||||
PropertyValue other_value{"Some other value"};
|
||||
v.add_label(label_);
|
||||
constraint_.UpdateOnAddLabel(label_, v, dba->transaction());
|
||||
v.PropsSet(property_, other_value);
|
||||
constraint_.UpdateOnAddProperty(property_, other_value, v,
|
||||
dba->transaction());
|
||||
dba->Commit();
|
||||
}
|
||||
}
|
||||
@ -113,18 +98,14 @@ TEST_F(UniqueLabelPropertyTest, InsertAbortInsert) {
|
||||
auto dba = db_.Access();
|
||||
auto v = dba->InsertVertex();
|
||||
v.add_label(label_);
|
||||
constraint_.UpdateOnAddLabel(label_, v, dba->transaction());
|
||||
v.PropsSet(property_, value_);
|
||||
constraint_.UpdateOnAddProperty(property_, value_, v, dba->transaction());
|
||||
dba->Abort();
|
||||
}
|
||||
{
|
||||
auto dba = db_.Access();
|
||||
auto v = dba->InsertVertex();
|
||||
v.add_label(label_);
|
||||
constraint_.UpdateOnAddLabel(label_, v, dba->transaction());
|
||||
v.PropsSet(property_, value_);
|
||||
constraint_.UpdateOnAddProperty(property_, value_, v, dba->transaction());
|
||||
dba->Commit();
|
||||
}
|
||||
}
|
||||
@ -135,9 +116,7 @@ TEST_F(UniqueLabelPropertyTest, InsertRemoveAbortInsert) {
|
||||
auto dba = db_.Access();
|
||||
auto v = dba->InsertVertex();
|
||||
v.add_label(label_);
|
||||
constraint_.UpdateOnAddLabel(label_, v, dba->transaction());
|
||||
v.PropsSet(property_, value_);
|
||||
constraint_.UpdateOnAddProperty(property_, value_, v, dba->transaction());
|
||||
gid = v.gid();
|
||||
dba->Commit();
|
||||
}
|
||||
@ -145,17 +124,13 @@ TEST_F(UniqueLabelPropertyTest, InsertRemoveAbortInsert) {
|
||||
auto dba = db_.Access();
|
||||
auto v = dba->FindVertex(gid, false);
|
||||
v.PropsErase(property_);
|
||||
constraint_.UpdateOnRemoveProperty(property_, v, dba->transaction());
|
||||
dba->Abort();
|
||||
}
|
||||
{
|
||||
auto dba = db_.Access();
|
||||
auto v = dba->InsertVertex();
|
||||
v.add_label(label_);
|
||||
constraint_.UpdateOnAddLabel(label_, v, dba->transaction());
|
||||
v.PropsSet(property_, value_);
|
||||
EXPECT_THROW(constraint_.UpdateOnAddProperty(property_, value_, v,
|
||||
dba->transaction()),
|
||||
EXPECT_THROW(v.PropsSet(property_, value_),
|
||||
database::IndexConstraintViolationException);
|
||||
}
|
||||
}
|
||||
@ -165,16 +140,11 @@ TEST_F(UniqueLabelPropertyTest, InsertInsertSameTransaction) {
|
||||
auto dba = db_.Access();
|
||||
auto v1 = dba->InsertVertex();
|
||||
v1.add_label(label_);
|
||||
constraint_.UpdateOnAddLabel(label_, v1, dba->transaction());
|
||||
v1.PropsSet(property_, value_);
|
||||
constraint_.UpdateOnAddProperty(property_, value_, v1, dba->transaction());
|
||||
|
||||
auto v2 = dba->InsertVertex();
|
||||
v2.add_label(label_);
|
||||
constraint_.UpdateOnAddLabel(label_, v2, dba->transaction());
|
||||
v2.PropsSet(property_, value_);
|
||||
EXPECT_THROW(constraint_.UpdateOnAddProperty(property_, value_, v2,
|
||||
dba->transaction()),
|
||||
EXPECT_THROW(v2.PropsSet(property_, value_),
|
||||
database::IndexConstraintViolationException);
|
||||
}
|
||||
}
|
||||
@ -185,17 +155,12 @@ TEST_F(UniqueLabelPropertyTest, InsertInsertReversed) {
|
||||
|
||||
auto v2 = dba2->InsertVertex();
|
||||
v2.add_label(label_);
|
||||
constraint_.UpdateOnAddLabel(label_, v2, dba2->transaction());
|
||||
v2.PropsSet(property_, value_);
|
||||
constraint_.UpdateOnAddProperty(property_, value_, v2, dba2->transaction());
|
||||
dba2->Commit();
|
||||
|
||||
auto v1 = dba1->InsertVertex();
|
||||
v1.add_label(label_);
|
||||
constraint_.UpdateOnAddLabel(label_, v1, dba1->transaction());
|
||||
v1.PropsSet(property_, value_);
|
||||
EXPECT_THROW(constraint_.UpdateOnAddProperty(property_, value_, v1,
|
||||
dba1->transaction()),
|
||||
EXPECT_THROW(v1.PropsSet(property_, value_),
|
||||
mvcc::SerializationError);
|
||||
}
|
||||
|
||||
@ -205,9 +170,7 @@ TEST_F(UniqueLabelPropertyTest, InsertRemoveInsert) {
|
||||
auto dba = db_.Access();
|
||||
auto v = dba->InsertVertex();
|
||||
v.add_label(label_);
|
||||
constraint_.UpdateOnAddLabel(label_, v, dba->transaction());
|
||||
v.PropsSet(property_, value_);
|
||||
constraint_.UpdateOnAddProperty(property_, value_, v, dba->transaction());
|
||||
gid = v.gid();
|
||||
dba->Commit();
|
||||
}
|
||||
@ -215,16 +178,13 @@ TEST_F(UniqueLabelPropertyTest, InsertRemoveInsert) {
|
||||
auto dba = db_.Access();
|
||||
auto v = dba->FindVertex(gid, false);
|
||||
v.PropsErase(property_);
|
||||
constraint_.UpdateOnRemoveProperty(property_, v, dba->transaction());
|
||||
dba->Commit();
|
||||
}
|
||||
{
|
||||
auto dba = db_.Access();
|
||||
auto v = dba->InsertVertex();
|
||||
v.add_label(label_);
|
||||
constraint_.UpdateOnAddLabel(label_, v, dba->transaction());
|
||||
v.PropsSet(property_, value_);
|
||||
constraint_.UpdateOnAddProperty(property_, value_, v, dba->transaction());
|
||||
}
|
||||
}
|
||||
|
||||
@ -232,13 +192,9 @@ TEST_F(UniqueLabelPropertyTest, InsertRemoveInsertSameTransaction) {
|
||||
auto dba = db_.Access();
|
||||
auto v = dba->InsertVertex();
|
||||
v.add_label(label_);
|
||||
constraint_.UpdateOnAddLabel(label_, v, dba->transaction());
|
||||
v.PropsSet(property_, value_);
|
||||
constraint_.UpdateOnAddProperty(property_, value_, v, dba->transaction());
|
||||
v.PropsErase(property_);
|
||||
constraint_.UpdateOnRemoveProperty(property_, v, dba->transaction());
|
||||
v.PropsSet(property_, value_);
|
||||
constraint_.UpdateOnAddProperty(property_, value_, v, dba->transaction());
|
||||
dba->Commit();
|
||||
}
|
||||
|
||||
@ -247,23 +203,19 @@ TEST_F(UniqueLabelPropertyTest, InsertDropInsert) {
|
||||
auto dba = db_.Access();
|
||||
auto v = dba->InsertVertex();
|
||||
v.add_label(label_);
|
||||
constraint_.UpdateOnAddLabel(label_, v, dba->transaction());
|
||||
v.PropsSet(property_, value_);
|
||||
constraint_.UpdateOnAddProperty(property_, value_, v, dba->transaction());
|
||||
dba->Commit();
|
||||
}
|
||||
{
|
||||
auto dba = db_.AccessBlocking();
|
||||
constraint_.RemoveConstraint(label_, property_);
|
||||
auto dba = db_.Access();
|
||||
dba->DeleteUniqueConstraint(label_, property_);
|
||||
dba->Commit();
|
||||
}
|
||||
{
|
||||
auto dba = db_.Access();
|
||||
auto v = dba->InsertVertex();
|
||||
v.add_label(label_);
|
||||
constraint_.UpdateOnAddLabel(label_, v, dba->transaction());
|
||||
v.PropsSet(property_, value_);
|
||||
constraint_.UpdateOnAddProperty(property_, value_, v, dba->transaction());
|
||||
dba->Commit();
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user