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 <cstdint>
#include <filesystem>
#include "storage/v3/id_types.hpp"
#include "storage/v3/isolation_level.hpp"
#include "storage/v3/transaction.hpp"

View File

@ -19,6 +19,7 @@
#include "storage/v3/edge_accessor.hpp"
#include "storage/v3/edge_ref.hpp"
#include "storage/v3/mvcc.hpp"
#include "storage/v3/schema_validator.hpp"
#include "storage/v3/schemas.hpp"
#include "storage/v3/vertex_accessor.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,
VerticesSkipList *vertices, utils::SkipList<Edge> *edges, NameIdMapper *name_id_mapper,
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,
utils::FileRetainer *file_retainer) {
// Ensure that the storage directory exists.
@ -718,7 +719,7 @@ void CreateSnapshot(Transaction *transaction, const std::filesystem::path &snaps
// here.
// TODO(jbajic) Fix snapshot with new schema rules
auto ea = EdgeAccessor{edge_ref, EdgeTypeId::FromUint(0UL), nullptr, nullptr, transaction, indices, constraints,
items, schema_validator};
items, vertex_validator};
// Get edge data.
auto maybe_props = ea.Properties(View::OLD);
@ -746,7 +747,7 @@ void CreateSnapshot(Transaction *transaction, const std::filesystem::path &snaps
auto acc = vertices->access();
for (auto &lgo_vertex : acc) {
// 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);
if (!va) continue;

View File

@ -51,11 +51,11 @@ bool EdgeAccessor::IsVisible(const View view) 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 {
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) {

View File

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

View File

@ -13,9 +13,9 @@
#include <limits>
#include "storage/v3/id_types.hpp"
#include "storage/v3/mvcc.hpp"
#include "storage/v3/property_value.hpp"
#include "storage/v3/schema_validator.hpp"
#include "storage/v3/schemas.hpp"
#include "utils/bound.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)
: self_(self),
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) {
AdvanceUntilValid();
}
@ -346,7 +346,7 @@ void LabelIndex::Iterable::Iterator::AdvanceUntilValid() {
if (CurrentVersionHasLabel(*index_iterator_->vertex, self_->label_, self_->transaction_, self_->view_)) {
current_vertex_ = index_iterator_->vertex;
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;
}
}
@ -354,7 +354,7 @@ void LabelIndex::Iterable::Iterator::AdvanceUntilValid() {
LabelIndex::Iterable::Iterable(utils::SkipList<Entry>::Accessor index_accessor, LabelId label, View view,
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)),
label_(label),
view_(view),
@ -362,7 +362,7 @@ LabelIndex::Iterable::Iterable(utils::SkipList<Entry>::Accessor index_accessor,
indices_(indices),
constraints_(constraints),
config_(config),
schema_validator_(&schema_validator) {}
vertex_validator_(&vertex_validator) {}
void LabelIndex::RunGC() {
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)
: self_(self),
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) {
AdvanceUntilValid();
}
@ -520,7 +520,7 @@ void LabelPropertyIndex::Iterable::Iterator::AdvanceUntilValid() {
index_iterator_->value, self_->transaction_, self_->view_)) {
current_vertex_ = index_iterator_->vertex;
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;
}
}
@ -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>> &upper_bound, View view,
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)),
label_(label),
property_(property),
@ -554,7 +554,7 @@ LabelPropertyIndex::Iterable::Iterable(utils::SkipList<Entry>::Accessor index_ac
indices_(indices),
constraints_(constraints),
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
// 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

View File

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

View File

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

View File

@ -103,4 +103,19 @@ SchemaValidator::SchemaValidator(Schemas &schemas) : schemas_{schemas} {}
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

View File

@ -63,6 +63,20 @@ class SchemaValidator {
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>
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,
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) {
*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) {
++it;
continue;
@ -85,14 +85,14 @@ auto AdvanceToVisibleVertex(VerticesSkipList::Iterator it, VerticesSkipList::Ite
AllVerticesIterable::Iterator::Iterator(AllVerticesIterable *self, VerticesSkipList::Iterator it)
: self_(self),
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_; }
AllVerticesIterable::Iterator &AllVerticesIterable::Iterator::operator++() {
++it_;
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;
}
@ -321,7 +321,8 @@ Shard::Shard(const LabelId primary_label, const PrimaryKey min_primary_key,
min_primary_key_{min_primary_key},
max_primary_key_{max_primary_key},
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},
config_{config},
snapshot_directory_{config_.durability.storage_directory / durability::kSnapshotDirectory},
@ -496,10 +497,10 @@ ResultSchema<VertexAccessor> Shard::Accessor::CreateVertexAndValidate(
}
auto acc = shard_->vertices_.access();
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_,
&shard_->constraints_, config_, shard_->schema_validator_};
&shard_->constraints_, config_, shard_->vertex_validator_};
MG_ASSERT(inserted, "The vertex must be inserted here!");
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 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) {
@ -550,7 +551,7 @@ Result<std::optional<VertexAccessor>> Shard::Accessor::DeleteVertex(VertexAccess
vertex_ptr->deleted = true;
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(
@ -578,7 +579,7 @@ Result<std::optional<std::pair<VertexAccessor, std::vector<EdgeAccessor>>>> Shar
for (const auto &item : in_edges) {
auto [edge_type, from_vertex, edge] = item;
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);
if (ret.HasError()) {
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) {
auto [edge_type, to_vertex, edge] = item;
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);
if (ret.HasError()) {
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;
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));
}
@ -662,7 +663,7 @@ Result<EdgeAccessor> Shard::Accessor::CreateEdge(VertexAccessor *from, VertexAcc
++shard_->edge_count_;
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,
@ -715,7 +716,7 @@ Result<EdgeAccessor> Shard::Accessor::CreateEdge(VertexAccessor *from, VertexAcc
++shard_->edge_count_;
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) {
@ -783,7 +784,7 @@ Result<std::optional<EdgeAccessor>> Shard::Accessor::DeleteEdge(EdgeAccessor *ed
--shard_->edge_count_;
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); }
@ -1208,20 +1209,20 @@ VerticesIterable Shard::Accessor::Vertices(LabelId label, View view) {
VerticesIterable Shard::Accessor::Vertices(LabelId label, PropertyId property, View view) {
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) {
return VerticesIterable(shard_->indices_.label_property_index.Vertices(
label, property, utils::MakeBoundInclusive(value), utils::MakeBoundInclusive(value), view, &transaction_,
shard_->schema_validator_));
shard_->vertex_validator_));
}
VerticesIterable Shard::Accessor::Vertices(LabelId label, PropertyId property,
const std::optional<utils::Bound<PropertyValue>> &lower_bound,
const std::optional<utils::Bound<PropertyValue>> &upper_bound, View view) {
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) {

View File

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

View File

@ -28,19 +28,11 @@
namespace memgraph::storage::v3 {
struct Vertex {
Vertex(Delta *delta, LabelId primary_label, const std::vector<PropertyValue> &primary_properties)
: primary_label{primary_label}, keys{primary_properties}, delta{delta} {
Vertex(Delta *delta, const std::vector<PropertyValue> &primary_properties) : keys{primary_properties}, delta{delta} {
MG_ASSERT(delta == nullptr || delta->action == Delta::Action::DELETE_OBJECT,
"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;
std::vector<LabelId> labels;
@ -57,8 +49,6 @@ struct Vertex {
static_assert(alignof(Vertex) >= 8, "The Vertex should be aligned to at least 8!");
inline bool VertexHasLabel(const Vertex &vertex, const LabelId label) {
return vertex.primary_label == label || utils::Contains(vertex.labels, label);
}
inline bool VertexHasLabel(const Vertex &vertex, const LabelId label) { return utils::Contains(vertex.labels, label); }
} // 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,
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) {
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 {
@ -96,7 +96,7 @@ Result<bool> VertexAccessor::AddLabel(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};
}
utils::MemoryTracker::OutOfMemoryExceptionEnabler oom_exception;
@ -132,7 +132,7 @@ Result<bool> VertexAccessor::RemoveLabel(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};
}
@ -157,7 +157,7 @@ Result<bool> VertexAccessor::HasLabel(LabelId label, View view) const {
Delta *delta = nullptr;
{
deleted = vertex_->deleted;
has_label = VertexHasLabel(*vertex_, label);
has_label = label == vertex_validator_->primary_label_ || VertexHasLabel(*vertex_, label);
delta = vertex_->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 (!for_deleted_ && deleted) return Error::DELETED_OBJECT;
return vertex_->primary_label;
return vertex_validator_->primary_label_;
}
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) {
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};
}
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) {
const auto &[edge_type, from_vertex, edge] = item;
ret.emplace_back(edge, edge_type, from_vertex, vertex_, transaction_, indices_, constraints_, config_,
*vertex_validator_.schema_validator);
*vertex_validator_);
}
return std::move(ret);
}
@ -626,7 +626,7 @@ Result<std::vector<EdgeAccessor>> VertexAccessor::OutEdges(View view, const std:
for (const auto &item : out_edges) {
const auto &[edge_type, to_vertex, edge] = item;
ret.emplace_back(edge, edge_type, vertex_, to_vertex, transaction_, indices_, constraints_, config_,
*vertex_validator_.schema_validator);
*vertex_validator_);
}
return std::move(ret);
}
@ -705,21 +705,4 @@ Result<size_t> VertexAccessor::OutDegree(View view) const {
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

View File

@ -31,39 +31,24 @@ struct Constraints;
class VertexAccessor final {
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;
public:
// Be careful when using VertexAccessor since it can be instantiated with
// nullptr values
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),
transaction_(transaction),
indices_(indices),
constraints_(constraints),
config_(config),
vertex_validator_{schema_validator, vertex},
vertex_validator_{&vertex_validator},
for_deleted_(for_deleted) {}
static std::optional<VertexAccessor> Create(Vertex *vertex, Transaction *transaction, Indices *indices,
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
bool IsVisible(View view) const;
@ -148,7 +133,7 @@ class VertexAccessor final {
Indices *indices_;
Constraints *constraints_;
Config::Items config_;
VertexValidator vertex_validator_;
const VertexValidator *vertex_validator_;
// if the accessor was created for a deleted vertex.
// Accessor behaves differently for some methods based on this