Remove primary label from vertex (#529)

- Remove the primary label from vertex
- Pass vertex_validator instead of schema validator
- Fix vertex ctors
This commit is contained in:
Jure Bajic 2022-09-07 13:36:10 +02:00 committed by GitHub
parent e9f0360fb3
commit a2a6a3855b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 106 additions and 115 deletions

View File

@ -14,6 +14,7 @@
#include <chrono> #include <chrono>
#include <cstdint> #include <cstdint>
#include <filesystem> #include <filesystem>
#include "storage/v3/id_types.hpp"
#include "storage/v3/isolation_level.hpp" #include "storage/v3/isolation_level.hpp"
#include "storage/v3/transaction.hpp" #include "storage/v3/transaction.hpp"

View File

@ -19,6 +19,7 @@
#include "storage/v3/edge_accessor.hpp" #include "storage/v3/edge_accessor.hpp"
#include "storage/v3/edge_ref.hpp" #include "storage/v3/edge_ref.hpp"
#include "storage/v3/mvcc.hpp" #include "storage/v3/mvcc.hpp"
#include "storage/v3/schema_validator.hpp"
#include "storage/v3/schemas.hpp" #include "storage/v3/schemas.hpp"
#include "storage/v3/vertex_accessor.hpp" #include "storage/v3/vertex_accessor.hpp"
#include "storage/v3/vertices_skip_list.hpp" #include "storage/v3/vertices_skip_list.hpp"
@ -636,7 +637,7 @@ void CreateSnapshot(Transaction *transaction, const std::filesystem::path &snaps
const std::filesystem::path &wal_directory, uint64_t snapshot_retention_count, const std::filesystem::path &wal_directory, uint64_t snapshot_retention_count,
VerticesSkipList *vertices, utils::SkipList<Edge> *edges, NameIdMapper *name_id_mapper, VerticesSkipList *vertices, utils::SkipList<Edge> *edges, NameIdMapper *name_id_mapper,
Indices *indices, Constraints *constraints, Config::Items items, Indices *indices, Constraints *constraints, Config::Items items,
const SchemaValidator &schema_validator, const std::string &uuid, const std::string_view epoch_id, const VertexValidator &vertex_validator, const std::string &uuid, const std::string_view epoch_id,
const std::deque<std::pair<std::string, uint64_t>> &epoch_history, const std::deque<std::pair<std::string, uint64_t>> &epoch_history,
utils::FileRetainer *file_retainer) { utils::FileRetainer *file_retainer) {
// Ensure that the storage directory exists. // Ensure that the storage directory exists.
@ -718,7 +719,7 @@ void CreateSnapshot(Transaction *transaction, const std::filesystem::path &snaps
// here. // here.
// TODO(jbajic) Fix snapshot with new schema rules // TODO(jbajic) Fix snapshot with new schema rules
auto ea = EdgeAccessor{edge_ref, EdgeTypeId::FromUint(0UL), nullptr, nullptr, transaction, indices, constraints, auto ea = EdgeAccessor{edge_ref, EdgeTypeId::FromUint(0UL), nullptr, nullptr, transaction, indices, constraints,
items, schema_validator}; items, vertex_validator};
// Get edge data. // Get edge data.
auto maybe_props = ea.Properties(View::OLD); auto maybe_props = ea.Properties(View::OLD);
@ -746,7 +747,7 @@ void CreateSnapshot(Transaction *transaction, const std::filesystem::path &snaps
auto acc = vertices->access(); auto acc = vertices->access();
for (auto &lgo_vertex : acc) { for (auto &lgo_vertex : acc) {
// The visibility check is implemented for vertices so we use it here. // The visibility check is implemented for vertices so we use it here.
auto va = VertexAccessor::Create(&lgo_vertex.vertex, transaction, indices, constraints, items, schema_validator, auto va = VertexAccessor::Create(&lgo_vertex.vertex, transaction, indices, constraints, items, vertex_validator,
View::OLD); View::OLD);
if (!va) continue; if (!va) continue;

View File

@ -51,11 +51,11 @@ bool EdgeAccessor::IsVisible(const View view) const {
} }
VertexAccessor EdgeAccessor::FromVertex() const { VertexAccessor EdgeAccessor::FromVertex() const {
return {from_vertex_, transaction_, indices_, constraints_, config_, *schema_validator_}; return {from_vertex_, transaction_, indices_, constraints_, config_, *vertex_validator_};
} }
VertexAccessor EdgeAccessor::ToVertex() const { VertexAccessor EdgeAccessor::ToVertex() const {
return {to_vertex_, transaction_, indices_, constraints_, config_, *schema_validator_}; return {to_vertex_, transaction_, indices_, constraints_, config_, *vertex_validator_};
} }
Result<PropertyValue> EdgeAccessor::SetProperty(PropertyId property, const PropertyValue &value) { Result<PropertyValue> EdgeAccessor::SetProperty(PropertyId property, const PropertyValue &value) {

View File

@ -17,6 +17,7 @@
#include "storage/v3/edge_ref.hpp" #include "storage/v3/edge_ref.hpp"
#include "storage/v3/config.hpp" #include "storage/v3/config.hpp"
#include "storage/v3/id_types.hpp"
#include "storage/v3/result.hpp" #include "storage/v3/result.hpp"
#include "storage/v3/schema_validator.hpp" #include "storage/v3/schema_validator.hpp"
#include "storage/v3/transaction.hpp" #include "storage/v3/transaction.hpp"
@ -36,7 +37,7 @@ class EdgeAccessor final {
public: public:
EdgeAccessor(EdgeRef edge, EdgeTypeId edge_type, Vertex *from_vertex, Vertex *to_vertex, Transaction *transaction, EdgeAccessor(EdgeRef edge, EdgeTypeId edge_type, Vertex *from_vertex, Vertex *to_vertex, Transaction *transaction,
Indices *indices, Constraints *constraints, Config::Items config, Indices *indices, Constraints *constraints, Config::Items config,
const SchemaValidator &schema_validator, bool for_deleted = false) const VertexValidator &vertex_validator, bool for_deleted = false)
: edge_(edge), : edge_(edge),
edge_type_(edge_type), edge_type_(edge_type),
from_vertex_(from_vertex), from_vertex_(from_vertex),
@ -45,7 +46,7 @@ class EdgeAccessor final {
indices_(indices), indices_(indices),
constraints_(constraints), constraints_(constraints),
config_(config), config_(config),
schema_validator_{&schema_validator}, vertex_validator_{&vertex_validator},
for_deleted_(for_deleted) {} for_deleted_(for_deleted) {}
/// @return true if the object is visible from the current transaction /// @return true if the object is visible from the current transaction
@ -94,7 +95,7 @@ class EdgeAccessor final {
Indices *indices_; Indices *indices_;
Constraints *constraints_; Constraints *constraints_;
Config::Items config_; Config::Items config_;
const SchemaValidator *schema_validator_; const VertexValidator *vertex_validator_;
// if the accessor was created for a deleted edge. // if the accessor was created for a deleted edge.
// Accessor behaves differently for some methods based on this // Accessor behaves differently for some methods based on this

View File

@ -13,9 +13,9 @@
#include <limits> #include <limits>
#include "storage/v3/id_types.hpp"
#include "storage/v3/mvcc.hpp" #include "storage/v3/mvcc.hpp"
#include "storage/v3/property_value.hpp" #include "storage/v3/property_value.hpp"
#include "storage/v3/schema_validator.hpp"
#include "storage/v3/schemas.hpp" #include "storage/v3/schemas.hpp"
#include "utils/bound.hpp" #include "utils/bound.hpp"
#include "utils/logging.hpp" #include "utils/logging.hpp"
@ -327,7 +327,7 @@ void LabelIndex::RemoveObsoleteEntries(uint64_t oldest_active_start_timestamp) {
LabelIndex::Iterable::Iterator::Iterator(Iterable *self, utils::SkipList<Entry>::Iterator index_iterator) LabelIndex::Iterable::Iterator::Iterator(Iterable *self, utils::SkipList<Entry>::Iterator index_iterator)
: self_(self), : self_(self),
index_iterator_(index_iterator), index_iterator_(index_iterator),
current_vertex_accessor_(nullptr, nullptr, nullptr, nullptr, self_->config_, *self_->schema_validator_), current_vertex_accessor_(nullptr, nullptr, nullptr, nullptr, self_->config_, *self_->vertex_validator_),
current_vertex_(nullptr) { current_vertex_(nullptr) {
AdvanceUntilValid(); AdvanceUntilValid();
} }
@ -346,7 +346,7 @@ void LabelIndex::Iterable::Iterator::AdvanceUntilValid() {
if (CurrentVersionHasLabel(*index_iterator_->vertex, self_->label_, self_->transaction_, self_->view_)) { if (CurrentVersionHasLabel(*index_iterator_->vertex, self_->label_, self_->transaction_, self_->view_)) {
current_vertex_ = index_iterator_->vertex; current_vertex_ = index_iterator_->vertex;
current_vertex_accessor_ = VertexAccessor{current_vertex_, self_->transaction_, self_->indices_, current_vertex_accessor_ = VertexAccessor{current_vertex_, self_->transaction_, self_->indices_,
self_->constraints_, self_->config_, *self_->schema_validator_}; self_->constraints_, self_->config_, *self_->vertex_validator_};
break; break;
} }
} }
@ -354,7 +354,7 @@ void LabelIndex::Iterable::Iterator::AdvanceUntilValid() {
LabelIndex::Iterable::Iterable(utils::SkipList<Entry>::Accessor index_accessor, LabelId label, View view, LabelIndex::Iterable::Iterable(utils::SkipList<Entry>::Accessor index_accessor, LabelId label, View view,
Transaction *transaction, Indices *indices, Constraints *constraints, Transaction *transaction, Indices *indices, Constraints *constraints,
Config::Items config, const SchemaValidator &schema_validator) Config::Items config, const VertexValidator &vertex_validator)
: index_accessor_(std::move(index_accessor)), : index_accessor_(std::move(index_accessor)),
label_(label), label_(label),
view_(view), view_(view),
@ -362,7 +362,7 @@ LabelIndex::Iterable::Iterable(utils::SkipList<Entry>::Accessor index_accessor,
indices_(indices), indices_(indices),
constraints_(constraints), constraints_(constraints),
config_(config), config_(config),
schema_validator_(&schema_validator) {} vertex_validator_(&vertex_validator) {}
void LabelIndex::RunGC() { void LabelIndex::RunGC() {
for (auto &index_entry : index_) { for (auto &index_entry : index_) {
@ -480,7 +480,7 @@ void LabelPropertyIndex::RemoveObsoleteEntries(uint64_t oldest_active_start_time
LabelPropertyIndex::Iterable::Iterator::Iterator(Iterable *self, utils::SkipList<Entry>::Iterator index_iterator) LabelPropertyIndex::Iterable::Iterator::Iterator(Iterable *self, utils::SkipList<Entry>::Iterator index_iterator)
: self_(self), : self_(self),
index_iterator_(index_iterator), index_iterator_(index_iterator),
current_vertex_accessor_(nullptr, nullptr, nullptr, nullptr, self_->config_, *self_->schema_validator_), current_vertex_accessor_(nullptr, nullptr, nullptr, nullptr, self_->config_, *self_->vertex_validator_),
current_vertex_(nullptr) { current_vertex_(nullptr) {
AdvanceUntilValid(); AdvanceUntilValid();
} }
@ -520,7 +520,7 @@ void LabelPropertyIndex::Iterable::Iterator::AdvanceUntilValid() {
index_iterator_->value, self_->transaction_, self_->view_)) { index_iterator_->value, self_->transaction_, self_->view_)) {
current_vertex_ = index_iterator_->vertex; current_vertex_ = index_iterator_->vertex;
current_vertex_accessor_ = VertexAccessor(current_vertex_, self_->transaction_, self_->indices_, current_vertex_accessor_ = VertexAccessor(current_vertex_, self_->transaction_, self_->indices_,
self_->constraints_, self_->config_, *self_->schema_validator_); self_->constraints_, self_->config_, *self_->vertex_validator_);
break; break;
} }
} }
@ -543,7 +543,7 @@ LabelPropertyIndex::Iterable::Iterable(utils::SkipList<Entry>::Accessor index_ac
const std::optional<utils::Bound<PropertyValue>> &lower_bound, const std::optional<utils::Bound<PropertyValue>> &lower_bound,
const std::optional<utils::Bound<PropertyValue>> &upper_bound, View view, const std::optional<utils::Bound<PropertyValue>> &upper_bound, View view,
Transaction *transaction, Indices *indices, Constraints *constraints, Transaction *transaction, Indices *indices, Constraints *constraints,
Config::Items config, const SchemaValidator &schema_validator) Config::Items config, const VertexValidator &vertex_validator)
: index_accessor_(std::move(index_accessor)), : index_accessor_(std::move(index_accessor)),
label_(label), label_(label),
property_(property), property_(property),
@ -554,7 +554,7 @@ LabelPropertyIndex::Iterable::Iterable(utils::SkipList<Entry>::Accessor index_ac
indices_(indices), indices_(indices),
constraints_(constraints), constraints_(constraints),
config_(config), config_(config),
schema_validator_(&schema_validator) { vertex_validator_(&vertex_validator) {
// We have to fix the bounds that the user provided to us. If the user // We have to fix the bounds that the user provided to us. If the user
// provided only one bound we should make sure that only values of that type // provided only one bound we should make sure that only values of that type
// are returned by the iterator. We ensure this by supplying either an // are returned by the iterator. We ensure this by supplying either an

View File

@ -18,7 +18,6 @@
#include "storage/v3/config.hpp" #include "storage/v3/config.hpp"
#include "storage/v3/property_value.hpp" #include "storage/v3/property_value.hpp"
#include "storage/v3/schema_validator.hpp"
#include "storage/v3/transaction.hpp" #include "storage/v3/transaction.hpp"
#include "storage/v3/vertex_accessor.hpp" #include "storage/v3/vertex_accessor.hpp"
#include "storage/v3/vertices_skip_list.hpp" #include "storage/v3/vertices_skip_list.hpp"
@ -54,8 +53,8 @@ class LabelIndex {
}; };
public: public:
LabelIndex(Indices *indices, Constraints *constraints, Config::Items config, const SchemaValidator &schema_validator) LabelIndex(Indices *indices, Constraints *constraints, Config::Items config, const VertexValidator &vertex_validator)
: indices_(indices), constraints_(constraints), config_(config), schema_validator_{&schema_validator} {} : indices_(indices), constraints_(constraints), config_(config), vertex_validator_{&vertex_validator} {}
/// @throw std::bad_alloc /// @throw std::bad_alloc
void UpdateOnAddLabel(LabelId label, Vertex *vertex, const Transaction &tx); void UpdateOnAddLabel(LabelId label, Vertex *vertex, const Transaction &tx);
@ -75,7 +74,7 @@ class LabelIndex {
class Iterable { class Iterable {
public: public:
Iterable(utils::SkipList<Entry>::Accessor index_accessor, LabelId label, View view, Transaction *transaction, Iterable(utils::SkipList<Entry>::Accessor index_accessor, LabelId label, View view, Transaction *transaction,
Indices *indices, Constraints *constraints, Config::Items config, const SchemaValidator &schema_validator); Indices *indices, Constraints *constraints, Config::Items config, const VertexValidator &vertex_validator);
class Iterator { class Iterator {
public: public:
@ -108,14 +107,14 @@ class LabelIndex {
Indices *indices_; Indices *indices_;
Constraints *constraints_; Constraints *constraints_;
Config::Items config_; Config::Items config_;
const SchemaValidator *schema_validator_; const VertexValidator *vertex_validator_;
}; };
/// Returns an self with vertices visible from the given transaction. /// Returns an self with vertices visible from the given transaction.
Iterable Vertices(LabelId label, View view, Transaction *transaction) { Iterable Vertices(LabelId label, View view, Transaction *transaction) {
auto it = index_.find(label); auto it = index_.find(label);
MG_ASSERT(it != index_.end(), "Index for label {} doesn't exist", label.AsUint()); MG_ASSERT(it != index_.end(), "Index for label {} doesn't exist", label.AsUint());
return {it->second.access(), label, view, transaction, indices_, constraints_, config_, *schema_validator_}; return {it->second.access(), label, view, transaction, indices_, constraints_, config_, *vertex_validator_};
} }
int64_t ApproximateVertexCount(LabelId label) { int64_t ApproximateVertexCount(LabelId label) {
@ -133,7 +132,7 @@ class LabelIndex {
Indices *indices_; Indices *indices_;
Constraints *constraints_; Constraints *constraints_;
Config::Items config_; Config::Items config_;
const SchemaValidator *schema_validator_; const VertexValidator *vertex_validator_;
}; };
class LabelPropertyIndex { class LabelPropertyIndex {
@ -152,8 +151,8 @@ class LabelPropertyIndex {
public: public:
LabelPropertyIndex(Indices *indices, Constraints *constraints, Config::Items config, LabelPropertyIndex(Indices *indices, Constraints *constraints, Config::Items config,
const SchemaValidator &schema_validator) const VertexValidator &vertex_validator)
: indices_(indices), constraints_(constraints), config_(config), schema_validator_{&schema_validator} {} : indices_(indices), constraints_(constraints), config_(config), vertex_validator_{&vertex_validator} {}
/// @throw std::bad_alloc /// @throw std::bad_alloc
void UpdateOnAddLabel(LabelId label, Vertex *vertex, const Transaction &tx); void UpdateOnAddLabel(LabelId label, Vertex *vertex, const Transaction &tx);
@ -177,7 +176,7 @@ class LabelPropertyIndex {
Iterable(utils::SkipList<Entry>::Accessor index_accessor, LabelId label, PropertyId property, Iterable(utils::SkipList<Entry>::Accessor index_accessor, LabelId label, PropertyId property,
const std::optional<utils::Bound<PropertyValue>> &lower_bound, const std::optional<utils::Bound<PropertyValue>> &lower_bound,
const std::optional<utils::Bound<PropertyValue>> &upper_bound, View view, Transaction *transaction, const std::optional<utils::Bound<PropertyValue>> &upper_bound, View view, Transaction *transaction,
Indices *indices, Constraints *constraints, Config::Items config, const SchemaValidator &schema_validator); Indices *indices, Constraints *constraints, Config::Items config, const VertexValidator &vertex_validator);
class Iterator { class Iterator {
public: public:
@ -214,17 +213,17 @@ class LabelPropertyIndex {
Indices *indices_; Indices *indices_;
Constraints *constraints_; Constraints *constraints_;
Config::Items config_; Config::Items config_;
const SchemaValidator *schema_validator_; const VertexValidator *vertex_validator_;
}; };
Iterable Vertices(LabelId label, PropertyId property, const std::optional<utils::Bound<PropertyValue>> &lower_bound, Iterable Vertices(LabelId label, PropertyId property, const std::optional<utils::Bound<PropertyValue>> &lower_bound,
const std::optional<utils::Bound<PropertyValue>> &upper_bound, View view, Transaction *transaction, const std::optional<utils::Bound<PropertyValue>> &upper_bound, View view, Transaction *transaction,
const SchemaValidator &schema_validator) { const VertexValidator &vertex_validator) {
auto it = index_.find({label, property}); auto it = index_.find({label, property});
MG_ASSERT(it != index_.end(), "Index for label {} and property {} doesn't exist", label.AsUint(), MG_ASSERT(it != index_.end(), "Index for label {} and property {} doesn't exist", label.AsUint(),
property.AsUint()); property.AsUint());
return {it->second.access(), label, property, lower_bound, upper_bound, view, return {it->second.access(), label, property, lower_bound, upper_bound, view,
transaction, indices_, constraints_, config_, schema_validator}; transaction, indices_, constraints_, config_, vertex_validator};
} }
int64_t ApproximateVertexCount(LabelId label, PropertyId property) const { int64_t ApproximateVertexCount(LabelId label, PropertyId property) const {
@ -253,13 +252,13 @@ class LabelPropertyIndex {
Indices *indices_; Indices *indices_;
Constraints *constraints_; Constraints *constraints_;
Config::Items config_; Config::Items config_;
const SchemaValidator *schema_validator_; const VertexValidator *vertex_validator_;
}; };
struct Indices { struct Indices {
Indices(Constraints *constraints, Config::Items config, const SchemaValidator &schema_validator) Indices(Constraints *constraints, Config::Items config, const VertexValidator &vertex_validator)
: label_index(this, constraints, config, schema_validator), : label_index(this, constraints, config, vertex_validator),
label_property_index(this, constraints, config, schema_validator) {} label_property_index(this, constraints, config, vertex_validator) {}
// Disable copy and move because members hold pointer to `this`. // Disable copy and move because members hold pointer to `this`.
Indices(const Indices &) = delete; Indices(const Indices &) = delete;

View File

@ -163,9 +163,9 @@ void Shard::ReplicationServer::SnapshotHandler(slk::Reader *req_reader, slk::Bui
shard_->constraints_ = Constraints(); shard_->constraints_ = Constraints();
shard_->indices_.label_index = shard_->indices_.label_index =
LabelIndex(&shard_->indices_, &shard_->constraints_, shard_->config_.items, shard_->schema_validator_); LabelIndex(&shard_->indices_, &shard_->constraints_, shard_->config_.items, shard_->vertex_validator_);
shard_->indices_.label_property_index = shard_->indices_.label_property_index =
LabelPropertyIndex(&shard_->indices_, &shard_->constraints_, shard_->config_.items, shard_->schema_validator_); LabelPropertyIndex(&shard_->indices_, &shard_->constraints_, shard_->config_.items, shard_->vertex_validator_);
try { try {
spdlog::debug("Loading snapshot"); spdlog::debug("Loading snapshot");
auto recovered_snapshot = durability::RecoveredSnapshot{}; auto recovered_snapshot = durability::RecoveredSnapshot{};

View File

@ -103,4 +103,19 @@ SchemaValidator::SchemaValidator(Schemas &schemas) : schemas_{schemas} {}
return std::nullopt; return std::nullopt;
} }
VertexValidator::VertexValidator(const SchemaValidator &schema_validator, const LabelId primary_label)
: schema_validator{&schema_validator}, primary_label_{primary_label} {}
[[nodiscard]] std::optional<SchemaViolation> VertexValidator::ValidatePropertyUpdate(PropertyId property_id) const {
return schema_validator->ValidatePropertyUpdate(primary_label_, property_id);
};
[[nodiscard]] std::optional<SchemaViolation> VertexValidator::ValidateAddLabel(LabelId label) const {
return schema_validator->ValidateLabelUpdate(label);
}
[[nodiscard]] std::optional<SchemaViolation> VertexValidator::ValidateRemoveLabel(LabelId label) const {
return schema_validator->ValidateLabelUpdate(label);
}
} // namespace memgraph::storage::v3 } // namespace memgraph::storage::v3

View File

@ -63,6 +63,20 @@ class SchemaValidator {
Schemas &schemas_; Schemas &schemas_;
}; };
struct VertexValidator {
explicit VertexValidator(const SchemaValidator &schema_validator, LabelId primary_label);
[[nodiscard]] std::optional<SchemaViolation> ValidatePropertyUpdate(PropertyId property_id) const;
[[nodiscard]] std::optional<SchemaViolation> ValidateAddLabel(LabelId label) const;
[[nodiscard]] std::optional<SchemaViolation> ValidateRemoveLabel(LabelId label) const;
const SchemaValidator *schema_validator;
LabelId primary_label_;
};
template <typename TValue> template <typename TValue>
using ResultSchema = utils::BasicResult<std::variant<SchemaViolation, Error>, TValue>; using ResultSchema = utils::BasicResult<std::variant<SchemaViolation, Error>, TValue>;

View File

@ -70,9 +70,9 @@ void InsertVertexPKIntoList(auto &container, const PrimaryKey &primary_key) { co
auto AdvanceToVisibleVertex(VerticesSkipList::Iterator it, VerticesSkipList::Iterator end, auto AdvanceToVisibleVertex(VerticesSkipList::Iterator it, VerticesSkipList::Iterator end,
std::optional<VertexAccessor> *vertex, Transaction *tx, View view, Indices *indices, std::optional<VertexAccessor> *vertex, Transaction *tx, View view, Indices *indices,
Constraints *constraints, Config::Items config, const SchemaValidator &schema_validator) { Constraints *constraints, Config::Items config, const VertexValidator &vertex_validator) {
while (it != end) { while (it != end) {
*vertex = VertexAccessor::Create(&it->vertex, tx, indices, constraints, config, schema_validator, view); *vertex = VertexAccessor::Create(&it->vertex, tx, indices, constraints, config, vertex_validator, view);
if (!*vertex) { if (!*vertex) {
++it; ++it;
continue; continue;
@ -85,14 +85,14 @@ auto AdvanceToVisibleVertex(VerticesSkipList::Iterator it, VerticesSkipList::Ite
AllVerticesIterable::Iterator::Iterator(AllVerticesIterable *self, VerticesSkipList::Iterator it) AllVerticesIterable::Iterator::Iterator(AllVerticesIterable *self, VerticesSkipList::Iterator it)
: self_(self), : self_(self),
it_(AdvanceToVisibleVertex(it, self->vertices_accessor_.end(), &self->vertex_, self->transaction_, self->view_, it_(AdvanceToVisibleVertex(it, self->vertices_accessor_.end(), &self->vertex_, self->transaction_, self->view_,
self->indices_, self_->constraints_, self->config_, *self_->schema_validator_)) {} self->indices_, self_->constraints_, self->config_, *self_->vertex_validator_)) {}
VertexAccessor AllVerticesIterable::Iterator::operator*() const { return *self_->vertex_; } VertexAccessor AllVerticesIterable::Iterator::operator*() const { return *self_->vertex_; }
AllVerticesIterable::Iterator &AllVerticesIterable::Iterator::operator++() { AllVerticesIterable::Iterator &AllVerticesIterable::Iterator::operator++() {
++it_; ++it_;
it_ = AdvanceToVisibleVertex(it_, self_->vertices_accessor_.end(), &self_->vertex_, self_->transaction_, self_->view_, it_ = AdvanceToVisibleVertex(it_, self_->vertices_accessor_.end(), &self_->vertex_, self_->transaction_, self_->view_,
self_->indices_, self_->constraints_, self_->config_, *self_->schema_validator_); self_->indices_, self_->constraints_, self_->config_, *self_->vertex_validator_);
return *this; return *this;
} }
@ -321,7 +321,8 @@ Shard::Shard(const LabelId primary_label, const PrimaryKey min_primary_key,
min_primary_key_{min_primary_key}, min_primary_key_{min_primary_key},
max_primary_key_{max_primary_key}, max_primary_key_{max_primary_key},
schema_validator_{schemas_}, schema_validator_{schemas_},
indices_{&constraints_, config.items, schema_validator_}, vertex_validator_{schema_validator_, primary_label},
indices_{&constraints_, config.items, vertex_validator_},
isolation_level_{config.transaction.isolation_level}, isolation_level_{config.transaction.isolation_level},
config_{config}, config_{config},
snapshot_directory_{config_.durability.storage_directory / durability::kSnapshotDirectory}, snapshot_directory_{config_.durability.storage_directory / durability::kSnapshotDirectory},
@ -496,10 +497,10 @@ ResultSchema<VertexAccessor> Shard::Accessor::CreateVertexAndValidate(
} }
auto acc = shard_->vertices_.access(); auto acc = shard_->vertices_.access();
auto *delta = CreateDeleteObjectDelta(&transaction_); auto *delta = CreateDeleteObjectDelta(&transaction_);
auto [it, inserted] = acc.insert({Vertex{delta, primary_label, primary_properties}}); auto [it, inserted] = acc.insert({Vertex{delta, primary_properties}});
VertexAccessor vertex_acc{&it->vertex, &transaction_, &shard_->indices_, VertexAccessor vertex_acc{&it->vertex, &transaction_, &shard_->indices_,
&shard_->constraints_, config_, shard_->schema_validator_}; &shard_->constraints_, config_, shard_->vertex_validator_};
MG_ASSERT(inserted, "The vertex must be inserted here!"); MG_ASSERT(inserted, "The vertex must be inserted here!");
MG_ASSERT(it != acc.end(), "Invalid Vertex accessor!"); MG_ASSERT(it != acc.end(), "Invalid Vertex accessor!");
@ -529,7 +530,7 @@ std::optional<VertexAccessor> Shard::Accessor::FindVertex(std::vector<PropertyVa
return std::nullopt; return std::nullopt;
} }
return VertexAccessor::Create(&it->vertex, &transaction_, &shard_->indices_, &shard_->constraints_, config_, return VertexAccessor::Create(&it->vertex, &transaction_, &shard_->indices_, &shard_->constraints_, config_,
shard_->schema_validator_, view); shard_->vertex_validator_, view);
} }
Result<std::optional<VertexAccessor>> Shard::Accessor::DeleteVertex(VertexAccessor *vertex) { Result<std::optional<VertexAccessor>> Shard::Accessor::DeleteVertex(VertexAccessor *vertex) {
@ -550,7 +551,7 @@ Result<std::optional<VertexAccessor>> Shard::Accessor::DeleteVertex(VertexAccess
vertex_ptr->deleted = true; vertex_ptr->deleted = true;
return std::make_optional<VertexAccessor>(vertex_ptr, &transaction_, &shard_->indices_, &shard_->constraints_, return std::make_optional<VertexAccessor>(vertex_ptr, &transaction_, &shard_->indices_, &shard_->constraints_,
config_, shard_->schema_validator_, true); config_, shard_->vertex_validator_, true);
} }
Result<std::optional<std::pair<VertexAccessor, std::vector<EdgeAccessor>>>> Shard::Accessor::DetachDeleteVertex( Result<std::optional<std::pair<VertexAccessor, std::vector<EdgeAccessor>>>> Shard::Accessor::DetachDeleteVertex(
@ -578,7 +579,7 @@ Result<std::optional<std::pair<VertexAccessor, std::vector<EdgeAccessor>>>> Shar
for (const auto &item : in_edges) { for (const auto &item : in_edges) {
auto [edge_type, from_vertex, edge] = item; auto [edge_type, from_vertex, edge] = item;
EdgeAccessor e(edge, edge_type, from_vertex, vertex_ptr, &transaction_, &shard_->indices_, &shard_->constraints_, EdgeAccessor e(edge, edge_type, from_vertex, vertex_ptr, &transaction_, &shard_->indices_, &shard_->constraints_,
config_, shard_->schema_validator_); config_, shard_->vertex_validator_);
auto ret = DeleteEdge(&e); auto ret = DeleteEdge(&e);
if (ret.HasError()) { if (ret.HasError()) {
MG_ASSERT(ret.GetError() == Error::SERIALIZATION_ERROR, "Invalid database state!"); MG_ASSERT(ret.GetError() == Error::SERIALIZATION_ERROR, "Invalid database state!");
@ -592,7 +593,7 @@ Result<std::optional<std::pair<VertexAccessor, std::vector<EdgeAccessor>>>> Shar
for (const auto &item : out_edges) { for (const auto &item : out_edges) {
auto [edge_type, to_vertex, edge] = item; auto [edge_type, to_vertex, edge] = item;
EdgeAccessor e(edge, edge_type, vertex_ptr, to_vertex, &transaction_, &shard_->indices_, &shard_->constraints_, EdgeAccessor e(edge, edge_type, vertex_ptr, to_vertex, &transaction_, &shard_->indices_, &shard_->constraints_,
config_, shard_->schema_validator_); config_, shard_->vertex_validator_);
auto ret = DeleteEdge(&e); auto ret = DeleteEdge(&e);
if (ret.HasError()) { if (ret.HasError()) {
MG_ASSERT(ret.GetError() == Error::SERIALIZATION_ERROR, "Invalid database state!"); MG_ASSERT(ret.GetError() == Error::SERIALIZATION_ERROR, "Invalid database state!");
@ -616,7 +617,7 @@ Result<std::optional<std::pair<VertexAccessor, std::vector<EdgeAccessor>>>> Shar
vertex_ptr->deleted = true; vertex_ptr->deleted = true;
return std::make_optional<ReturnType>(VertexAccessor{vertex_ptr, &transaction_, &shard_->indices_, return std::make_optional<ReturnType>(VertexAccessor{vertex_ptr, &transaction_, &shard_->indices_,
&shard_->constraints_, config_, shard_->schema_validator_, true}, &shard_->constraints_, config_, shard_->vertex_validator_, true},
std::move(deleted_edges)); std::move(deleted_edges));
} }
@ -662,7 +663,7 @@ Result<EdgeAccessor> Shard::Accessor::CreateEdge(VertexAccessor *from, VertexAcc
++shard_->edge_count_; ++shard_->edge_count_;
return EdgeAccessor(edge, edge_type, from_vertex, to_vertex, &transaction_, &shard_->indices_, &shard_->constraints_, return EdgeAccessor(edge, edge_type, from_vertex, to_vertex, &transaction_, &shard_->indices_, &shard_->constraints_,
config_, shard_->schema_validator_); config_, shard_->vertex_validator_);
} }
Result<EdgeAccessor> Shard::Accessor::CreateEdge(VertexAccessor *from, VertexAccessor *to, EdgeTypeId edge_type, Result<EdgeAccessor> Shard::Accessor::CreateEdge(VertexAccessor *from, VertexAccessor *to, EdgeTypeId edge_type,
@ -715,7 +716,7 @@ Result<EdgeAccessor> Shard::Accessor::CreateEdge(VertexAccessor *from, VertexAcc
++shard_->edge_count_; ++shard_->edge_count_;
return EdgeAccessor(edge, edge_type, from_vertex, to_vertex, &transaction_, &shard_->indices_, &shard_->constraints_, return EdgeAccessor(edge, edge_type, from_vertex, to_vertex, &transaction_, &shard_->indices_, &shard_->constraints_,
config_, shard_->schema_validator_); config_, shard_->vertex_validator_);
} }
Result<std::optional<EdgeAccessor>> Shard::Accessor::DeleteEdge(EdgeAccessor *edge) { Result<std::optional<EdgeAccessor>> Shard::Accessor::DeleteEdge(EdgeAccessor *edge) {
@ -783,7 +784,7 @@ Result<std::optional<EdgeAccessor>> Shard::Accessor::DeleteEdge(EdgeAccessor *ed
--shard_->edge_count_; --shard_->edge_count_;
return std::make_optional<EdgeAccessor>(edge_ref, edge_type, from_vertex, to_vertex, &transaction_, &shard_->indices_, return std::make_optional<EdgeAccessor>(edge_ref, edge_type, from_vertex, to_vertex, &transaction_, &shard_->indices_,
&shard_->constraints_, config_, shard_->schema_validator_, true); &shard_->constraints_, config_, shard_->vertex_validator_, true);
} }
const std::string &Shard::Accessor::LabelToName(LabelId label) const { return shard_->LabelToName(label); } const std::string &Shard::Accessor::LabelToName(LabelId label) const { return shard_->LabelToName(label); }
@ -1208,20 +1209,20 @@ VerticesIterable Shard::Accessor::Vertices(LabelId label, View view) {
VerticesIterable Shard::Accessor::Vertices(LabelId label, PropertyId property, View view) { VerticesIterable Shard::Accessor::Vertices(LabelId label, PropertyId property, View view) {
return VerticesIterable(shard_->indices_.label_property_index.Vertices( return VerticesIterable(shard_->indices_.label_property_index.Vertices(
label, property, std::nullopt, std::nullopt, view, &transaction_, shard_->schema_validator_)); label, property, std::nullopt, std::nullopt, view, &transaction_, shard_->vertex_validator_));
} }
VerticesIterable Shard::Accessor::Vertices(LabelId label, PropertyId property, const PropertyValue &value, View view) { VerticesIterable Shard::Accessor::Vertices(LabelId label, PropertyId property, const PropertyValue &value, View view) {
return VerticesIterable(shard_->indices_.label_property_index.Vertices( return VerticesIterable(shard_->indices_.label_property_index.Vertices(
label, property, utils::MakeBoundInclusive(value), utils::MakeBoundInclusive(value), view, &transaction_, label, property, utils::MakeBoundInclusive(value), utils::MakeBoundInclusive(value), view, &transaction_,
shard_->schema_validator_)); shard_->vertex_validator_));
} }
VerticesIterable Shard::Accessor::Vertices(LabelId label, PropertyId property, VerticesIterable Shard::Accessor::Vertices(LabelId label, PropertyId property,
const std::optional<utils::Bound<PropertyValue>> &lower_bound, const std::optional<utils::Bound<PropertyValue>> &lower_bound,
const std::optional<utils::Bound<PropertyValue>> &upper_bound, View view) { const std::optional<utils::Bound<PropertyValue>> &upper_bound, View view) {
return VerticesIterable(shard_->indices_.label_property_index.Vertices( return VerticesIterable(shard_->indices_.label_property_index.Vertices(
label, property, lower_bound, upper_bound, view, &transaction_, shard_->schema_validator_)); label, property, lower_bound, upper_bound, view, &transaction_, shard_->vertex_validator_));
} }
Transaction Shard::CreateTransaction(IsolationLevel isolation_level) { Transaction Shard::CreateTransaction(IsolationLevel isolation_level) {

View File

@ -79,7 +79,7 @@ class AllVerticesIterable final {
Indices *indices_; Indices *indices_;
Constraints *constraints_; Constraints *constraints_;
Config::Items config_; Config::Items config_;
const SchemaValidator *schema_validator_; const VertexValidator *vertex_validator_;
const Schemas *schemas_; const Schemas *schemas_;
std::optional<VertexAccessor> vertex_; std::optional<VertexAccessor> vertex_;
@ -102,14 +102,14 @@ class AllVerticesIterable final {
AllVerticesIterable(VerticesSkipList::Accessor vertices_accessor, Transaction *transaction, View view, AllVerticesIterable(VerticesSkipList::Accessor vertices_accessor, Transaction *transaction, View view,
Indices *indices, Constraints *constraints, Config::Items config, Indices *indices, Constraints *constraints, Config::Items config,
const SchemaValidator &schema_validator) const VertexValidator &vertex_validator)
: vertices_accessor_(std::move(vertices_accessor)), : vertices_accessor_(std::move(vertices_accessor)),
transaction_(transaction), transaction_(transaction),
view_(view), view_(view),
indices_(indices), indices_(indices),
constraints_(constraints), constraints_(constraints),
config_(config), config_(config),
schema_validator_{&schema_validator} {} vertex_validator_{&vertex_validator} {}
Iterator begin() { return {this, vertices_accessor_.begin()}; } Iterator begin() { return {this, vertices_accessor_.begin()}; }
Iterator end() { return {this, vertices_accessor_.end()}; } Iterator end() { return {this, vertices_accessor_.end()}; }
@ -246,7 +246,7 @@ class Shard final {
VerticesIterable Vertices(View view) { VerticesIterable Vertices(View view) {
return VerticesIterable(AllVerticesIterable(shard_->vertices_.access(), &transaction_, view, &shard_->indices_, return VerticesIterable(AllVerticesIterable(shard_->vertices_.access(), &transaction_, view, &shard_->indices_,
&shard_->constraints_, shard_->config_.items, &shard_->constraints_, shard_->config_.items,
shard_->schema_validator_)); shard_->vertex_validator_));
} }
VerticesIterable Vertices(LabelId label, View view); VerticesIterable Vertices(LabelId label, View view);
@ -519,6 +519,7 @@ class Shard final {
uint64_t edge_count_{0}; uint64_t edge_count_{0};
SchemaValidator schema_validator_; SchemaValidator schema_validator_;
VertexValidator vertex_validator_;
Constraints constraints_; Constraints constraints_;
Indices indices_; Indices indices_;
Schemas schemas_; Schemas schemas_;

View File

@ -28,19 +28,11 @@
namespace memgraph::storage::v3 { namespace memgraph::storage::v3 {
struct Vertex { struct Vertex {
Vertex(Delta *delta, LabelId primary_label, const std::vector<PropertyValue> &primary_properties) Vertex(Delta *delta, const std::vector<PropertyValue> &primary_properties) : keys{primary_properties}, delta{delta} {
: primary_label{primary_label}, keys{primary_properties}, delta{delta} {
MG_ASSERT(delta == nullptr || delta->action == Delta::Action::DELETE_OBJECT, MG_ASSERT(delta == nullptr || delta->action == Delta::Action::DELETE_OBJECT,
"Vertex must be created with an initial DELETE_OBJECT delta!"); "Vertex must be created with an initial DELETE_OBJECT delta!");
} }
Vertex(LabelId primary_label, const std::vector<PropertyValue> &primary_properties)
: primary_label{primary_label}, keys(primary_properties) {
MG_ASSERT(delta == nullptr || delta->action == Delta::Action::DELETE_OBJECT,
"Vertex must be created with an initial DELETE_OBJECT delta!");
}
LabelId primary_label;
KeyStore keys; KeyStore keys;
std::vector<LabelId> labels; std::vector<LabelId> labels;
@ -57,8 +49,6 @@ struct Vertex {
static_assert(alignof(Vertex) >= 8, "The Vertex should be aligned to at least 8!"); static_assert(alignof(Vertex) >= 8, "The Vertex should be aligned to at least 8!");
inline bool VertexHasLabel(const Vertex &vertex, const LabelId label) { inline bool VertexHasLabel(const Vertex &vertex, const LabelId label) { return utils::Contains(vertex.labels, label); }
return vertex.primary_label == label || utils::Contains(vertex.labels, label);
}
} // namespace memgraph::storage::v3 } // namespace memgraph::storage::v3

View File

@ -64,12 +64,12 @@ std::pair<bool, bool> IsVisible(Vertex *vertex, Transaction *transaction, View v
std::optional<VertexAccessor> VertexAccessor::Create(Vertex *vertex, Transaction *transaction, Indices *indices, std::optional<VertexAccessor> VertexAccessor::Create(Vertex *vertex, Transaction *transaction, Indices *indices,
Constraints *constraints, Config::Items config, Constraints *constraints, Config::Items config,
const SchemaValidator &schema_validator, View view) { const VertexValidator &vertex_validator, View view) {
if (const auto [exists, deleted] = detail::IsVisible(vertex, transaction, view); !exists || deleted) { if (const auto [exists, deleted] = detail::IsVisible(vertex, transaction, view); !exists || deleted) {
return std::nullopt; return std::nullopt;
} }
return VertexAccessor{vertex, transaction, indices, constraints, config, schema_validator}; return VertexAccessor{vertex, transaction, indices, constraints, config, vertex_validator};
} }
bool VertexAccessor::IsVisible(View view) const { bool VertexAccessor::IsVisible(View view) const {
@ -96,7 +96,7 @@ Result<bool> VertexAccessor::AddLabel(LabelId label) {
} }
ResultSchema<bool> VertexAccessor::AddLabelAndValidate(LabelId label) { ResultSchema<bool> VertexAccessor::AddLabelAndValidate(LabelId label) {
if (const auto maybe_violation_error = vertex_validator_.ValidateAddLabel(label); maybe_violation_error) { if (const auto maybe_violation_error = vertex_validator_->ValidateAddLabel(label); maybe_violation_error) {
return {*maybe_violation_error}; return {*maybe_violation_error};
} }
utils::MemoryTracker::OutOfMemoryExceptionEnabler oom_exception; utils::MemoryTracker::OutOfMemoryExceptionEnabler oom_exception;
@ -132,7 +132,7 @@ Result<bool> VertexAccessor::RemoveLabel(LabelId label) {
} }
ResultSchema<bool> VertexAccessor::RemoveLabelAndValidate(LabelId label) { ResultSchema<bool> VertexAccessor::RemoveLabelAndValidate(LabelId label) {
if (const auto maybe_violation_error = vertex_validator_.ValidateRemoveLabel(label); maybe_violation_error) { if (const auto maybe_violation_error = vertex_validator_->ValidateRemoveLabel(label); maybe_violation_error) {
return {*maybe_violation_error}; return {*maybe_violation_error};
} }
@ -157,7 +157,7 @@ Result<bool> VertexAccessor::HasLabel(LabelId label, View view) const {
Delta *delta = nullptr; Delta *delta = nullptr;
{ {
deleted = vertex_->deleted; deleted = vertex_->deleted;
has_label = VertexHasLabel(*vertex_, label); has_label = label == vertex_validator_->primary_label_ || VertexHasLabel(*vertex_, label);
delta = vertex_->delta; delta = vertex_->delta;
} }
ApplyDeltasForRead(transaction_, delta, view, [&exists, &deleted, &has_label, label](const Delta &delta) { ApplyDeltasForRead(transaction_, delta, view, [&exists, &deleted, &has_label, label](const Delta &delta) {
@ -227,7 +227,7 @@ Result<LabelId> VertexAccessor::PrimaryLabel(const View view) const {
}); });
if (!exists) return Error::NONEXISTENT_OBJECT; if (!exists) return Error::NONEXISTENT_OBJECT;
if (!for_deleted_ && deleted) return Error::DELETED_OBJECT; if (!for_deleted_ && deleted) return Error::DELETED_OBJECT;
return vertex_->primary_label; return vertex_validator_->primary_label_;
} }
Result<PrimaryKey> VertexAccessor::PrimaryKey(const View view) const { Result<PrimaryKey> VertexAccessor::PrimaryKey(const View view) const {
@ -338,7 +338,7 @@ Result<PropertyValue> VertexAccessor::SetProperty(PropertyId property, const Pro
} }
ResultSchema<PropertyValue> VertexAccessor::SetPropertyAndValidate(PropertyId property, const PropertyValue &value) { ResultSchema<PropertyValue> VertexAccessor::SetPropertyAndValidate(PropertyId property, const PropertyValue &value) {
if (auto maybe_violation_error = vertex_validator_.ValidatePropertyUpdate(property); maybe_violation_error) { if (auto maybe_violation_error = vertex_validator_->ValidatePropertyUpdate(property); maybe_violation_error) {
return {*maybe_violation_error}; return {*maybe_violation_error};
} }
utils::MemoryTracker::OutOfMemoryExceptionEnabler oom_exception; utils::MemoryTracker::OutOfMemoryExceptionEnabler oom_exception;
@ -546,7 +546,7 @@ Result<std::vector<EdgeAccessor>> VertexAccessor::InEdges(View view, const std::
for (const auto &item : in_edges) { for (const auto &item : in_edges) {
const auto &[edge_type, from_vertex, edge] = item; const auto &[edge_type, from_vertex, edge] = item;
ret.emplace_back(edge, edge_type, from_vertex, vertex_, transaction_, indices_, constraints_, config_, ret.emplace_back(edge, edge_type, from_vertex, vertex_, transaction_, indices_, constraints_, config_,
*vertex_validator_.schema_validator); *vertex_validator_);
} }
return std::move(ret); return std::move(ret);
} }
@ -626,7 +626,7 @@ Result<std::vector<EdgeAccessor>> VertexAccessor::OutEdges(View view, const std:
for (const auto &item : out_edges) { for (const auto &item : out_edges) {
const auto &[edge_type, to_vertex, edge] = item; const auto &[edge_type, to_vertex, edge] = item;
ret.emplace_back(edge, edge_type, vertex_, to_vertex, transaction_, indices_, constraints_, config_, ret.emplace_back(edge, edge_type, vertex_, to_vertex, transaction_, indices_, constraints_, config_,
*vertex_validator_.schema_validator); *vertex_validator_);
} }
return std::move(ret); return std::move(ret);
} }
@ -705,21 +705,4 @@ Result<size_t> VertexAccessor::OutDegree(View view) const {
return degree; return degree;
} }
VertexAccessor::VertexValidator::VertexValidator(const SchemaValidator &schema_validator, const Vertex *vertex)
: schema_validator{&schema_validator}, vertex_{vertex} {}
[[nodiscard]] std::optional<SchemaViolation> VertexAccessor::VertexValidator::ValidatePropertyUpdate(
PropertyId property_id) const {
MG_ASSERT(vertex_ != nullptr, "Cannot validate vertex which is nullptr");
return schema_validator->ValidatePropertyUpdate(vertex_->primary_label, property_id);
};
[[nodiscard]] std::optional<SchemaViolation> VertexAccessor::VertexValidator::ValidateAddLabel(LabelId label) const {
return schema_validator->ValidateLabelUpdate(label);
}
[[nodiscard]] std::optional<SchemaViolation> VertexAccessor::VertexValidator::ValidateRemoveLabel(LabelId label) const {
return schema_validator->ValidateLabelUpdate(label);
}
} // namespace memgraph::storage::v3 } // namespace memgraph::storage::v3

View File

@ -31,39 +31,24 @@ struct Constraints;
class VertexAccessor final { class VertexAccessor final {
private: private:
struct VertexValidator {
// TODO(jbajic) Beware since vertex is pointer it will be accessed even as nullptr
explicit VertexValidator(const SchemaValidator &schema_validator, const Vertex *vertex);
[[nodiscard]] std::optional<SchemaViolation> ValidatePropertyUpdate(PropertyId property_id) const;
[[nodiscard]] std::optional<SchemaViolation> ValidateAddLabel(LabelId label) const;
[[nodiscard]] std::optional<SchemaViolation> ValidateRemoveLabel(LabelId label) const;
const SchemaValidator *schema_validator;
private:
const Vertex *vertex_;
};
friend class Shard; friend class Shard;
public: public:
// Be careful when using VertexAccessor since it can be instantiated with // Be careful when using VertexAccessor since it can be instantiated with
// nullptr values // nullptr values
VertexAccessor(Vertex *vertex, Transaction *transaction, Indices *indices, Constraints *constraints, VertexAccessor(Vertex *vertex, Transaction *transaction, Indices *indices, Constraints *constraints,
Config::Items config, const SchemaValidator &schema_validator, bool for_deleted = false) Config::Items config, const VertexValidator &vertex_validator, bool for_deleted = false)
: vertex_(vertex), : vertex_(vertex),
transaction_(transaction), transaction_(transaction),
indices_(indices), indices_(indices),
constraints_(constraints), constraints_(constraints),
config_(config), config_(config),
vertex_validator_{schema_validator, vertex}, vertex_validator_{&vertex_validator},
for_deleted_(for_deleted) {} for_deleted_(for_deleted) {}
static std::optional<VertexAccessor> Create(Vertex *vertex, Transaction *transaction, Indices *indices, static std::optional<VertexAccessor> Create(Vertex *vertex, Transaction *transaction, Indices *indices,
Constraints *constraints, Config::Items config, Constraints *constraints, Config::Items config,
const SchemaValidator &schema_validator, View view); const VertexValidator &vertex_validator, View view);
/// @return true if the object is visible from the current transaction /// @return true if the object is visible from the current transaction
bool IsVisible(View view) const; bool IsVisible(View view) const;
@ -148,7 +133,7 @@ class VertexAccessor final {
Indices *indices_; Indices *indices_;
Constraints *constraints_; Constraints *constraints_;
Config::Items config_; Config::Items config_;
VertexValidator vertex_validator_; const VertexValidator *vertex_validator_;
// if the accessor was created for a deleted vertex. // if the accessor was created for a deleted vertex.
// Accessor behaves differently for some methods based on this // Accessor behaves differently for some methods based on this