From d70792f1ce2c4cd6e9b6f8ee50f6655534575658 Mon Sep 17 00:00:00 2001 From: Matija Santl <matija.santl@memgraph.com> Date: Mon, 13 May 2019 13:47:22 +0200 Subject: [PATCH] Remove existence constraint Summary: Removing existence constraint Reviewers: ipaljak, mferencevic, vkasljevic Reviewed By: mferencevic Subscribers: pullbot Differential Revision: https://phabricator.memgraph.io/D2043 --- src/CMakeLists.txt | 1 - src/database/single_node/graph_db.cpp | 2 - .../single_node/graph_db_accessor.cpp | 70 --------- .../single_node/graph_db_accessor.hpp | 25 ---- src/durability/single_node/recovery.cpp | 87 ----------- src/durability/single_node/recovery.hpp | 13 -- src/durability/single_node/snapshooter.cpp | 16 +- src/durability/single_node/state_delta.cpp | 48 ------ src/durability/single_node/state_delta.lcp | 12 -- src/durability/single_node/version.hpp | 14 +- src/durability/single_node/wal.cpp | 2 - src/query/interpreter.cpp | 58 +++---- .../constraints/existence_constraints.hpp | 87 ----------- src/storage/single_node/storage.hpp | 4 - tests/benchmark/CMakeLists.txt | 3 - tests/benchmark/existence_constraint.cpp | 133 ----------------- tests/manual/snapshot_explorer.cpp | 28 +--- tests/manual/wal_explorer.cpp | 4 - tests/unit/CMakeLists.txt | 3 - tests/unit/durability.cpp | 111 -------------- tests/unit/existence_constraints.cpp | 141 ------------------ tools/src/mg_import_csv/main.cpp | 3 +- 22 files changed, 38 insertions(+), 827 deletions(-) delete mode 100644 src/storage/single_node/constraints/existence_constraints.hpp delete mode 100644 tests/benchmark/existence_constraint.cpp delete mode 100644 tests/unit/existence_constraints.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 2628d8bff..b3b855a27 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -69,7 +69,6 @@ set(mg_single_node_sources storage/common/types/property_value_store.cpp storage/single_node/record_accessor.cpp storage/single_node/vertex_accessor.cpp - storage/single_node/constraints/existence_constraints.cpp storage/single_node/constraints/record.cpp storage/single_node/constraints/unique_label_properties_constraint.cpp storage/single_node/constraints/unique_label_property_constraint.cpp diff --git a/src/database/single_node/graph_db.cpp b/src/database/single_node/graph_db.cpp index 333d7a50c..f47bbf598 100644 --- a/src/database/single_node/graph_db.cpp +++ b/src/database/single_node/graph_db.cpp @@ -40,8 +40,6 @@ GraphDb::GraphDb(Config config) : config_(config) { durability::RecoverWal(config_.durability_directory, this, &recovery_data, &recovery_transactions); durability::RecoverIndexes(this, recovery_data.indexes); - durability::RecoverExistenceConstraints( - this, recovery_data.existence_constraints); durability::RecoverUniqueConstraints( this, recovery_data.unique_constraints); } diff --git a/src/database/single_node/graph_db_accessor.cpp b/src/database/single_node/graph_db_accessor.cpp index ba101701c..aa58c6d61 100644 --- a/src/database/single_node/graph_db_accessor.cpp +++ b/src/database/single_node/graph_db_accessor.cpp @@ -291,11 +291,6 @@ void GraphDbAccessor::UpdateOnAddLabel(storage::Label label, "Node couldn't be updated due to index constraint violation!"); } - if (!db_->storage().existence_constraints_.CheckOnAddLabel(vertex, label)) { - throw IndexConstraintViolationException( - "Node couldn't be updated due to existence constraint violation!"); - } - db_->storage().labels_index_.Update(label, vlist_ptr, vertex); } @@ -325,71 +320,6 @@ void GraphDbAccessor::UpdateOnRemoveProperty( const Vertex *vertex) { db_->storage().unique_label_property_constraints_.UpdateOnRemoveProperty( property, accessor, transaction()); - - if (!db_->storage().existence_constraints_.CheckOnRemoveProperty(vertex, - property)) { - throw IndexConstraintViolationException( - "Node couldn't be updated due to existence constraint violation!"); - } -} - -void GraphDbAccessor::BuildExistenceConstraint( - storage::Label label, const std::vector<storage::Property> &properties) { - auto dba = db_->AccessBlocking(std::make_optional(transaction().id_)); - storage::constraints::ExistenceRule rule{label, properties}; - - for (auto v : dba.Vertices(false)) { - if (!CheckIfSatisfiesExistenceRule(v.GetOld(), rule)) { - throw IndexConstraintViolationException( - "Existence constraint couldn't be built because existing data is " - "violating it!"); - } - } - - 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(), - [&dba](auto p) { return dba.PropertyName(p); }); - - dba.wal().Emplace(database::StateDelta::BuildExistenceConstraint( - dba.transaction().id_, label, dba.LabelName(label), properties, - property_names)); - dba.Commit(); -} - -void GraphDbAccessor::DeleteExistenceConstraint( - storage::Label label, const std::vector<storage::Property> &properties) { - auto dba = db_->AccessBlocking(std::make_optional(transaction().id_)); - 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(), - [&dba](auto p) { return dba.PropertyName(p); }); - - dba.wal().Emplace(database::StateDelta::DropExistenceConstraint( - dba.transaction().id_, label, dba.LabelName(label), properties, - property_names)); - dba.Commit(); -} - -bool GraphDbAccessor::ExistenceConstraintExists( - storage::Label label, - const std::vector<storage::Property> &properties) const { - storage::constraints::ExistenceRule rule{label, properties}; - return db_->storage().existence_constraints_.Exists(rule); -} - -std::vector<storage::constraints::ExistenceRule> -GraphDbAccessor::ListExistenceConstraints() const { - return db_->storage().existence_constraints_.ListConstraints(); } int64_t GraphDbAccessor::VerticesCount() const { diff --git a/src/database/single_node/graph_db_accessor.hpp b/src/database/single_node/graph_db_accessor.hpp index c29f4113c..01910af67 100644 --- a/src/database/single_node/graph_db_accessor.hpp +++ b/src/database/single_node/graph_db_accessor.hpp @@ -472,31 +472,6 @@ class GraphDbAccessor { return db_->storage().label_property_index_.Keys(); } - /** - * Creates new existence constraint. - */ - void BuildExistenceConstraint( - storage::Label label, const std::vector<storage::Property> &properties); - - /** - * Deletes existing existence constraint. - */ - void DeleteExistenceConstraint( - storage::Label label, const std::vector<storage::Property> &properties); - - /** - * Checks whether constraint exists. - */ - bool ExistenceConstraintExists( - storage::Label label, - const std::vector<storage::Property> &properties) const; - - /** - * Returns the list of existence constraints currently active. - */ - std::vector<storage::constraints::ExistenceRule> ListExistenceConstraints() - const; - /** * Return approximate number of all vertices in the database. * Note that this is always an over-estimate and never an under-estimate. diff --git a/src/durability/single_node/recovery.cpp b/src/durability/single_node/recovery.cpp index c878677a2..007f5ca9f 100644 --- a/src/durability/single_node/recovery.cpp +++ b/src/durability/single_node/recovery.cpp @@ -150,31 +150,6 @@ bool RecoverSnapshot(const fs::path &snapshot_file, database::GraphDb *db, /*create = */ true, unique.ValueBool()}); } - // Read a list of existence constraints - RETURN_IF_NOT(decoder.ReadValue(&dv, Value::Type::List)); - auto existence_constraints = dv.ValueList(); - for (auto it = existence_constraints.begin(); - it != existence_constraints.end();) { - RETURN_IF_NOT(it->IsString()); - auto label = it->ValueString(); - ++it; - RETURN_IF_NOT(it != existence_constraints.end()); - RETURN_IF_NOT(it->IsInt()); - auto prop_size = it->ValueInt(); - ++it; - std::vector<std::string> properties; - properties.reserve(prop_size); - for (size_t i = 0; i < prop_size; ++i) { - RETURN_IF_NOT(it != existence_constraints.end()); - RETURN_IF_NOT(it->IsString()); - properties.emplace_back(it->ValueString()); - ++it; - } - - recovery_data->existence_constraints.emplace_back( - ExistenceConstraintRecoveryData{label, std::move(properties), true}); - } - // Read a list of unique constraints RETURN_IF_NOT(decoder.ReadValue(&dv, Value::Type::List)); auto unique_constraints = dv.ValueList(); @@ -499,48 +474,6 @@ void RecoverWal(const fs::path &durability_dir, database::GraphDb *db, } break; } - case database::StateDelta::Type::BUILD_EXISTENCE_CONSTRAINT: { - auto drop_it = std::find_if( - recovery_data->existence_constraints.begin(), - recovery_data->existence_constraints.end(), - [&delta](const ExistenceConstraintRecoveryData &data) { - return data.label == delta.label_name && - std::is_permutation(data.properties.begin(), - data.properties.end(), - delta.property_names.begin()) && - data.create == false; - }); - - if (drop_it != recovery_data->existence_constraints.end()) { - recovery_data->existence_constraints.erase(drop_it); - } else { - recovery_data->existence_constraints.emplace_back( - ExistenceConstraintRecoveryData{delta.label_name, - delta.property_names, true}); - } - break; - } - case database::StateDelta::Type::DROP_EXISTENCE_CONSTRAINT: { - auto build_it = std::find_if( - recovery_data->existence_constraints.begin(), - recovery_data->existence_constraints.end(), - [&delta](const ExistenceConstraintRecoveryData &data) { - return data.label == delta.label_name && - std::is_permutation(data.properties.begin(), - data.properties.end(), - delta.property_names.begin()) && - data.create == true; - }); - - if (build_it != recovery_data->existence_constraints.end()) { - recovery_data->existence_constraints.erase(build_it); - } else { - recovery_data->existence_constraints.emplace_back( - ExistenceConstraintRecoveryData{delta.label_name, - delta.property_names, false}); - } - break; - } case database::StateDelta::Type::BUILD_UNIQUE_CONSTRAINT: { auto drop_it = std::find_if( recovery_data->unique_constraints.begin(), @@ -612,26 +545,6 @@ void RecoverIndexes(database::GraphDb *db, dba.Commit(); } -void RecoverExistenceConstraints( - database::GraphDb *db, - const std::vector<ExistenceConstraintRecoveryData> &constraints) { - auto dba = db->Access(); - for (auto &constraint : constraints) { - auto label = dba.Label(constraint.label); - std::vector<storage::Property> properties; - properties.reserve(constraint.properties.size()); - for (auto &prop : constraint.properties) { - properties.push_back(dba.Property(prop)); - } - - if (constraint.create) { - dba.BuildExistenceConstraint(label, properties); - } else { - dba.DeleteExistenceConstraint(label, properties); - } - } -} - void RecoverUniqueConstraints( database::GraphDb *db, const std::vector<UniqueConstraintRecoveryData> &constraints) { diff --git a/src/durability/single_node/recovery.hpp b/src/durability/single_node/recovery.hpp index 27a8ec65b..e6dcb7e1b 100644 --- a/src/durability/single_node/recovery.hpp +++ b/src/durability/single_node/recovery.hpp @@ -43,13 +43,6 @@ struct IndexRecoveryData { bool unique; // used only when creating an index }; -struct ExistenceConstraintRecoveryData { - std::string label; - std::vector<std::string> properties; - // distinguish between creating and dropping existence constraint - bool create; -}; - struct UniqueConstraintRecoveryData { std::string label; std::vector<std::string> properties; @@ -67,14 +60,12 @@ struct RecoveryData { // can be rebuilt at the end of the recovery transaction. std::vector<IndexRecoveryData> indexes; - std::vector<ExistenceConstraintRecoveryData> existence_constraints; std::vector<UniqueConstraintRecoveryData> unique_constraints; void Clear() { snapshooter_tx_id = 0; snapshooter_tx_snapshot.clear(); indexes.clear(); - existence_constraints.clear(); unique_constraints.clear(); } }; @@ -165,10 +156,6 @@ void RecoverWal(const std::filesystem::path &durability_dir, void RecoverIndexes(database::GraphDb *db, const std::vector<IndexRecoveryData> &indexes); -void RecoverExistenceConstraints( - database::GraphDb *db, - const std::vector<ExistenceConstraintRecoveryData> &constraints); - void RecoverUniqueConstraints( database::GraphDb *db, const std::vector<UniqueConstraintRecoveryData> &constraints); diff --git a/src/durability/single_node/snapshooter.cpp b/src/durability/single_node/snapshooter.cpp index d9b7829af..361ac2568 100644 --- a/src/durability/single_node/snapshooter.cpp +++ b/src/durability/single_node/snapshooter.cpp @@ -17,7 +17,7 @@ namespace fs = std::filesystem; namespace durability { // Snapshot layout is described in durability/version.hpp -static_assert(durability::kVersion == 9, +static_assert(durability::kVersion == 10, "Wrong snapshot version, please update!"); namespace { @@ -55,20 +55,6 @@ bool Encode(const fs::path &snapshot_file, database::GraphDb &db, encoder.WriteList(index_vec); } - // Write existence constraints to snapshoot - { - std::vector<communication::bolt::Value> existence_constraints; - 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())); - for (auto &prop : rule.properties) { - existence_constraints.emplace_back(dba.PropertyName(prop)); - } - } - encoder.WriteList(existence_constraints); - } - // Write unique constraints to snapshoot { std::vector<communication::bolt::Value> unique_constraints; diff --git a/src/durability/single_node/state_delta.cpp b/src/durability/single_node/state_delta.cpp index 8c8118706..d840f586f 100644 --- a/src/durability/single_node/state_delta.cpp +++ b/src/durability/single_node/state_delta.cpp @@ -126,32 +126,6 @@ StateDelta StateDelta::DropIndex(tx::TransactionId tx_id, storage::Label label, return op; } -StateDelta StateDelta::BuildExistenceConstraint( - tx::TransactionId tx_id, storage::Label label, - const std::string &label_name, - const std::vector<storage::Property> &properties, - const std::vector<std::string> &property_names) { - StateDelta op(StateDelta::Type::BUILD_EXISTENCE_CONSTRAINT, tx_id); - op.label = label; - op.label_name = label_name; - op.properties = properties; - op.property_names = property_names; - return op; -} - -StateDelta StateDelta::DropExistenceConstraint( - tx::TransactionId tx_id, storage::Label label, - const std::string &label_name, - const std::vector<storage::Property> &properties, - const std::vector<std::string> &property_names) { - StateDelta op(StateDelta::Type::DROP_EXISTENCE_CONSTRAINT, tx_id); - op.label = label; - op.label_name = label_name; - op.properties = properties; - op.property_names = property_names; - return op; -} - StateDelta StateDelta::BuildUniqueConstraint( tx::TransactionId tx_id, storage::Label label, const std::string &label_name, @@ -236,7 +210,6 @@ void StateDelta::Encode( encoder.WriteInt(property.Id()); encoder.WriteString(property_name); break; - case Type::BUILD_EXISTENCE_CONSTRAINT: case Type::BUILD_UNIQUE_CONSTRAINT: encoder.WriteInt(label.Id()); encoder.WriteString(label_name); @@ -248,7 +221,6 @@ void StateDelta::Encode( encoder.WriteString(name); } break; - case Type::DROP_EXISTENCE_CONSTRAINT: case Type::DROP_UNIQUE_CONSTRAINT: encoder.WriteInt(label.Id()); encoder.WriteString(label_name); @@ -341,7 +313,6 @@ std::optional<StateDelta> StateDelta::Decode( DECODE_MEMBER_CAST(property, ValueInt, storage::Property) DECODE_MEMBER(property_name, ValueString) break; - case Type::BUILD_EXISTENCE_CONSTRAINT: case Type::BUILD_UNIQUE_CONSTRAINT: { DECODE_MEMBER_CAST(label, ValueInt, storage::Label) DECODE_MEMBER(label_name, ValueString) @@ -358,7 +329,6 @@ std::optional<StateDelta> StateDelta::Decode( } break; } - case Type::DROP_EXISTENCE_CONSTRAINT: case Type::DROP_UNIQUE_CONSTRAINT: { DECODE_MEMBER_CAST(label, ValueInt, storage::Label) DECODE_MEMBER(label_name, ValueString) @@ -444,24 +414,6 @@ void StateDelta::Apply(GraphDbAccessor &dba) const { LOG(FATAL) << "Index handling not handled in Apply"; break; } - case Type::BUILD_EXISTENCE_CONSTRAINT: { - std::vector<storage::Property> properties; - properties.reserve(property_names.size()); - for (auto &p : property_names) { - properties.push_back(dba.Property(p)); - } - - dba.BuildExistenceConstraint(dba.Label(label_name), properties); - } break; - case Type::DROP_EXISTENCE_CONSTRAINT: { - std::vector<storage::Property> properties; - properties.reserve(property_names.size()); - for (auto &p : property_names) { - properties.push_back(dba.Property(p)); - } - - dba.DeleteExistenceConstraint(dba.Label(label_name), properties); - } break; case Type::BUILD_UNIQUE_CONSTRAINT: { std::vector<storage::Property> properties; properties.reserve(property_names.size()); diff --git a/src/durability/single_node/state_delta.lcp b/src/durability/single_node/state_delta.lcp index 7a4d52f33..f60316116 100644 --- a/src/durability/single_node/state_delta.lcp +++ b/src/durability/single_node/state_delta.lcp @@ -73,8 +73,6 @@ in StateDeltas.") remove-edge ;; edge_id build-index ;; label, label_name, property, property_name, unique drop-index ;; label, label_name, property, property_name - build-existence-constraint ;; label, label_name, properties, property_names - drop-existence-constraint ;; label, label_name, properties, property_names build-unique_constraint ;; label, label_name, properties, property_names drop-unique_constraint ;; label, label_name, properties, property_names ) @@ -135,16 +133,6 @@ omitted in the comment.")) const std::string &label_name, storage::Property property, const std::string &property_name); - static StateDelta BuildExistenceConstraint( - tx::TransactionId tx_id, storage::Label label, - const std::string &label_name, - const std::vector<storage::Property> &properties, - const std::vector<std::string> &property_names); - static StateDelta DropExistenceConstraint( - tx::TransactionId tx_id, storage::Label label, - const std::string &label_name, - const std::vector<storage::Property> &property, - const std::vector<std::string> &property_names); static StateDelta BuildUniqueConstraint( tx::TransactionId tx_id, storage::Label label, const std::string &label_name, diff --git a/src/durability/single_node/version.hpp b/src/durability/single_node/version.hpp index 034243222..e4b7bf6ae 100644 --- a/src/durability/single_node/version.hpp +++ b/src/durability/single_node/version.hpp @@ -15,9 +15,9 @@ constexpr std::array<uint8_t, 4> kSnapshotMagic{{'M', 'G', 's', 'n'}}; constexpr std::array<uint8_t, 4> kWalMagic{{'M', 'G', 'w', 'l'}}; // The current default version of snapshot and WAL encoding / decoding. -constexpr int64_t kVersion{9}; +constexpr int64_t kVersion{10}; -// Snapshot format (version 8): +// Snapshot format (version 10): // 1) Magic number + snapshot version // // The following two entries are required when recovering from snapshot combined @@ -27,17 +27,15 @@ constexpr int64_t kVersion{9}; // // 4) A list of label+property indices. // -// 5) A list of existence constraints +// 5) A list of unique constraints // -// 6) A list of unique constraints -// -// 7) Bolt encoded nodes. Each node is written in the following format: +// 6) Bolt encoded nodes. Each node is written in the following format: // * gid, labels, properties -// 8) Bolt encoded edges. Each edge is written in the following format: +// 7) Bolt encoded edges. Each edge is written in the following format: // * gid // * from, to // * edge_type // * properties // -// 9) Snapshot summary (number of nodes, number of edges, hash) +// 8) Snapshot summary (number of nodes, number of edges, hash) } // namespace durability diff --git a/src/durability/single_node/wal.cpp b/src/durability/single_node/wal.cpp index a159d6cf1..3f69d83c2 100644 --- a/src/durability/single_node/wal.cpp +++ b/src/durability/single_node/wal.cpp @@ -144,8 +144,6 @@ bool WriteAheadLog::IsStateDeltaTransactionEnd( case database::StateDelta::Type::REMOVE_EDGE: case database::StateDelta::Type::BUILD_INDEX: case database::StateDelta::Type::DROP_INDEX: - case database::StateDelta::Type::BUILD_EXISTENCE_CONSTRAINT: - case database::StateDelta::Type::DROP_EXISTENCE_CONSTRAINT: case database::StateDelta::Type::BUILD_UNIQUE_CONSTRAINT: case database::StateDelta::Type::DROP_UNIQUE_CONSTRAINT: return false; diff --git a/src/query/interpreter.cpp b/src/query/interpreter.cpp index 1f55a0195..f79c45def 100644 --- a/src/query/interpreter.cpp +++ b/src/query/interpreter.cpp @@ -654,36 +654,36 @@ Callback HandleInfoQuery(InfoQuery *info_query, Callback HandleConstraintQuery(ConstraintQuery *constraint_query, database::GraphDbAccessor *db_accessor) { - Callback callback; - std::vector<std::string> property_names; - property_names.reserve(constraint_query->constraint_.properties.size()); - for (const auto &prop_ix : constraint_query->constraint_.properties) { - property_names.push_back(prop_ix.name); - } - std::string label_name = constraint_query->constraint_.label.name; - std::string type; - switch (constraint_query->constraint_.type) { - case Constraint::Type::EXISTS: - type = "exists"; - break; - case Constraint::Type::UNIQUE: - type = "unique"; - break; - case Constraint::Type::NODE_KEY: - type = "node key"; - break; - } - switch (constraint_query->action_type_) { - case ConstraintQuery::ActionType::CREATE: - throw utils::NotYetImplemented("create constraint :{}({}) {}", label_name, - utils::Join(property_names, ", "), type); - break; - case ConstraintQuery::ActionType::DROP: - throw utils::NotYetImplemented("drop constraint :{}({}) {}", label_name, - utils::Join(property_names, ", "), type); - break; - } +#ifdef MG_SINGLE_NODE + Callback callback; + switch (constraint_query->action_type_) { + case ConstraintQuery::ActionType::CREATE: { + switch (constraint_query->constraint_.type) { + case Constraint::Type::NODE_KEY: + throw utils::NotYetImplemented("Node key constraints"); + case Constraint::Type::EXISTS: + throw utils::NotYetImplemented("Existence constraints"); + case Constraint::Type::UNIQUE: + throw utils::NotYetImplemented("Unique constraints"); + } + break; + } + case ConstraintQuery::ActionType::DROP: { + switch (constraint_query->constraint_.type) { + case Constraint::Type::NODE_KEY: + throw utils::NotYetImplemented("Node key constraints"); + case Constraint::Type::EXISTS: + throw utils::NotYetImplemented("Existence constraints"); + case Constraint::Type::UNIQUE: + throw utils::NotYetImplemented("Unique constraints"); + } + break; + } + } return callback; +#else + throw utils::NotYetImplemented("Constraints"); +#endif } Interpreter::Interpreter() : is_tsc_available_(utils::CheckAvailableTSC()) {} diff --git a/src/storage/single_node/constraints/existence_constraints.hpp b/src/storage/single_node/constraints/existence_constraints.hpp deleted file mode 100644 index 108513261..000000000 --- a/src/storage/single_node/constraints/existence_constraints.hpp +++ /dev/null @@ -1,87 +0,0 @@ -/// @file -#pragma once - -#include <list> -#include <unordered_map> -#include <vector> - -#include "storage/common/types/property_value.hpp" -#include "storage/common/types/types.hpp" -#include "storage/single_node/vertex.hpp" -#include "transactions/type.hpp" - -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 -/// properties. This rule doesn't care about the PropertyValues for those -/// properties. -struct ExistenceRule { - storage::Label label; - std::vector<storage::Property> properties; - - bool operator==(const ExistenceRule &rule) const { - return label == rule.label && - std::is_permutation(properties.begin(), properties.end(), - rule.properties.begin()); - } - - bool operator!=(const ExistenceRule &rule) const { return !(*this == rule); } -}; - -bool CheckIfSatisfiesExistenceRule(const Vertex *vertex, - const ExistenceRule &rule); - -/// ExistenceConstraints contains all active constrains. Existence constraints -/// are restriction on the vertices and are defined by ExistenceRule. -/// To create and delete constraint, the caller must ensure that there are no -/// other transactions running in parallel. -/// Additionally, for adding constraint caller must check existing vertices for -/// constraint violations before adding that constraint. You may use -/// CheckIfSatisfiesExistenceRule function for that. -/// This is needed to ensure logical correctness of transactions. -/// Once created, the client uses method CheckIfSatisfies to check that updated -/// vertex doesn't violate any of the existing constraints. If it does, that -/// update must be reverted. -class ExistenceConstraints { - public: - ExistenceConstraints() = default; - ExistenceConstraints(const ExistenceConstraints &) = delete; - ExistenceConstraints(ExistenceConstraints &&) = delete; - ExistenceConstraints &operator=(const ExistenceConstraints &) = delete; - ExistenceConstraints &operator=(ExistenceConstraints &&) = delete; - - /// Adds new constraint, if the constraint already exists this method does - /// nothing. This method doesn't check if any of the existing vertices breaks - /// this constraint. Caller must do that instead. Caller must also ensure - /// that no other transaction is running in parallel. - /// - /// @returns true if constraint was added, false otherwise - bool AddConstraint(const ExistenceRule &rule); - - /// Removes existing constraint, if the constraint doesn't exist this method - /// does nothing. Caller must ensure that no other transaction is running in - /// parallel. - /// - /// @returns true if constraint was removed, false otherwise - bool RemoveConstraint(const ExistenceRule &rule); - - /// Checks whether given constraint is visible. - bool Exists(const ExistenceRule &rule) const; - - /// Check if add label update satisfies all visible constraints. - /// @return true if all constraints are satisfied, false otherwise - bool CheckOnAddLabel(const Vertex *vertex, storage::Label label) const; - - /// Check if remove property update satisfies all visible constraints. - /// @return true if all constraints are satisfied, false otherwise - bool CheckOnRemoveProperty(const Vertex *vertex, - storage::Property property) const; - - /// Returns list of all constraints. - const std::vector<ExistenceRule> &ListConstraints() const; - - private: - std::vector<ExistenceRule> constraints_; -}; -}; // namespace storage::constraints diff --git a/src/storage/single_node/storage.hpp b/src/storage/single_node/storage.hpp index f0cd13492..ed6f23d93 100644 --- a/src/storage/single_node/storage.hpp +++ b/src/storage/single_node/storage.hpp @@ -6,7 +6,6 @@ #include "data_structures/concurrent/concurrent_map.hpp" #include "storage/common/kvstore/kvstore.hpp" #include "storage/common/types/types.hpp" -#include "storage/single_node/constraints/existence_constraints.hpp" #include "storage/single_node/constraints/unique_label_property_constraint.hpp" #include "storage/single_node/edge.hpp" #include "storage/single_node/indexes/key_index.hpp" @@ -77,9 +76,6 @@ class Storage { KeyIndex<storage::Label, Vertex> labels_index_; LabelPropertyIndex label_property_index_; - // existence constraints - storage::constraints::ExistenceConstraints existence_constraints_; - // unique constraints storage::constraints::UniqueLabelPropertyConstraint unique_label_property_constraints_; diff --git a/tests/benchmark/CMakeLists.txt b/tests/benchmark/CMakeLists.txt index 256b8843d..7aba74bb0 100644 --- a/tests/benchmark/CMakeLists.txt +++ b/tests/benchmark/CMakeLists.txt @@ -18,9 +18,6 @@ function(add_benchmark test_cpp) add_dependencies(memgraph__benchmark ${target_name}) endfunction(add_benchmark) -add_benchmark(existence_constraint.cpp) -target_link_libraries(${test_prefix}existence_constraint mg-single-node kvstore_dummy_lib) - add_benchmark(data_structures/concurrent/map_mix_concurrent.cpp) target_link_libraries(${test_prefix}map_mix_concurrent mg-single-node kvstore_dummy_lib) diff --git a/tests/benchmark/existence_constraint.cpp b/tests/benchmark/existence_constraint.cpp deleted file mode 100644 index d49d1b31e..000000000 --- a/tests/benchmark/existence_constraint.cpp +++ /dev/null @@ -1,133 +0,0 @@ -#include <benchmark/benchmark.h> -#include <benchmark/benchmark_api.h> -#include <glog/logging.h> - -#include <random> - -#include "database/single_node/graph_db.hpp" -#include "database/single_node/graph_db_accessor.hpp" - -const constexpr size_t kNumOfConstraints = 10; -const constexpr size_t kNumOfPropsInConstraint = 5; - -const constexpr size_t kNumOfProps = 100; -const constexpr size_t kNumOfLabels = 10; - -const constexpr size_t kNumOfVertices = 10000; - -struct TestSet { - public: - TestSet() { - constraint_labels.reserve(kNumOfConstraints); - for (size_t i = 0; i < kNumOfConstraints; ++i) { - constraint_labels.emplace_back("clabel_" + std::to_string(i)); - } - - constraint_props.reserve(kNumOfConstraints * kNumOfPropsInConstraint); - for (size_t i = 0; i < kNumOfConstraints * kNumOfPropsInConstraint; ++i) { - constraint_props.emplace_back("cprop_" + std::to_string(i)); - } - - labels.reserve(kNumOfLabels); - for (size_t i = 0; i < kNumOfLabels; ++i) { - labels.emplace_back("label_" + std::to_string(i)); - } - - props.reserve(kNumOfProps); - for (size_t i = 0; i < kNumOfProps; ++i) { - props.emplace_back("prop_" + std::to_string(i)); - } - } - - std::vector<std::string> constraint_labels; - std::vector<std::string> constraint_props; - - std::vector<std::string> labels; - std::vector<std::string> props; - - long short_prop_value{0}; - std::string long_prop_value{20, ' '}; -}; - -void Run(benchmark::State &state, bool enable_constraint) { - while (state.KeepRunning()) { - database::GraphDb db; - TestSet test_set; - - // CreateExistence constraints - if (enable_constraint) { - state.PauseTiming(); - for (size_t i = 0; i < kNumOfConstraints; ++i) { - auto dba = db.Access(); - auto label = dba.Label(test_set.constraint_labels.at(i)); - std::vector<storage::Property> props; - props.reserve(kNumOfPropsInConstraint); - for (size_t j = 0; j < kNumOfPropsInConstraint; ++j) { - props.push_back(dba.Property( - test_set.constraint_props.at(kNumOfPropsInConstraint * i + j))); - } - dba.BuildExistenceConstraint(label, props); - dba.Commit(); - } - state.ResumeTiming(); - } - - // Add all verices and also add labels and properties - std::vector<gid::Gid> vertices; - vertices.reserve(kNumOfVertices); - for (size_t k = 0; k < kNumOfVertices; ++k) { - auto dba = db.Access(); - auto v = dba.InsertVertex(); - vertices.push_back(v.gid()); - - // Labels and properties that define constraints - for (size_t i = 0; i < kNumOfConstraints; ++i) { - for (size_t j = 0; j < kNumOfPropsInConstraint; ++j) { - v.PropsSet(dba.Property(test_set.constraint_props.at( - kNumOfPropsInConstraint * i + j)), - test_set.short_prop_value); - } - auto label = dba.Label(test_set.constraint_labels.at(i)); - v.add_label(label); - } - - // Add other labels - for (auto label : test_set.labels) { - v.add_label(dba.Label(label)); - } - - // Add other properties - for (auto prop : test_set.props) { - v.PropsSet(dba.Property(prop), test_set.short_prop_value); - } - - dba.Commit(); - } - - // Delete all properties and labels - for (auto gid : vertices) { - auto dba = db.Access(); - auto v = dba.FindVertex(gid, false); - std::vector<storage::Label> labels_to_del(v.labels()); - for (auto &label : labels_to_del) { - v.remove_label(label); - } - - v.PropsClear(); - } - - // Delete all vertices - for (auto gid : vertices) { - auto dba = db.Access(); - auto v = dba.FindVertex(gid, false); - dba.RemoveVertex(v); - dba.Commit(); - } - } -} - -BENCHMARK_CAPTURE(Run, WithoutConstraint, false)->Unit(benchmark::kMillisecond); - -BENCHMARK_CAPTURE(Run, WithConstraint, true)->Unit(benchmark::kMillisecond); - -BENCHMARK_MAIN(); diff --git a/tests/manual/snapshot_explorer.cpp b/tests/manual/snapshot_explorer.cpp index b99668bc0..da2afcaf0 100644 --- a/tests/manual/snapshot_explorer.cpp +++ b/tests/manual/snapshot_explorer.cpp @@ -20,7 +20,7 @@ int main(int argc, char *argv[]) { // This makes sure we update the explorer when we bump the snapshot version. // Snapshot layout is described in durability/version.hpp - static_assert(durability::kVersion == 9, + static_assert(durability::kVersion == 10, "Wrong snapshot version, please update!"); fs::path snapshot_path(FLAGS_snapshot_file); @@ -76,32 +76,6 @@ int main(int argc, char *argv[]) { << property.ValueString(); } - decoder.ReadValue(&dv, Value::Type::List); - auto existence_constraint = dv.ValueList(); - for (auto it = existence_constraint.begin(); it != existence_constraint.end();) { - std::string log("Adding existence constraint: "); - CHECK(it->IsString()) << "Label is not a string!"; - log.append(it->ValueString()); - log.append(" -> ["); - ++it; - CHECK(it->IsInt()) << "Number of properties is not an int!"; - int64_t prop_size = it->ValueInt(); - ++it; - for (size_t i = 0; i < prop_size; ++i) { - CHECK(it->IsString()) << "Property is not a string!"; - log.append(it->ValueString()); - if (i != prop_size -1) { - log.append(", "); - } else { - log.append("]"); - } - - ++it; - } - - LOG(INFO) << log; - } - decoder.ReadValue(&dv, Value::Type::List); auto unique_constraint = dv.ValueList(); for (auto it = unique_constraint.begin(); it != unique_constraint.end();) { diff --git a/tests/manual/wal_explorer.cpp b/tests/manual/wal_explorer.cpp index 0794065d3..daa1c935d 100644 --- a/tests/manual/wal_explorer.cpp +++ b/tests/manual/wal_explorer.cpp @@ -45,10 +45,6 @@ std::string StateDeltaTypeToString(database::StateDelta::Type type) { return "BUILD_INDEX"; case database::StateDelta::Type::DROP_INDEX: return "DROP_INDEX"; - case database::StateDelta::Type::BUILD_EXISTENCE_CONSTRAINT: - return "BUILD_EXISTENCE_CONSTRAINT"; - case database::StateDelta::Type::DROP_EXISTENCE_CONSTRAINT: - return "DROP_EXISTENCE_CONSTRAINT"; case database::StateDelta::Type::BUILD_UNIQUE_CONSTRAINT: return "BUILD_UNIQUE_CONSTRAINT"; case database::StateDelta::Type::DROP_UNIQUE_CONSTRAINT: diff --git a/tests/unit/CMakeLists.txt b/tests/unit/CMakeLists.txt index 5bed9fe15..bdbd36cd3 100644 --- a/tests/unit/CMakeLists.txt +++ b/tests/unit/CMakeLists.txt @@ -133,9 +133,6 @@ target_link_libraries(${test_prefix}edges_distributed mg-distributed kvstore_dum add_unit_test(edges_single_node.cpp) target_link_libraries(${test_prefix}edges_single_node mg-single-node kvstore_dummy_lib) -add_unit_test(existence_constraints.cpp) -target_link_libraries(${test_prefix}existence_constraints mg-single-node kvstore_dummy_lib) - add_unit_test(gid.cpp) target_link_libraries(${test_prefix}gid mg-distributed kvstore_dummy_lib) diff --git a/tests/unit/durability.cpp b/tests/unit/durability.cpp index 21c38500c..2e3a97d49 100644 --- a/tests/unit/durability.cpp +++ b/tests/unit/durability.cpp @@ -166,36 +166,6 @@ class DbGenerator { } }; -bool CompareExistenceConstraints(const database::GraphDbAccessor &dba1, - const database::GraphDbAccessor &dba2) { - 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; - p1_names.reserve(p1.size()); - std::vector<std::string> p2_names; - p2_names.reserve(p2.size()); - - std::transform(p1.begin(), p1.end(), std::back_inserter(p1_names), - [&dba1](auto p) { return dba1.PropertyName(p); }); - std::transform(p2.begin(), p2.end(), std::back_inserter(p2_names), - [&dba2](auto p) { return dba2.PropertyName(p); }); - - return p1_names.size() == p2_names.size() && - std::is_permutation(p1_names.begin(), p1_names.end(), - p2_names.begin()); - }; - - return c1.size() == c2.size() && - std::is_permutation( - c1.begin(), c1.end(), c2.begin(), - [&dba1, &dba2, &compare_prop](auto &r1, auto &r2) { - return dba1.LabelName(r1.label) == dba2.LabelName(r2.label) && - compare_prop(dba1, r1.properties, dba2, r2.properties); - }); -} - bool CompareUniqueConstraints(const database::GraphDbAccessor &dba1, const database::GraphDbAccessor &dba2) { auto c1 = dba1.ListUniqueLabelPropertyConstraints(); @@ -226,7 +196,6 @@ void CompareDbs(database::GraphDb &a, database::GraphDb &b) { << "Indexes not equal [" << utils::Join(index_a, ", ") << "] != [" << utils::Join(index_b, ", "); } - EXPECT_TRUE(CompareExistenceConstraints(dba_a, dba_b)); EXPECT_TRUE(CompareUniqueConstraints(dba_a, dba_b)); auto is_permutation_props = [&dba_a, &dba_b](const auto &p1_id, @@ -532,11 +501,6 @@ TEST_F(Durability, SnapshotEncoding) { EXPECT_EQ(dv.ValueList()[1].ValueString(), "p1"); EXPECT_EQ(dv.ValueList()[2].ValueBool(), false); - // Existence constraints - decoder.ReadValue(&dv); - ASSERT_TRUE(dv.IsList()); - ASSERT_EQ(dv.ValueList().size(), 0); - // Unique constraints decoder.ReadValue(&dv); ASSERT_TRUE(dv.IsList()); @@ -1041,81 +1005,6 @@ TEST_F(Durability, UniqueIndexRecoveryWal) { } } -TEST_F(Durability, ExistenceConstraintRecoveryWal) { - auto config = DbConfig(true, false); - database::GraphDb db{config}; - { - // Fill database with some data - auto dba = db.Access(); - DbGenerator gen(dba); - dba.InsertVertex(); - gen.InsertVertex(); - gen.InsertVertex(); - auto l1 = dba.Label("l1"); - std::vector<storage::Property> p1{dba.Property("p1"), dba.Property("p2")}; - dba.BuildExistenceConstraint(l1, p1); - gen.InsertEdge(); - auto l2 = dba.Label("l2"); - std::vector<storage::Property> p2{dba.Property("p3"), dba.Property("p4")}; - dba.BuildExistenceConstraint(l2, p2); - gen.InsertVertex(); - gen.InsertEdge(); - dba.DeleteExistenceConstraint(l1, p1); - dba.Commit(); - } - { - // Recover and compare - db.wal().Flush(); - auto recovered_config = DbConfig(false, true); - database::GraphDb recovered_db{recovered_config}; - CompareDbs(db, recovered_db); - } -} - -TEST_F(Durability, ExistenceConstraintRecoverySnapshotAndWal) { - auto config = DbConfig(true, false); - database::GraphDb db{config}; - { - // Fill database with some data - auto dba = db.Access(); - DbGenerator gen(dba); - dba.InsertVertex(); - gen.InsertVertex(); - gen.InsertVertex(); - auto l1 = dba.Label("l1"); - std::vector<storage::Property> p1{dba.Property("p1"), dba.Property("p2")}; - dba.BuildExistenceConstraint(l1, p1); - gen.InsertEdge(); - auto l2 = dba.Label("l2"); - std::vector<storage::Property> p2{dba.Property("p3"), dba.Property("p4")}; - dba.BuildExistenceConstraint(l2, p2); - gen.InsertVertex(); - gen.InsertEdge(); - dba.DeleteExistenceConstraint(l1, p1); - dba.Commit(); - } - // create snapshot with build existence constraint - MakeSnapshot(db); - { - auto dba = db.Access(); - DbGenerator gen(dba); - gen.InsertVertex(); - gen.InsertVertex(); - - auto l3 = dba.Label("l3"); - std::vector<storage::Property> p3{dba.Property("p5"), dba.Property("p6")}; - dba.BuildExistenceConstraint(l3, p3); - dba.Commit(); - } - { - // Recover and compare - db.wal().Flush(); - auto recovered_config = DbConfig(false, true); - database::GraphDb recovered_db{recovered_config}; - CompareDbs(db, recovered_db); - } -} - TEST_F(Durability, UniqueConstraintRecoveryWal) { auto config = DbConfig(true, false); database::GraphDb db{config}; diff --git a/tests/unit/existence_constraints.cpp b/tests/unit/existence_constraints.cpp deleted file mode 100644 index d7f31bfd6..000000000 --- a/tests/unit/existence_constraints.cpp +++ /dev/null @@ -1,141 +0,0 @@ -#include <gflags/gflags.h> -#include <glog/logging.h> -#include <gtest/gtest.h> - -#include "database/single_node/graph_db.hpp" -#include "database/single_node/graph_db_accessor.hpp" - -class ExistenceConstraintsTest : public ::testing::Test { - public: - 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, BuildDrop) { - { - auto dba = db_.Access(); - EXPECT_FALSE(dba.ExistenceConstraintExists(label_, properties_)); - dba.Commit(); - } - { - 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, BuildWithViolation) { - { - auto dba = db_.Access(); - auto v = dba.InsertVertex(); - v.add_label(label_); - dba.Commit(); - } - { - auto dba = db_.Access(); - EXPECT_THROW(dba.BuildExistenceConstraint(label_, properties_), - database::IndexConstraintViolationException); - } -} - -TEST_F(ExistenceConstraintsTest, InsertFail) { - { - auto dba = db_.Access(); - dba.BuildExistenceConstraint(label_, properties_); - dba.Commit(); - } - { - auto dba = db_.Access(); - auto v = dba.InsertVertex(); - 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, 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_); - 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); - v.remove_label(label_); - v.PropsErase(property_); - dba.Commit(); - } -} - -int main(int argc, char **argv) { - google::InitGoogleLogging(argv[0]); - ::testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); -} diff --git a/tools/src/mg_import_csv/main.cpp b/tools/src/mg_import_csv/main.cpp index d5d915913..d437aea40 100644 --- a/tools/src/mg_import_csv/main.cpp +++ b/tools/src/mg_import_csv/main.cpp @@ -20,7 +20,7 @@ #include "utils/timer.hpp" // Snapshot layout is described in durability/version.hpp -static_assert(durability::kVersion == 9, +static_assert(durability::kVersion == 10, "Wrong snapshot version, please update!"); bool ValidateNotEmpty(const char *flagname, const std::string &value) { @@ -424,7 +424,6 @@ void Convert(const std::vector<std::string> &nodes, encoder.WriteInt(0); // Id of transaction that is snapshooting. encoder.WriteList({}); // Transactional snapshot. encoder.WriteList({}); // Label + property indexes. - encoder.WriteList({}); // Existence constraints encoder.WriteList({}); // Unique constraints // PassNodes streams vertices to the encoder. for (const auto &nodes_file : nodes) {