Implement SchemaTypes
This commit is contained in:
parent
65b8e055a6
commit
eb4d23c504
@ -9,7 +9,6 @@
|
||||
// by the Apache License, Version 2.0, included in the file
|
||||
// licenses/APL.txt.
|
||||
|
||||
#include <tuple>
|
||||
#include <unordered_map>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
@ -19,40 +18,53 @@
|
||||
|
||||
namespace memgraph::storage {
|
||||
|
||||
Schemas::CreationStatus Schemas::CreateSchema(
|
||||
const LabelId label, const std::vector<std::pair<PropertyId, PropertyValue::Type>> &property_types) {
|
||||
auto res = schemas_.insert({label, property_types}).second;
|
||||
SchemaViolation::SchemaViolation(ValidationStatus status, LabelId label) : status{status}, label{label} {}
|
||||
|
||||
SchemaViolation::SchemaViolation(ValidationStatus status, LabelId label, SchemaType violated_type)
|
||||
: status{status}, label{label}, violated_type{violated_type} {}
|
||||
|
||||
SchemaViolation::SchemaViolation(ValidationStatus status, LabelId label, SchemaType violated_type,
|
||||
PropertyValue violated_property_value)
|
||||
: status{status}, label{label}, violated_type{violated_type}, violated_property_value{violated_property_value} {}
|
||||
|
||||
Schemas::CreationStatus Schemas::CreateSchema(const LabelId primary_label,
|
||||
const std::vector<SchemaType> &schemas_types) {
|
||||
auto res = schemas_.insert({primary_label, schemas_types}).second;
|
||||
return res ? Schemas::CreationStatus::SUCCESS : Schemas::CreationStatus::FAIL;
|
||||
}
|
||||
|
||||
Schemas::DeletionStatus Schemas::DeleteSchema(const LabelId label) {
|
||||
auto res = schemas_.erase(label);
|
||||
Schemas::DeletionStatus Schemas::DeleteSchema(const LabelId primary_label) {
|
||||
auto res = schemas_.erase(primary_label);
|
||||
return res != 0 ? Schemas::DeletionStatus::SUCCESS : Schemas::DeletionStatus::FAIL;
|
||||
}
|
||||
|
||||
Schemas::ValidationStatus Schemas::ValidateVertex(const LabelId primary_label, const Vertex &vertex) {
|
||||
[[nodiscard]] std::optional<SchemaViolation> Schemas::ValidateVertex(const LabelId primary_label,
|
||||
const Vertex &vertex) {
|
||||
// TODO Check for multiple defined primary labels
|
||||
std::vector<std::pair<SchemaType, PropertyValue>> type_violations;
|
||||
if (!schemas_.contains(primary_label)) {
|
||||
return Schemas::ValidationStatus::NO_SCHEMA_DEFINED_FOR_LABEL;
|
||||
return SchemaViolation(SchemaViolation::ValidationStatus::NO_SCHEMA_DEFINED_FOR_LABEL, primary_label);
|
||||
}
|
||||
if (!utils::Contains(vertex.labels, primary_label)) {
|
||||
return Schemas::ValidationStatus::VERTEX_HAS_NO_PRIMARY_LABEL;
|
||||
return SchemaViolation(SchemaViolation::ValidationStatus::VERTEX_HAS_NO_PRIMARY_LABEL, primary_label);
|
||||
}
|
||||
|
||||
for (auto &[property_id, property_type] : schemas_[primary_label]) {
|
||||
// Property existence check
|
||||
if (!vertex.properties.HasProperty(property_id)) {
|
||||
return Schemas::ValidationStatus::VERTEX_HAS_NO_PROPERTY;
|
||||
for (auto &schema_type : schemas_[primary_label]) {
|
||||
if (!vertex.properties.HasProperty(schema_type.property_id)) {
|
||||
return SchemaViolation(SchemaViolation::ValidationStatus::VERTEX_HAS_NO_PROPERTY, primary_label, schema_type);
|
||||
}
|
||||
// Property type check
|
||||
if (vertex.properties.GetProperty(property_id).type() != property_type) {
|
||||
return Schemas::ValidationStatus::VERTEX_PROPERTY_WRONG_TYPE;
|
||||
// TODO Can this be replaced with just property id check?
|
||||
if (auto vertex_property = vertex.properties.GetProperty(schema_type.property_id);
|
||||
PropertyValueTypeToSchemaType(vertex_property) != schema_type.type) {
|
||||
return SchemaViolation(SchemaViolation::ValidationStatus::VERTEX_PROPERTY_WRONG_TYPE, primary_label, schema_type,
|
||||
vertex_property);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO after the introduction of vertex hashing introduce check for vertex
|
||||
// primary key uniqueness
|
||||
|
||||
return Schemas::ValidationStatus::SUCCESS;
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
Schemas::SchemasList Schemas::ListSchemas() const {
|
||||
|
@ -11,25 +11,61 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <unordered_map>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "storage/v2/id_types.hpp"
|
||||
#include "storage/v2/indices.hpp"
|
||||
#include "storage/v2/property_value.hpp"
|
||||
#include "storage/v2/temporal.hpp"
|
||||
#include "storage/v2/transaction.hpp"
|
||||
#include "storage/v2/vertex.hpp"
|
||||
#include "utils/result.hpp"
|
||||
|
||||
namespace memgraph::storage {
|
||||
|
||||
///
|
||||
class SchemaViolationException : public utils::BasicException {
|
||||
using utils::BasicException::BasicException;
|
||||
};
|
||||
|
||||
struct SchemaType {
|
||||
enum class Type : uint8_t { Bool, Int, Double, String, List, Map, Date, LocalTime, LocalDateTime, Duration };
|
||||
|
||||
Type type;
|
||||
PropertyId property_id;
|
||||
std::shared_ptr<SchemaType> nested_value;
|
||||
};
|
||||
|
||||
struct SchemaViolation {
|
||||
enum class ValidationStatus : uint8_t {
|
||||
VERTEX_HAS_NO_PRIMARY_LABEL,
|
||||
VERTEX_HAS_NO_PROPERTY,
|
||||
NO_SCHEMA_DEFINED_FOR_LABEL,
|
||||
VERTEX_PROPERTY_WRONG_TYPE
|
||||
};
|
||||
|
||||
SchemaViolation(ValidationStatus status, LabelId label);
|
||||
|
||||
SchemaViolation(ValidationStatus status, LabelId label, SchemaType violated_type);
|
||||
|
||||
SchemaViolation(ValidationStatus status, LabelId label, SchemaType violated_type,
|
||||
PropertyValue violated_property_value);
|
||||
|
||||
ValidationStatus status;
|
||||
LabelId label;
|
||||
std::optional<SchemaType> violated_type;
|
||||
std::optional<PropertyValue> violated_property_value;
|
||||
};
|
||||
|
||||
/// Structure that represents a collection of schemas
|
||||
/// Schema can be mapped under only one label => primary label
|
||||
class Schemas {
|
||||
public:
|
||||
using SchemasStructure = std::unordered_map<LabelId, std::vector<std::pair<PropertyId, PropertyValue::Type>>>;
|
||||
using SchemasList = std::vector<std::pair<LabelId, std::vector<std::pair<PropertyId, PropertyValue::Type>>>>;
|
||||
using SchemasStructure = std::unordered_map<LabelId, std::vector<SchemaType>>;
|
||||
using SchemasList = std::vector<std::pair<LabelId, std::vector<SchemaType>>>;
|
||||
|
||||
Schemas() = default;
|
||||
Schemas(const Schemas &) = delete;
|
||||
@ -40,21 +76,12 @@ class Schemas {
|
||||
|
||||
enum class CreationStatus : uint8_t { SUCCESS, FAIL };
|
||||
enum class DeletionStatus : uint8_t { SUCCESS, FAIL };
|
||||
enum class ValidationStatus : uint8_t {
|
||||
SUCCESS,
|
||||
VERTEX_DELETED,
|
||||
VERTEX_HAS_NO_PRIMARY_LABEL,
|
||||
VERTEX_HAS_NO_PROPERTY,
|
||||
NO_SCHEMA_DEFINED_FOR_LABEL,
|
||||
VERTEX_PROPERTY_WRONG_TYPE
|
||||
};
|
||||
|
||||
CreationStatus CreateSchema(LabelId label,
|
||||
const std::vector<std::pair<PropertyId, PropertyValue::Type>> &property_types);
|
||||
CreationStatus CreateSchema(LabelId label, const std::vector<SchemaType> &schemas_types);
|
||||
|
||||
DeletionStatus DeleteSchema(LabelId label);
|
||||
|
||||
ValidationStatus ValidateVertex(LabelId primary_label, const Vertex &vertex);
|
||||
std::optional<SchemaViolation> ValidateVertex(LabelId primary_label, const Vertex &vertex);
|
||||
|
||||
SchemasList ListSchemas() const;
|
||||
|
||||
@ -62,4 +89,88 @@ class Schemas {
|
||||
SchemasStructure schemas_;
|
||||
};
|
||||
|
||||
inline std::optional<SchemaType::Type> PropertyValueTypeToSchemaType(const PropertyValue &property_value) {
|
||||
switch (property_value.type()) {
|
||||
case PropertyValue::Type::Bool: {
|
||||
return SchemaType::Type::Bool;
|
||||
}
|
||||
case PropertyValue::Type::Int: {
|
||||
return SchemaType::Type::Int;
|
||||
}
|
||||
case PropertyValue::Type::Double: {
|
||||
return SchemaType::Type::Double;
|
||||
}
|
||||
case PropertyValue::Type::String: {
|
||||
return SchemaType::Type::String;
|
||||
}
|
||||
case PropertyValue::Type::List: {
|
||||
return SchemaType::Type::List;
|
||||
}
|
||||
case PropertyValue::Type::Map: {
|
||||
return SchemaType::Type::Map;
|
||||
}
|
||||
case PropertyValue::Type::TemporalData: {
|
||||
switch (property_value.ValueTemporalData().type) {
|
||||
case TemporalType::Date: {
|
||||
return SchemaType::Type::Date;
|
||||
}
|
||||
case TemporalType::LocalDateTime: {
|
||||
return SchemaType::Type::LocalDateTime;
|
||||
}
|
||||
case TemporalType::LocalTime: {
|
||||
return SchemaType::Type::LocalTime;
|
||||
}
|
||||
case TemporalType::Duration: {
|
||||
return SchemaType::Type::Duration;
|
||||
}
|
||||
}
|
||||
}
|
||||
default: {
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline std::string SchemaTypeToString(const SchemaType::Type type) {
|
||||
switch (type) {
|
||||
case SchemaType::Type::Bool: {
|
||||
return "Bool";
|
||||
}
|
||||
case SchemaType::Type::Int: {
|
||||
return "Integer";
|
||||
}
|
||||
case SchemaType::Type::Double: {
|
||||
return "Double";
|
||||
}
|
||||
case SchemaType::Type::String: {
|
||||
return "String";
|
||||
}
|
||||
case SchemaType::Type::List: {
|
||||
return "List";
|
||||
}
|
||||
case SchemaType::Type::Map: {
|
||||
return "Map";
|
||||
}
|
||||
case SchemaType::Type::Date: {
|
||||
return "Date";
|
||||
}
|
||||
case SchemaType::Type::LocalTime: {
|
||||
return "LocalTime";
|
||||
}
|
||||
case SchemaType::Type::LocalDateTime: {
|
||||
return "LocalDateTime";
|
||||
}
|
||||
case SchemaType::Type::Duration: {
|
||||
return "Duration";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline std::string PropertyTypeToString(const PropertyValue &property_value) {
|
||||
if (const auto schema_type = PropertyValueTypeToSchemaType(property_value); schema_type) {
|
||||
return SchemaTypeToString(*schema_type);
|
||||
}
|
||||
return "Unknown";
|
||||
}
|
||||
|
||||
} // namespace memgraph::storage
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include "storage/v2/indices.hpp"
|
||||
#include "storage/v2/mvcc.hpp"
|
||||
#include "storage/v2/replication/config.hpp"
|
||||
#include "storage/v2/schemas.hpp"
|
||||
#include "storage/v2/transaction.hpp"
|
||||
#include "storage/v2/vertex_accessor.hpp"
|
||||
#include "utils/file.hpp"
|
||||
@ -456,12 +457,13 @@ VertexAccessor Storage::Accessor::CreateVertex() {
|
||||
OOMExceptionEnabler oom_exception;
|
||||
auto gid = storage_->vertex_id_.fetch_add(1, std::memory_order_acq_rel);
|
||||
auto acc = storage_->vertices_.access();
|
||||
auto delta = CreateDeleteObjectDelta(&transaction_);
|
||||
auto *delta = CreateDeleteObjectDelta(&transaction_);
|
||||
auto [it, inserted] = acc.insert(Vertex{storage::Gid::FromUint(gid), delta});
|
||||
MG_ASSERT(inserted, "The vertex must be inserted here!");
|
||||
MG_ASSERT(it != acc.end(), "Invalid Vertex accessor!");
|
||||
|
||||
delta->prev.Set(&*it);
|
||||
return VertexAccessor(&*it, &transaction_, &storage_->indices_, &storage_->constraints_, config_);
|
||||
return {&*it, &transaction_, &storage_->indices_, &storage_->constraints_, config_};
|
||||
}
|
||||
|
||||
VertexAccessor Storage::Accessor::CreateVertex(storage::Gid gid) {
|
||||
|
@ -414,6 +414,12 @@ class Storage final {
|
||||
|
||||
ConstraintsInfo ListAllConstraints() const;
|
||||
|
||||
/// @throw std::bad_alloc
|
||||
bool CreateSchema(LabelId primary_label, std::vector<SchemaType> &schemas_types);
|
||||
|
||||
/// @throw std::bad_alloc
|
||||
bool DeleteSchema(LabelId primary_label);
|
||||
|
||||
SchemasInfo ListAllSchemas() const;
|
||||
|
||||
StorageInfo GetInfo() const;
|
||||
|
Loading…
Reference in New Issue
Block a user