Adapt schema validator
This commit is contained in:
parent
ef755e466c
commit
618237cc96
@ -17,6 +17,7 @@
|
|||||||
#include <string_view>
|
#include <string_view>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
|
#include "storage/v3/id_types.hpp"
|
||||||
#include "utils/logging.hpp"
|
#include "utils/logging.hpp"
|
||||||
#include "utils/skip_list.hpp"
|
#include "utils/skip_list.hpp"
|
||||||
|
|
||||||
@ -47,6 +48,10 @@ class NameIdMapper final {
|
|||||||
return kUnmappedId;
|
return kUnmappedId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const std::string &IdToName(const LabelId label_id) const { return IdToName(label_id.AsInt()); }
|
||||||
|
|
||||||
|
const std::string &IdToName(const PropertyId property_id) const { return IdToName(property_id.AsInt()); }
|
||||||
|
|
||||||
const std::string &IdToName(const uint64_t id) const {
|
const std::string &IdToName(const uint64_t id) const {
|
||||||
auto it = id_to_name_.find(id);
|
auto it = id_to_name_.find(id);
|
||||||
MG_ASSERT(it != id_to_name_.end(), "Id not know in mapper!");
|
MG_ASSERT(it != id_to_name_.end(), "Id not know in mapper!");
|
||||||
|
@ -16,67 +16,60 @@
|
|||||||
#include <ranges>
|
#include <ranges>
|
||||||
|
|
||||||
#include "common/types.hpp"
|
#include "common/types.hpp"
|
||||||
|
#include "storage/v3/name_id_mapper.hpp"
|
||||||
|
#include "storage/v3/result.hpp"
|
||||||
#include "storage/v3/schemas.hpp"
|
#include "storage/v3/schemas.hpp"
|
||||||
|
|
||||||
namespace memgraph::storage::v3 {
|
namespace memgraph::storage::v3 {
|
||||||
|
|
||||||
bool operator==(const SchemaViolation &lhs, const SchemaViolation &rhs) {
|
SchemaValidator::SchemaValidator(Schemas &schemas, const NameIdMapper &name_id_mapper)
|
||||||
return lhs.status == rhs.status && lhs.label == rhs.label &&
|
: schemas_{&schemas}, name_id_mapper_{&name_id_mapper} {}
|
||||||
lhs.violated_schema_property == rhs.violated_schema_property &&
|
|
||||||
lhs.violated_property_value == rhs.violated_property_value;
|
|
||||||
}
|
|
||||||
|
|
||||||
SchemaViolation::SchemaViolation(ValidationStatus status, LabelId label) : status{status}, label{label} {}
|
std::optional<ShardError> SchemaValidator::ValidateVertexCreate(
|
||||||
|
|
||||||
SchemaViolation::SchemaViolation(ValidationStatus status, LabelId label, SchemaProperty violated_schema_property)
|
|
||||||
: status{status}, label{label}, violated_schema_property{violated_schema_property} {}
|
|
||||||
|
|
||||||
SchemaViolation::SchemaViolation(ValidationStatus status, LabelId label, SchemaProperty violated_schema_property,
|
|
||||||
PropertyValue violated_property_value)
|
|
||||||
: status{status},
|
|
||||||
label{label},
|
|
||||||
violated_schema_property{violated_schema_property},
|
|
||||||
violated_property_value{violated_property_value} {}
|
|
||||||
|
|
||||||
SchemaValidator::SchemaValidator(Schemas &schemas) : schemas_{schemas} {}
|
|
||||||
|
|
||||||
std::optional<SchemaViolation> SchemaValidator::ValidateVertexCreate(
|
|
||||||
LabelId primary_label, const std::vector<LabelId> &labels,
|
LabelId primary_label, const std::vector<LabelId> &labels,
|
||||||
const std::vector<PropertyValue> &primary_properties) const {
|
const std::vector<PropertyValue> &primary_properties) const {
|
||||||
// Schema on primary label
|
// Schema on primary label
|
||||||
const auto *schema = schemas_.GetSchema(primary_label);
|
const auto *schema = schemas_->GetSchema(primary_label);
|
||||||
if (schema == nullptr) {
|
if (schema == nullptr) {
|
||||||
return SchemaViolation(SchemaViolation::ValidationStatus::NO_SCHEMA_DEFINED_FOR_LABEL, primary_label);
|
return SHARD_ERROR(ErrorCode::SCHEMA_NO_SCHEMA_DEFINED_FOR_LABEL,
|
||||||
|
fmt::format("Schema not defined for label :{}", name_id_mapper_->IdToName(primary_label)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Is there another primary label among secondary labels
|
// Is there another primary label among secondary labels
|
||||||
for (const auto &secondary_label : labels) {
|
for (const auto &secondary_label : labels) {
|
||||||
if (schemas_.GetSchema(secondary_label)) {
|
if (schemas_->GetSchema(secondary_label)) {
|
||||||
return SchemaViolation(SchemaViolation::ValidationStatus::VERTEX_SECONDARY_LABEL_IS_PRIMARY, secondary_label);
|
return SHARD_ERROR(ErrorCode::SCHEMA_VERTEX_SECONDARY_LABEL_IS_PRIMARY,
|
||||||
|
fmt::format("Cannot add label :{}, since it is defined as a primary label",
|
||||||
|
name_id_mapper_->IdToName(secondary_label)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Quick size check
|
// Quick size check
|
||||||
if (schema->second.size() != primary_properties.size()) {
|
if (schema->second.size() != primary_properties.size()) {
|
||||||
return SchemaViolation(SchemaViolation::ValidationStatus::VERTEX_PRIMARY_PROPERTIES_UNDEFINED, primary_label);
|
return SHARD_ERROR(ErrorCode::SCHEMA_VERTEX_PRIMARY_PROPERTIES_UNDEFINED,
|
||||||
|
fmt::format("Not all primary properties have been specified for :{} vertex",
|
||||||
|
name_id_mapper_->IdToName(primary_label)));
|
||||||
}
|
}
|
||||||
// Check only properties defined by schema
|
// Check only properties defined by schema
|
||||||
for (size_t i{0}; i < schema->second.size(); ++i) {
|
for (size_t i{0}; i < schema->second.size(); ++i) {
|
||||||
// Check schema property type
|
// Check schema property type
|
||||||
if (auto property_schema_type = PropertyTypeToSchemaType(primary_properties[i]);
|
if (auto property_schema_type = PropertyTypeToSchemaType(primary_properties[i]);
|
||||||
property_schema_type && *property_schema_type != schema->second[i].type) {
|
property_schema_type && *property_schema_type != schema->second[i].type) {
|
||||||
return SchemaViolation(SchemaViolation::ValidationStatus::VERTEX_PROPERTY_WRONG_TYPE, primary_label,
|
return SHARD_ERROR(
|
||||||
schema->second[i], primary_properties[i]);
|
ErrorCode::SCHEMA_VERTEX_PROPERTY_WRONG_TYPE,
|
||||||
|
fmt::format("Property {} is of wrong type, expected {}, actual {}",
|
||||||
|
name_id_mapper_->IdToName(schema->second[i].property_id),
|
||||||
|
SchemaTypeToString(schema->second[i].type), SchemaTypeToString(*property_schema_type)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<SchemaViolation> SchemaValidator::ValidatePropertyUpdate(const LabelId primary_label,
|
std::optional<ShardError> SchemaValidator::ValidatePropertyUpdate(const LabelId primary_label,
|
||||||
const PropertyId property_id) const {
|
const PropertyId property_id) const {
|
||||||
// Verify existence of schema on primary label
|
// Verify existence of schema on primary label
|
||||||
const auto *schema = schemas_.GetSchema(primary_label);
|
const auto *schema = schemas_->GetSchema(primary_label);
|
||||||
MG_ASSERT(schema, "Cannot validate against non existing schema!");
|
MG_ASSERT(schema, "Cannot validate against non existing schema!");
|
||||||
|
|
||||||
// Verify that updating property is not part of schema
|
// Verify that updating property is not part of schema
|
||||||
@ -84,16 +77,19 @@ std::optional<SchemaViolation> SchemaValidator::ValidatePropertyUpdate(const Lab
|
|||||||
schema->second,
|
schema->second,
|
||||||
[property_id](const auto &schema_property) { return property_id == schema_property.property_id; });
|
[property_id](const auto &schema_property) { return property_id == schema_property.property_id; });
|
||||||
schema_property != schema->second.end()) {
|
schema_property != schema->second.end()) {
|
||||||
return SchemaViolation(SchemaViolation::ValidationStatus::VERTEX_UPDATE_PRIMARY_KEY, primary_label,
|
return SHARD_ERROR(
|
||||||
*schema_property);
|
ErrorCode::SCHEMA_VERTEX_UPDATE_PRIMARY_KEY,
|
||||||
|
fmt::format("Cannot update primary property {} of schema on label :{}",
|
||||||
|
name_id_mapper_->IdToName(schema_property->property_id), name_id_mapper_->IdToName(primary_label)));
|
||||||
}
|
}
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<SchemaViolation> SchemaValidator::ValidateLabelUpdate(const LabelId label) const {
|
std::optional<ShardError> SchemaValidator::ValidateLabelUpdate(const LabelId label) const {
|
||||||
const auto *schema = schemas_.GetSchema(label);
|
const auto *schema = schemas_->GetSchema(label);
|
||||||
if (schema) {
|
if (schema) {
|
||||||
return SchemaViolation(SchemaViolation::ValidationStatus::VERTEX_UPDATE_PRIMARY_LABEL, label);
|
return SHARD_ERROR(ErrorCode::SCHEMA_VERTEX_UPDATE_PRIMARY_LABEL,
|
||||||
|
fmt::format("Cannot add/remove primary label :{}", name_id_mapper_->IdToName(label)));
|
||||||
}
|
}
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
@ -103,15 +99,15 @@ const Schemas::Schema *SchemaValidator::GetSchema(LabelId label) const { return
|
|||||||
VertexValidator::VertexValidator(const SchemaValidator &schema_validator, const LabelId primary_label)
|
VertexValidator::VertexValidator(const SchemaValidator &schema_validator, const LabelId primary_label)
|
||||||
: schema_validator{&schema_validator}, primary_label_{primary_label} {}
|
: schema_validator{&schema_validator}, primary_label_{primary_label} {}
|
||||||
|
|
||||||
std::optional<SchemaViolation> VertexValidator::ValidatePropertyUpdate(PropertyId property_id) const {
|
std::optional<ShardError> VertexValidator::ValidatePropertyUpdate(PropertyId property_id) const {
|
||||||
return schema_validator->ValidatePropertyUpdate(primary_label_, property_id);
|
return schema_validator->ValidatePropertyUpdate(primary_label_, property_id);
|
||||||
};
|
};
|
||||||
|
|
||||||
std::optional<SchemaViolation> VertexValidator::ValidateAddLabel(LabelId label) const {
|
std::optional<ShardError> VertexValidator::ValidateAddLabel(LabelId label) const {
|
||||||
return schema_validator->ValidateLabelUpdate(label);
|
return schema_validator->ValidateLabelUpdate(label);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<SchemaViolation> VertexValidator::ValidateRemoveLabel(LabelId label) const {
|
std::optional<ShardError> VertexValidator::ValidateRemoveLabel(LabelId label) const {
|
||||||
return schema_validator->ValidateLabelUpdate(label);
|
return schema_validator->ValidateLabelUpdate(label);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,65 +14,42 @@
|
|||||||
#include <optional>
|
#include <optional>
|
||||||
#include <variant>
|
#include <variant>
|
||||||
|
|
||||||
|
#include "storage/v2/result.hpp"
|
||||||
#include "storage/v3/id_types.hpp"
|
#include "storage/v3/id_types.hpp"
|
||||||
|
#include "storage/v3/name_id_mapper.hpp"
|
||||||
#include "storage/v3/property_value.hpp"
|
#include "storage/v3/property_value.hpp"
|
||||||
#include "storage/v3/result.hpp"
|
#include "storage/v3/result.hpp"
|
||||||
#include "storage/v3/schemas.hpp"
|
#include "storage/v3/schemas.hpp"
|
||||||
|
|
||||||
namespace memgraph::storage::v3 {
|
namespace memgraph::storage::v3 {
|
||||||
|
|
||||||
struct SchemaViolation {
|
|
||||||
enum class ValidationStatus : uint8_t {
|
|
||||||
NO_SCHEMA_DEFINED_FOR_LABEL,
|
|
||||||
VERTEX_PROPERTY_WRONG_TYPE,
|
|
||||||
VERTEX_UPDATE_PRIMARY_KEY,
|
|
||||||
VERTEX_UPDATE_PRIMARY_LABEL,
|
|
||||||
VERTEX_SECONDARY_LABEL_IS_PRIMARY,
|
|
||||||
VERTEX_PRIMARY_PROPERTIES_UNDEFINED,
|
|
||||||
};
|
|
||||||
|
|
||||||
SchemaViolation(ValidationStatus status, LabelId label);
|
|
||||||
|
|
||||||
SchemaViolation(ValidationStatus status, LabelId label, SchemaProperty violated_schema_property);
|
|
||||||
|
|
||||||
SchemaViolation(ValidationStatus status, LabelId label, SchemaProperty violated_schema_property,
|
|
||||||
PropertyValue violated_property_value);
|
|
||||||
|
|
||||||
friend bool operator==(const SchemaViolation &lhs, const SchemaViolation &rhs);
|
|
||||||
|
|
||||||
ValidationStatus status;
|
|
||||||
LabelId label;
|
|
||||||
std::optional<SchemaProperty> violated_schema_property;
|
|
||||||
std::optional<PropertyValue> violated_property_value;
|
|
||||||
};
|
|
||||||
|
|
||||||
class SchemaValidator {
|
class SchemaValidator {
|
||||||
public:
|
public:
|
||||||
explicit SchemaValidator(Schemas &schemas);
|
explicit SchemaValidator(Schemas &schemas, const NameIdMapper &name_id_mapper);
|
||||||
|
|
||||||
[[nodiscard]] std::optional<SchemaViolation> ValidateVertexCreate(
|
[[nodiscard]] std::optional<ShardError> ValidateVertexCreate(
|
||||||
LabelId primary_label, const std::vector<LabelId> &labels,
|
LabelId primary_label, const std::vector<LabelId> &labels,
|
||||||
const std::vector<PropertyValue> &primary_properties) const;
|
const std::vector<PropertyValue> &primary_properties) const;
|
||||||
|
|
||||||
[[nodiscard]] std::optional<SchemaViolation> ValidatePropertyUpdate(LabelId primary_label,
|
[[nodiscard]] std::optional<ShardError> ValidatePropertyUpdate(LabelId primary_label, PropertyId property_id) const;
|
||||||
PropertyId property_id) const;
|
|
||||||
|
|
||||||
[[nodiscard]] std::optional<SchemaViolation> ValidateLabelUpdate(LabelId label) const;
|
[[nodiscard]] std::optional<ShardError> ValidateLabelUpdate(LabelId label) const;
|
||||||
|
|
||||||
const Schemas::Schema *GetSchema(LabelId label) const;
|
const Schemas::Schema *GetSchema(LabelId label) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Schemas &schemas_;
|
Schemas *schemas_;
|
||||||
|
const NameIdMapper *name_id_mapper_;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct VertexValidator {
|
struct VertexValidator {
|
||||||
explicit VertexValidator(const SchemaValidator &schema_validator, LabelId primary_label);
|
explicit VertexValidator(const SchemaValidator &schema_validator, LabelId primary_label);
|
||||||
|
|
||||||
[[nodiscard]] std::optional<SchemaViolation> ValidatePropertyUpdate(PropertyId property_id) const;
|
[[nodiscard]] std::optional<ShardError> ValidatePropertyUpdate(PropertyId property_id) const;
|
||||||
|
|
||||||
[[nodiscard]] std::optional<SchemaViolation> ValidateAddLabel(LabelId label) const;
|
[[nodiscard]] std::optional<ShardError> ValidateAddLabel(LabelId label) const;
|
||||||
|
|
||||||
[[nodiscard]] std::optional<SchemaViolation> ValidateRemoveLabel(LabelId label) const;
|
[[nodiscard]] std::optional<ShardError> ValidateRemoveLabel(LabelId label) const;
|
||||||
|
|
||||||
const SchemaValidator *schema_validator;
|
const SchemaValidator *schema_validator;
|
||||||
|
|
||||||
|
@ -31,6 +31,7 @@
|
|||||||
#include "storage/v3/indices.hpp"
|
#include "storage/v3/indices.hpp"
|
||||||
#include "storage/v3/key_store.hpp"
|
#include "storage/v3/key_store.hpp"
|
||||||
#include "storage/v3/mvcc.hpp"
|
#include "storage/v3/mvcc.hpp"
|
||||||
|
#include "storage/v3/name_id_mapper.hpp"
|
||||||
#include "storage/v3/property_value.hpp"
|
#include "storage/v3/property_value.hpp"
|
||||||
#include "storage/v3/schema_validator.hpp"
|
#include "storage/v3/schema_validator.hpp"
|
||||||
#include "storage/v3/shard_operation_result.hpp"
|
#include "storage/v3/shard_operation_result.hpp"
|
||||||
@ -327,7 +328,7 @@ Shard::Shard(const LabelId primary_label, const PrimaryKey min_primary_key,
|
|||||||
: primary_label_{primary_label},
|
: primary_label_{primary_label},
|
||||||
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_, name_id_mapper_},
|
||||||
vertex_validator_{schema_validator_, primary_label},
|
vertex_validator_{schema_validator_, primary_label},
|
||||||
indices_{config.items, vertex_validator_},
|
indices_{config.items, vertex_validator_},
|
||||||
isolation_level_{config.transaction.isolation_level},
|
isolation_level_{config.transaction.isolation_level},
|
||||||
|
Loading…
Reference in New Issue
Block a user