Merge branch 'project-pineapples' into T1163-MG-add-multiframe-and-some-operators

This commit is contained in:
Jeremy B 2022-11-28 17:34:07 +01:00 committed by GitHub
commit 18b3550dbe
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
71 changed files with 4403 additions and 6506 deletions

View File

@ -99,7 +99,7 @@ jobs:
echo ${file} echo ${file}
if [[ ${file} == *.py ]]; then if [[ ${file} == *.py ]]; then
python3 -m black --check --diff ${file} python3 -m black --check --diff ${file}
python3 -m isort --check-only --diff ${file} python3 -m isort --check-only --profile "black" --diff ${file}
fi fi
done done

View File

@ -14,6 +14,7 @@ repos:
hooks: hooks:
- id: isort - id: isort
name: isort (python) name: isort (python)
args: ["--profile", "black"]
- repo: https://github.com/pre-commit/mirrors-clang-format - repo: https://github.com/pre-commit/mirrors-clang-format
rev: v13.0.0 rev: v13.0.0
hooks: hooks:

View File

@ -182,7 +182,8 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)
# c99-designator is disabled because of required mixture of designated and # c99-designator is disabled because of required mixture of designated and
# non-designated initializers in Python Query Module code (`py_module.cpp`). # non-designated initializers in Python Query Module code (`py_module.cpp`).
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall \ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall \
-Werror=switch -Werror=switch-bool -Werror=return-type \ -Werror=switch -Werror=switch-bool -Werror=implicit-fallthrough \
-Werror=return-type \
-Werror=return-stack-address \ -Werror=return-stack-address \
-Wno-c99-designator \ -Wno-c99-designator \
-DBOOST_ASIO_USE_TS_EXECUTOR_AS_DEFAULT") -DBOOST_ASIO_USE_TS_EXECUTOR_AS_DEFAULT")

View File

@ -21,6 +21,7 @@ add_subdirectory(auth)
add_subdirectory(parser) add_subdirectory(parser)
add_subdirectory(expr) add_subdirectory(expr)
add_subdirectory(coordinator) add_subdirectory(coordinator)
add_subdirectory(functions)
if (MG_ENTERPRISE) if (MG_ENTERPRISE)
add_subdirectory(audit) add_subdirectory(audit)

68
src/common/errors.hpp Normal file
View File

@ -0,0 +1,68 @@
// Copyright 2022 Memgraph Ltd.
//
// Use of this software is governed by the Business Source License
// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
// License, and you may not use this file except in compliance with the Business Source License.
//
// As of the Change Date specified in that file, in accordance with
// the Business Source License, use of this software will be governed
// by the Apache License, Version 2.0, included in the file
// licenses/APL.txt.
#pragma once
#include <cstdint>
#include <string_view>
namespace memgraph::common {
enum class ErrorCode : uint8_t {
SERIALIZATION_ERROR,
NONEXISTENT_OBJECT,
DELETED_OBJECT,
VERTEX_HAS_EDGES,
PROPERTIES_DISABLED,
VERTEX_ALREADY_INSERTED,
// Schema Violations
SCHEMA_NO_SCHEMA_DEFINED_FOR_LABEL,
SCHEMA_VERTEX_PROPERTY_WRONG_TYPE,
SCHEMA_VERTEX_UPDATE_PRIMARY_KEY,
SCHEMA_VERTEX_UPDATE_PRIMARY_LABEL,
SCHEMA_VERTEX_SECONDARY_LABEL_IS_PRIMARY,
SCHEMA_VERTEX_PRIMARY_PROPERTIES_UNDEFINED,
OBJECT_NOT_FOUND,
};
constexpr std::string_view ErrorCodeToString(const ErrorCode code) {
switch (code) {
case ErrorCode::SERIALIZATION_ERROR:
return "SERIALIZATION_ERROR";
case ErrorCode::NONEXISTENT_OBJECT:
return "NONEXISTENT_OBJECT";
case ErrorCode::DELETED_OBJECT:
return "DELETED_OBJECT";
case ErrorCode::VERTEX_HAS_EDGES:
return "VERTEX_HAS_EDGES";
case ErrorCode::PROPERTIES_DISABLED:
return "PROPERTIES_DISABLED";
case ErrorCode::VERTEX_ALREADY_INSERTED:
return "VERTEX_ALREADY_INSERTED";
case ErrorCode::SCHEMA_NO_SCHEMA_DEFINED_FOR_LABEL:
return "SCHEMA_NO_SCHEMA_DEFINED_FOR_LABEL";
case ErrorCode::SCHEMA_VERTEX_PROPERTY_WRONG_TYPE:
return "SCHEMA_VERTEX_PROPERTY_WRONG_TYPE";
case ErrorCode::SCHEMA_VERTEX_UPDATE_PRIMARY_KEY:
return "SCHEMA_VERTEX_UPDATE_PRIMARY_KEY";
case ErrorCode::SCHEMA_VERTEX_UPDATE_PRIMARY_LABEL:
return "SCHEMA_VERTEX_UPDATE_PRIMARY_LABEL";
case ErrorCode::SCHEMA_VERTEX_SECONDARY_LABEL_IS_PRIMARY:
return "SCHEMA_VERTEX_SECONDARY_LABEL_IS_PRIMARY";
case ErrorCode::SCHEMA_VERTEX_PRIMARY_PROPERTIES_UNDEFINED:
return "SCHEMA_VERTEX_PRIMARY_PROPERTIES_UNDEFINED";
case ErrorCode::OBJECT_NOT_FOUND:
return "OBJECT_NOT_FOUND";
}
}
} // namespace memgraph::common

View File

@ -74,7 +74,7 @@ State RunHandlerV4(Signature signature, TSession &session, State state, Marker m
} }
case Signature::Route: { case Signature::Route: {
if constexpr (bolt_minor >= 3) { if constexpr (bolt_minor >= 3) {
if (signature == Signature::Route) return HandleRoute<TSession>(session); return HandleRoute<TSession>(session);
} else { } else {
spdlog::trace("Supported only in bolt v4.3"); spdlog::trace("Supported only in bolt v4.3");
return State::Close; return State::Close;

View File

@ -17,4 +17,4 @@ target_include_directories(mg-expr PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
target_include_directories(mg-expr PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/ast) target_include_directories(mg-expr PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/ast)
target_include_directories(mg-expr PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/interpret) target_include_directories(mg-expr PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/interpret)
target_include_directories(mg-expr PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/semantic) target_include_directories(mg-expr PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/semantic)
target_link_libraries(mg-expr cppitertools Boost::headers mg-utils mg-parser) target_link_libraries(mg-expr cppitertools Boost::headers mg-utils mg-parser mg-functions)

View File

@ -24,6 +24,7 @@
#include "expr/exceptions.hpp" #include "expr/exceptions.hpp"
#include "expr/interpret/frame.hpp" #include "expr/interpret/frame.hpp"
#include "expr/semantic/symbol_table.hpp" #include "expr/semantic/symbol_table.hpp"
#include "functions/awesome_memgraph_functions.hpp"
#include "utils/exceptions.hpp" #include "utils/exceptions.hpp"
namespace memgraph::expr { namespace memgraph::expr {
@ -100,6 +101,28 @@ class ExpressionEvaluator : public ExpressionVisitor<TypedValue> {
#undef BINARY_OPERATOR_VISITOR #undef BINARY_OPERATOR_VISITOR
#undef UNARY_OPERATOR_VISITOR #undef UNARY_OPERATOR_VISITOR
void HandleObjectAccessError(Error &shard_error, const std::string_view accessed_object) {
switch (shard_error) {
case Error::DELETED_OBJECT:
throw ExpressionRuntimeException("Trying to access {} on a deleted object.", accessed_object);
case Error::NONEXISTENT_OBJECT:
throw ExpressionRuntimeException("Trying to access {} from a node object doesn't exist.", accessed_object);
case Error::SERIALIZATION_ERROR:
case Error::VERTEX_HAS_EDGES:
case Error::PROPERTIES_DISABLED:
case Error::VERTEX_ALREADY_INSERTED:
case Error::OBJECT_NOT_FOUND:
throw ExpressionRuntimeException("Unexpected error when accessing {}.", accessed_object);
case Error::SCHEMA_NO_SCHEMA_DEFINED_FOR_LABEL:
case Error::SCHEMA_VERTEX_PROPERTY_WRONG_TYPE:
case Error::SCHEMA_VERTEX_UPDATE_PRIMARY_KEY:
case Error::SCHEMA_VERTEX_UPDATE_PRIMARY_LABEL:
case Error::SCHEMA_VERTEX_SECONDARY_LABEL_IS_PRIMARY:
case Error::SCHEMA_VERTEX_PRIMARY_PROPERTIES_UNDEFINED:
throw ExpressionRuntimeException("Unexpected schema violation when accessing {}.", accessed_object);
}
}
TypedValue Visit(AndOperator &op) override { TypedValue Visit(AndOperator &op) override {
auto value1 = op.expression1_->Accept(*this); auto value1 = op.expression1_->Accept(*this);
if (value1.IsBool() && !value1.ValueBool()) { if (value1.IsBool() && !value1.ValueBool()) {
@ -396,17 +419,7 @@ class ExpressionEvaluator : public ExpressionVisitor<TypedValue> {
has_label = vertex.HasLabel(StorageView::NEW, GetLabel(label)); has_label = vertex.HasLabel(StorageView::NEW, GetLabel(label));
} }
if (has_label.HasError()) { if (has_label.HasError()) {
switch (has_label.GetError()) { HandleObjectAccessError(has_label.GetError().code, "labels");
case Error::DELETED_OBJECT:
throw ExpressionRuntimeException("Trying to access labels on a deleted node.");
case Error::NONEXISTENT_OBJECT:
throw ExpressionRuntimeException("Trying to access labels from a node that doesn't exist.");
case Error::SERIALIZATION_ERROR:
case Error::VERTEX_HAS_EDGES:
case Error::PROPERTIES_DISABLED:
case Error::VERTEX_ALREADY_INSERTED:
throw ExpressionRuntimeException("Unexpected error when accessing labels.");
}
} }
return *has_label; return *has_label;
} }
@ -415,8 +428,7 @@ class ExpressionEvaluator : public ExpressionVisitor<TypedValue> {
typename TReturnType = std::enable_if_t<std::is_same_v<TTag, QueryEngineTag>, bool>> typename TReturnType = std::enable_if_t<std::is_same_v<TTag, QueryEngineTag>, bool>>
TReturnType HasLabelImpl(const VertexAccessor &vertex, const LabelIx &label_ix, QueryEngineTag /*tag*/) { TReturnType HasLabelImpl(const VertexAccessor &vertex, const LabelIx &label_ix, QueryEngineTag /*tag*/) {
auto label = typename VertexAccessor::Label{LabelId::FromUint(label_ix.ix)}; auto label = typename VertexAccessor::Label{LabelId::FromUint(label_ix.ix)};
auto has_label = vertex.HasLabel(label); return vertex.HasLabel(label);
return !has_label;
} }
TypedValue Visit(LabelsTest &labels_test) override { TypedValue Visit(LabelsTest &labels_test) override {
@ -479,7 +491,7 @@ class ExpressionEvaluator : public ExpressionVisitor<TypedValue> {
} }
TypedValue Visit(Function &function) override { TypedValue Visit(Function &function) override {
FunctionContext function_ctx{dba_, ctx_->memory, ctx_->timestamp, &ctx_->counters, view_}; functions::FunctionContext<DbAccessor> function_ctx{dba_, ctx_->memory, ctx_->timestamp, &ctx_->counters, view_};
// Stack allocate evaluated arguments when there's a small number of them. // Stack allocate evaluated arguments when there's a small number of them.
if (function.arguments_.size() <= 8) { if (function.arguments_.size() <= 8) {
TypedValue arguments[8] = {TypedValue(ctx_->memory), TypedValue(ctx_->memory), TypedValue(ctx_->memory), TypedValue arguments[8] = {TypedValue(ctx_->memory), TypedValue(ctx_->memory), TypedValue(ctx_->memory),
@ -744,17 +756,7 @@ class ExpressionEvaluator : public ExpressionVisitor<TypedValue> {
maybe_prop = record_accessor.GetProperty(StorageView::NEW, ctx_->properties[prop.ix]); maybe_prop = record_accessor.GetProperty(StorageView::NEW, ctx_->properties[prop.ix]);
} }
if (maybe_prop.HasError()) { if (maybe_prop.HasError()) {
switch (maybe_prop.GetError()) { HandleObjectAccessError(maybe_prop.GetError().code, "property");
case Error::DELETED_OBJECT:
throw ExpressionRuntimeException("Trying to get a property from a deleted object.");
case Error::NONEXISTENT_OBJECT:
throw ExpressionRuntimeException("Trying to get a property from an object that doesn't exist.");
case Error::SERIALIZATION_ERROR:
case Error::VERTEX_HAS_EDGES:
case Error::PROPERTIES_DISABLED:
case Error::VERTEX_ALREADY_INSERTED:
throw ExpressionRuntimeException("Unexpected error when getting a property.");
}
} }
return conv_(*maybe_prop, ctx_->memory); return conv_(*maybe_prop, ctx_->memory);
} }
@ -773,17 +775,7 @@ class ExpressionEvaluator : public ExpressionVisitor<TypedValue> {
maybe_prop = record_accessor.GetProperty(view_, dba_->NameToProperty(name)); maybe_prop = record_accessor.GetProperty(view_, dba_->NameToProperty(name));
} }
if (maybe_prop.HasError()) { if (maybe_prop.HasError()) {
switch (maybe_prop.GetError()) { HandleObjectAccessError(maybe_prop.GetError().code, "property");
case Error::DELETED_OBJECT:
throw ExpressionRuntimeException("Trying to get a property from a deleted object.");
case Error::NONEXISTENT_OBJECT:
throw ExpressionRuntimeException("Trying to get a property from an object that doesn't exist.");
case Error::SERIALIZATION_ERROR:
case Error::VERTEX_HAS_EDGES:
case Error::PROPERTIES_DISABLED:
case Error::VERTEX_ALREADY_INSERTED:
throw ExpressionRuntimeException("Unexpected error when getting a property.");
}
} }
return conv_(*maybe_prop, ctx_->memory); return conv_(*maybe_prop, ctx_->memory);
} }

View File

@ -0,0 +1 @@
add_library(mg-functions INTERFACE)

File diff suppressed because it is too large Load Diff

View File

@ -15,13 +15,13 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include "common/errors.hpp"
#include "coordinator/shard_map.hpp" #include "coordinator/shard_map.hpp"
#include "query/v2/accessors.hpp" #include "query/v2/accessors.hpp"
#include "query/v2/requests.hpp" #include "query/v2/requests.hpp"
#include "query/v2/shard_request_manager.hpp" #include "query/v2/shard_request_manager.hpp"
#include "storage/v3/edge_accessor.hpp" #include "storage/v3/edge_accessor.hpp"
#include "storage/v3/id_types.hpp" #include "storage/v3/id_types.hpp"
#include "storage/v3/result.hpp"
#include "storage/v3/shard.hpp" #include "storage/v3/shard.hpp"
#include "storage/v3/vertex_accessor.hpp" #include "storage/v3/vertex_accessor.hpp"
#include "storage/v3/view.hpp" #include "storage/v3/view.hpp"
@ -71,8 +71,8 @@ query::v2::TypedValue ToTypedValue(const Value &value) {
} }
} }
storage::v3::Result<communication::bolt::Vertex> ToBoltVertex( communication::bolt::Vertex ToBoltVertex(const query::v2::accessors::VertexAccessor &vertex,
const query::v2::accessors::VertexAccessor &vertex, const msgs::ShardRequestManagerInterface *shard_request_manager, const query::v2::ShardRequestManagerInterface *shard_request_manager,
storage::v3::View /*view*/) { storage::v3::View /*view*/) {
auto id = communication::bolt::Id::FromUint(0); auto id = communication::bolt::Id::FromUint(0);
@ -91,8 +91,8 @@ storage::v3::Result<communication::bolt::Vertex> ToBoltVertex(
return communication::bolt::Vertex{id, new_labels, new_properties}; return communication::bolt::Vertex{id, new_labels, new_properties};
} }
storage::v3::Result<communication::bolt::Edge> ToBoltEdge( communication::bolt::Edge ToBoltEdge(const query::v2::accessors::EdgeAccessor &edge,
const query::v2::accessors::EdgeAccessor &edge, const msgs::ShardRequestManagerInterface *shard_request_manager, const query::v2::ShardRequestManagerInterface *shard_request_manager,
storage::v3::View /*view*/) { storage::v3::View /*view*/) {
// TODO(jbajic) Fix bolt communication // TODO(jbajic) Fix bolt communication
auto id = communication::bolt::Id::FromUint(0); auto id = communication::bolt::Id::FromUint(0);
@ -108,69 +108,64 @@ storage::v3::Result<communication::bolt::Edge> ToBoltEdge(
return communication::bolt::Edge{id, from, to, type, new_properties}; return communication::bolt::Edge{id, from, to, type, new_properties};
} }
storage::v3::Result<communication::bolt::Path> ToBoltPath( communication::bolt::Path ToBoltPath(const query::v2::accessors::Path & /*edge*/,
const query::v2::accessors::Path & /*edge*/, const msgs::ShardRequestManagerInterface * /*shard_request_manager*/, const query::v2::ShardRequestManagerInterface * /*shard_request_manager*/,
storage::v3::View /*view*/) { storage::v3::View /*view*/) {
// TODO(jbajic) Fix bolt communication // TODO(jbajic) Fix bolt communication
return {storage::v3::Error::DELETED_OBJECT}; MG_ASSERT(false, "Path is unimplemented!");
return {};
} }
storage::v3::Result<Value> ToBoltValue(const query::v2::TypedValue &value, Value ToBoltValue(const query::v2::TypedValue &value,
const msgs::ShardRequestManagerInterface *shard_request_manager, const query::v2::ShardRequestManagerInterface *shard_request_manager, storage::v3::View view) {
storage::v3::View view) {
switch (value.type()) { switch (value.type()) {
case query::v2::TypedValue::Type::Null: case query::v2::TypedValue::Type::Null:
return Value(); return {};
case query::v2::TypedValue::Type::Bool: case query::v2::TypedValue::Type::Bool:
return Value(value.ValueBool()); return {value.ValueBool()};
case query::v2::TypedValue::Type::Int: case query::v2::TypedValue::Type::Int:
return Value(value.ValueInt()); return {value.ValueInt()};
case query::v2::TypedValue::Type::Double: case query::v2::TypedValue::Type::Double:
return Value(value.ValueDouble()); return {value.ValueDouble()};
case query::v2::TypedValue::Type::String: case query::v2::TypedValue::Type::String:
return Value(std::string(value.ValueString())); return {std::string(value.ValueString())};
case query::v2::TypedValue::Type::List: { case query::v2::TypedValue::Type::List: {
std::vector<Value> values; std::vector<Value> values;
values.reserve(value.ValueList().size()); values.reserve(value.ValueList().size());
for (const auto &v : value.ValueList()) { for (const auto &v : value.ValueList()) {
auto maybe_value = ToBoltValue(v, shard_request_manager, view); auto value = ToBoltValue(v, shard_request_manager, view);
if (maybe_value.HasError()) return maybe_value.GetError(); values.emplace_back(std::move(value));
values.emplace_back(std::move(*maybe_value));
} }
return Value(std::move(values)); return {std::move(values)};
} }
case query::v2::TypedValue::Type::Map: { case query::v2::TypedValue::Type::Map: {
std::map<std::string, Value> map; std::map<std::string, Value> map;
for (const auto &kv : value.ValueMap()) { for (const auto &kv : value.ValueMap()) {
auto maybe_value = ToBoltValue(kv.second, shard_request_manager, view); auto value = ToBoltValue(kv.second, shard_request_manager, view);
if (maybe_value.HasError()) return maybe_value.GetError(); map.emplace(kv.first, std::move(value));
map.emplace(kv.first, std::move(*maybe_value));
} }
return Value(std::move(map)); return {std::move(map)};
} }
case query::v2::TypedValue::Type::Vertex: { case query::v2::TypedValue::Type::Vertex: {
auto maybe_vertex = ToBoltVertex(value.ValueVertex(), shard_request_manager, view); auto vertex = ToBoltVertex(value.ValueVertex(), shard_request_manager, view);
if (maybe_vertex.HasError()) return maybe_vertex.GetError(); return {std::move(vertex)};
return Value(std::move(*maybe_vertex));
} }
case query::v2::TypedValue::Type::Edge: { case query::v2::TypedValue::Type::Edge: {
auto maybe_edge = ToBoltEdge(value.ValueEdge(), shard_request_manager, view); auto edge = ToBoltEdge(value.ValueEdge(), shard_request_manager, view);
if (maybe_edge.HasError()) return maybe_edge.GetError(); return {std::move(edge)};
return Value(std::move(*maybe_edge));
} }
case query::v2::TypedValue::Type::Path: { case query::v2::TypedValue::Type::Path: {
auto maybe_path = ToBoltPath(value.ValuePath(), shard_request_manager, view); auto path = ToBoltPath(value.ValuePath(), shard_request_manager, view);
if (maybe_path.HasError()) return maybe_path.GetError(); return {std::move(path)};
return Value(std::move(*maybe_path));
} }
case query::v2::TypedValue::Type::Date: case query::v2::TypedValue::Type::Date:
return Value(value.ValueDate()); return {value.ValueDate()};
case query::v2::TypedValue::Type::LocalTime: case query::v2::TypedValue::Type::LocalTime:
return Value(value.ValueLocalTime()); return {value.ValueLocalTime()};
case query::v2::TypedValue::Type::LocalDateTime: case query::v2::TypedValue::Type::LocalDateTime:
return Value(value.ValueLocalDateTime()); return {value.ValueLocalDateTime()};
case query::v2::TypedValue::Type::Duration: case query::v2::TypedValue::Type::Duration:
return Value(value.ValueDuration()); return {value.ValueDuration()};
} }
} }

View File

@ -20,6 +20,7 @@
#include "storage/v3/result.hpp" #include "storage/v3/result.hpp"
#include "storage/v3/shard.hpp" #include "storage/v3/shard.hpp"
#include "storage/v3/view.hpp" #include "storage/v3/view.hpp"
#include "utils/result.hpp"
namespace memgraph::storage::v3 { namespace memgraph::storage::v3 {
class EdgeAccessor; class EdgeAccessor;
@ -31,39 +32,39 @@ namespace memgraph::glue::v2 {
/// @param storage::v3::VertexAccessor for converting to /// @param storage::v3::VertexAccessor for converting to
/// communication::bolt::Vertex. /// communication::bolt::Vertex.
/// @param msgs::ShardRequestManagerInterface *shard_request_manager getting label and property names. /// @param query::v2::ShardRequestManagerInterface *shard_request_manager getting label and property names.
/// @param storage::v3::View for deciding which vertex attributes are visible. /// @param storage::v3::View for deciding which vertex attributes are visible.
/// ///
/// @throw std::bad_alloc /// @throw std::bad_alloc
storage::v3::Result<communication::bolt::Vertex> ToBoltVertex( communication::bolt::Vertex ToBoltVertex(const storage::v3::VertexAccessor &vertex,
const storage::v3::VertexAccessor &vertex, const msgs::ShardRequestManagerInterface *shard_request_manager, const query::v2::ShardRequestManagerInterface *shard_request_manager,
storage::v3::View view); storage::v3::View view);
/// @param storage::v3::EdgeAccessor for converting to communication::bolt::Edge. /// @param storage::v3::EdgeAccessor for converting to communication::bolt::Edge.
/// @param msgs::ShardRequestManagerInterface *shard_request_manager getting edge type and property names. /// @param query::v2::ShardRequestManagerInterface *shard_request_manager getting edge type and property names.
/// @param storage::v3::View for deciding which edge attributes are visible. /// @param storage::v3::View for deciding which edge attributes are visible.
/// ///
/// @throw std::bad_alloc /// @throw std::bad_alloc
storage::v3::Result<communication::bolt::Edge> ToBoltEdge( communication::bolt::Edge ToBoltEdge(const storage::v3::EdgeAccessor &edge,
const storage::v3::EdgeAccessor &edge, const msgs::ShardRequestManagerInterface *shard_request_manager, const query::v2::ShardRequestManagerInterface *shard_request_manager,
storage::v3::View view); storage::v3::View view);
/// @param query::v2::Path for converting to communication::bolt::Path. /// @param query::v2::Path for converting to communication::bolt::Path.
/// @param msgs::ShardRequestManagerInterface *shard_request_manager ToBoltVertex and ToBoltEdge. /// @param query::v2::ShardRequestManagerInterface *shard_request_manager ToBoltVertex and ToBoltEdge.
/// @param storage::v3::View for ToBoltVertex and ToBoltEdge. /// @param storage::v3::View for ToBoltVertex and ToBoltEdge.
/// ///
/// @throw std::bad_alloc /// @throw std::bad_alloc
storage::v3::Result<communication::bolt::Path> ToBoltPath( communication::bolt::Path ToBoltPath(const query::v2::accessors::Path &path,
const query::v2::accessors::Path &path, const msgs::ShardRequestManagerInterface *shard_request_manager, const query::v2::ShardRequestManagerInterface *shard_request_manager,
storage::v3::View view); storage::v3::View view);
/// @param query::v2::TypedValue for converting to communication::bolt::Value. /// @param query::v2::TypedValue for converting to communication::bolt::Value.
/// @param msgs::ShardRequestManagerInterface *shard_request_manager ToBoltVertex and ToBoltEdge. /// @param query::v2::ShardRequestManagerInterface *shard_request_manager ToBoltVertex and ToBoltEdge.
/// @param storage::v3::View for ToBoltVertex and ToBoltEdge. /// @param storage::v3::View for ToBoltVertex and ToBoltEdge.
/// ///
/// @throw std::bad_alloc /// @throw std::bad_alloc
storage::v3::Result<communication::bolt::Value> ToBoltValue( communication::bolt::Value ToBoltValue(const query::v2::TypedValue &value,
const query::v2::TypedValue &value, const msgs::ShardRequestManagerInterface *shard_request_manager, const query::v2::ShardRequestManagerInterface *shard_request_manager,
storage::v3::View view); storage::v3::View view);
query::v2::TypedValue ToTypedValue(const communication::bolt::Value &value); query::v2::TypedValue ToTypedValue(const communication::bolt::Value &value);
@ -75,7 +76,7 @@ storage::v3::PropertyValue ToPropertyValue(const communication::bolt::Value &val
communication::bolt::Value ToBoltValue(msgs::Value value); communication::bolt::Value ToBoltValue(msgs::Value value);
communication::bolt::Value ToBoltValue(msgs::Value value, communication::bolt::Value ToBoltValue(msgs::Value value,
const msgs::ShardRequestManagerInterface *shard_request_manager, const query::v2::ShardRequestManagerInterface *shard_request_manager,
storage::v3::View view); storage::v3::View view);
} // namespace memgraph::glue::v2 } // namespace memgraph::glue::v2

View File

@ -33,6 +33,7 @@
#include <spdlog/sinks/dist_sink.h> #include <spdlog/sinks/dist_sink.h>
#include <spdlog/sinks/stdout_color_sinks.h> #include <spdlog/sinks/stdout_color_sinks.h>
#include "common/errors.hpp"
#include "communication/bolt/v1/constants.hpp" #include "communication/bolt/v1/constants.hpp"
#include "communication/websocket/auth.hpp" #include "communication/websocket/auth.hpp"
#include "communication/websocket/server.hpp" #include "communication/websocket/server.hpp"
@ -480,20 +481,9 @@ class BoltSession final : public memgraph::communication::bolt::Session<memgraph
const auto &summary = interpreter_.Pull(&stream, n, qid); const auto &summary = interpreter_.Pull(&stream, n, qid);
std::map<std::string, memgraph::communication::bolt::Value> decoded_summary; std::map<std::string, memgraph::communication::bolt::Value> decoded_summary;
for (const auto &kv : summary) { for (const auto &kv : summary) {
auto maybe_value = memgraph::glue::v2::ToBoltValue(kv.second, interpreter_.GetShardRequestManager(), auto bolt_value = memgraph::glue::v2::ToBoltValue(kv.second, interpreter_.GetShardRequestManager(),
memgraph::storage::v3::View::NEW); memgraph::storage::v3::View::NEW);
if (maybe_value.HasError()) { decoded_summary.emplace(kv.first, std::move(bolt_value));
switch (maybe_value.GetError()) {
case memgraph::storage::v3::Error::DELETED_OBJECT:
case memgraph::storage::v3::Error::SERIALIZATION_ERROR:
case memgraph::storage::v3::Error::VERTEX_HAS_EDGES:
case memgraph::storage::v3::Error::PROPERTIES_DISABLED:
case memgraph::storage::v3::Error::NONEXISTENT_OBJECT:
case memgraph::storage::v3::Error::VERTEX_ALREADY_INSERTED:
throw memgraph::communication::bolt::ClientError("Unexpected storage error when streaming summary.");
}
}
decoded_summary.emplace(kv.first, std::move(*maybe_value));
} }
return decoded_summary; return decoded_summary;
} catch (const memgraph::query::v2::QueryException &e) { } catch (const memgraph::query::v2::QueryException &e) {
@ -507,35 +497,23 @@ class BoltSession final : public memgraph::communication::bolt::Session<memgraph
/// before forwarding the calls to original TEncoder. /// before forwarding the calls to original TEncoder.
class TypedValueResultStream { class TypedValueResultStream {
public: public:
TypedValueResultStream(TEncoder *encoder, const memgraph::msgs::ShardRequestManagerInterface *shard_request_manager) TypedValueResultStream(TEncoder *encoder,
const memgraph::query::v2::ShardRequestManagerInterface *shard_request_manager)
: encoder_(encoder), shard_request_manager_(shard_request_manager) {} : encoder_(encoder), shard_request_manager_(shard_request_manager) {}
void Result(const std::vector<memgraph::query::v2::TypedValue> &values) { void Result(const std::vector<memgraph::query::v2::TypedValue> &values) {
std::vector<memgraph::communication::bolt::Value> decoded_values; std::vector<memgraph::communication::bolt::Value> decoded_values;
decoded_values.reserve(values.size()); decoded_values.reserve(values.size());
for (const auto &v : values) { for (const auto &v : values) {
auto maybe_value = memgraph::glue::v2::ToBoltValue(v, shard_request_manager_, memgraph::storage::v3::View::NEW); auto bolt_value = memgraph::glue::v2::ToBoltValue(v, shard_request_manager_, memgraph::storage::v3::View::NEW);
if (maybe_value.HasError()) { decoded_values.emplace_back(std::move(bolt_value));
switch (maybe_value.GetError()) {
case memgraph::storage::v3::Error::DELETED_OBJECT:
throw memgraph::communication::bolt::ClientError("Returning a deleted object as a result.");
case memgraph::storage::v3::Error::NONEXISTENT_OBJECT:
throw memgraph::communication::bolt::ClientError("Returning a nonexistent object as a result.");
case memgraph::storage::v3::Error::VERTEX_HAS_EDGES:
case memgraph::storage::v3::Error::SERIALIZATION_ERROR:
case memgraph::storage::v3::Error::PROPERTIES_DISABLED:
case memgraph::storage::v3::Error::VERTEX_ALREADY_INSERTED:
throw memgraph::communication::bolt::ClientError("Unexpected storage error when streaming results.");
}
}
decoded_values.emplace_back(std::move(*maybe_value));
} }
encoder_->MessageRecord(decoded_values); encoder_->MessageRecord(decoded_values);
} }
private: private:
TEncoder *encoder_; TEncoder *encoder_;
const memgraph::msgs::ShardRequestManagerInterface *shard_request_manager_{nullptr}; const memgraph::query::v2::ShardRequestManagerInterface *shard_request_manager_{nullptr};
}; };
memgraph::query::v2::Interpreter interpreter_; memgraph::query::v2::Interpreter interpreter_;
memgraph::communication::v2::ServerEndpoint endpoint_; memgraph::communication::v2::ServerEndpoint endpoint_;

View File

@ -11,7 +11,6 @@ set(mg_query_v2_sources
cypher_query_interpreter.cpp cypher_query_interpreter.cpp
frontend/semantic/required_privileges.cpp frontend/semantic/required_privileges.cpp
frontend/stripped.cpp frontend/stripped.cpp
interpret/awesome_memgraph_functions.cpp
interpreter.cpp interpreter.cpp
metadata.cpp metadata.cpp
plan/operator.cpp plan/operator.cpp
@ -35,7 +34,7 @@ target_include_directories(mg-query-v2 PUBLIC ${CMAKE_SOURCE_DIR}/include)
target_include_directories(mg-query-v2 PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/bindings) target_include_directories(mg-query-v2 PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/bindings)
target_link_libraries(mg-query-v2 dl cppitertools Boost::headers) target_link_libraries(mg-query-v2 dl cppitertools Boost::headers)
target_link_libraries(mg-query-v2 mg-integrations-pulsar mg-integrations-kafka mg-storage-v3 mg-license mg-utils mg-kvstore mg-memory mg-coordinator) target_link_libraries(mg-query-v2 mg-integrations-pulsar mg-integrations-kafka mg-storage-v3 mg-license mg-utils mg-kvstore mg-memory mg-coordinator)
target_link_libraries(mg-query-v2 mg-expr) target_link_libraries(mg-query-v2 mg-expr mg-functions)
if(NOT "${MG_PYTHON_PATH}" STREQUAL "") if(NOT "${MG_PYTHON_PATH}" STREQUAL "")
set(Python3_ROOT_DIR "${MG_PYTHON_PATH}") set(Python3_ROOT_DIR "${MG_PYTHON_PATH}")

View File

@ -15,7 +15,7 @@
#include "storage/v3/id_types.hpp" #include "storage/v3/id_types.hpp"
namespace memgraph::query::v2::accessors { namespace memgraph::query::v2::accessors {
EdgeAccessor::EdgeAccessor(Edge edge, const msgs::ShardRequestManagerInterface *manager) EdgeAccessor::EdgeAccessor(Edge edge, const ShardRequestManagerInterface *manager)
: edge(std::move(edge)), manager_(manager) {} : edge(std::move(edge)), manager_(manager) {}
EdgeTypeId EdgeAccessor::EdgeType() const { return edge.type.id; } EdgeTypeId EdgeAccessor::EdgeType() const { return edge.type.id; }
@ -23,11 +23,12 @@ EdgeTypeId EdgeAccessor::EdgeType() const { return edge.type.id; }
const std::vector<std::pair<PropertyId, Value>> &EdgeAccessor::Properties() const { return edge.properties; } const std::vector<std::pair<PropertyId, Value>> &EdgeAccessor::Properties() const { return edge.properties; }
Value EdgeAccessor::GetProperty(const std::string &prop_name) const { Value EdgeAccessor::GetProperty(const std::string &prop_name) const {
auto prop_id = manager_->NameToProperty(prop_name); auto maybe_prop = manager_->MaybeNameToProperty(prop_name);
auto it = std::find_if(edge.properties.begin(), edge.properties.end(), [&](auto &pr) { return prop_id == pr.first; }); if (!maybe_prop) {
if (it == edge.properties.end()) {
return {}; return {};
} }
const auto prop_id = *maybe_prop;
auto it = std::find_if(edge.properties.begin(), edge.properties.end(), [&](auto &pr) { return prop_id == pr.first; });
return it->second; return it->second;
} }
@ -35,6 +36,8 @@ const Edge &EdgeAccessor::GetEdge() const { return edge; }
bool EdgeAccessor::IsCycle() const { return edge.src == edge.dst; }; bool EdgeAccessor::IsCycle() const { return edge.src == edge.dst; };
size_t EdgeAccessor::CypherId() const { return edge.id.gid; }
VertexAccessor EdgeAccessor::To() const { VertexAccessor EdgeAccessor::To() const {
return VertexAccessor(Vertex{edge.dst}, std::vector<std::pair<PropertyId, msgs::Value>>{}, manager_); return VertexAccessor(Vertex{edge.dst}, std::vector<std::pair<PropertyId, msgs::Value>>{}, manager_);
} }
@ -44,11 +47,11 @@ VertexAccessor EdgeAccessor::From() const {
} }
VertexAccessor::VertexAccessor(Vertex v, std::vector<std::pair<PropertyId, Value>> props, VertexAccessor::VertexAccessor(Vertex v, std::vector<std::pair<PropertyId, Value>> props,
const msgs::ShardRequestManagerInterface *manager) const ShardRequestManagerInterface *manager)
: vertex(std::move(v)), properties(std::move(props)), manager_(manager) {} : vertex(std::move(v)), properties(std::move(props)), manager_(manager) {}
VertexAccessor::VertexAccessor(Vertex v, std::map<PropertyId, Value> &&props, VertexAccessor::VertexAccessor(Vertex v, std::map<PropertyId, Value> &&props,
const msgs::ShardRequestManagerInterface *manager) const ShardRequestManagerInterface *manager)
: vertex(std::move(v)), manager_(manager) { : vertex(std::move(v)), manager_(manager) {
properties.reserve(props.size()); properties.reserve(props.size());
for (auto &[id, value] : props) { for (auto &[id, value] : props) {
@ -57,7 +60,7 @@ VertexAccessor::VertexAccessor(Vertex v, std::map<PropertyId, Value> &&props,
} }
VertexAccessor::VertexAccessor(Vertex v, const std::map<PropertyId, Value> &props, VertexAccessor::VertexAccessor(Vertex v, const std::map<PropertyId, Value> &props,
const msgs::ShardRequestManagerInterface *manager) const ShardRequestManagerInterface *manager)
: vertex(std::move(v)), manager_(manager) { : vertex(std::move(v)), manager_(manager) {
properties.reserve(props.size()); properties.reserve(props.size());
for (const auto &[id, value] : props) { for (const auto &[id, value] : props) {
@ -88,7 +91,11 @@ Value VertexAccessor::GetProperty(PropertyId prop_id) const {
// NOLINTNEXTLINE(readability-convert-member-functions-to-static) // NOLINTNEXTLINE(readability-convert-member-functions-to-static)
Value VertexAccessor::GetProperty(const std::string &prop_name) const { Value VertexAccessor::GetProperty(const std::string &prop_name) const {
return GetProperty(manager_->NameToProperty(prop_name)); auto maybe_prop = manager_->MaybeNameToProperty(prop_name);
if (!maybe_prop) {
return {};
}
return GetProperty(*maybe_prop);
} }
msgs::Vertex VertexAccessor::GetVertex() const { return vertex; } msgs::Vertex VertexAccessor::GetVertex() const { return vertex; }

View File

@ -24,24 +24,24 @@
#include "utils/memory.hpp" #include "utils/memory.hpp"
#include "utils/memory_tracker.hpp" #include "utils/memory_tracker.hpp"
namespace memgraph::msgs { namespace memgraph::query::v2 {
class ShardRequestManagerInterface; class ShardRequestManagerInterface;
} // namespace memgraph::msgs } // namespace memgraph::query::v2
namespace memgraph::query::v2::accessors { namespace memgraph::query::v2::accessors {
using Value = memgraph::msgs::Value; using Value = msgs::Value;
using Edge = memgraph::msgs::Edge; using Edge = msgs::Edge;
using Vertex = memgraph::msgs::Vertex; using Vertex = msgs::Vertex;
using Label = memgraph::msgs::Label; using Label = msgs::Label;
using PropertyId = memgraph::msgs::PropertyId; using PropertyId = msgs::PropertyId;
using EdgeTypeId = memgraph::msgs::EdgeTypeId; using EdgeTypeId = msgs::EdgeTypeId;
class VertexAccessor; class VertexAccessor;
class EdgeAccessor final { class EdgeAccessor final {
public: public:
explicit EdgeAccessor(Edge edge, const msgs::ShardRequestManagerInterface *manager); explicit EdgeAccessor(Edge edge, const ShardRequestManagerInterface *manager);
[[nodiscard]] EdgeTypeId EdgeType() const; [[nodiscard]] EdgeTypeId EdgeType() const;
@ -53,12 +53,7 @@ class EdgeAccessor final {
[[nodiscard]] bool IsCycle() const; [[nodiscard]] bool IsCycle() const;
// Dummy function [[nodiscard]] size_t CypherId() const;
// NOLINTNEXTLINE(readability-convert-member-functions-to-static)
[[nodiscard]] size_t CypherId() const { return 10; }
// bool HasSrcAccessor const { return src == nullptr; }
// bool HasDstAccessor const { return dst == nullptr; }
[[nodiscard]] VertexAccessor To() const; [[nodiscard]] VertexAccessor To() const;
[[nodiscard]] VertexAccessor From() const; [[nodiscard]] VertexAccessor From() const;
@ -69,7 +64,7 @@ class EdgeAccessor final {
private: private:
Edge edge; Edge edge;
const msgs::ShardRequestManagerInterface *manager_; const ShardRequestManagerInterface *manager_;
}; };
class VertexAccessor final { class VertexAccessor final {
@ -78,10 +73,10 @@ class VertexAccessor final {
using Label = msgs::Label; using Label = msgs::Label;
using VertexId = msgs::VertexId; using VertexId = msgs::VertexId;
VertexAccessor(Vertex v, std::vector<std::pair<PropertyId, Value>> props, VertexAccessor(Vertex v, std::vector<std::pair<PropertyId, Value>> props,
const msgs::ShardRequestManagerInterface *manager); const ShardRequestManagerInterface *manager);
VertexAccessor(Vertex v, std::map<PropertyId, Value> &&props, const msgs::ShardRequestManagerInterface *manager); VertexAccessor(Vertex v, std::map<PropertyId, Value> &&props, const ShardRequestManagerInterface *manager);
VertexAccessor(Vertex v, const std::map<PropertyId, Value> &props, const msgs::ShardRequestManagerInterface *manager); VertexAccessor(Vertex v, const std::map<PropertyId, Value> &props, const ShardRequestManagerInterface *manager);
[[nodiscard]] Label PrimaryLabel() const; [[nodiscard]] Label PrimaryLabel() const;
@ -98,48 +93,11 @@ class VertexAccessor final {
[[nodiscard]] msgs::Vertex GetVertex() const; [[nodiscard]] msgs::Vertex GetVertex() const;
// Dummy function
// NOLINTNEXTLINE(readability-convert-member-functions-to-static) // NOLINTNEXTLINE(readability-convert-member-functions-to-static)
[[nodiscard]] size_t CypherId() const { return 10; } [[nodiscard]] size_t InDegree() const { throw utils::NotYetImplemented("InDegree() not yet implemented"); }
// auto InEdges(storage::View view, const std::vector<storage::EdgeTypeId> &edge_types) const // NOLINTNEXTLINE(readability-convert-member-functions-to-static)
// -> storage::Result<decltype(iter::imap(MakeEdgeAccessor, *impl_.InEdges(view)))> { [[nodiscard]] size_t OutDegree() const { throw utils::NotYetImplemented("OutDegree() not yet implemented"); }
// auto maybe_edges = impl_.InEdges(view, edge_types);
// if (maybe_edges.HasError()) return maybe_edges.GetError();
// return iter::imap(MakeEdgeAccessor, std::move(*maybe_edges));
// }
//
// auto InEdges(storage::View view) const { return InEdges(view, {}); }
//
// auto InEdges(storage::View view, const std::vector<storage::EdgeTypeId> &edge_types, const VertexAccessor &dest)
// const
// -> storage::Result<decltype(iter::imap(MakeEdgeAccessor, *impl_.InEdges(view)))> {
// auto maybe_edges = impl_.InEdges(view, edge_types, &dest.impl_);
// if (maybe_edges.HasError()) return maybe_edges.GetError();
// return iter::imap(MakeEdgeAccessor, std::move(*maybe_edges));
// }
//
// auto OutEdges(storage::View view, const std::vector<storage::EdgeTypeId> &edge_types) const
// -> storage::Result<decltype(iter::imap(MakeEdgeAccessor, *impl_.OutEdges(view)))> {
// auto maybe_edges = impl_.OutEdges(view, edge_types);
// if (maybe_edges.HasError()) return maybe_edges.GetError();
// return iter::imap(MakeEdgeAccessor, std::move(*maybe_edges));
// }
//
// auto OutEdges(storage::View view) const { return OutEdges(view, {}); }
//
// auto OutEdges(storage::View view, const std::vector<storage::EdgeTypeId> &edge_types,
// const VertexAccessor &dest) const
// -> storage::Result<decltype(iter::imap(MakeEdgeAccessor, *impl_.OutEdges(view)))> {
// auto maybe_edges = impl_.OutEdges(view, edge_types, &dest.impl_);
// if (maybe_edges.HasError()) return maybe_edges.GetError();
// return iter::imap(MakeEdgeAccessor, std::move(*maybe_edges));
// }
// storage::Result<size_t> InDegree(storage::View view) const { return impl_.InDegree(view); }
//
// storage::Result<size_t> OutDegree(storage::View view) const { return impl_.OutDegree(view); }
//
friend bool operator==(const VertexAccessor &lhs, const VertexAccessor &rhs) { friend bool operator==(const VertexAccessor &lhs, const VertexAccessor &rhs) {
return lhs.vertex == rhs.vertex && lhs.properties == rhs.properties; return lhs.vertex == rhs.vertex && lhs.properties == rhs.properties;
@ -150,13 +108,9 @@ class VertexAccessor final {
private: private:
Vertex vertex; Vertex vertex;
std::vector<std::pair<PropertyId, Value>> properties; std::vector<std::pair<PropertyId, Value>> properties;
const msgs::ShardRequestManagerInterface *manager_; const ShardRequestManagerInterface *manager_;
}; };
// inline VertexAccessor EdgeAccessor::To() const { return VertexAccessor(impl_.ToVertex()); }
// inline VertexAccessor EdgeAccessor::From() const { return VertexAccessor(impl_.FromVertex()); }
// Highly mocked interface. Won't work if used. // Highly mocked interface. Won't work if used.
class Path { class Path {
public: public:
@ -197,7 +151,14 @@ class Path {
friend bool operator==(const Path & /*lhs*/, const Path & /*rhs*/) { return true; }; friend bool operator==(const Path & /*lhs*/, const Path & /*rhs*/) { return true; };
utils::MemoryResource *GetMemoryResource() { return mem; } utils::MemoryResource *GetMemoryResource() { return mem; }
auto &vertices() { return vertices_; }
auto &edges() { return edges_; }
const auto &vertices() const { return vertices_; }
const auto &edges() const { return edges_; }
private: private:
std::vector<VertexAccessor> vertices_;
std::vector<EdgeAccessor> edges_;
utils::MemoryResource *mem = utils::NewDeleteResource(); utils::MemoryResource *mem = utils::NewDeleteResource();
}; };
} // namespace memgraph::query::v2::accessors } // namespace memgraph::query::v2::accessors

View File

@ -21,29 +21,28 @@
#include "query/v2/requests.hpp" #include "query/v2/requests.hpp"
#include "storage/v3/conversions.hpp" #include "storage/v3/conversions.hpp"
#include "storage/v3/property_value.hpp" #include "storage/v3/property_value.hpp"
#include "storage/v3/result.hpp"
#include "storage/v3/view.hpp" #include "storage/v3/view.hpp"
namespace memgraph::msgs {
class ShardRequestManagerInterface;
} // namespace memgraph::msgs
namespace memgraph::query::v2 { namespace memgraph::query::v2 {
inline const auto lam = [](const auto &val) { return ValueToTypedValue(val); }; class ShardRequestManagerInterface;
namespace detail { namespace detail {
class Callable { class Callable {
public: public:
auto operator()(const memgraph::storage::v3::PropertyValue &val) const { auto operator()(const storage::v3::PropertyValue &val) const {
return memgraph::storage::v3::PropertyToTypedValue<TypedValue>(val); return storage::v3::PropertyToTypedValue<TypedValue>(val);
}; };
auto operator()(const msgs::Value &val, memgraph::msgs::ShardRequestManagerInterface *manager) const { auto operator()(const msgs::Value &val, ShardRequestManagerInterface *manager) const {
return ValueToTypedValue(val, manager); return ValueToTypedValue(val, manager);
}; };
}; };
} // namespace detail } // namespace detail
using ExpressionEvaluator = memgraph::expr::ExpressionEvaluator< using ExpressionEvaluator =
TypedValue, memgraph::query::v2::EvaluationContext, memgraph::msgs::ShardRequestManagerInterface, storage::v3::View, expr::ExpressionEvaluator<TypedValue, query::v2::EvaluationContext, ShardRequestManagerInterface, storage::v3::View,
storage::v3::LabelId, msgs::Value, detail::Callable, memgraph::storage::v3::Error, memgraph::expr::QueryEngineTag>; storage::v3::LabelId, msgs::Value, detail::Callable, common::ErrorCode,
expr::QueryEngineTag>;
} // namespace memgraph::query::v2 } // namespace memgraph::query::v2

View File

@ -20,7 +20,6 @@
#include "query/v2/bindings/symbol.hpp" #include "query/v2/bindings/symbol.hpp"
#include "query/v2/bindings/typed_value.hpp" #include "query/v2/bindings/typed_value.hpp"
#include "query/v2/db_accessor.hpp"
#include "query/v2/exceptions.hpp" #include "query/v2/exceptions.hpp"
#include "query/v2/frontend/ast/ast.hpp" #include "query/v2/frontend/ast/ast.hpp"
#include "query/v2/path.hpp" #include "query/v2/path.hpp"
@ -28,7 +27,6 @@
#include "storage/v3/id_types.hpp" #include "storage/v3/id_types.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/shard_operation_result.hpp"
#include "storage/v3/view.hpp" #include "storage/v3/view.hpp"
#include "utils/exceptions.hpp" #include "utils/exceptions.hpp"
#include "utils/logging.hpp" #include "utils/logging.hpp"
@ -82,39 +80,5 @@ inline void ExpectType(const Symbol &symbol, const TypedValue &value, TypedValue
throw QueryRuntimeException("Expected a {} for '{}', but got {}.", expected, symbol.name(), value.type()); throw QueryRuntimeException("Expected a {} for '{}', but got {}.", expected, symbol.name(), value.type());
} }
template <typename T>
concept AccessorWithSetProperty = requires(T accessor, const storage::v3::PropertyId key,
const storage::v3::PropertyValue new_value) {
{ accessor.SetProperty(key, new_value) } -> std::same_as<storage::v3::Result<storage::v3::PropertyValue>>;
};
template <typename T>
concept AccessorWithSetPropertyAndValidate = requires(T accessor, const storage::v3::PropertyId key,
const storage::v3::PropertyValue new_value) {
{
accessor.SetPropertyAndValidate(key, new_value)
} -> std::same_as<storage::v3::ShardOperationResult<storage::v3::PropertyValue>>;
};
template <typename TRecordAccessor>
concept RecordAccessor =
AccessorWithSetProperty<TRecordAccessor> || AccessorWithSetPropertyAndValidate<TRecordAccessor>;
inline void HandleErrorOnPropertyUpdate(const storage::v3::Error error) {
switch (error) {
case storage::v3::Error::SERIALIZATION_ERROR:
throw TransactionSerializationException();
case storage::v3::Error::DELETED_OBJECT:
throw QueryRuntimeException("Trying to set properties on a deleted object.");
case storage::v3::Error::PROPERTIES_DISABLED:
throw QueryRuntimeException("Can't set property because properties on edges are disabled.");
case storage::v3::Error::VERTEX_HAS_EDGES:
case storage::v3::Error::NONEXISTENT_OBJECT:
case storage::v3::Error::VERTEX_ALREADY_INSERTED:
throw QueryRuntimeException("Unexpected error when setting a property.");
}
}
int64_t QueryTimestamp(); int64_t QueryTimestamp();
} // namespace memgraph::query::v2 } // namespace memgraph::query::v2

View File

@ -60,8 +60,8 @@ struct EvaluationContext {
mutable std::unordered_map<std::string, int64_t> counters; mutable std::unordered_map<std::string, int64_t> counters;
}; };
inline std::vector<storage::v3::PropertyId> NamesToProperties( inline std::vector<storage::v3::PropertyId> NamesToProperties(const std::vector<std::string> &property_names,
const std::vector<std::string> &property_names, msgs::ShardRequestManagerInterface *shard_request_manager) { ShardRequestManagerInterface *shard_request_manager) {
std::vector<storage::v3::PropertyId> properties; std::vector<storage::v3::PropertyId> properties;
// TODO Fix by using reference // TODO Fix by using reference
properties.reserve(property_names.size()); properties.reserve(property_names.size());
@ -74,7 +74,7 @@ inline std::vector<storage::v3::PropertyId> NamesToProperties(
} }
inline std::vector<storage::v3::LabelId> NamesToLabels(const std::vector<std::string> &label_names, inline std::vector<storage::v3::LabelId> NamesToLabels(const std::vector<std::string> &label_names,
msgs::ShardRequestManagerInterface *shard_request_manager) { ShardRequestManagerInterface *shard_request_manager) {
std::vector<storage::v3::LabelId> labels; std::vector<storage::v3::LabelId> labels;
labels.reserve(label_names.size()); labels.reserve(label_names.size());
// TODO Fix by using reference // TODO Fix by using reference
@ -97,7 +97,7 @@ struct ExecutionContext {
plan::ProfilingStats *stats_root{nullptr}; plan::ProfilingStats *stats_root{nullptr};
ExecutionStats execution_stats; ExecutionStats execution_stats;
utils::AsyncTimer timer; utils::AsyncTimer timer;
msgs::ShardRequestManagerInterface *shard_request_manager{nullptr}; ShardRequestManagerInterface *shard_request_manager{nullptr};
IdAllocator *edge_ids_alloc; IdAllocator *edge_ids_alloc;
}; };

View File

@ -17,7 +17,7 @@
namespace memgraph::query::v2 { namespace memgraph::query::v2 {
inline TypedValue ValueToTypedValue(const msgs::Value &value, msgs::ShardRequestManagerInterface *manager) { inline TypedValue ValueToTypedValue(const msgs::Value &value, ShardRequestManagerInterface *manager) {
using Value = msgs::Value; using Value = msgs::Value;
switch (value.type) { switch (value.type) {
case Value::Type::Null: case Value::Type::Null:
@ -56,6 +56,10 @@ inline TypedValue ValueToTypedValue(const msgs::Value &value, msgs::ShardRequest
throw std::runtime_error("Incorrect type in conversion"); throw std::runtime_error("Incorrect type in conversion");
} }
inline const auto ValueToTypedValueFunctor = [](const msgs::Value &value, ShardRequestManagerInterface *manager) {
return ValueToTypedValue(value, manager);
};
inline msgs::Value TypedValueToValue(const TypedValue &value) { inline msgs::Value TypedValueToValue(const TypedValue &value) {
using Value = msgs::Value; using Value = msgs::Value;
switch (value.type()) { switch (value.type()) {

View File

@ -118,7 +118,7 @@ ParsedQuery ParseQuery(const std::string &query_string, const std::map<std::stri
} }
std::unique_ptr<LogicalPlan> MakeLogicalPlan(AstStorage ast_storage, CypherQuery *query, const Parameters &parameters, std::unique_ptr<LogicalPlan> MakeLogicalPlan(AstStorage ast_storage, CypherQuery *query, const Parameters &parameters,
msgs::ShardRequestManagerInterface *shard_manager, ShardRequestManagerInterface *shard_manager,
const std::vector<Identifier *> &predefined_identifiers) { const std::vector<Identifier *> &predefined_identifiers) {
auto vertex_counts = plan::MakeVertexCountCache(shard_manager); auto vertex_counts = plan::MakeVertexCountCache(shard_manager);
auto symbol_table = expr::MakeSymbolTable(query, predefined_identifiers); auto symbol_table = expr::MakeSymbolTable(query, predefined_identifiers);
@ -130,7 +130,7 @@ std::unique_ptr<LogicalPlan> MakeLogicalPlan(AstStorage ast_storage, CypherQuery
std::shared_ptr<CachedPlan> CypherQueryToPlan(uint64_t hash, AstStorage ast_storage, CypherQuery *query, std::shared_ptr<CachedPlan> CypherQueryToPlan(uint64_t hash, AstStorage ast_storage, CypherQuery *query,
const Parameters &parameters, utils::SkipList<PlanCacheEntry> *plan_cache, const Parameters &parameters, utils::SkipList<PlanCacheEntry> *plan_cache,
msgs::ShardRequestManagerInterface *shard_manager, ShardRequestManagerInterface *shard_manager,
const std::vector<Identifier *> &predefined_identifiers) { const std::vector<Identifier *> &predefined_identifiers) {
std::optional<utils::SkipList<PlanCacheEntry>::Accessor> plan_cache_access; std::optional<utils::SkipList<PlanCacheEntry>::Accessor> plan_cache_access;
if (plan_cache) { if (plan_cache) {

View File

@ -132,7 +132,7 @@ class SingleNodeLogicalPlan final : public LogicalPlan {
}; };
std::unique_ptr<LogicalPlan> MakeLogicalPlan(AstStorage ast_storage, CypherQuery *query, const Parameters &parameters, std::unique_ptr<LogicalPlan> MakeLogicalPlan(AstStorage ast_storage, CypherQuery *query, const Parameters &parameters,
msgs::ShardRequestManagerInterface *shard_manager, ShardRequestManagerInterface *shard_manager,
const std::vector<Identifier *> &predefined_identifiers); const std::vector<Identifier *> &predefined_identifiers);
/** /**
@ -145,7 +145,7 @@ std::unique_ptr<LogicalPlan> MakeLogicalPlan(AstStorage ast_storage, CypherQuery
*/ */
std::shared_ptr<CachedPlan> CypherQueryToPlan(uint64_t hash, AstStorage ast_storage, CypherQuery *query, std::shared_ptr<CachedPlan> CypherQueryToPlan(uint64_t hash, AstStorage ast_storage, CypherQuery *query,
const Parameters &parameters, utils::SkipList<PlanCacheEntry> *plan_cache, const Parameters &parameters, utils::SkipList<PlanCacheEntry> *plan_cache,
msgs::ShardRequestManagerInterface *shard_manager, ShardRequestManagerInterface *shard_manager,
const std::vector<Identifier *> &predefined_identifiers = {}); const std::vector<Identifier *> &predefined_identifiers = {});
} // namespace memgraph::query::v2 } // namespace memgraph::query::v2

View File

@ -23,7 +23,6 @@
#include "storage/v3/key_store.hpp" #include "storage/v3/key_store.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/shard_operation_result.hpp"
/////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////
// Our communication layer and query engine don't mix // Our communication layer and query engine don't mix
@ -65,24 +64,11 @@ class EdgeAccessor final {
auto Properties(storage::v3::View view) const { return impl_.Properties(view); } auto Properties(storage::v3::View view) const { return impl_.Properties(view); }
storage::v3::Result<storage::v3::PropertyValue> GetProperty(storage::v3::View view, storage::v3::ShardResult<storage::v3::PropertyValue> GetProperty(storage::v3::View view,
storage::v3::PropertyId key) const { storage::v3::PropertyId key) const {
return impl_.GetProperty(key, view); return impl_.GetProperty(key, view);
} }
storage::v3::Result<storage::v3::PropertyValue> SetProperty(storage::v3::PropertyId key,
const storage::v3::PropertyValue &value) {
return impl_.SetProperty(key, value);
}
storage::v3::Result<storage::v3::PropertyValue> RemoveProperty(storage::v3::PropertyId key) {
return SetProperty(key, storage::v3::PropertyValue());
}
storage::v3::Result<std::map<storage::v3::PropertyId, storage::v3::PropertyValue>> ClearProperties() {
return impl_.ClearProperties();
}
VertexAccessor To() const; VertexAccessor To() const;
VertexAccessor From() const; VertexAccessor From() const;
@ -114,53 +100,19 @@ class VertexAccessor final {
auto PrimaryKey(storage::v3::View view) const { return impl_.PrimaryKey(view); } auto PrimaryKey(storage::v3::View view) const { return impl_.PrimaryKey(view); }
storage::v3::ShardOperationResult<bool> AddLabel(storage::v3::LabelId label) { storage::v3::ShardResult<bool> HasLabel(storage::v3::View view, storage::v3::LabelId label) const {
return impl_.AddLabelAndValidate(label);
}
storage::v3::ShardOperationResult<bool> AddLabelAndValidate(storage::v3::LabelId label) {
return impl_.AddLabelAndValidate(label);
}
storage::v3::ShardOperationResult<bool> RemoveLabel(storage::v3::LabelId label) {
return impl_.RemoveLabelAndValidate(label);
}
storage::v3::ShardOperationResult<bool> RemoveLabelAndValidate(storage::v3::LabelId label) {
return impl_.RemoveLabelAndValidate(label);
}
storage::v3::Result<bool> HasLabel(storage::v3::View view, storage::v3::LabelId label) const {
return impl_.HasLabel(label, view); return impl_.HasLabel(label, view);
} }
auto Properties(storage::v3::View view) const { return impl_.Properties(view); } auto Properties(storage::v3::View view) const { return impl_.Properties(view); }
storage::v3::Result<storage::v3::PropertyValue> GetProperty(storage::v3::View view, storage::v3::ShardResult<storage::v3::PropertyValue> GetProperty(storage::v3::View view,
storage::v3::PropertyId key) const { storage::v3::PropertyId key) const {
return impl_.GetProperty(key, view); return impl_.GetProperty(key, view);
} }
storage::v3::ShardOperationResult<storage::v3::PropertyValue> SetProperty(storage::v3::PropertyId key,
const storage::v3::PropertyValue &value) {
return impl_.SetPropertyAndValidate(key, value);
}
storage::v3::ShardOperationResult<storage::v3::PropertyValue> SetPropertyAndValidate(
storage::v3::PropertyId key, const storage::v3::PropertyValue &value) {
return impl_.SetPropertyAndValidate(key, value);
}
storage::v3::ShardOperationResult<storage::v3::PropertyValue> RemovePropertyAndValidate(storage::v3::PropertyId key) {
return SetPropertyAndValidate(key, storage::v3::PropertyValue{});
}
storage::v3::Result<std::map<storage::v3::PropertyId, storage::v3::PropertyValue>> ClearProperties() {
return impl_.ClearProperties();
}
auto InEdges(storage::v3::View view, const std::vector<storage::v3::EdgeTypeId> &edge_types) const auto InEdges(storage::v3::View view, const std::vector<storage::v3::EdgeTypeId> &edge_types) const
-> storage::v3::Result<decltype(iter::imap(MakeEdgeAccessor, *impl_.InEdges(view)))> { -> storage::v3::ShardResult<decltype(iter::imap(MakeEdgeAccessor, *impl_.InEdges(view)))> {
auto maybe_edges = impl_.InEdges(view, edge_types); auto maybe_edges = impl_.InEdges(view, edge_types);
if (maybe_edges.HasError()) return maybe_edges.GetError(); if (maybe_edges.HasError()) return maybe_edges.GetError();
return iter::imap(MakeEdgeAccessor, std::move(*maybe_edges)); return iter::imap(MakeEdgeAccessor, std::move(*maybe_edges));
@ -170,7 +122,7 @@ class VertexAccessor final {
auto InEdges(storage::v3::View view, const std::vector<storage::v3::EdgeTypeId> &edge_types, auto InEdges(storage::v3::View view, const std::vector<storage::v3::EdgeTypeId> &edge_types,
const VertexAccessor &dest) const const VertexAccessor &dest) const
-> storage::v3::Result<decltype(iter::imap(MakeEdgeAccessor, *impl_.InEdges(view)))> { -> storage::v3::ShardResult<decltype(iter::imap(MakeEdgeAccessor, *impl_.InEdges(view)))> {
const auto dest_id = dest.impl_.Id(view).GetValue(); const auto dest_id = dest.impl_.Id(view).GetValue();
auto maybe_edges = impl_.InEdges(view, edge_types, &dest_id); auto maybe_edges = impl_.InEdges(view, edge_types, &dest_id);
if (maybe_edges.HasError()) return maybe_edges.GetError(); if (maybe_edges.HasError()) return maybe_edges.GetError();
@ -178,7 +130,7 @@ class VertexAccessor final {
} }
auto OutEdges(storage::v3::View view, const std::vector<storage::v3::EdgeTypeId> &edge_types) const auto OutEdges(storage::v3::View view, const std::vector<storage::v3::EdgeTypeId> &edge_types) const
-> storage::v3::Result<decltype(iter::imap(MakeEdgeAccessor, *impl_.OutEdges(view)))> { -> storage::v3::ShardResult<decltype(iter::imap(MakeEdgeAccessor, *impl_.OutEdges(view)))> {
auto maybe_edges = impl_.OutEdges(view, edge_types); auto maybe_edges = impl_.OutEdges(view, edge_types);
if (maybe_edges.HasError()) return maybe_edges.GetError(); if (maybe_edges.HasError()) return maybe_edges.GetError();
return iter::imap(MakeEdgeAccessor, std::move(*maybe_edges)); return iter::imap(MakeEdgeAccessor, std::move(*maybe_edges));
@ -188,16 +140,16 @@ class VertexAccessor final {
auto OutEdges(storage::v3::View view, const std::vector<storage::v3::EdgeTypeId> &edge_types, auto OutEdges(storage::v3::View view, const std::vector<storage::v3::EdgeTypeId> &edge_types,
const VertexAccessor &dest) const const VertexAccessor &dest) const
-> storage::v3::Result<decltype(iter::imap(MakeEdgeAccessor, *impl_.OutEdges(view)))> { -> storage::v3::ShardResult<decltype(iter::imap(MakeEdgeAccessor, *impl_.OutEdges(view)))> {
const auto dest_id = dest.impl_.Id(view).GetValue(); const auto dest_id = dest.impl_.Id(view).GetValue();
auto maybe_edges = impl_.OutEdges(view, edge_types, &dest_id); auto maybe_edges = impl_.OutEdges(view, edge_types, &dest_id);
if (maybe_edges.HasError()) return maybe_edges.GetError(); if (maybe_edges.HasError()) return maybe_edges.GetError();
return iter::imap(MakeEdgeAccessor, std::move(*maybe_edges)); return iter::imap(MakeEdgeAccessor, std::move(*maybe_edges));
} }
storage::v3::Result<size_t> InDegree(storage::v3::View view) const { return impl_.InDegree(view); } storage::v3::ShardResult<size_t> InDegree(storage::v3::View view) const { return impl_.InDegree(view); }
storage::v3::Result<size_t> OutDegree(storage::v3::View view) const { return impl_.OutDegree(view); } storage::v3::ShardResult<size_t> OutDegree(storage::v3::View view) const { return impl_.OutDegree(view); }
// TODO(jbajic) Fix Remove Gid // TODO(jbajic) Fix Remove Gid
static int64_t CypherId() { return 1; } static int64_t CypherId() { return 1; }

View File

@ -224,12 +224,4 @@ class VersionInfoInMulticommandTxException : public QueryException {
: QueryException("Version info query not allowed in multicommand transactions.") {} : QueryException("Version info query not allowed in multicommand transactions.") {}
}; };
/**
* An exception for an illegal operation that violates schema
*/
class SchemaViolationException : public QueryRuntimeException {
public:
using QueryRuntimeException::QueryRuntimeException;
};
} // namespace memgraph::query::v2 } // namespace memgraph::query::v2

View File

@ -20,11 +20,13 @@
#include "query/v2/bindings/ast_visitor.hpp" #include "query/v2/bindings/ast_visitor.hpp"
#include "common/types.hpp" #include "common/types.hpp"
#include "query/v2/bindings/symbol.hpp" #include "query/v2/bindings/symbol.hpp"
#include "query/v2/interpret/awesome_memgraph_functions.hpp" #include "functions/awesome_memgraph_functions.hpp"
#include "query/v2/bindings/typed_value.hpp" #include "query/v2/bindings/typed_value.hpp"
#include "query/v2/db_accessor.hpp" #include "query/v2/db_accessor.hpp"
#include "query/v2/path.hpp" #include "query/v2/path.hpp"
#include "query/v2/shard_request_manager.hpp"
#include "utils/typeinfo.hpp" #include "utils/typeinfo.hpp"
#include "query/v2/conversions.hpp"
cpp<# cpp<#
@ -836,13 +838,15 @@ cpp<#
:slk-load (slk-load-ast-vector "Expression")) :slk-load (slk-load-ast-vector "Expression"))
(function-name "std::string" :scope :public) (function-name "std::string" :scope :public)
(function "std::function<TypedValue(const TypedValue *, int64_t, (function "std::function<TypedValue(const TypedValue *, int64_t,
const FunctionContext &)>" const functions::FunctionContext<ShardRequestManagerInterface> &)>"
:scope :public :scope :public
:dont-save t :dont-save t
:clone :copy :clone :copy
:slk-load (lambda (member) :slk-load (lambda (member)
#>cpp #>cpp
self->${member} = query::v2::NameToFunction(self->function_name_); self->${member} = functions::NameToFunction<TypedValue,
functions::FunctionContext<ShardRequestManagerInterface>,
functions::QueryEngineTag, decltype(ValueToTypedValueFunctor)>(self->function_name_);
cpp<#))) cpp<#)))
(:public (:public
#>cpp #>cpp
@ -865,7 +869,8 @@ cpp<#
const std::vector<Expression *> &arguments) const std::vector<Expression *> &arguments)
: arguments_(arguments), : arguments_(arguments),
function_name_(function_name), function_name_(function_name),
function_(NameToFunction(function_name_)) { function_(functions::NameToFunction<TypedValue, functions::FunctionContext<ShardRequestManagerInterface>,
functions::QueryEngineTag, decltype(ValueToTypedValueFunctor)>(function_name_)) {
if (!function_) { if (!function_) {
throw SemanticException("Function '{}' doesn't exist.", function_name); throw SemanticException("Function '{}' doesn't exist.", function_name);
} }

File diff suppressed because it is too large Load Diff

View File

@ -20,12 +20,10 @@
#include "storage/v3/view.hpp" #include "storage/v3/view.hpp"
#include "utils/memory.hpp" #include "utils/memory.hpp"
namespace memgraph::msgs {
class ShardRequestManagerInterface;
} // namespace memgraph::msgs
namespace memgraph::query::v2 { namespace memgraph::query::v2 {
class ShardRequestManagerInterface;
namespace { namespace {
const char kStartsWith[] = "STARTSWITH"; const char kStartsWith[] = "STARTSWITH";
const char kEndsWith[] = "ENDSWITH"; const char kEndsWith[] = "ENDSWITH";
@ -36,7 +34,7 @@ const char kId[] = "ID";
struct FunctionContext { struct FunctionContext {
// TODO(kostasrim) consider optional here. ShardRequestManager does not exist on the storage. // TODO(kostasrim) consider optional here. ShardRequestManager does not exist on the storage.
// DbAccessor *db_accessor; // DbAccessor *db_accessor;
msgs::ShardRequestManagerInterface *manager; ShardRequestManagerInterface *manager;
utils::MemoryResource *memory; utils::MemoryResource *memory;
int64_t timestamp; int64_t timestamp;
std::unordered_map<std::string, int64_t> *counters; std::unordered_map<std::string, int64_t> *counters;

View File

@ -144,7 +144,7 @@ class ReplQueryHandler final : public query::v2::ReplicationQueryHandler {
/// @throw QueryRuntimeException if an error ocurred. /// @throw QueryRuntimeException if an error ocurred.
Callback HandleAuthQuery(AuthQuery *auth_query, AuthQueryHandler *auth, const Parameters &parameters, Callback HandleAuthQuery(AuthQuery *auth_query, AuthQueryHandler *auth, const Parameters &parameters,
msgs::ShardRequestManagerInterface *manager) { ShardRequestManagerInterface *manager) {
// Empty frame for evaluation of password expression. This is OK since // Empty frame for evaluation of password expression. This is OK since
// password should be either null or string literal and it's evaluation // password should be either null or string literal and it's evaluation
// should not depend on frame. // should not depend on frame.
@ -313,7 +313,7 @@ Callback HandleAuthQuery(AuthQuery *auth_query, AuthQueryHandler *auth, const Pa
} }
Callback HandleReplicationQuery(ReplicationQuery *repl_query, const Parameters &parameters, Callback HandleReplicationQuery(ReplicationQuery *repl_query, const Parameters &parameters,
InterpreterContext *interpreter_context, msgs::ShardRequestManagerInterface *manager, InterpreterContext *interpreter_context, ShardRequestManagerInterface *manager,
std::vector<Notification> *notifications) { std::vector<Notification> *notifications) {
expr::Frame<TypedValue> frame(0); expr::Frame<TypedValue> frame(0);
SymbolTable symbol_table; SymbolTable symbol_table;
@ -449,7 +449,7 @@ Callback HandleReplicationQuery(ReplicationQuery *repl_query, const Parameters &
} }
Callback HandleSettingQuery(SettingQuery *setting_query, const Parameters &parameters, Callback HandleSettingQuery(SettingQuery *setting_query, const Parameters &parameters,
msgs::ShardRequestManagerInterface *manager) { ShardRequestManagerInterface *manager) {
expr::Frame<TypedValue> frame(0); expr::Frame<TypedValue> frame(0);
SymbolTable symbol_table; SymbolTable symbol_table;
EvaluationContext evaluation_context; EvaluationContext evaluation_context;
@ -650,7 +650,7 @@ struct PullPlanVector {
struct PullPlan { struct PullPlan {
explicit PullPlan(std::shared_ptr<CachedPlan> plan, const Parameters &parameters, bool is_profile_query, explicit PullPlan(std::shared_ptr<CachedPlan> plan, const Parameters &parameters, bool is_profile_query,
DbAccessor *dba, InterpreterContext *interpreter_context, utils::MemoryResource *execution_memory, DbAccessor *dba, InterpreterContext *interpreter_context, utils::MemoryResource *execution_memory,
msgs::ShardRequestManagerInterface *shard_request_manager = nullptr, ShardRequestManagerInterface *shard_request_manager = nullptr,
// TriggerContextCollector *trigger_context_collector = nullptr, // TriggerContextCollector *trigger_context_collector = nullptr,
std::optional<size_t> memory_limit = {}); std::optional<size_t> memory_limit = {});
std::optional<plan::ProfilingStatsWithTotalTime> Pull(AnyStream *stream, std::optional<int> n, std::optional<plan::ProfilingStatsWithTotalTime> Pull(AnyStream *stream, std::optional<int> n,
@ -684,7 +684,7 @@ struct PullPlan {
PullPlan::PullPlan(const std::shared_ptr<CachedPlan> plan, const Parameters &parameters, const bool is_profile_query, PullPlan::PullPlan(const std::shared_ptr<CachedPlan> plan, const Parameters &parameters, const bool is_profile_query,
DbAccessor *dba, InterpreterContext *interpreter_context, utils::MemoryResource *execution_memory, DbAccessor *dba, InterpreterContext *interpreter_context, utils::MemoryResource *execution_memory,
msgs::ShardRequestManagerInterface *shard_request_manager, const std::optional<size_t> memory_limit) ShardRequestManagerInterface *shard_request_manager, const std::optional<size_t> memory_limit)
: plan_(plan), : plan_(plan),
cursor_(plan->plan().MakeCursor(execution_memory)), cursor_(plan->plan().MakeCursor(execution_memory)),
frame_(plan->symbol_table().max_position(), execution_memory), frame_(plan->symbol_table().max_position(), execution_memory),
@ -917,7 +917,7 @@ Interpreter::Interpreter(InterpreterContext *interpreter_context) : interpreter_
auto random_uuid = boost::uuids::uuid{boost::uuids::random_generator()()}; auto random_uuid = boost::uuids::uuid{boost::uuids::random_generator()()};
auto query_io = interpreter_context_->io.ForkLocal(random_uuid); auto query_io = interpreter_context_->io.ForkLocal(random_uuid);
shard_request_manager_ = std::make_unique<msgs::ShardRequestManager<io::local_transport::LocalTransport>>( shard_request_manager_ = std::make_unique<ShardRequestManager<io::local_transport::LocalTransport>>(
coordinator::CoordinatorClient<io::local_transport::LocalTransport>( coordinator::CoordinatorClient<io::local_transport::LocalTransport>(
query_io, interpreter_context_->coordinator_address, std::vector{interpreter_context_->coordinator_address}), query_io, interpreter_context_->coordinator_address, std::vector{interpreter_context_->coordinator_address}),
std::move(query_io)); std::move(query_io));
@ -994,7 +994,7 @@ PreparedQuery Interpreter::PrepareTransactionQuery(std::string_view query_upper)
PreparedQuery PrepareCypherQuery(ParsedQuery parsed_query, std::map<std::string, TypedValue> *summary, PreparedQuery PrepareCypherQuery(ParsedQuery parsed_query, std::map<std::string, TypedValue> *summary,
InterpreterContext *interpreter_context, DbAccessor *dba, InterpreterContext *interpreter_context, DbAccessor *dba,
utils::MemoryResource *execution_memory, std::vector<Notification> *notifications, utils::MemoryResource *execution_memory, std::vector<Notification> *notifications,
msgs::ShardRequestManagerInterface *shard_request_manager) { ShardRequestManagerInterface *shard_request_manager) {
// TriggerContextCollector *trigger_context_collector = nullptr) { // TriggerContextCollector *trigger_context_collector = nullptr) {
auto *cypher_query = utils::Downcast<CypherQuery>(parsed_query.query); auto *cypher_query = utils::Downcast<CypherQuery>(parsed_query.query);
@ -1055,7 +1055,7 @@ PreparedQuery PrepareCypherQuery(ParsedQuery parsed_query, std::map<std::string,
PreparedQuery PrepareExplainQuery(ParsedQuery parsed_query, std::map<std::string, TypedValue> *summary, PreparedQuery PrepareExplainQuery(ParsedQuery parsed_query, std::map<std::string, TypedValue> *summary,
InterpreterContext *interpreter_context, InterpreterContext *interpreter_context,
msgs::ShardRequestManagerInterface *shard_request_manager, ShardRequestManagerInterface *shard_request_manager,
utils::MemoryResource *execution_memory) { utils::MemoryResource *execution_memory) {
const std::string kExplainQueryStart = "explain "; const std::string kExplainQueryStart = "explain ";
MG_ASSERT(utils::StartsWith(utils::ToLowerCase(parsed_query.stripped_query.query()), kExplainQueryStart), MG_ASSERT(utils::StartsWith(utils::ToLowerCase(parsed_query.stripped_query.query()), kExplainQueryStart),
@ -1104,7 +1104,7 @@ PreparedQuery PrepareExplainQuery(ParsedQuery parsed_query, std::map<std::string
PreparedQuery PrepareProfileQuery(ParsedQuery parsed_query, bool in_explicit_transaction, PreparedQuery PrepareProfileQuery(ParsedQuery parsed_query, bool in_explicit_transaction,
std::map<std::string, TypedValue> *summary, InterpreterContext *interpreter_context, std::map<std::string, TypedValue> *summary, InterpreterContext *interpreter_context,
DbAccessor *dba, utils::MemoryResource *execution_memory, DbAccessor *dba, utils::MemoryResource *execution_memory,
msgs::ShardRequestManagerInterface *shard_request_manager = nullptr) { ShardRequestManagerInterface *shard_request_manager = nullptr) {
const std::string kProfileQueryStart = "profile "; const std::string kProfileQueryStart = "profile ";
MG_ASSERT(utils::StartsWith(utils::ToLowerCase(parsed_query.stripped_query.query()), kProfileQueryStart), MG_ASSERT(utils::StartsWith(utils::ToLowerCase(parsed_query.stripped_query.query()), kProfileQueryStart),
@ -1298,7 +1298,7 @@ PreparedQuery PrepareIndexQuery(ParsedQuery parsed_query, bool in_explicit_trans
PreparedQuery PrepareAuthQuery(ParsedQuery parsed_query, bool in_explicit_transaction, PreparedQuery PrepareAuthQuery(ParsedQuery parsed_query, bool in_explicit_transaction,
std::map<std::string, TypedValue> *summary, InterpreterContext *interpreter_context, std::map<std::string, TypedValue> *summary, InterpreterContext *interpreter_context,
DbAccessor *dba, utils::MemoryResource *execution_memory, DbAccessor *dba, utils::MemoryResource *execution_memory,
msgs::ShardRequestManagerInterface *manager) { ShardRequestManagerInterface *manager) {
if (in_explicit_transaction) { if (in_explicit_transaction) {
throw UserModificationInMulticommandTxException(); throw UserModificationInMulticommandTxException();
} }
@ -1334,7 +1334,7 @@ PreparedQuery PrepareAuthQuery(ParsedQuery parsed_query, bool in_explicit_transa
PreparedQuery PrepareReplicationQuery(ParsedQuery parsed_query, const bool in_explicit_transaction, PreparedQuery PrepareReplicationQuery(ParsedQuery parsed_query, const bool in_explicit_transaction,
std::vector<Notification> *notifications, InterpreterContext *interpreter_context, std::vector<Notification> *notifications, InterpreterContext *interpreter_context,
msgs::ShardRequestManagerInterface *manager) { ShardRequestManagerInterface *manager) {
if (in_explicit_transaction) { if (in_explicit_transaction) {
throw ReplicationModificationInMulticommandTxException(); throw ReplicationModificationInMulticommandTxException();
} }
@ -1430,7 +1430,7 @@ PreparedQuery PrepareCreateSnapshotQuery(ParsedQuery parsed_query, bool in_expli
} }
PreparedQuery PrepareSettingQuery(ParsedQuery parsed_query, const bool in_explicit_transaction, PreparedQuery PrepareSettingQuery(ParsedQuery parsed_query, const bool in_explicit_transaction,
msgs::ShardRequestManagerInterface *manager) { ShardRequestManagerInterface *manager) {
if (in_explicit_transaction) { if (in_explicit_transaction) {
throw SettingConfigInMulticommandTxException{}; throw SettingConfigInMulticommandTxException{};
} }

View File

@ -296,7 +296,7 @@ class Interpreter final {
*/ */
void Abort(); void Abort();
const msgs::ShardRequestManagerInterface *GetShardRequestManager() const { return shard_request_manager_.get(); } const ShardRequestManagerInterface *GetShardRequestManager() const { return shard_request_manager_.get(); }
private: private:
struct QueryExecution { struct QueryExecution {
@ -342,7 +342,7 @@ class Interpreter final {
// move this unique_ptr into a shared_ptr. // move this unique_ptr into a shared_ptr.
std::unique_ptr<storage::v3::Shard::Accessor> db_accessor_; std::unique_ptr<storage::v3::Shard::Accessor> db_accessor_;
std::optional<DbAccessor> execution_db_accessor_; std::optional<DbAccessor> execution_db_accessor_;
std::unique_ptr<msgs::ShardRequestManagerInterface> shard_request_manager_; std::unique_ptr<ShardRequestManagerInterface> shard_request_manager_;
bool in_explicit_transaction_{false}; bool in_explicit_transaction_{false};
bool expect_rollback_{false}; bool expect_rollback_{false};

View File

@ -26,6 +26,7 @@
#include <cppitertools/chain.hpp> #include <cppitertools/chain.hpp>
#include <cppitertools/imap.hpp> #include <cppitertools/imap.hpp>
#include "common/errors.hpp"
#include "expr/ast/pretty_print_ast_to_original_expression.hpp" #include "expr/ast/pretty_print_ast_to_original_expression.hpp"
#include "expr/exceptions.hpp" #include "expr/exceptions.hpp"
#include "query/exceptions.hpp" #include "query/exceptions.hpp"
@ -251,7 +252,7 @@ class DistributedCreateNodeCursor : public Cursor {
std::vector<const NodeCreationInfo *> nodes_info_; std::vector<const NodeCreationInfo *> nodes_info_;
std::vector<std::vector<std::pair<storage::v3::PropertyId, msgs::Value>>> src_vertex_props_; std::vector<std::vector<std::pair<storage::v3::PropertyId, msgs::Value>>> src_vertex_props_;
std::vector<msgs::PrimaryKey> primary_keys_; std::vector<msgs::PrimaryKey> primary_keys_;
msgs::ExecutionState<msgs::CreateVerticesRequest> state_; ExecutionState<msgs::CreateVerticesRequest> state_;
}; };
bool Once::OnceCursor::Pull(Frame &, ExecutionContext &context) { bool Once::OnceCursor::Pull(Frame &, ExecutionContext &context) {
@ -381,7 +382,7 @@ class ScanAllCursor : public Cursor {
std::optional<decltype(vertices_.value().begin())> vertices_it_; std::optional<decltype(vertices_.value().begin())> vertices_it_;
const char *op_name_; const char *op_name_;
std::vector<msgs::ScanVerticesResponse> current_batch; std::vector<msgs::ScanVerticesResponse> current_batch;
msgs::ExecutionState<msgs::ScanVerticesRequest> request_state; ExecutionState<msgs::ScanVerticesRequest> request_state;
}; };
class DistributedScanAllAndFilterCursor : public Cursor { class DistributedScanAllAndFilterCursor : public Cursor {
@ -402,7 +403,7 @@ class DistributedScanAllAndFilterCursor : public Cursor {
using VertexAccessor = accessors::VertexAccessor; using VertexAccessor = accessors::VertexAccessor;
bool MakeRequest(msgs::ShardRequestManagerInterface &shard_manager, ExecutionContext &context) { bool MakeRequest(ShardRequestManagerInterface &shard_manager, ExecutionContext &context) {
{ {
SCOPED_REQUEST_WAIT_PROFILE; SCOPED_REQUEST_WAIT_PROFILE;
current_batch = shard_manager.Request(request_state_); current_batch = shard_manager.Request(request_state_);
@ -419,7 +420,7 @@ class DistributedScanAllAndFilterCursor : public Cursor {
if (MustAbort(context)) { if (MustAbort(context)) {
throw HintedAbortError(); throw HintedAbortError();
} }
using State = msgs::ExecutionState<msgs::ScanVerticesRequest>; using State = ExecutionState<msgs::ScanVerticesRequest>;
if (request_state_.state == State::INITIALIZING) { if (request_state_.state == State::INITIALIZING) {
if (!input_cursor_->Pull(frame, context)) { if (!input_cursor_->Pull(frame, context)) {
@ -446,7 +447,7 @@ class DistributedScanAllAndFilterCursor : public Cursor {
void ResetExecutionState() { void ResetExecutionState() {
current_batch.clear(); current_batch.clear();
current_vertex_it = current_batch.end(); current_vertex_it = current_batch.end();
request_state_ = msgs::ExecutionState<msgs::ScanVerticesRequest>{}; request_state_ = ExecutionState<msgs::ScanVerticesRequest>{};
} }
void Reset() override { void Reset() override {
@ -460,7 +461,7 @@ class DistributedScanAllAndFilterCursor : public Cursor {
const char *op_name_; const char *op_name_;
std::vector<VertexAccessor> current_batch; std::vector<VertexAccessor> current_batch;
std::vector<VertexAccessor>::iterator current_vertex_it; std::vector<VertexAccessor>::iterator current_vertex_it;
msgs::ExecutionState<msgs::ScanVerticesRequest> request_state_; ExecutionState<msgs::ScanVerticesRequest> request_state_;
std::optional<storage::v3::LabelId> label_; std::optional<storage::v3::LabelId> label_;
std::optional<std::pair<storage::v3::PropertyId, Expression *>> property_expression_pair_; std::optional<std::pair<storage::v3::PropertyId, Expression *>> property_expression_pair_;
std::optional<std::vector<Expression *>> filter_expressions_; std::optional<std::vector<Expression *>> filter_expressions_;
@ -580,27 +581,6 @@ UniqueCursorPtr ScanAllById::MakeCursor(utils::MemoryResource *mem) const {
std::move(vertices), "ScanAllById"); std::move(vertices), "ScanAllById");
} }
namespace {
template <class TEdges>
auto UnwrapEdgesResult(storage::v3::Result<TEdges> &&result) {
if (result.HasError()) {
switch (result.GetError()) {
case storage::v3::Error::DELETED_OBJECT:
throw QueryRuntimeException("Trying to get relationships of a deleted node.");
case storage::v3::Error::NONEXISTENT_OBJECT:
throw query::v2::QueryRuntimeException("Trying to get relationships from a node that doesn't exist.");
case storage::v3::Error::VERTEX_HAS_EDGES:
case storage::v3::Error::SERIALIZATION_ERROR:
case storage::v3::Error::PROPERTIES_DISABLED:
throw QueryRuntimeException("Unexpected error when accessing relationships.");
}
}
return std::move(*result);
}
} // namespace
Expand::Expand(const std::shared_ptr<LogicalOperator> &input, Symbol input_symbol, Symbol node_symbol, Expand::Expand(const std::shared_ptr<LogicalOperator> &input, Symbol input_symbol, Symbol node_symbol,
Symbol edge_symbol, EdgeAtom::Direction direction, Symbol edge_symbol, EdgeAtom::Direction direction,
const std::vector<storage::v3::EdgeTypeId> &edge_types, bool existing_node, storage::v3::View view) const std::vector<storage::v3::EdgeTypeId> &edge_types, bool existing_node, storage::v3::View view)
@ -870,45 +850,9 @@ std::vector<Symbol> SetProperties::ModifiedSymbols(const SymbolTable &table) con
SetProperties::SetPropertiesCursor::SetPropertiesCursor(const SetProperties &self, utils::MemoryResource *mem) SetProperties::SetPropertiesCursor::SetPropertiesCursor(const SetProperties &self, utils::MemoryResource *mem)
: self_(self), input_cursor_(self.input_->MakeCursor(mem)) {} : self_(self), input_cursor_(self.input_->MakeCursor(mem)) {}
namespace {
template <typename T>
concept AccessorWithProperties = requires(T value, storage::v3::PropertyId property_id,
storage::v3::PropertyValue property_value) {
{
value.ClearProperties()
} -> std::same_as<storage::v3::Result<std::map<storage::v3::PropertyId, storage::v3::PropertyValue>>>;
{value.SetProperty(property_id, property_value)};
};
} // namespace
bool SetProperties::SetPropertiesCursor::Pull(Frame &frame, ExecutionContext &context) { bool SetProperties::SetPropertiesCursor::Pull(Frame &frame, ExecutionContext &context) {
SCOPED_PROFILE_OP("SetProperties"); SCOPED_PROFILE_OP("SetProperties");
return false; return false;
// if (!input_cursor_->Pull(frame, context)) return false;
//
// TypedValue &lhs = frame[self_.input_symbol_];
//
// // Set, just like Create needs to see the latest changes.
// ExpressionEvaluator evaluator(&frame, context.symbol_table, context.evaluation_context, context.db_accessor,
// storage::v3::View::NEW);
// TypedValue rhs = self_.rhs_->Accept(evaluator);
//
// switch (lhs.type()) {
// case TypedValue::Type::Vertex:
// SetPropertiesOnRecord(&lhs.ValueVertex(), rhs, self_.op_, &context);
// break;
// case TypedValue::Type::Edge:
// SetPropertiesOnRecord(&lhs.ValueEdge(), rhs, self_.op_, &context);
// break;
// case TypedValue::Type::Null:
// // Skip setting properties on Null (can occur in optional match).
// break;
// default:
// throw QueryRuntimeException("Properties can only be set on edges and vertices.");
// }
// return true;
} }
void SetProperties::SetPropertiesCursor::Shutdown() { input_cursor_->Shutdown(); } void SetProperties::SetPropertiesCursor::Shutdown() { input_cursor_->Shutdown(); }
@ -2516,7 +2460,7 @@ class DistributedCreateExpandCursor : public Cursor {
const UniqueCursorPtr input_cursor_; const UniqueCursorPtr input_cursor_;
const CreateExpand &self_; const CreateExpand &self_;
msgs::ExecutionState<msgs::CreateExpandRequest> state_; ExecutionState<msgs::CreateExpandRequest> state_;
}; };
class DistributedExpandCursor : public Cursor { class DistributedExpandCursor : public Cursor {
@ -2563,7 +2507,7 @@ class DistributedExpandCursor : public Cursor {
request.edge_properties.emplace(); request.edge_properties.emplace();
request.src_vertices.push_back(get_dst_vertex(edge, direction)); request.src_vertices.push_back(get_dst_vertex(edge, direction));
request.direction = (direction == EdgeAtom::Direction::IN) ? msgs::EdgeDirection::OUT : msgs::EdgeDirection::IN; request.direction = (direction == EdgeAtom::Direction::IN) ? msgs::EdgeDirection::OUT : msgs::EdgeDirection::IN;
msgs::ExecutionState<msgs::ExpandOneRequest> request_state; ExecutionState<msgs::ExpandOneRequest> request_state;
auto result_rows = context.shard_request_manager->Request(request_state, std::move(request)); auto result_rows = context.shard_request_manager->Request(request_state, std::move(request));
MG_ASSERT(result_rows.size() == 1); MG_ASSERT(result_rows.size() == 1);
auto &result_row = result_rows.front(); auto &result_row = result_rows.front();
@ -2589,7 +2533,7 @@ class DistributedExpandCursor : public Cursor {
// to not fetch any properties of the edges // to not fetch any properties of the edges
request.edge_properties.emplace(); request.edge_properties.emplace();
request.src_vertices.push_back(vertex.Id()); request.src_vertices.push_back(vertex.Id());
msgs::ExecutionState<msgs::ExpandOneRequest> request_state; ExecutionState<msgs::ExpandOneRequest> request_state;
auto result_rows = std::invoke([&context, &request_state, &request]() mutable { auto result_rows = std::invoke([&context, &request_state, &request]() mutable {
SCOPED_REQUEST_WAIT_PROFILE; SCOPED_REQUEST_WAIT_PROFILE;
return context.shard_request_manager->Request(request_state, std::move(request)); return context.shard_request_manager->Request(request_state, std::move(request));

View File

@ -398,7 +398,7 @@ void Filters::AnalyzeAndStoreFilter(Expression *expr, const SymbolTable &symbol_
auto add_id_equal = [&](auto *maybe_id_fun, auto *val_expr) -> bool { auto add_id_equal = [&](auto *maybe_id_fun, auto *val_expr) -> bool {
auto *id_fun = utils::Downcast<Function>(maybe_id_fun); auto *id_fun = utils::Downcast<Function>(maybe_id_fun);
if (!id_fun) return false; if (!id_fun) return false;
if (id_fun->function_name_ != kId) return false; if (id_fun->function_name_ != functions::kId) return false;
if (id_fun->arguments_.size() != 1U) return false; if (id_fun->arguments_.size() != 1U) return false;
auto *ident = utils::Downcast<Identifier>(id_fun->arguments_.front()); auto *ident = utils::Downcast<Identifier>(id_fun->arguments_.front());
if (!ident) return false; if (!ident) return false;

View File

@ -19,7 +19,7 @@
namespace memgraph::query::v2::plan { namespace memgraph::query::v2::plan {
PlanPrinter::PlanPrinter(const msgs::ShardRequestManagerInterface *request_manager, std::ostream *out) PlanPrinter::PlanPrinter(const ShardRequestManagerInterface *request_manager, std::ostream *out)
: request_manager_(request_manager), out_(out) {} : request_manager_(request_manager), out_(out) {}
#define PRE_VISIT(TOp) \ #define PRE_VISIT(TOp) \
@ -263,14 +263,14 @@ void PlanPrinter::Branch(query::v2::plan::LogicalOperator &op, const std::string
--depth_; --depth_;
} }
void PrettyPrint(const msgs::ShardRequestManagerInterface &request_manager, const LogicalOperator *plan_root, void PrettyPrint(const ShardRequestManagerInterface &request_manager, const LogicalOperator *plan_root,
std::ostream *out) { std::ostream *out) {
PlanPrinter printer(&request_manager, out); PlanPrinter printer(&request_manager, out);
// FIXME(mtomic): We should make visitors that take const arguments. // FIXME(mtomic): We should make visitors that take const arguments.
const_cast<LogicalOperator *>(plan_root)->Accept(printer); const_cast<LogicalOperator *>(plan_root)->Accept(printer);
} }
nlohmann::json PlanToJson(const msgs::ShardRequestManagerInterface &request_manager, const LogicalOperator *plan_root) { nlohmann::json PlanToJson(const ShardRequestManagerInterface &request_manager, const LogicalOperator *plan_root) {
impl::PlanToJsonVisitor visitor(&request_manager); impl::PlanToJsonVisitor visitor(&request_manager);
// FIXME(mtomic): We should make visitors that take const arguments. // FIXME(mtomic): We should make visitors that take const arguments.
const_cast<LogicalOperator *>(plan_root)->Accept(visitor); const_cast<LogicalOperator *>(plan_root)->Accept(visitor);
@ -349,15 +349,15 @@ json ToJson(const utils::Bound<Expression *> &bound) {
json ToJson(const Symbol &symbol) { return symbol.name(); } json ToJson(const Symbol &symbol) { return symbol.name(); }
json ToJson(storage::v3::EdgeTypeId edge_type, const msgs::ShardRequestManagerInterface &request_manager) { json ToJson(storage::v3::EdgeTypeId edge_type, const ShardRequestManagerInterface &request_manager) {
return request_manager.EdgeTypeToName(edge_type); return request_manager.EdgeTypeToName(edge_type);
} }
json ToJson(storage::v3::LabelId label, const msgs::ShardRequestManagerInterface &request_manager) { json ToJson(storage::v3::LabelId label, const ShardRequestManagerInterface &request_manager) {
return request_manager.LabelToName(label); return request_manager.LabelToName(label);
} }
json ToJson(storage::v3::PropertyId property, const msgs::ShardRequestManagerInterface &request_manager) { json ToJson(storage::v3::PropertyId property, const ShardRequestManagerInterface &request_manager) {
return request_manager.PropertyToName(property); return request_manager.PropertyToName(property);
} }
@ -369,7 +369,7 @@ json ToJson(NamedExpression *nexpr) {
} }
json ToJson(const std::vector<std::pair<storage::v3::PropertyId, Expression *>> &properties, json ToJson(const std::vector<std::pair<storage::v3::PropertyId, Expression *>> &properties,
const msgs::ShardRequestManagerInterface &request_manager) { const ShardRequestManagerInterface &request_manager) {
json json; json json;
for (const auto &prop_pair : properties) { for (const auto &prop_pair : properties) {
json.emplace(ToJson(prop_pair.first, request_manager), ToJson(prop_pair.second)); json.emplace(ToJson(prop_pair.first, request_manager), ToJson(prop_pair.second));
@ -377,7 +377,7 @@ json ToJson(const std::vector<std::pair<storage::v3::PropertyId, Expression *>>
return json; return json;
} }
json ToJson(const NodeCreationInfo &node_info, const msgs::ShardRequestManagerInterface &request_manager) { json ToJson(const NodeCreationInfo &node_info, const ShardRequestManagerInterface &request_manager) {
json self; json self;
self["symbol"] = ToJson(node_info.symbol); self["symbol"] = ToJson(node_info.symbol);
self["labels"] = ToJson(node_info.labels, request_manager); self["labels"] = ToJson(node_info.labels, request_manager);
@ -386,7 +386,7 @@ json ToJson(const NodeCreationInfo &node_info, const msgs::ShardRequestManagerIn
return self; return self;
} }
json ToJson(const EdgeCreationInfo &edge_info, const msgs::ShardRequestManagerInterface &request_manager) { json ToJson(const EdgeCreationInfo &edge_info, const ShardRequestManagerInterface &request_manager) {
json self; json self;
self["symbol"] = ToJson(edge_info.symbol); self["symbol"] = ToJson(edge_info.symbol);
const auto *props = std::get_if<PropertiesMapList>(&edge_info.properties); const auto *props = std::get_if<PropertiesMapList>(&edge_info.properties);

View File

@ -30,17 +30,17 @@ class LogicalOperator;
/// ShardRequestManager is needed for resolving label and property names. /// ShardRequestManager is needed for resolving label and property names.
/// Note that `plan_root` isn't modified, but we can't take it as a const /// Note that `plan_root` isn't modified, but we can't take it as a const
/// because we don't have support for visiting a const LogicalOperator. /// because we don't have support for visiting a const LogicalOperator.
void PrettyPrint(const msgs::ShardRequestManagerInterface &request_manager, const LogicalOperator *plan_root, void PrettyPrint(const ShardRequestManagerInterface &request_manager, const LogicalOperator *plan_root,
std::ostream *out); std::ostream *out);
/// Overload of `PrettyPrint` which defaults the `std::ostream` to `std::cout`. /// Overload of `PrettyPrint` which defaults the `std::ostream` to `std::cout`.
inline void PrettyPrint(const msgs::ShardRequestManagerInterface &request_manager, const LogicalOperator *plan_root) { inline void PrettyPrint(const ShardRequestManagerInterface &request_manager, const LogicalOperator *plan_root) {
PrettyPrint(request_manager, plan_root, &std::cout); PrettyPrint(request_manager, plan_root, &std::cout);
} }
/// Convert a `LogicalOperator` plan to a JSON representation. /// Convert a `LogicalOperator` plan to a JSON representation.
/// DbAccessor is needed for resolving label and property names. /// DbAccessor is needed for resolving label and property names.
nlohmann::json PlanToJson(const msgs::ShardRequestManagerInterface &request_manager, const LogicalOperator *plan_root); nlohmann::json PlanToJson(const ShardRequestManagerInterface &request_manager, const LogicalOperator *plan_root);
class PlanPrinter : public virtual HierarchicalLogicalOperatorVisitor { class PlanPrinter : public virtual HierarchicalLogicalOperatorVisitor {
public: public:
@ -48,7 +48,7 @@ class PlanPrinter : public virtual HierarchicalLogicalOperatorVisitor {
using HierarchicalLogicalOperatorVisitor::PreVisit; using HierarchicalLogicalOperatorVisitor::PreVisit;
using HierarchicalLogicalOperatorVisitor::Visit; using HierarchicalLogicalOperatorVisitor::Visit;
PlanPrinter(const msgs::ShardRequestManagerInterface *request_manager, std::ostream *out); PlanPrinter(const ShardRequestManagerInterface *request_manager, std::ostream *out);
bool DefaultPreVisit() override; bool DefaultPreVisit() override;
@ -115,7 +115,7 @@ class PlanPrinter : public virtual HierarchicalLogicalOperatorVisitor {
void Branch(LogicalOperator &op, const std::string &branch_name = ""); void Branch(LogicalOperator &op, const std::string &branch_name = "");
int64_t depth_{0}; int64_t depth_{0};
const msgs::ShardRequestManagerInterface *request_manager_{nullptr}; const ShardRequestManagerInterface *request_manager_{nullptr};
std::ostream *out_{nullptr}; std::ostream *out_{nullptr};
}; };
@ -133,20 +133,20 @@ nlohmann::json ToJson(const utils::Bound<Expression *> &bound);
nlohmann::json ToJson(const Symbol &symbol); nlohmann::json ToJson(const Symbol &symbol);
nlohmann::json ToJson(storage::v3::EdgeTypeId edge_type, const msgs::ShardRequestManagerInterface &request_manager); nlohmann::json ToJson(storage::v3::EdgeTypeId edge_type, const ShardRequestManagerInterface &request_manager);
nlohmann::json ToJson(storage::v3::LabelId label, const msgs::ShardRequestManagerInterface &request_manager); nlohmann::json ToJson(storage::v3::LabelId label, const ShardRequestManagerInterface &request_manager);
nlohmann::json ToJson(storage::v3::PropertyId property, const msgs::ShardRequestManagerInterface &request_manager); nlohmann::json ToJson(storage::v3::PropertyId property, const ShardRequestManagerInterface &request_manager);
nlohmann::json ToJson(NamedExpression *nexpr); nlohmann::json ToJson(NamedExpression *nexpr);
nlohmann::json ToJson(const std::vector<std::pair<storage::v3::PropertyId, Expression *>> &properties, nlohmann::json ToJson(const std::vector<std::pair<storage::v3::PropertyId, Expression *>> &properties,
const msgs::ShardRequestManagerInterface &request_manager); const ShardRequestManagerInterface &request_manager);
nlohmann::json ToJson(const NodeCreationInfo &node_info, const msgs::ShardRequestManagerInterface &request_manager); nlohmann::json ToJson(const NodeCreationInfo &node_info, const ShardRequestManagerInterface &request_manager);
nlohmann::json ToJson(const EdgeCreationInfo &edge_info, const msgs::ShardRequestManagerInterface &request_manager); nlohmann::json ToJson(const EdgeCreationInfo &edge_info, const ShardRequestManagerInterface &request_manager);
nlohmann::json ToJson(const Aggregate::Element &elem); nlohmann::json ToJson(const Aggregate::Element &elem);
@ -161,8 +161,7 @@ nlohmann::json ToJson(const std::vector<T> &items, Args &&...args) {
class PlanToJsonVisitor : public virtual HierarchicalLogicalOperatorVisitor { class PlanToJsonVisitor : public virtual HierarchicalLogicalOperatorVisitor {
public: public:
explicit PlanToJsonVisitor(const msgs::ShardRequestManagerInterface *request_manager) explicit PlanToJsonVisitor(const ShardRequestManagerInterface *request_manager) : request_manager_(request_manager) {}
: request_manager_(request_manager) {}
using HierarchicalLogicalOperatorVisitor::PostVisit; using HierarchicalLogicalOperatorVisitor::PostVisit;
using HierarchicalLogicalOperatorVisitor::PreVisit; using HierarchicalLogicalOperatorVisitor::PreVisit;
@ -218,7 +217,7 @@ class PlanToJsonVisitor : public virtual HierarchicalLogicalOperatorVisitor {
protected: protected:
nlohmann::json output_; nlohmann::json output_;
const msgs::ShardRequestManagerInterface *request_manager_; const ShardRequestManagerInterface *request_manager_;
nlohmann::json PopOutput() { nlohmann::json PopOutput() {
nlohmann::json tmp; nlohmann::json tmp;

View File

@ -57,7 +57,7 @@ class VertexCountCache {
bool LabelPropertyIndexExists(storage::v3::LabelId /*label*/, storage::v3::PropertyId /*property*/) { return false; } bool LabelPropertyIndexExists(storage::v3::LabelId /*label*/, storage::v3::PropertyId /*property*/) { return false; }
msgs::ShardRequestManagerInterface *shard_request_manager_; ShardRequestManagerInterface *shard_request_manager_;
}; };
template <class TDbAccessor> template <class TDbAccessor>

View File

@ -24,6 +24,7 @@
#include "coordinator/hybrid_logical_clock.hpp" #include "coordinator/hybrid_logical_clock.hpp"
#include "storage/v3/id_types.hpp" #include "storage/v3/id_types.hpp"
#include "storage/v3/property_value.hpp" #include "storage/v3/property_value.hpp"
#include "storage/v3/result.hpp"
namespace memgraph::msgs { namespace memgraph::msgs {
@ -317,6 +318,11 @@ struct Value {
} }
}; };
struct ShardError {
common::ErrorCode code;
std::string message;
};
struct Expression { struct Expression {
std::string expression; std::string expression;
}; };
@ -361,7 +367,7 @@ struct ScanResultRow {
}; };
struct ScanVerticesResponse { struct ScanVerticesResponse {
bool success; std::optional<ShardError> error;
std::optional<VertexId> next_start_id; std::optional<VertexId> next_start_id;
std::vector<ScanResultRow> results; std::vector<ScanResultRow> results;
}; };
@ -381,7 +387,7 @@ struct GetPropertiesRequest {
}; };
struct GetPropertiesResponse { struct GetPropertiesResponse {
bool success; std::optional<ShardError> error;
}; };
enum class EdgeDirection : uint8_t { OUT = 1, IN = 2, BOTH = 3 }; enum class EdgeDirection : uint8_t { OUT = 1, IN = 2, BOTH = 3 };
@ -448,7 +454,7 @@ struct ExpandOneResultRow {
}; };
struct ExpandOneResponse { struct ExpandOneResponse {
bool success; std::optional<ShardError> error;
std::vector<ExpandOneResultRow> result; std::vector<ExpandOneResultRow> result;
}; };
@ -484,7 +490,7 @@ struct CreateVerticesRequest {
}; };
struct CreateVerticesResponse { struct CreateVerticesResponse {
bool success; std::optional<ShardError> error;
}; };
struct DeleteVerticesRequest { struct DeleteVerticesRequest {
@ -495,7 +501,7 @@ struct DeleteVerticesRequest {
}; };
struct DeleteVerticesResponse { struct DeleteVerticesResponse {
bool success; std::optional<ShardError> error;
}; };
struct UpdateVerticesRequest { struct UpdateVerticesRequest {
@ -504,7 +510,7 @@ struct UpdateVerticesRequest {
}; };
struct UpdateVerticesResponse { struct UpdateVerticesResponse {
bool success; std::optional<ShardError> error;
}; };
/* /*
@ -526,7 +532,7 @@ struct CreateExpandRequest {
}; };
struct CreateExpandResponse { struct CreateExpandResponse {
bool success; std::optional<ShardError> error;
}; };
struct DeleteEdgesRequest { struct DeleteEdgesRequest {
@ -535,7 +541,7 @@ struct DeleteEdgesRequest {
}; };
struct DeleteEdgesResponse { struct DeleteEdgesResponse {
bool success; std::optional<ShardError> error;
}; };
struct UpdateEdgesRequest { struct UpdateEdgesRequest {
@ -544,7 +550,7 @@ struct UpdateEdgesRequest {
}; };
struct UpdateEdgesResponse { struct UpdateEdgesResponse {
bool success; std::optional<ShardError> error;
}; };
struct CommitRequest { struct CommitRequest {
@ -553,7 +559,7 @@ struct CommitRequest {
}; };
struct CommitResponse { struct CommitResponse {
bool success; std::optional<ShardError> error;
}; };
using ReadRequests = std::variant<ExpandOneRequest, GetPropertiesRequest, ScanVerticesRequest>; using ReadRequests = std::variant<ExpandOneRequest, GetPropertiesRequest, ScanVerticesRequest>;

View File

@ -42,13 +42,12 @@
#include "storage/v3/value_conversions.hpp" #include "storage/v3/value_conversions.hpp"
#include "utils/result.hpp" #include "utils/result.hpp"
namespace memgraph::msgs { namespace memgraph::query::v2 {
template <typename TStorageClient> template <typename TStorageClient>
class RsmStorageClientManager { class RsmStorageClientManager {
public: public:
using CompoundKey = memgraph::io::rsm::ShardRsmKey; using CompoundKey = io::rsm::ShardRsmKey;
using Shard = memgraph::coordinator::Shard; using Shard = coordinator::Shard;
using LabelId = memgraph::storage::v3::LabelId;
RsmStorageClientManager() = default; RsmStorageClientManager() = default;
RsmStorageClientManager(const RsmStorageClientManager &) = delete; RsmStorageClientManager(const RsmStorageClientManager &) = delete;
RsmStorageClientManager(RsmStorageClientManager &&) = delete; RsmStorageClientManager(RsmStorageClientManager &&) = delete;
@ -74,8 +73,8 @@ class RsmStorageClientManager {
template <typename TRequest> template <typename TRequest>
struct ExecutionState { struct ExecutionState {
using CompoundKey = memgraph::io::rsm::ShardRsmKey; using CompoundKey = io::rsm::ShardRsmKey;
using Shard = memgraph::coordinator::Shard; using Shard = coordinator::Shard;
enum State : int8_t { INITIALIZING, EXECUTING, COMPLETED }; enum State : int8_t { INITIALIZING, EXECUTING, COMPLETED };
// label is optional because some operators can create/remove etc, vertices. These kind of requests contain the label // label is optional because some operators can create/remove etc, vertices. These kind of requests contain the label
@ -85,7 +84,7 @@ struct ExecutionState {
// of a shard. One example is ScanAll, where we only require the field label. // of a shard. One example is ScanAll, where we only require the field label.
std::optional<CompoundKey> key; std::optional<CompoundKey> key;
// Transaction id to be filled by the ShardRequestManager implementation // Transaction id to be filled by the ShardRequestManager implementation
memgraph::coordinator::Hlc transaction_id; coordinator::Hlc transaction_id;
// Initialized by ShardRequestManager implementation. This vector is filled with the shards that // Initialized by ShardRequestManager implementation. This vector is filled with the shards that
// the ShardRequestManager impl will send requests to. When a request to a shard exhausts it, meaning that // the ShardRequestManager impl will send requests to. When a request to a shard exhausts it, meaning that
// it pulled all the requested data from the given Shard, it will be removed from the Vector. When the Vector becomes // it pulled all the requested data from the given Shard, it will be removed from the Vector. When the Vector becomes
@ -104,7 +103,7 @@ struct ExecutionState {
class ShardRequestManagerInterface { class ShardRequestManagerInterface {
public: public:
using VertexAccessor = memgraph::query::v2::accessors::VertexAccessor; using VertexAccessor = query::v2::accessors::VertexAccessor;
ShardRequestManagerInterface() = default; ShardRequestManagerInterface() = default;
ShardRequestManagerInterface(const ShardRequestManagerInterface &) = delete; ShardRequestManagerInterface(const ShardRequestManagerInterface &) = delete;
ShardRequestManagerInterface(ShardRequestManagerInterface &&) = delete; ShardRequestManagerInterface(ShardRequestManagerInterface &&) = delete;
@ -115,13 +114,13 @@ class ShardRequestManagerInterface {
virtual void StartTransaction() = 0; virtual void StartTransaction() = 0;
virtual void Commit() = 0; virtual void Commit() = 0;
virtual std::vector<VertexAccessor> Request(ExecutionState<ScanVerticesRequest> &state) = 0; virtual std::vector<VertexAccessor> Request(ExecutionState<msgs::ScanVerticesRequest> &state) = 0;
virtual std::vector<CreateVerticesResponse> Request(ExecutionState<CreateVerticesRequest> &state, virtual std::vector<msgs::CreateVerticesResponse> Request(ExecutionState<msgs::CreateVerticesRequest> &state,
std::vector<NewVertex> new_vertices) = 0; std::vector<msgs::NewVertex> new_vertices) = 0;
virtual std::vector<ExpandOneResultRow> Request(ExecutionState<ExpandOneRequest> &state, virtual std::vector<msgs::ExpandOneResultRow> Request(ExecutionState<msgs::ExpandOneRequest> &state,
ExpandOneRequest request) = 0; msgs::ExpandOneRequest request) = 0;
virtual std::vector<CreateExpandResponse> Request(ExecutionState<CreateExpandRequest> &state, virtual std::vector<msgs::CreateExpandResponse> Request(ExecutionState<msgs::CreateExpandRequest> &state,
std::vector<NewExpand> new_edges) = 0; std::vector<msgs::NewExpand> new_edges) = 0;
virtual storage::v3::EdgeTypeId NameToEdgeType(const std::string &name) const = 0; virtual storage::v3::EdgeTypeId NameToEdgeType(const std::string &name) const = 0;
virtual storage::v3::PropertyId NameToProperty(const std::string &name) const = 0; virtual storage::v3::PropertyId NameToProperty(const std::string &name) const = 0;
@ -129,24 +128,27 @@ class ShardRequestManagerInterface {
virtual const std::string &PropertyToName(memgraph::storage::v3::PropertyId prop) const = 0; virtual const std::string &PropertyToName(memgraph::storage::v3::PropertyId prop) const = 0;
virtual const std::string &LabelToName(memgraph::storage::v3::LabelId label) const = 0; virtual const std::string &LabelToName(memgraph::storage::v3::LabelId label) const = 0;
virtual const std::string &EdgeTypeToName(memgraph::storage::v3::EdgeTypeId type) const = 0; virtual const std::string &EdgeTypeToName(memgraph::storage::v3::EdgeTypeId type) const = 0;
virtual bool IsPrimaryLabel(LabelId label) const = 0; virtual std::optional<storage::v3::PropertyId> MaybeNameToProperty(const std::string &name) const = 0;
virtual bool IsPrimaryKey(LabelId primary_label, PropertyId property) const = 0; virtual std::optional<storage::v3::EdgeTypeId> MaybeNameToEdgeType(const std::string &name) const = 0;
virtual std::optional<storage::v3::LabelId> MaybeNameToLabel(const std::string &name) const = 0;
virtual bool IsPrimaryLabel(storage::v3::LabelId label) const = 0;
virtual bool IsPrimaryKey(storage::v3::LabelId primary_label, storage::v3::PropertyId property) const = 0;
}; };
// TODO(kostasrim)rename this class template // TODO(kostasrim)rename this class template
template <typename TTransport> template <typename TTransport>
class ShardRequestManager : public ShardRequestManagerInterface { class ShardRequestManager : public ShardRequestManagerInterface {
public: public:
using StorageClient = using StorageClient = coordinator::RsmClient<TTransport, msgs::WriteRequests, msgs::WriteResponses,
memgraph::coordinator::RsmClient<TTransport, WriteRequests, WriteResponses, ReadRequests, ReadResponses>; msgs::ReadRequests, msgs::ReadResponses>;
using CoordinatorWriteRequests = memgraph::coordinator::CoordinatorWriteRequests; using CoordinatorWriteRequests = coordinator::CoordinatorWriteRequests;
using CoordinatorClient = memgraph::coordinator::CoordinatorClient<TTransport>; using CoordinatorClient = coordinator::CoordinatorClient<TTransport>;
using Address = memgraph::io::Address; using Address = io::Address;
using Shard = memgraph::coordinator::Shard; using Shard = coordinator::Shard;
using ShardMap = memgraph::coordinator::ShardMap; using ShardMap = coordinator::ShardMap;
using CompoundKey = memgraph::coordinator::PrimaryKey; using CompoundKey = coordinator::PrimaryKey;
using VertexAccessor = memgraph::query::v2::accessors::VertexAccessor; using VertexAccessor = query::v2::accessors::VertexAccessor;
ShardRequestManager(CoordinatorClient coord, memgraph::io::Io<TTransport> &&io) ShardRequestManager(CoordinatorClient coord, io::Io<TTransport> &&io)
: coord_cli_(std::move(coord)), io_(std::move(io)) {} : coord_cli_(std::move(coord)), io_(std::move(io)) {}
ShardRequestManager(const ShardRequestManager &) = delete; ShardRequestManager(const ShardRequestManager &) = delete;
@ -157,14 +159,14 @@ class ShardRequestManager : public ShardRequestManagerInterface {
~ShardRequestManager() override {} ~ShardRequestManager() override {}
void StartTransaction() override { void StartTransaction() override {
memgraph::coordinator::HlcRequest req{.last_shard_map_version = shards_map_.GetHlc()}; coordinator::HlcRequest req{.last_shard_map_version = shards_map_.GetHlc()};
CoordinatorWriteRequests write_req = req; CoordinatorWriteRequests write_req = req;
auto write_res = coord_cli_.SendWriteRequest(write_req); auto write_res = coord_cli_.SendWriteRequest(write_req);
if (write_res.HasError()) { if (write_res.HasError()) {
throw std::runtime_error("HLC request failed"); throw std::runtime_error("HLC request failed");
} }
auto coordinator_write_response = write_res.GetValue(); auto coordinator_write_response = write_res.GetValue();
auto hlc_response = std::get<memgraph::coordinator::HlcResponse>(coordinator_write_response); auto hlc_response = std::get<coordinator::HlcResponse>(coordinator_write_response);
// Transaction ID to be used later... // Transaction ID to be used later...
transaction_id_ = hlc_response.new_hlc; transaction_id_ = hlc_response.new_hlc;
@ -176,14 +178,14 @@ class ShardRequestManager : public ShardRequestManagerInterface {
} }
void Commit() override { void Commit() override {
memgraph::coordinator::HlcRequest req{.last_shard_map_version = shards_map_.GetHlc()}; coordinator::HlcRequest req{.last_shard_map_version = shards_map_.GetHlc()};
CoordinatorWriteRequests write_req = req; CoordinatorWriteRequests write_req = req;
auto write_res = coord_cli_.SendWriteRequest(write_req); auto write_res = coord_cli_.SendWriteRequest(write_req);
if (write_res.HasError()) { if (write_res.HasError()) {
throw std::runtime_error("HLC request for commit failed"); throw std::runtime_error("HLC request for commit failed");
} }
auto coordinator_write_response = write_res.GetValue(); auto coordinator_write_response = write_res.GetValue();
auto hlc_response = std::get<memgraph::coordinator::HlcResponse>(coordinator_write_response); auto hlc_response = std::get<coordinator::HlcResponse>(coordinator_write_response);
if (hlc_response.fresher_shard_map) { if (hlc_response.fresher_shard_map) {
shards_map_ = hlc_response.fresher_shard_map.value(); shards_map_ = hlc_response.fresher_shard_map.value();
@ -204,9 +206,9 @@ class ShardRequestManager : public ShardRequestManagerInterface {
if (commit_response.HasError()) { if (commit_response.HasError()) {
throw std::runtime_error("Commit request timed out"); throw std::runtime_error("Commit request timed out");
} }
WriteResponses write_response_variant = commit_response.GetValue(); msgs::WriteResponses write_response_variant = commit_response.GetValue();
auto &response = std::get<CommitResponse>(write_response_variant); auto &response = std::get<msgs::CommitResponse>(write_response_variant);
if (!response.success) { if (response.error) {
throw std::runtime_error("Commit request did not succeed"); throw std::runtime_error("Commit request did not succeed");
} }
} }
@ -225,17 +227,15 @@ class ShardRequestManager : public ShardRequestManagerInterface {
return shards_map_.GetLabelId(name).value(); return shards_map_.GetLabelId(name).value();
} }
const std::string &PropertyToName(memgraph::storage::v3::PropertyId id) const override { const std::string &PropertyToName(storage::v3::PropertyId id) const override {
return properties_.IdToName(id.AsUint()); return properties_.IdToName(id.AsUint());
} }
const std::string &LabelToName(memgraph::storage::v3::LabelId id) const override { const std::string &LabelToName(storage::v3::LabelId id) const override { return labels_.IdToName(id.AsUint()); }
return labels_.IdToName(id.AsUint()); const std::string &EdgeTypeToName(storage::v3::EdgeTypeId id) const override {
}
const std::string &EdgeTypeToName(memgraph::storage::v3::EdgeTypeId id) const override {
return edge_types_.IdToName(id.AsUint()); return edge_types_.IdToName(id.AsUint());
} }
bool IsPrimaryKey(LabelId primary_label, PropertyId property) const override { bool IsPrimaryKey(storage::v3::LabelId primary_label, storage::v3::PropertyId property) const override {
const auto schema_it = shards_map_.schemas.find(primary_label); const auto schema_it = shards_map_.schemas.find(primary_label);
MG_ASSERT(schema_it != shards_map_.schemas.end(), "Invalid primary label id: {}", primary_label.AsUint()); MG_ASSERT(schema_it != shards_map_.schemas.end(), "Invalid primary label id: {}", primary_label.AsUint());
@ -244,12 +244,12 @@ class ShardRequestManager : public ShardRequestManagerInterface {
}) != schema_it->second.end(); }) != schema_it->second.end();
} }
bool IsPrimaryLabel(LabelId label) const override { return shards_map_.label_spaces.contains(label); } bool IsPrimaryLabel(storage::v3::LabelId label) const override { return shards_map_.label_spaces.contains(label); }
// TODO(kostasrim) Simplify return result // TODO(kostasrim) Simplify return result
std::vector<VertexAccessor> Request(ExecutionState<ScanVerticesRequest> &state) override { std::vector<VertexAccessor> Request(ExecutionState<msgs::ScanVerticesRequest> &state) override {
MaybeInitializeExecutionState(state); MaybeInitializeExecutionState(state);
std::vector<ScanVerticesResponse> responses; std::vector<msgs::ScanVerticesResponse> responses;
SendAllRequests(state); SendAllRequests(state);
auto all_requests_gathered = [](auto &paginated_rsp_tracker) { auto all_requests_gathered = [](auto &paginated_rsp_tracker) {
@ -273,11 +273,11 @@ class ShardRequestManager : public ShardRequestManagerInterface {
return PostProcess(std::move(responses)); return PostProcess(std::move(responses));
} }
std::vector<CreateVerticesResponse> Request(ExecutionState<CreateVerticesRequest> &state, std::vector<msgs::CreateVerticesResponse> Request(ExecutionState<msgs::CreateVerticesRequest> &state,
std::vector<NewVertex> new_vertices) override { std::vector<msgs::NewVertex> new_vertices) override {
MG_ASSERT(!new_vertices.empty()); MG_ASSERT(!new_vertices.empty());
MaybeInitializeExecutionState(state, new_vertices); MaybeInitializeExecutionState(state, new_vertices);
std::vector<CreateVerticesResponse> responses; std::vector<msgs::CreateVerticesResponse> responses;
auto &shard_cache_ref = state.shard_cache; auto &shard_cache_ref = state.shard_cache;
// 1. Send the requests. // 1. Send the requests.
@ -294,24 +294,24 @@ class ShardRequestManager : public ShardRequestManagerInterface {
return responses; return responses;
} }
std::vector<CreateExpandResponse> Request(ExecutionState<CreateExpandRequest> &state, std::vector<msgs::CreateExpandResponse> Request(ExecutionState<msgs::CreateExpandRequest> &state,
std::vector<NewExpand> new_edges) override { std::vector<msgs::NewExpand> new_edges) override {
MG_ASSERT(!new_edges.empty()); MG_ASSERT(!new_edges.empty());
MaybeInitializeExecutionState(state, new_edges); MaybeInitializeExecutionState(state, new_edges);
std::vector<CreateExpandResponse> responses; std::vector<msgs::CreateExpandResponse> responses;
auto &shard_cache_ref = state.shard_cache; auto &shard_cache_ref = state.shard_cache;
size_t id{0}; size_t id{0};
for (auto shard_it = shard_cache_ref.begin(); shard_it != shard_cache_ref.end(); ++id) { for (auto shard_it = shard_cache_ref.begin(); shard_it != shard_cache_ref.end(); ++id) {
auto &storage_client = GetStorageClientForShard(*shard_it); auto &storage_client = GetStorageClientForShard(*shard_it);
WriteRequests req = state.requests[id]; msgs::WriteRequests req = state.requests[id];
auto write_response_result = storage_client.SendWriteRequest(std::move(req)); auto write_response_result = storage_client.SendWriteRequest(std::move(req));
if (write_response_result.HasError()) { if (write_response_result.HasError()) {
throw std::runtime_error("CreateVertices request timedout"); throw std::runtime_error("CreateVertices request timedout");
} }
WriteResponses response_variant = write_response_result.GetValue(); msgs::WriteResponses response_variant = write_response_result.GetValue();
CreateExpandResponse mapped_response = std::get<CreateExpandResponse>(response_variant); msgs::CreateExpandResponse mapped_response = std::get<msgs::CreateExpandResponse>(response_variant);
if (!mapped_response.success) { if (mapped_response.error) {
throw std::runtime_error("CreateExpand request did not succeed"); throw std::runtime_error("CreateExpand request did not succeed");
} }
responses.push_back(mapped_response); responses.push_back(mapped_response);
@ -322,14 +322,15 @@ class ShardRequestManager : public ShardRequestManagerInterface {
return responses; return responses;
} }
std::vector<ExpandOneResultRow> Request(ExecutionState<ExpandOneRequest> &state, ExpandOneRequest request) override { std::vector<msgs::ExpandOneResultRow> Request(ExecutionState<msgs::ExpandOneRequest> &state,
msgs::ExpandOneRequest request) override {
// TODO(kostasrim)Update to limit the batch size here // TODO(kostasrim)Update to limit the batch size here
// Expansions of the destination must be handled by the caller. For example // Expansions of the destination must be handled by the caller. For example
// match (u:L1 { prop : 1 })-[:Friend]-(v:L1) // match (u:L1 { prop : 1 })-[:Friend]-(v:L1)
// For each vertex U, the ExpandOne will result in <U, Edges>. The destination vertex and its properties // For each vertex U, the ExpandOne will result in <U, Edges>. The destination vertex and its properties
// must be fetched again with an ExpandOne(Edges.dst) // must be fetched again with an ExpandOne(Edges.dst)
MaybeInitializeExecutionState(state, std::move(request)); MaybeInitializeExecutionState(state, std::move(request));
std::vector<ExpandOneResponse> responses; std::vector<msgs::ExpandOneResponse> responses;
auto &shard_cache_ref = state.shard_cache; auto &shard_cache_ref = state.shard_cache;
// 1. Send the requests. // 1. Send the requests.
@ -339,10 +340,11 @@ class ShardRequestManager : public ShardRequestManagerInterface {
do { do {
AwaitOnResponses(state, responses); AwaitOnResponses(state, responses);
} while (!state.shard_cache.empty()); } while (!state.shard_cache.empty());
std::vector<ExpandOneResultRow> result_rows; std::vector<msgs::ExpandOneResultRow> result_rows;
const auto total_row_count = std::accumulate( const auto total_row_count = std::accumulate(responses.begin(), responses.end(), 0,
responses.begin(), responses.end(), 0, [](const int64_t partial_count, const msgs::ExpandOneResponse &resp) {
[](const int64_t partial_count, const ExpandOneResponse &resp) { return partial_count + resp.result.size(); }); return partial_count + resp.result.size();
});
result_rows.reserve(total_row_count); result_rows.reserve(total_row_count);
for (auto &response : responses) { for (auto &response : responses) {
@ -353,10 +355,22 @@ class ShardRequestManager : public ShardRequestManagerInterface {
return result_rows; return result_rows;
} }
std::optional<storage::v3::PropertyId> MaybeNameToProperty(const std::string &name) const override {
return shards_map_.GetPropertyId(name);
}
std::optional<storage::v3::EdgeTypeId> MaybeNameToEdgeType(const std::string &name) const override {
return shards_map_.GetEdgeTypeId(name);
}
std::optional<storage::v3::LabelId> MaybeNameToLabel(const std::string &name) const override {
return shards_map_.GetLabelId(name);
}
private: private:
enum class PaginatedResponseState { Pending, PartiallyFinished }; enum class PaginatedResponseState { Pending, PartiallyFinished };
std::vector<VertexAccessor> PostProcess(std::vector<ScanVerticesResponse> &&responses) const { std::vector<VertexAccessor> PostProcess(std::vector<msgs::ScanVerticesResponse> &&responses) const {
std::vector<VertexAccessor> accessors; std::vector<VertexAccessor> accessors;
for (auto &response : responses) { for (auto &response : responses) {
for (auto &result_row : response.results) { for (auto &result_row : response.results) {
@ -385,22 +399,22 @@ class ShardRequestManager : public ShardRequestManagerInterface {
return state.state != ExecutionState::INITIALIZING; return state.state != ExecutionState::INITIALIZING;
} }
void MaybeInitializeExecutionState(ExecutionState<CreateVerticesRequest> &state, void MaybeInitializeExecutionState(ExecutionState<msgs::CreateVerticesRequest> &state,
std::vector<NewVertex> new_vertices) { std::vector<msgs::NewVertex> new_vertices) {
ThrowIfStateCompleted(state); ThrowIfStateCompleted(state);
if (ShallNotInitializeState(state)) { if (ShallNotInitializeState(state)) {
return; return;
} }
state.transaction_id = transaction_id_; state.transaction_id = transaction_id_;
std::map<Shard, CreateVerticesRequest> per_shard_request_table; std::map<Shard, msgs::CreateVerticesRequest> per_shard_request_table;
for (auto &new_vertex : new_vertices) { for (auto &new_vertex : new_vertices) {
MG_ASSERT(!new_vertex.label_ids.empty(), "This is error!"); MG_ASSERT(!new_vertex.label_ids.empty(), "This is error!");
auto shard = shards_map_.GetShardForKey(new_vertex.label_ids[0].id, auto shard = shards_map_.GetShardForKey(new_vertex.label_ids[0].id,
storage::conversions::ConvertPropertyVector(new_vertex.primary_key)); storage::conversions::ConvertPropertyVector(new_vertex.primary_key));
if (!per_shard_request_table.contains(shard)) { if (!per_shard_request_table.contains(shard)) {
CreateVerticesRequest create_v_rqst{.transaction_id = transaction_id_}; msgs::CreateVerticesRequest create_v_rqst{.transaction_id = transaction_id_};
per_shard_request_table.insert(std::pair(shard, std::move(create_v_rqst))); per_shard_request_table.insert(std::pair(shard, std::move(create_v_rqst)));
state.shard_cache.push_back(shard); state.shard_cache.push_back(shard);
} }
@ -410,21 +424,22 @@ class ShardRequestManager : public ShardRequestManagerInterface {
for (auto &[shard, rqst] : per_shard_request_table) { for (auto &[shard, rqst] : per_shard_request_table) {
state.requests.push_back(std::move(rqst)); state.requests.push_back(std::move(rqst));
} }
state.state = ExecutionState<CreateVerticesRequest>::EXECUTING; state.state = ExecutionState<msgs::CreateVerticesRequest>::EXECUTING;
} }
void MaybeInitializeExecutionState(ExecutionState<CreateExpandRequest> &state, std::vector<NewExpand> new_expands) { void MaybeInitializeExecutionState(ExecutionState<msgs::CreateExpandRequest> &state,
std::vector<msgs::NewExpand> new_expands) {
ThrowIfStateCompleted(state); ThrowIfStateCompleted(state);
if (ShallNotInitializeState(state)) { if (ShallNotInitializeState(state)) {
return; return;
} }
state.transaction_id = transaction_id_; state.transaction_id = transaction_id_;
std::map<Shard, CreateExpandRequest> per_shard_request_table; std::map<Shard, msgs::CreateExpandRequest> per_shard_request_table;
auto ensure_shard_exists_in_table = [&per_shard_request_table, auto ensure_shard_exists_in_table = [&per_shard_request_table,
transaction_id = transaction_id_](const Shard &shard) { transaction_id = transaction_id_](const Shard &shard) {
if (!per_shard_request_table.contains(shard)) { if (!per_shard_request_table.contains(shard)) {
CreateExpandRequest create_expand_request{.transaction_id = transaction_id}; msgs::CreateExpandRequest create_expand_request{.transaction_id = transaction_id};
per_shard_request_table.insert({shard, std::move(create_expand_request)}); per_shard_request_table.insert({shard, std::move(create_expand_request)});
} }
}; };
@ -448,10 +463,10 @@ class ShardRequestManager : public ShardRequestManagerInterface {
state.shard_cache.push_back(shard); state.shard_cache.push_back(shard);
state.requests.push_back(std::move(request)); state.requests.push_back(std::move(request));
} }
state.state = ExecutionState<CreateExpandRequest>::EXECUTING; state.state = ExecutionState<msgs::CreateExpandRequest>::EXECUTING;
} }
void MaybeInitializeExecutionState(ExecutionState<ScanVerticesRequest> &state) { void MaybeInitializeExecutionState(ExecutionState<msgs::ScanVerticesRequest> &state) {
ThrowIfStateCompleted(state); ThrowIfStateCompleted(state);
if (ShallNotInitializeState(state)) { if (ShallNotInitializeState(state)) {
return; return;
@ -471,23 +486,23 @@ class ShardRequestManager : public ShardRequestManagerInterface {
for (auto &[key, shard] : shards) { for (auto &[key, shard] : shards) {
MG_ASSERT(!shard.empty()); MG_ASSERT(!shard.empty());
state.shard_cache.push_back(std::move(shard)); state.shard_cache.push_back(std::move(shard));
ScanVerticesRequest rqst; msgs::ScanVerticesRequest rqst;
rqst.transaction_id = transaction_id_; rqst.transaction_id = transaction_id_;
rqst.start_id.second = storage::conversions::ConvertValueVector(key); rqst.start_id.second = storage::conversions::ConvertValueVector(key);
state.requests.push_back(std::move(rqst)); state.requests.push_back(std::move(rqst));
} }
} }
state.state = ExecutionState<ScanVerticesRequest>::EXECUTING; state.state = ExecutionState<msgs::ScanVerticesRequest>::EXECUTING;
} }
void MaybeInitializeExecutionState(ExecutionState<ExpandOneRequest> &state, ExpandOneRequest request) { void MaybeInitializeExecutionState(ExecutionState<msgs::ExpandOneRequest> &state, msgs::ExpandOneRequest request) {
ThrowIfStateCompleted(state); ThrowIfStateCompleted(state);
if (ShallNotInitializeState(state)) { if (ShallNotInitializeState(state)) {
return; return;
} }
state.transaction_id = transaction_id_; state.transaction_id = transaction_id_;
std::map<Shard, ExpandOneRequest> per_shard_request_table; std::map<Shard, msgs::ExpandOneRequest> per_shard_request_table;
auto top_level_rqst_template = request; auto top_level_rqst_template = request;
top_level_rqst_template.transaction_id = transaction_id_; top_level_rqst_template.transaction_id = transaction_id_;
top_level_rqst_template.src_vertices.clear(); top_level_rqst_template.src_vertices.clear();
@ -505,7 +520,7 @@ class ShardRequestManager : public ShardRequestManagerInterface {
for (auto &[shard, rqst] : per_shard_request_table) { for (auto &[shard, rqst] : per_shard_request_table) {
state.requests.push_back(std::move(rqst)); state.requests.push_back(std::move(rqst));
} }
state.state = ExecutionState<ExpandOneRequest>::EXECUTING; state.state = ExecutionState<msgs::ExpandOneRequest>::EXECUTING;
} }
StorageClient &GetStorageClientForShard(Shard shard) { StorageClient &GetStorageClientForShard(Shard shard) {
@ -532,20 +547,20 @@ class ShardRequestManager : public ShardRequestManagerInterface {
storage_cli_manager_.AddClient(target_shard, std::move(cli)); storage_cli_manager_.AddClient(target_shard, std::move(cli));
} }
void SendAllRequests(ExecutionState<ScanVerticesRequest> &state) { void SendAllRequests(ExecutionState<msgs::ScanVerticesRequest> &state) {
int64_t shard_idx = 0; int64_t shard_idx = 0;
for (const auto &request : state.requests) { for (const auto &request : state.requests) {
const auto &current_shard = state.shard_cache[shard_idx]; const auto &current_shard = state.shard_cache[shard_idx];
auto &storage_client = GetStorageClientForShard(current_shard); auto &storage_client = GetStorageClientForShard(current_shard);
ReadRequests req = request; msgs::ReadRequests req = request;
storage_client.SendAsyncReadRequest(request); storage_client.SendAsyncReadRequest(request);
++shard_idx; ++shard_idx;
} }
} }
void SendAllRequests(ExecutionState<CreateVerticesRequest> &state, void SendAllRequests(ExecutionState<msgs::CreateVerticesRequest> &state,
std::vector<memgraph::coordinator::Shard> &shard_cache_ref) { std::vector<memgraph::coordinator::Shard> &shard_cache_ref) {
size_t id = 0; size_t id = 0;
for (auto shard_it = shard_cache_ref.begin(); shard_it != shard_cache_ref.end(); ++shard_it) { for (auto shard_it = shard_cache_ref.begin(); shard_it != shard_cache_ref.end(); ++shard_it) {
@ -559,24 +574,25 @@ class ShardRequestManager : public ShardRequestManagerInterface {
auto &storage_client = GetStorageClientForShard(*shard_it); auto &storage_client = GetStorageClientForShard(*shard_it);
WriteRequests req = req_deep_copy; msgs::WriteRequests req = req_deep_copy;
storage_client.SendAsyncWriteRequest(req); storage_client.SendAsyncWriteRequest(req);
++id; ++id;
} }
} }
void SendAllRequests(ExecutionState<ExpandOneRequest> &state, void SendAllRequests(ExecutionState<msgs::ExpandOneRequest> &state,
std::vector<memgraph::coordinator::Shard> &shard_cache_ref) { std::vector<memgraph::coordinator::Shard> &shard_cache_ref) {
size_t id = 0; size_t id = 0;
for (auto shard_it = shard_cache_ref.begin(); shard_it != shard_cache_ref.end(); ++shard_it) { for (auto shard_it = shard_cache_ref.begin(); shard_it != shard_cache_ref.end(); ++shard_it) {
auto &storage_client = GetStorageClientForShard(*shard_it); auto &storage_client = GetStorageClientForShard(*shard_it);
ReadRequests req = state.requests[id]; msgs::ReadRequests req = state.requests[id];
storage_client.SendAsyncReadRequest(req); storage_client.SendAsyncReadRequest(req);
++id; ++id;
} }
} }
void AwaitOnResponses(ExecutionState<CreateVerticesRequest> &state, std::vector<CreateVerticesResponse> &responses) { void AwaitOnResponses(ExecutionState<msgs::CreateVerticesRequest> &state,
std::vector<msgs::CreateVerticesResponse> &responses) {
auto &shard_cache_ref = state.shard_cache; auto &shard_cache_ref = state.shard_cache;
int64_t request_idx = 0; int64_t request_idx = 0;
@ -598,10 +614,10 @@ class ShardRequestManager : public ShardRequestManagerInterface {
throw std::runtime_error("CreateVertices request timed out"); throw std::runtime_error("CreateVertices request timed out");
} }
WriteResponses response_variant = poll_result->GetValue(); msgs::WriteResponses response_variant = poll_result->GetValue();
auto response = std::get<CreateVerticesResponse>(response_variant); auto response = std::get<msgs::CreateVerticesResponse>(response_variant);
if (!response.success) { if (response.error) {
throw std::runtime_error("CreateVertices request did not succeed"); throw std::runtime_error("CreateVertices request did not succeed");
} }
responses.push_back(response); responses.push_back(response);
@ -613,7 +629,8 @@ class ShardRequestManager : public ShardRequestManagerInterface {
} }
} }
void AwaitOnResponses(ExecutionState<ExpandOneRequest> &state, std::vector<ExpandOneResponse> &responses) { void AwaitOnResponses(ExecutionState<msgs::ExpandOneRequest> &state,
std::vector<msgs::ExpandOneResponse> &responses) {
auto &shard_cache_ref = state.shard_cache; auto &shard_cache_ref = state.shard_cache;
int64_t request_idx = 0; int64_t request_idx = 0;
@ -631,13 +648,13 @@ class ShardRequestManager : public ShardRequestManagerInterface {
throw std::runtime_error("ExpandOne request timed out"); throw std::runtime_error("ExpandOne request timed out");
} }
ReadResponses response_variant = poll_result->GetValue(); msgs::ReadResponses response_variant = poll_result->GetValue();
auto response = std::get<ExpandOneResponse>(response_variant); auto response = std::get<msgs::ExpandOneResponse>(response_variant);
// -NOTE- // -NOTE-
// Currently a boolean flag for signaling the overall success of the // Currently a boolean flag for signaling the overall success of the
// ExpandOne request does not exist. But it should, so here we assume // ExpandOne request does not exist. But it should, so here we assume
// that it is already in place. // that it is already in place.
if (!response.success) { if (response.error) {
throw std::runtime_error("ExpandOne request did not succeed"); throw std::runtime_error("ExpandOne request did not succeed");
} }
@ -649,8 +666,8 @@ class ShardRequestManager : public ShardRequestManagerInterface {
} }
} }
void AwaitOnPaginatedRequests(ExecutionState<ScanVerticesRequest> &state, void AwaitOnPaginatedRequests(ExecutionState<msgs::ScanVerticesRequest> &state,
std::vector<ScanVerticesResponse> &responses, std::vector<msgs::ScanVerticesResponse> &responses,
std::map<Shard, PaginatedResponseState> &paginated_response_tracker) { std::map<Shard, PaginatedResponseState> &paginated_response_tracker) {
auto &shard_cache_ref = state.shard_cache; auto &shard_cache_ref = state.shard_cache;
@ -678,9 +695,9 @@ class ShardRequestManager : public ShardRequestManagerInterface {
throw std::runtime_error("ScanAll request timed out"); throw std::runtime_error("ScanAll request timed out");
} }
ReadResponses read_response_variant = await_result->GetValue(); msgs::ReadResponses read_response_variant = await_result->GetValue();
auto response = std::get<ScanVerticesResponse>(read_response_variant); auto response = std::get<msgs::ScanVerticesResponse>(read_response_variant);
if (!response.success) { if (response.error) {
throw std::runtime_error("ScanAll request did not succeed"); throw std::runtime_error("ScanAll request did not succeed");
} }
@ -723,8 +740,8 @@ class ShardRequestManager : public ShardRequestManagerInterface {
storage::v3::NameIdMapper labels_; storage::v3::NameIdMapper labels_;
CoordinatorClient coord_cli_; CoordinatorClient coord_cli_;
RsmStorageClientManager<StorageClient> storage_cli_manager_; RsmStorageClientManager<StorageClient> storage_cli_manager_;
memgraph::io::Io<TTransport> io_; io::Io<TTransport> io_;
memgraph::coordinator::Hlc transaction_id_; coordinator::Hlc transaction_id_;
// TODO(kostasrim) Add batch prefetching // TODO(kostasrim) Add batch prefetching
}; };
} // namespace memgraph::msgs } // namespace memgraph::query::v2

View File

@ -97,15 +97,15 @@ bool LastCommittedVersionHasLabelProperty(const Vertex &vertex, LabelId label, c
if (delta->label == label) { if (delta->label == label) {
MG_ASSERT(!has_label, "Invalid database state!"); MG_ASSERT(!has_label, "Invalid database state!");
has_label = true; has_label = true;
break;
} }
break;
} }
case Delta::Action::REMOVE_LABEL: { case Delta::Action::REMOVE_LABEL: {
if (delta->label == label) { if (delta->label == label) {
MG_ASSERT(has_label, "Invalid database state!"); MG_ASSERT(has_label, "Invalid database state!");
has_label = false; has_label = false;
break;
} }
break;
} }
case Delta::Action::ADD_IN_EDGE: case Delta::Action::ADD_IN_EDGE:
case Delta::Action::ADD_OUT_EDGE: case Delta::Action::ADD_OUT_EDGE:

View File

@ -31,4 +31,4 @@ target_link_libraries(mg-storage-v3 Threads::Threads mg-utils gflags)
target_include_directories(mg-storage-v3 PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/bindings) target_include_directories(mg-storage-v3 PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/bindings)
add_dependencies(mg-storage-v3 generate_lcp_storage) add_dependencies(mg-storage-v3 generate_lcp_storage)
target_link_libraries(mg-storage-v3 mg-slk mg-expr mg-io) target_link_libraries(mg-storage-v3 mg-slk mg-expr mg-io mg-functions)

View File

@ -24,6 +24,8 @@
#include "storage/v3/conversions.hpp" #include "storage/v3/conversions.hpp"
#include "storage/v3/path.hpp" #include "storage/v3/path.hpp"
#include "utils/typeinfo.hpp" #include "utils/typeinfo.hpp"
#include "utils/exceptions.hpp"
#include "functions/awesome_memgraph_functions.hpp"
cpp<# cpp<#
@ -178,14 +180,6 @@ cpp<#
(:serialize (:slk :load-args '((storage "storage::v3::AstStorage *"))))) (:serialize (:slk :load-args '((storage "storage::v3::AstStorage *")))))
#>cpp #>cpp
struct FunctionContext {
DbAccessor *db_accessor;
utils::MemoryResource *memory;
int64_t timestamp;
std::unordered_map<std::string, int64_t> *counters;
View view;
};
inline bool operator==(const LabelIx &a, const LabelIx &b) { inline bool operator==(const LabelIx &a, const LabelIx &b) {
return a.ix == b.ix && a.name == b.name; return a.ix == b.ix && a.name == b.name;
} }
@ -845,16 +839,24 @@ cpp<#
:slk-load (slk-load-ast-vector "Expression")) :slk-load (slk-load-ast-vector "Expression"))
(function-name "std::string" :scope :public) (function-name "std::string" :scope :public)
(function "std::function<TypedValue(const TypedValue *, int64_t, (function "std::function<TypedValue(const TypedValue *, int64_t,
const FunctionContext &)>" const functions::FunctionContext<memgraph::storage::v3::DbAccessor> &)>"
:scope :public :scope :public
:dont-save t :dont-save t
:clone :copy :clone :copy
:slk-load (lambda (member) :slk-load (lambda (member)
#>cpp #>cpp
self->${member} = functions::NameToFunction<memgraph::storage::v3::TypedValue,
functions::FunctionContext<memgraph::storage::v3::DbAccessor>,
functions::StorageEngineTag, Conv>(self->function_name_);
cpp<#))) cpp<#)))
(:public (:public
#>cpp #>cpp
Function() = default; Function() = default;
using Conv = decltype(PropertyToTypedValueFunctor<TypedValue>);
class SemanticException : public memgraph::utils::BasicException {
using utils::BasicException::BasicException;
};
DEFVISITABLE(ExpressionVisitor<TypedValue>); DEFVISITABLE(ExpressionVisitor<TypedValue>);
DEFVISITABLE(ExpressionVisitor<void>); DEFVISITABLE(ExpressionVisitor<void>);
@ -872,7 +874,13 @@ cpp<#
Function(const std::string &function_name, Function(const std::string &function_name,
const std::vector<Expression *> &arguments) const std::vector<Expression *> &arguments)
: arguments_(arguments), : arguments_(arguments),
function_name_(function_name) { function_name_(function_name),
function_(functions::NameToFunction<memgraph::storage::v3::TypedValue,
functions::FunctionContext<memgraph::storage::v3::DbAccessor>,
functions::StorageEngineTag, Conv>(function_name_)) {
if (!function_) {
throw SemanticException("Function '{}' doesn't exist.", function_name);
}
} }
cpp<#) cpp<#)
(:private (:private

View File

@ -78,7 +78,7 @@ class DbAccessor final {
return VerticesIterable(accessor_->Vertices(label, property, lower, upper, view)); return VerticesIterable(accessor_->Vertices(label, property, lower, upper, view));
} }
storage::v3::Result<EdgeAccessor> InsertEdge(VertexAccessor *from, VertexAccessor *to, storage::v3::ShardResult<EdgeAccessor> InsertEdge(VertexAccessor *from, VertexAccessor *to,
const storage::v3::EdgeTypeId &edge_type) { const storage::v3::EdgeTypeId &edge_type) {
static constexpr auto kDummyGid = storage::v3::Gid::FromUint(0); static constexpr auto kDummyGid = storage::v3::Gid::FromUint(0);
auto maybe_edge = accessor_->CreateEdge(from->Id(storage::v3::View::NEW).GetValue(), auto maybe_edge = accessor_->CreateEdge(from->Id(storage::v3::View::NEW).GetValue(),
@ -87,8 +87,8 @@ class DbAccessor final {
return EdgeAccessor(*maybe_edge); return EdgeAccessor(*maybe_edge);
} }
storage::v3::Result<std::optional<EdgeAccessor>> RemoveEdge(EdgeAccessor *edge) { storage::v3::ShardResult<std::optional<EdgeAccessor>> RemoveEdge(EdgeAccessor *edge) {
auto res = accessor_->DeleteEdge(edge->FromVertex(), edge->ToVertex(), edge->Gid()); auto res = accessor_->DeleteEdge(edge->From(), edge->To(), edge->Gid());
if (res.HasError()) { if (res.HasError()) {
return res.GetError(); return res.GetError();
} }
@ -101,7 +101,7 @@ class DbAccessor final {
return std::make_optional<EdgeAccessor>(*value); return std::make_optional<EdgeAccessor>(*value);
} }
storage::v3::Result<std::optional<std::pair<VertexAccessor, std::vector<EdgeAccessor>>>> DetachRemoveVertex( storage::v3::ShardResult<std::optional<std::pair<VertexAccessor, std::vector<EdgeAccessor>>>> DetachRemoveVertex(
VertexAccessor *vertex_accessor) { VertexAccessor *vertex_accessor) {
using ReturnType = std::pair<VertexAccessor, std::vector<EdgeAccessor>>; using ReturnType = std::pair<VertexAccessor, std::vector<EdgeAccessor>>;
@ -125,7 +125,7 @@ class DbAccessor final {
return std::make_optional<ReturnType>(vertex, std::move(deleted_edges)); return std::make_optional<ReturnType>(vertex, std::move(deleted_edges));
} }
storage::v3::Result<std::optional<VertexAccessor>> RemoveVertex(VertexAccessor *vertex_accessor) { storage::v3::ShardResult<std::optional<VertexAccessor>> RemoveVertex(VertexAccessor *vertex_accessor) {
auto res = accessor_->DeleteVertex(vertex_accessor); auto res = accessor_->DeleteVertex(vertex_accessor);
if (res.HasError()) { if (res.HasError()) {
return res.GetError(); return res.GetError();

View File

@ -21,6 +21,7 @@
#include "storage/v3/id_types.hpp" #include "storage/v3/id_types.hpp"
#include "storage/v3/property_store.hpp" #include "storage/v3/property_store.hpp"
#include "storage/v3/property_value.hpp" #include "storage/v3/property_value.hpp"
#include "storage/v3/result.hpp"
#include "storage/v3/view.hpp" #include "storage/v3/view.hpp"
#include "utils/memory.hpp" #include "utils/memory.hpp"
@ -87,6 +88,6 @@ struct EvaluationContext {
using ExpressionEvaluator = using ExpressionEvaluator =
memgraph::expr::ExpressionEvaluator<TypedValue, EvaluationContext, DbAccessor, storage::v3::View, memgraph::expr::ExpressionEvaluator<TypedValue, EvaluationContext, DbAccessor, storage::v3::View,
storage::v3::LabelId, storage::v3::PropertyStore, PropertyToTypedValueConverter, storage::v3::LabelId, storage::v3::PropertyStore, PropertyToTypedValueConverter,
memgraph::storage::v3::Error>; common::ErrorCode>;
} // namespace memgraph::storage::v3 } // namespace memgraph::storage::v3

View File

@ -69,6 +69,10 @@ TTypedValue PropertyToTypedValue(const PropertyValue &value) {
LOG_FATAL("Unsupported type"); LOG_FATAL("Unsupported type");
} }
template <typename TypedValueT>
inline const auto PropertyToTypedValueFunctor =
[](const PropertyValue &value) { return PropertyToTypedValue<TypedValueT>(value); };
template <typename TTypedValue> template <typename TTypedValue>
TTypedValue PropertyToTypedValue(const PropertyValue &value, utils::MemoryResource *mem) { TTypedValue PropertyToTypedValue(const PropertyValue &value, utils::MemoryResource *mem) {
switch (value.type()) { switch (value.type()) {

View File

@ -15,6 +15,7 @@
#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/result.hpp"
#include "storage/v3/schema_validator.hpp" #include "storage/v3/schema_validator.hpp"
#include "storage/v3/vertex_accessor.hpp" #include "storage/v3/vertex_accessor.hpp"
#include "utils/memory_tracker.hpp" #include "utils/memory_tracker.hpp"
@ -50,17 +51,17 @@ bool EdgeAccessor::IsVisible(const View view) const {
return exists && (for_deleted_ || !deleted); return exists && (for_deleted_ || !deleted);
} }
const VertexId &EdgeAccessor::FromVertex() const { return from_vertex_; } const VertexId &EdgeAccessor::From() const { return from_vertex_; }
const VertexId &EdgeAccessor::ToVertex() const { return to_vertex_; } const VertexId &EdgeAccessor::To() const { return to_vertex_; }
Result<PropertyValue> EdgeAccessor::SetProperty(PropertyId property, const PropertyValue &value) { ShardResult<PropertyValue> EdgeAccessor::SetProperty(PropertyId property, const PropertyValue &value) {
utils::MemoryTracker::OutOfMemoryExceptionEnabler oom_exception; utils::MemoryTracker::OutOfMemoryExceptionEnabler oom_exception;
if (!config_.properties_on_edges) return Error::PROPERTIES_DISABLED; if (!config_.properties_on_edges) return SHARD_ERROR(ErrorCode::PROPERTIES_DISABLED);
if (!PrepareForWrite(transaction_, edge_.ptr)) return Error::SERIALIZATION_ERROR; if (!PrepareForWrite(transaction_, edge_.ptr)) return SHARD_ERROR(ErrorCode::SERIALIZATION_ERROR);
if (edge_.ptr->deleted) return Error::DELETED_OBJECT; if (edge_.ptr->deleted) return SHARD_ERROR(ErrorCode::DELETED_OBJECT);
auto current_value = edge_.ptr->properties.GetProperty(property); auto current_value = edge_.ptr->properties.GetProperty(property);
// We could skip setting the value if the previous one is the same to the new // We could skip setting the value if the previous one is the same to the new
@ -75,12 +76,12 @@ Result<PropertyValue> EdgeAccessor::SetProperty(PropertyId property, const Prope
return std::move(current_value); return std::move(current_value);
} }
Result<std::map<PropertyId, PropertyValue>> EdgeAccessor::ClearProperties() { ShardResult<std::map<PropertyId, PropertyValue>> EdgeAccessor::ClearProperties() {
if (!config_.properties_on_edges) return Error::PROPERTIES_DISABLED; if (!config_.properties_on_edges) return SHARD_ERROR(ErrorCode::PROPERTIES_DISABLED);
if (!PrepareForWrite(transaction_, edge_.ptr)) return Error::SERIALIZATION_ERROR; if (!PrepareForWrite(transaction_, edge_.ptr)) return SHARD_ERROR(ErrorCode::SERIALIZATION_ERROR);
if (edge_.ptr->deleted) return Error::DELETED_OBJECT; if (edge_.ptr->deleted) return SHARD_ERROR(ErrorCode::DELETED_OBJECT);
auto properties = edge_.ptr->properties.Properties(); auto properties = edge_.ptr->properties.Properties();
for (const auto &property : properties) { for (const auto &property : properties) {
@ -92,11 +93,11 @@ Result<std::map<PropertyId, PropertyValue>> EdgeAccessor::ClearProperties() {
return std::move(properties); return std::move(properties);
} }
Result<PropertyValue> EdgeAccessor::GetProperty(View view, PropertyId property) const { ShardResult<PropertyValue> EdgeAccessor::GetProperty(View view, PropertyId property) const {
return GetProperty(property, view); return GetProperty(property, view);
} }
Result<PropertyValue> EdgeAccessor::GetProperty(PropertyId property, View view) const { ShardResult<PropertyValue> EdgeAccessor::GetProperty(PropertyId property, View view) const {
if (!config_.properties_on_edges) return PropertyValue(); if (!config_.properties_on_edges) return PropertyValue();
auto exists = true; auto exists = true;
auto deleted = edge_.ptr->deleted; auto deleted = edge_.ptr->deleted;
@ -128,12 +129,12 @@ Result<PropertyValue> EdgeAccessor::GetProperty(PropertyId property, View view)
break; break;
} }
}); });
if (!exists) return Error::NONEXISTENT_OBJECT; if (!exists) return SHARD_ERROR(ErrorCode::NONEXISTENT_OBJECT);
if (!for_deleted_ && deleted) return Error::DELETED_OBJECT; if (!for_deleted_ && deleted) return SHARD_ERROR(ErrorCode::DELETED_OBJECT);
return std::move(value); return std::move(value);
} }
Result<std::map<PropertyId, PropertyValue>> EdgeAccessor::Properties(View view) const { ShardResult<std::map<PropertyId, PropertyValue>> EdgeAccessor::Properties(View view) const {
if (!config_.properties_on_edges) return std::map<PropertyId, PropertyValue>{}; if (!config_.properties_on_edges) return std::map<PropertyId, PropertyValue>{};
auto exists = true; auto exists = true;
auto deleted = edge_.ptr->deleted; auto deleted = edge_.ptr->deleted;
@ -174,9 +175,12 @@ Result<std::map<PropertyId, PropertyValue>> EdgeAccessor::Properties(View view)
break; break;
} }
}); });
if (!exists) return Error::NONEXISTENT_OBJECT; if (!exists) return SHARD_ERROR(ErrorCode::NONEXISTENT_OBJECT);
if (!for_deleted_ && deleted) return Error::DELETED_OBJECT; if (!for_deleted_ && deleted) return SHARD_ERROR(ErrorCode::DELETED_OBJECT);
return std::move(properties); return std::move(properties);
} }
// NOLINTNEXTLINE(readability-convert-member-functions-to-static)
size_t EdgeAccessor::CypherId() const { return Gid().AsUint(); }
} // namespace memgraph::storage::v3 } // namespace memgraph::storage::v3

View File

@ -48,27 +48,27 @@ class EdgeAccessor final {
/// @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;
const VertexId &FromVertex() const; const VertexId &From() const;
const VertexId &ToVertex() const; const VertexId &To() const;
EdgeTypeId EdgeType() const { return edge_type_; } EdgeTypeId EdgeType() const { return edge_type_; }
/// Set a property value and return the old value. /// Set a property value and return the old value.
/// @throw std::bad_alloc /// @throw std::bad_alloc
Result<PropertyValue> SetProperty(PropertyId property, const PropertyValue &value); ShardResult<PropertyValue> SetProperty(PropertyId property, const PropertyValue &value);
/// Remove all properties and return old values for each removed property. /// Remove all properties and return old values for each removed property.
/// @throw std::bad_alloc /// @throw std::bad_alloc
Result<std::map<PropertyId, PropertyValue>> ClearProperties(); ShardResult<std::map<PropertyId, PropertyValue>> ClearProperties();
/// @throw std::bad_alloc /// @throw std::bad_alloc
Result<PropertyValue> GetProperty(PropertyId property, View view) const; ShardResult<PropertyValue> GetProperty(PropertyId property, View view) const;
Result<PropertyValue> GetProperty(View view, PropertyId property) const; ShardResult<PropertyValue> GetProperty(View view, PropertyId property) const;
/// @throw std::bad_alloc /// @throw std::bad_alloc
Result<std::map<PropertyId, PropertyValue>> Properties(View view) const; ShardResult<std::map<PropertyId, PropertyValue>> Properties(View view) const;
Gid Gid() const noexcept { Gid Gid() const noexcept {
if (config_.properties_on_edges) { if (config_.properties_on_edges) {
@ -84,6 +84,9 @@ class EdgeAccessor final {
} }
bool operator!=(const EdgeAccessor &other) const noexcept { return !(*this == other); } bool operator!=(const EdgeAccessor &other) const noexcept { return !(*this == other); }
// Dummy function
size_t CypherId() const;
private: private:
EdgeRef edge_; EdgeRef edge_;
EdgeTypeId edge_type_; EdgeTypeId edge_type_;

View File

@ -52,13 +52,12 @@ msgs::Value ConstructValueEdge(const EdgeAccessor &acc, View view) {
msgs::EdgeType type = {.id = acc.EdgeType()}; msgs::EdgeType type = {.id = acc.EdgeType()};
msgs::EdgeId gid = {.gid = acc.Gid().AsUint()}; msgs::EdgeId gid = {.gid = acc.Gid().AsUint()};
msgs::Label src_prim_label = {.id = acc.FromVertex().primary_label}; msgs::Label src_prim_label = {.id = acc.From().primary_label};
memgraph::msgs::VertexId src_vertex = memgraph::msgs::VertexId src_vertex =
std::make_pair(src_prim_label, conversions::ConvertValueVector(acc.FromVertex().primary_key)); std::make_pair(src_prim_label, conversions::ConvertValueVector(acc.From().primary_key));
msgs::Label dst_prim_label = {.id = acc.ToVertex().primary_label}; msgs::Label dst_prim_label = {.id = acc.To().primary_label};
msgs::VertexId dst_vertex = msgs::VertexId dst_vertex = std::make_pair(dst_prim_label, conversions::ConvertValueVector(acc.To().primary_key));
std::make_pair(dst_prim_label, conversions::ConvertValueVector(acc.ToVertex().primary_key));
auto properties = acc.Properties(view); auto properties = acc.Properties(view);

View File

@ -16,6 +16,7 @@
#include "storage/v3/bindings/db_accessor.hpp" #include "storage/v3/bindings/db_accessor.hpp"
#include "storage/v3/bindings/pretty_print_ast_to_original_expression.hpp" #include "storage/v3/bindings/pretty_print_ast_to_original_expression.hpp"
#include "storage/v3/expr.hpp" #include "storage/v3/expr.hpp"
#include "storage/v3/result.hpp"
#include "storage/v3/value_conversions.hpp" #include "storage/v3/value_conversions.hpp"
namespace memgraph::storage::v3 { namespace memgraph::storage::v3 {
@ -28,11 +29,11 @@ using conversions::ToMsgsVertexId;
namespace { namespace {
using AllEdgePropertyDataSructure = std::map<PropertyId, msgs::Value>; using AllEdgePropertyDataStucture = std::map<PropertyId, msgs::Value>;
using SpecificEdgePropertyDataSructure = std::vector<msgs::Value>; using SpecificEdgePropertyDataStucture = std::vector<msgs::Value>;
using AllEdgeProperties = std::tuple<msgs::VertexId, msgs::Gid, AllEdgePropertyDataSructure>; using AllEdgeProperties = std::tuple<msgs::VertexId, msgs::Gid, AllEdgePropertyDataStucture>;
using SpecificEdgeProperties = std::tuple<msgs::VertexId, msgs::Gid, SpecificEdgePropertyDataSructure>; using SpecificEdgeProperties = std::tuple<msgs::VertexId, msgs::Gid, SpecificEdgePropertyDataStucture>;
using SpecificEdgePropertiesVector = std::vector<SpecificEdgeProperties>; using SpecificEdgePropertiesVector = std::vector<SpecificEdgeProperties>;
using AllEdgePropertiesVector = std::vector<AllEdgeProperties>; using AllEdgePropertiesVector = std::vector<AllEdgeProperties>;
@ -59,13 +60,13 @@ std::optional<std::map<PropertyId, Value>> PrimaryKeysFromAccessor(const VertexA
return ret; return ret;
} }
std::optional<std::vector<msgs::Label>> FillUpSourceVertexSecondaryLabels(const std::optional<VertexAccessor> &v_acc, ShardResult<std::vector<msgs::Label>> FillUpSourceVertexSecondaryLabels(const std::optional<VertexAccessor> &v_acc,
const msgs::ExpandOneRequest &req) { const msgs::ExpandOneRequest &req) {
auto secondary_labels = v_acc->Labels(View::NEW); auto secondary_labels = v_acc->Labels(View::NEW);
if (secondary_labels.HasError()) { if (secondary_labels.HasError()) {
spdlog::debug("Encountered an error while trying to get the secondary labels of a vertex. Transaction id: {}", spdlog::debug("Encountered an error while trying to get the secondary labels of a vertex. Transaction id: {}",
req.transaction_id.logical_id); req.transaction_id.logical_id);
return std::nullopt; return secondary_labels.GetError();
} }
auto &sec_labels = secondary_labels.GetValue(); auto &sec_labels = secondary_labels.GetValue();
@ -78,7 +79,7 @@ std::optional<std::vector<msgs::Label>> FillUpSourceVertexSecondaryLabels(const
return msgs_secondary_labels; return msgs_secondary_labels;
} }
std::optional<std::map<PropertyId, Value>> FillUpSourceVertexProperties(const std::optional<VertexAccessor> &v_acc, ShardResult<std::map<PropertyId, Value>> FillUpSourceVertexProperties(const std::optional<VertexAccessor> &v_acc,
const msgs::ExpandOneRequest &req, const msgs::ExpandOneRequest &req,
storage::v3::View view, storage::v3::View view,
const Schemas::Schema &schema) { const Schemas::Schema &schema) {
@ -89,7 +90,7 @@ std::optional<std::map<PropertyId, Value>> FillUpSourceVertexProperties(const st
if (props.HasError()) { if (props.HasError()) {
spdlog::debug("Encountered an error while trying to access vertex properties. Transaction id: {}", spdlog::debug("Encountered an error while trying to access vertex properties. Transaction id: {}",
req.transaction_id.logical_id); req.transaction_id.logical_id);
return std::nullopt; return props.GetError();
} }
for (auto &[key, val] : props.GetValue()) { for (auto &[key, val] : props.GetValue()) {
@ -108,7 +109,7 @@ std::optional<std::map<PropertyId, Value>> FillUpSourceVertexProperties(const st
if (prop_val.HasError()) { if (prop_val.HasError()) {
spdlog::debug("Encountered an error while trying to access vertex properties. Transaction id: {}", spdlog::debug("Encountered an error while trying to access vertex properties. Transaction id: {}",
req.transaction_id.logical_id); req.transaction_id.logical_id);
return std::nullopt; return prop_val.GetError();
} }
src_vertex_properties.insert(std::make_pair(prop, FromPropertyValueToValue(std::move(prop_val.GetValue())))); src_vertex_properties.insert(std::make_pair(prop, FromPropertyValueToValue(std::move(prop_val.GetValue()))));
} }
@ -117,9 +118,9 @@ std::optional<std::map<PropertyId, Value>> FillUpSourceVertexProperties(const st
return src_vertex_properties; return src_vertex_properties;
} }
std::optional<std::array<std::vector<EdgeAccessor>, 2>> FillUpConnectingEdges( ShardResult<std::array<std::vector<EdgeAccessor>, 2>> FillUpConnectingEdges(
const std::optional<VertexAccessor> &v_acc, const msgs::ExpandOneRequest &req, const std::optional<VertexAccessor> &v_acc, const msgs::ExpandOneRequest &req,
const EdgeUniqunessFunction &maybe_filter_based_on_edge_uniquness) { const EdgeUniquenessFunction &maybe_filter_based_on_edge_uniqueness) {
std::vector<EdgeTypeId> edge_types{}; std::vector<EdgeTypeId> edge_types{};
edge_types.reserve(req.edge_types.size()); edge_types.reserve(req.edge_types.size());
std::transform(req.edge_types.begin(), req.edge_types.end(), std::back_inserter(edge_types), std::transform(req.edge_types.begin(), req.edge_types.end(), std::back_inserter(edge_types),
@ -134,10 +135,10 @@ std::optional<std::array<std::vector<EdgeAccessor>, 2>> FillUpConnectingEdges(
if (out_edges_result.HasError()) { if (out_edges_result.HasError()) {
spdlog::debug("Encountered an error while trying to get out-going EdgeAccessors. Transaction id: {}", spdlog::debug("Encountered an error while trying to get out-going EdgeAccessors. Transaction id: {}",
req.transaction_id.logical_id); req.transaction_id.logical_id);
return std::nullopt; return out_edges_result.GetError();
} }
out_edges = out_edges =
maybe_filter_based_on_edge_uniquness(std::move(out_edges_result.GetValue()), msgs::EdgeDirection::OUT); maybe_filter_based_on_edge_uniqueness(std::move(out_edges_result.GetValue()), msgs::EdgeDirection::OUT);
break; break;
} }
case msgs::EdgeDirection::IN: { case msgs::EdgeDirection::IN: {
@ -146,9 +147,9 @@ std::optional<std::array<std::vector<EdgeAccessor>, 2>> FillUpConnectingEdges(
spdlog::debug( spdlog::debug(
"Encountered an error while trying to get in-going EdgeAccessors. Transaction id: {}"[req.transaction_id "Encountered an error while trying to get in-going EdgeAccessors. Transaction id: {}"[req.transaction_id
.logical_id]); .logical_id]);
return std::nullopt; return in_edges_result.GetError();
} }
in_edges = maybe_filter_based_on_edge_uniquness(std::move(in_edges_result.GetValue()), msgs::EdgeDirection::IN); in_edges = maybe_filter_based_on_edge_uniqueness(std::move(in_edges_result.GetValue()), msgs::EdgeDirection::IN);
break; break;
} }
case msgs::EdgeDirection::BOTH: { case msgs::EdgeDirection::BOTH: {
@ -156,17 +157,17 @@ std::optional<std::array<std::vector<EdgeAccessor>, 2>> FillUpConnectingEdges(
if (in_edges_result.HasError()) { if (in_edges_result.HasError()) {
spdlog::debug("Encountered an error while trying to get in-going EdgeAccessors. Transaction id: {}", spdlog::debug("Encountered an error while trying to get in-going EdgeAccessors. Transaction id: {}",
req.transaction_id.logical_id); req.transaction_id.logical_id);
return std::nullopt; return in_edges_result.GetError();
} }
in_edges = maybe_filter_based_on_edge_uniquness(std::move(in_edges_result.GetValue()), msgs::EdgeDirection::IN); in_edges = maybe_filter_based_on_edge_uniqueness(std::move(in_edges_result.GetValue()), msgs::EdgeDirection::IN);
auto out_edges_result = v_acc->OutEdges(View::NEW, edge_types); auto out_edges_result = v_acc->OutEdges(View::NEW, edge_types);
if (out_edges_result.HasError()) { if (out_edges_result.HasError()) {
spdlog::debug("Encountered an error while trying to get out-going EdgeAccessors. Transaction id: {}", spdlog::debug("Encountered an error while trying to get out-going EdgeAccessors. Transaction id: {}",
req.transaction_id.logical_id); req.transaction_id.logical_id);
return std::nullopt; return out_edges_result.GetError();
} }
out_edges = out_edges =
maybe_filter_based_on_edge_uniquness(std::move(out_edges_result.GetValue()), msgs::EdgeDirection::OUT); maybe_filter_based_on_edge_uniqueness(std::move(out_edges_result.GetValue()), msgs::EdgeDirection::OUT);
break; break;
} }
} }
@ -174,19 +175,20 @@ std::optional<std::array<std::vector<EdgeAccessor>, 2>> FillUpConnectingEdges(
} }
template <bool are_in_edges> template <bool are_in_edges>
bool FillEdges(const std::vector<EdgeAccessor> &edges, msgs::ExpandOneResultRow &row, const EdgeFiller &edge_filler) { ShardResult<void> FillEdges(const std::vector<EdgeAccessor> &edges, msgs::ExpandOneResultRow &row,
const EdgeFiller &edge_filler) {
for (const auto &edge : edges) { for (const auto &edge : edges) {
if (!edge_filler(edge, are_in_edges, row)) { if (const auto res = edge_filler(edge, are_in_edges, row); res.HasError()) {
return false; return res.GetError();
} }
} }
return true; return {};
} }
}; // namespace }; // namespace
std::optional<std::map<PropertyId, Value>> CollectSpecificPropertiesFromAccessor(const VertexAccessor &acc, ShardResult<std::map<PropertyId, Value>> CollectSpecificPropertiesFromAccessor(const VertexAccessor &acc,
const std::vector<PropertyId> &props, const std::vector<PropertyId> &props,
View view) { View view) {
std::map<PropertyId, Value> ret; std::map<PropertyId, Value> ret;
@ -195,7 +197,7 @@ std::optional<std::map<PropertyId, Value>> CollectSpecificPropertiesFromAccessor
auto result = acc.GetProperty(prop, view); auto result = acc.GetProperty(prop, view);
if (result.HasError()) { if (result.HasError()) {
spdlog::debug("Encountered an Error while trying to get a vertex property."); spdlog::debug("Encountered an Error while trying to get a vertex property.");
return std::nullopt; return result.GetError();
} }
auto &value = result.GetValue(); auto &value = result.GetValue();
ret.emplace(std::make_pair(prop, FromPropertyValueToValue(std::move(value)))); ret.emplace(std::make_pair(prop, FromPropertyValueToValue(std::move(value))));
@ -218,13 +220,13 @@ std::vector<TypedValue> EvaluateVertexExpressions(DbAccessor &dba, const VertexA
return evaluated_expressions; return evaluated_expressions;
} }
std::optional<std::map<PropertyId, Value>> CollectAllPropertiesFromAccessor(const VertexAccessor &acc, View view, ShardResult<std::map<PropertyId, Value>> CollectAllPropertiesFromAccessor(const VertexAccessor &acc, View view,
const Schemas::Schema &schema) { const Schemas::Schema &schema) {
std::map<PropertyId, Value> ret; std::map<PropertyId, Value> ret;
auto props = acc.Properties(view); auto props = acc.Properties(view);
if (props.HasError()) { if (props.HasError()) {
spdlog::debug("Encountered an error while trying to get vertex properties."); spdlog::debug("Encountered an error while trying to get vertex properties.");
return std::nullopt; return props.GetError();
} }
auto &properties = props.GetValue(); auto &properties = props.GetValue();
@ -242,9 +244,9 @@ std::optional<std::map<PropertyId, Value>> CollectAllPropertiesFromAccessor(cons
return ret; return ret;
} }
EdgeUniqunessFunction InitializeEdgeUniqunessFunction(bool only_unique_neighbor_rows) { EdgeUniquenessFunction InitializeEdgeUniquenessFunction(bool only_unique_neighbor_rows) {
// Functions to select connecting edges based on uniquness // Functions to select connecting edges based on uniquness
EdgeUniqunessFunction maybe_filter_based_on_edge_uniquness; EdgeUniquenessFunction maybe_filter_based_on_edge_uniquness;
if (only_unique_neighbor_rows) { if (only_unique_neighbor_rows) {
maybe_filter_based_on_edge_uniquness = [](EdgeAccessors &&edges, maybe_filter_based_on_edge_uniquness = [](EdgeAccessors &&edges,
@ -255,7 +257,7 @@ EdgeUniqunessFunction InitializeEdgeUniqunessFunction(bool only_unique_neighbor_
case msgs::EdgeDirection::OUT: { case msgs::EdgeDirection::OUT: {
is_edge_unique = [](std::set<const storage::v3::VertexId *, VertexIdCmpr> &other_vertex_set, is_edge_unique = [](std::set<const storage::v3::VertexId *, VertexIdCmpr> &other_vertex_set,
const storage::v3::EdgeAccessor &edge_acc) { const storage::v3::EdgeAccessor &edge_acc) {
auto [it, insertion_happened] = other_vertex_set.insert(&edge_acc.ToVertex()); auto [it, insertion_happened] = other_vertex_set.insert(&edge_acc.To());
return insertion_happened; return insertion_happened;
}; };
break; break;
@ -263,7 +265,7 @@ EdgeUniqunessFunction InitializeEdgeUniqunessFunction(bool only_unique_neighbor_
case msgs::EdgeDirection::IN: { case msgs::EdgeDirection::IN: {
is_edge_unique = [](std::set<const storage::v3::VertexId *, VertexIdCmpr> &other_vertex_set, is_edge_unique = [](std::set<const storage::v3::VertexId *, VertexIdCmpr> &other_vertex_set,
const storage::v3::EdgeAccessor &edge_acc) { const storage::v3::EdgeAccessor &edge_acc) {
auto [it, insertion_happened] = other_vertex_set.insert(&edge_acc.FromVertex()); auto [it, insertion_happened] = other_vertex_set.insert(&edge_acc.From());
return insertion_happened; return insertion_happened;
}; };
break; break;
@ -295,12 +297,13 @@ EdgeFiller InitializeEdgeFillerFunction(const msgs::ExpandOneRequest &req) {
EdgeFiller edge_filler; EdgeFiller edge_filler;
if (!req.edge_properties) { if (!req.edge_properties) {
edge_filler = [transaction_id = req.transaction_id.logical_id](const EdgeAccessor &edge, const bool is_in_edge, edge_filler = [transaction_id = req.transaction_id.logical_id](
msgs::ExpandOneResultRow &result_row) -> bool { const EdgeAccessor &edge, const bool is_in_edge,
msgs::ExpandOneResultRow &result_row) -> ShardResult<void> {
auto properties_results = edge.Properties(View::NEW); auto properties_results = edge.Properties(View::NEW);
if (properties_results.HasError()) { if (properties_results.HasError()) {
spdlog::debug("Encountered an error while trying to get edge properties. Transaction id: {}", transaction_id); spdlog::debug("Encountered an error while trying to get edge properties. Transaction id: {}", transaction_id);
return false; return properties_results.GetError();
} }
std::map<PropertyId, msgs::Value> value_properties; std::map<PropertyId, msgs::Value> value_properties;
@ -308,19 +311,19 @@ EdgeFiller InitializeEdgeFillerFunction(const msgs::ExpandOneRequest &req) {
value_properties.insert(std::make_pair(prop_key, FromPropertyValueToValue(std::move(prop_val)))); value_properties.insert(std::make_pair(prop_key, FromPropertyValueToValue(std::move(prop_val))));
} }
using EdgeWithAllProperties = msgs::ExpandOneResultRow::EdgeWithAllProperties; using EdgeWithAllProperties = msgs::ExpandOneResultRow::EdgeWithAllProperties;
EdgeWithAllProperties edges{ToMsgsVertexId(edge.FromVertex()), msgs::EdgeType{edge.EdgeType()}, EdgeWithAllProperties edges{ToMsgsVertexId(edge.From()), msgs::EdgeType{edge.EdgeType()}, edge.Gid().AsUint(),
edge.Gid().AsUint(), std::move(value_properties)}; std::move(value_properties)};
if (is_in_edge) { if (is_in_edge) {
result_row.in_edges_with_all_properties.push_back(std::move(edges)); result_row.in_edges_with_all_properties.push_back(std::move(edges));
} else { } else {
result_row.out_edges_with_all_properties.push_back(std::move(edges)); result_row.out_edges_with_all_properties.push_back(std::move(edges));
} }
return true; return {};
}; };
} else { } else {
// TODO(gvolfing) - do we want to set the action_successful here? // TODO(gvolfing) - do we want to set the action_successful here?
edge_filler = [&req](const EdgeAccessor &edge, const bool is_in_edge, edge_filler = [&req](const EdgeAccessor &edge, const bool is_in_edge,
msgs::ExpandOneResultRow &result_row) -> bool { msgs::ExpandOneResultRow &result_row) -> ShardResult<void> {
std::vector<msgs::Value> value_properties; std::vector<msgs::Value> value_properties;
value_properties.reserve(req.edge_properties.value().size()); value_properties.reserve(req.edge_properties.value().size());
for (const auto &edge_prop : req.edge_properties.value()) { for (const auto &edge_prop : req.edge_properties.value()) {
@ -328,19 +331,19 @@ EdgeFiller InitializeEdgeFillerFunction(const msgs::ExpandOneRequest &req) {
if (property_result.HasError()) { if (property_result.HasError()) {
spdlog::debug("Encountered an error while trying to get edge properties. Transaction id: {}", spdlog::debug("Encountered an error while trying to get edge properties. Transaction id: {}",
req.transaction_id.logical_id); req.transaction_id.logical_id);
return false; return property_result.GetError();
} }
value_properties.emplace_back(FromPropertyValueToValue(std::move(property_result.GetValue()))); value_properties.emplace_back(FromPropertyValueToValue(std::move(property_result.GetValue())));
} }
using EdgeWithSpecificProperties = msgs::ExpandOneResultRow::EdgeWithSpecificProperties; using EdgeWithSpecificProperties = msgs::ExpandOneResultRow::EdgeWithSpecificProperties;
EdgeWithSpecificProperties edges{ToMsgsVertexId(edge.FromVertex()), msgs::EdgeType{edge.EdgeType()}, EdgeWithSpecificProperties edges{ToMsgsVertexId(edge.From()), msgs::EdgeType{edge.EdgeType()},
edge.Gid().AsUint(), std::move(value_properties)}; edge.Gid().AsUint(), std::move(value_properties)};
if (is_in_edge) { if (is_in_edge) {
result_row.in_edges_with_specific_properties.push_back(std::move(edges)); result_row.in_edges_with_specific_properties.push_back(std::move(edges));
} else { } else {
result_row.out_edges_with_specific_properties.push_back(std::move(edges)); result_row.out_edges_with_specific_properties.push_back(std::move(edges));
} }
return true; return {};
}; };
} }
@ -355,83 +358,81 @@ bool FilterOnVertex(DbAccessor &dba, const storage::v3::VertexAccessor &v_acc, c
}); });
} }
std::optional<msgs::ExpandOneResultRow> GetExpandOneResult( ShardResult<msgs::ExpandOneResultRow> GetExpandOneResult(
Shard::Accessor &acc, msgs::VertexId src_vertex, const msgs::ExpandOneRequest &req, Shard::Accessor &acc, msgs::VertexId src_vertex, const msgs::ExpandOneRequest &req,
const EdgeUniqunessFunction &maybe_filter_based_on_edge_uniquness, const EdgeFiller &edge_filler, const EdgeUniquenessFunction &maybe_filter_based_on_edge_uniqueness, const EdgeFiller &edge_filler,
const Schemas::Schema &schema) { const Schemas::Schema &schema) {
/// Fill up source vertex /// Fill up source vertex
const auto primary_key = ConvertPropertyVector(src_vertex.second); const auto primary_key = ConvertPropertyVector(src_vertex.second);
auto v_acc = acc.FindVertex(primary_key, View::NEW); auto v_acc = acc.FindVertex(primary_key, View::NEW);
msgs::Vertex source_vertex = {.id = src_vertex}; msgs::Vertex source_vertex = {.id = src_vertex};
if (const auto maybe_secondary_labels = FillUpSourceVertexSecondaryLabels(v_acc, req); maybe_secondary_labels) { auto maybe_secondary_labels = FillUpSourceVertexSecondaryLabels(v_acc, req);
source_vertex.labels = *maybe_secondary_labels; if (maybe_secondary_labels.HasError()) {
} else { return maybe_secondary_labels.GetError();
return std::nullopt;
} }
source_vertex.labels = std::move(*maybe_secondary_labels);
auto src_vertex_properties = FillUpSourceVertexProperties(v_acc, req, storage::v3::View::NEW, schema); auto src_vertex_properties = FillUpSourceVertexProperties(v_acc, req, storage::v3::View::NEW, schema);
if (src_vertex_properties.HasError()) {
if (!src_vertex_properties) { return src_vertex_properties.GetError();
return std::nullopt;
} }
/// Fill up connecting edges /// Fill up connecting edges
auto fill_up_connecting_edges = FillUpConnectingEdges(v_acc, req, maybe_filter_based_on_edge_uniquness); auto fill_up_connecting_edges = FillUpConnectingEdges(v_acc, req, maybe_filter_based_on_edge_uniqueness);
if (!fill_up_connecting_edges) { if (fill_up_connecting_edges.HasError()) {
return std::nullopt; return fill_up_connecting_edges.GetError();
} }
auto [in_edges, out_edges] = fill_up_connecting_edges.GetValue();
auto [in_edges, out_edges] = fill_up_connecting_edges.value();
msgs::ExpandOneResultRow result_row; msgs::ExpandOneResultRow result_row;
result_row.src_vertex = std::move(source_vertex); result_row.src_vertex = std::move(source_vertex);
result_row.src_vertex_properties = std::move(*src_vertex_properties); result_row.src_vertex_properties = std::move(*src_vertex_properties);
static constexpr bool kInEdges = true; static constexpr bool kInEdges = true;
static constexpr bool kOutEdges = false; static constexpr bool kOutEdges = false;
if (!in_edges.empty() && !FillEdges<kInEdges>(in_edges, result_row, edge_filler)) { if (const auto fill_edges_res = FillEdges<kInEdges>(in_edges, result_row, edge_filler); fill_edges_res.HasError()) {
return std::nullopt; return fill_edges_res.GetError();
} }
if (!out_edges.empty() && !FillEdges<kOutEdges>(out_edges, result_row, edge_filler)) { if (const auto fill_edges_res = FillEdges<kOutEdges>(out_edges, result_row, edge_filler); fill_edges_res.HasError()) {
return std::nullopt; return fill_edges_res.GetError();
} }
return result_row; return result_row;
} }
std::optional<msgs::ExpandOneResultRow> GetExpandOneResult( ShardResult<msgs::ExpandOneResultRow> GetExpandOneResult(
VertexAccessor v_acc, msgs::VertexId src_vertex, const msgs::ExpandOneRequest &req, VertexAccessor v_acc, msgs::VertexId src_vertex, const msgs::ExpandOneRequest &req,
std::vector<EdgeAccessor> in_edge_accessors, std::vector<EdgeAccessor> out_edge_accessors, std::vector<EdgeAccessor> in_edge_accessors, std::vector<EdgeAccessor> out_edge_accessors,
const EdgeUniqunessFunction &maybe_filter_based_on_edge_uniquness, const EdgeFiller &edge_filler, const EdgeUniquenessFunction &maybe_filter_based_on_edge_uniqueness, const EdgeFiller &edge_filler,
const Schemas::Schema &schema) { const Schemas::Schema &schema) {
/// Fill up source vertex /// Fill up source vertex
msgs::Vertex source_vertex = {.id = src_vertex}; msgs::Vertex source_vertex = {.id = src_vertex};
if (const auto maybe_secondary_labels = FillUpSourceVertexSecondaryLabels(v_acc, req); maybe_secondary_labels) { auto maybe_secondary_labels = FillUpSourceVertexSecondaryLabels(v_acc, req);
source_vertex.labels = *maybe_secondary_labels; if (maybe_secondary_labels.HasError()) {
} else { return maybe_secondary_labels.GetError();
return std::nullopt;
} }
source_vertex.labels = std::move(*maybe_secondary_labels);
/// Fill up source vertex properties /// Fill up source vertex properties
auto src_vertex_properties = FillUpSourceVertexProperties(v_acc, req, storage::v3::View::NEW, schema); auto src_vertex_properties = FillUpSourceVertexProperties(v_acc, req, storage::v3::View::NEW, schema);
if (!src_vertex_properties) { if (src_vertex_properties.HasError()) {
return std::nullopt; return src_vertex_properties.GetError();
} }
/// Fill up connecting edges /// Fill up connecting edges
auto in_edges = maybe_filter_based_on_edge_uniquness(std::move(in_edge_accessors), msgs::EdgeDirection::IN); auto in_edges = maybe_filter_based_on_edge_uniqueness(std::move(in_edge_accessors), msgs::EdgeDirection::IN);
auto out_edges = maybe_filter_based_on_edge_uniquness(std::move(out_edge_accessors), msgs::EdgeDirection::OUT); auto out_edges = maybe_filter_based_on_edge_uniqueness(std::move(out_edge_accessors), msgs::EdgeDirection::OUT);
msgs::ExpandOneResultRow result_row; msgs::ExpandOneResultRow result_row;
result_row.src_vertex = std::move(source_vertex); result_row.src_vertex = std::move(source_vertex);
result_row.src_vertex_properties = std::move(*src_vertex_properties); result_row.src_vertex_properties = std::move(*src_vertex_properties);
static constexpr bool kInEdges = true; static constexpr bool kInEdges = true;
static constexpr bool kOutEdges = false; static constexpr bool kOutEdges = false;
if (!in_edges.empty() && !FillEdges<kInEdges>(in_edges, result_row, edge_filler)) { if (const auto fill_edges_res = FillEdges<kInEdges>(in_edges, result_row, edge_filler); fill_edges_res.HasError()) {
return std::nullopt; return fill_edges_res.GetError();
} }
if (!out_edges.empty() && !FillEdges<kOutEdges>(out_edges, result_row, edge_filler)) { if (const auto fill_edges_res = FillEdges<kOutEdges>(out_edges, result_row, edge_filler); fill_edges_res.HasError()) {
return std::nullopt; return fill_edges_res.GetError();
} }
return result_row; return result_row;
@ -471,12 +472,14 @@ std::array<std::vector<EdgeAccessor>, 2> GetEdgesFromVertex(const VertexAccessor
if (edges.HasValue()) { if (edges.HasValue()) {
in_edges = edges.GetValue(); in_edges = edges.GetValue();
} }
break;
} }
case memgraph::msgs::EdgeDirection::OUT: { case memgraph::msgs::EdgeDirection::OUT: {
auto edges = vertex_accessor.OutEdges(View::OLD); auto edges = vertex_accessor.OutEdges(View::OLD);
if (edges.HasValue()) { if (edges.HasValue()) {
out_edges = edges.GetValue(); out_edges = edges.GetValue();
} }
break;
} }
case memgraph::msgs::EdgeDirection::BOTH: { case memgraph::msgs::EdgeDirection::BOTH: {
auto maybe_in_edges = vertex_accessor.InEdges(View::OLD); auto maybe_in_edges = vertex_accessor.InEdges(View::OLD);
@ -488,6 +491,7 @@ std::array<std::vector<EdgeAccessor>, 2> GetEdgesFromVertex(const VertexAccessor
if (maybe_out_edges.HasValue()) { if (maybe_out_edges.HasValue()) {
out_edges = maybe_out_edges.GetValue(); out_edges = maybe_out_edges.GetValue();
} }
break;
} }
} }
@ -522,38 +526,4 @@ std::vector<Element<EdgeAccessor>> OrderByEdges(DbAccessor &dba, std::vector<Edg
return ordered; return ordered;
} }
void LogResultError(const ResultErrorType &error, const std::string_view action) {
std::visit(
[action]<typename T>(T &&error) {
using ErrorType = std::remove_cvref_t<T>;
if constexpr (std::is_same_v<ErrorType, SchemaViolation>) {
spdlog::debug("{} failed with error: SchemaViolation", action);
} else if constexpr (std::is_same_v<ErrorType, Error>) {
switch (error) {
case Error::DELETED_OBJECT:
spdlog::debug("{} failed with error: DELETED_OBJECT", action);
break;
case Error::NONEXISTENT_OBJECT:
spdlog::debug("{} failed with error: NONEXISTENT_OBJECT", action);
break;
case Error::SERIALIZATION_ERROR:
spdlog::debug("{} failed with error: SERIALIZATION_ERROR", action);
break;
case Error::PROPERTIES_DISABLED:
spdlog::debug("{} failed with error: PROPERTIES_DISABLED", action);
break;
case Error::VERTEX_HAS_EDGES:
spdlog::debug("{} failed with error: VERTEX_HAS_EDGES", action);
break;
case Error::VERTEX_ALREADY_INSERTED:
spdlog::debug("{} failed with error: VERTEX_ALREADY_INSERTED", action);
break;
}
} else {
static_assert(utils::kAlwaysFalse<T>, "Missing type from variant visitor");
}
},
error);
}
} // namespace memgraph::storage::v3 } // namespace memgraph::storage::v3

View File

@ -25,8 +25,9 @@
namespace memgraph::storage::v3 { namespace memgraph::storage::v3 {
using EdgeAccessors = std::vector<storage::v3::EdgeAccessor>; using EdgeAccessors = std::vector<storage::v3::EdgeAccessor>;
using EdgeUniqunessFunction = std::function<EdgeAccessors(EdgeAccessors &&, msgs::EdgeDirection)>; using EdgeUniquenessFunction = std::function<EdgeAccessors(EdgeAccessors &&, msgs::EdgeDirection)>;
using EdgeFiller = std::function<bool(const EdgeAccessor &edge, bool is_in_edge, msgs::ExpandOneResultRow &result_row)>; using EdgeFiller =
std::function<ShardResult<void>(const EdgeAccessor &edge, bool is_in_edge, msgs::ExpandOneResultRow &result_row)>;
using msgs::Value; using msgs::Value;
template <typename T> template <typename T>
@ -162,8 +163,6 @@ std::vector<Element<VertexAccessor>> OrderByVertices(DbAccessor &dba, TIterable
return ordered; return ordered;
} }
void LogResultError(const ResultErrorType &error, std::string_view action);
std::vector<Element<EdgeAccessor>> OrderByEdges(DbAccessor &dba, std::vector<EdgeAccessor> &iterable, std::vector<Element<EdgeAccessor>> OrderByEdges(DbAccessor &dba, std::vector<EdgeAccessor> &iterable,
std::vector<msgs::OrderBy> &order_by_edges, std::vector<msgs::OrderBy> &order_by_edges,
const VertexAccessor &vertex_acc); const VertexAccessor &vertex_acc);
@ -185,25 +184,25 @@ std::vector<TypedValue> EvaluateVertexExpressions(DbAccessor &dba, const VertexA
const std::vector<std::string> &expressions, const std::vector<std::string> &expressions,
std::string_view node_name); std::string_view node_name);
std::optional<std::map<PropertyId, Value>> CollectSpecificPropertiesFromAccessor(const VertexAccessor &acc, ShardResult<std::map<PropertyId, Value>> CollectSpecificPropertiesFromAccessor(const VertexAccessor &acc,
const std::vector<PropertyId> &props, const std::vector<PropertyId> &props,
View view); View view);
std::optional<std::map<PropertyId, Value>> CollectAllPropertiesFromAccessor(const VertexAccessor &acc, View view, ShardResult<std::map<PropertyId, Value>> CollectAllPropertiesFromAccessor(const VertexAccessor &acc, View view,
const Schemas::Schema &schema); const Schemas::Schema &schema);
EdgeUniqunessFunction InitializeEdgeUniqunessFunction(bool only_unique_neighbor_rows); EdgeUniquenessFunction InitializeEdgeUniquenessFunction(bool only_unique_neighbor_rows);
EdgeFiller InitializeEdgeFillerFunction(const msgs::ExpandOneRequest &req); EdgeFiller InitializeEdgeFillerFunction(const msgs::ExpandOneRequest &req);
std::optional<msgs::ExpandOneResultRow> GetExpandOneResult( ShardResult<msgs::ExpandOneResultRow> GetExpandOneResult(
Shard::Accessor &acc, msgs::VertexId src_vertex, const msgs::ExpandOneRequest &req, Shard::Accessor &acc, msgs::VertexId src_vertex, const msgs::ExpandOneRequest &req,
const EdgeUniqunessFunction &maybe_filter_based_on_edge_uniquness, const EdgeFiller &edge_filler, const EdgeUniquenessFunction &maybe_filter_based_on_edge_uniqueness, const EdgeFiller &edge_filler,
const Schemas::Schema &schema); const Schemas::Schema &schema);
std::optional<msgs::ExpandOneResultRow> GetExpandOneResult( ShardResult<msgs::ExpandOneResultRow> GetExpandOneResult(
VertexAccessor v_acc, msgs::VertexId src_vertex, const msgs::ExpandOneRequest &req, VertexAccessor v_acc, msgs::VertexId src_vertex, const msgs::ExpandOneRequest &req,
std::vector<EdgeAccessor> in_edge_accessors, std::vector<EdgeAccessor> out_edge_accessors, std::vector<EdgeAccessor> in_edge_accessors, std::vector<EdgeAccessor> out_edge_accessors,
const EdgeUniqunessFunction &maybe_filter_based_on_edge_uniquness, const EdgeFiller &edge_filler, const EdgeUniquenessFunction &maybe_filter_based_on_edge_uniqueness, const EdgeFiller &edge_filler,
const Schemas::Schema &schema); const Schemas::Schema &schema);
} // namespace memgraph::storage::v3 } // namespace memgraph::storage::v3

View File

@ -11,24 +11,43 @@
#pragma once #pragma once
#include <cstdint>
#include <experimental/source_location>
#include <string>
#include <string_view>
#include <type_traits> #include <type_traits>
#include "common/errors.hpp"
#include "utils/result.hpp" #include "utils/result.hpp"
namespace memgraph::storage::v3 { namespace memgraph::storage::v3 {
static_assert(std::is_same_v<uint8_t, unsigned char>); static_assert(std::is_same_v<uint8_t, unsigned char>);
enum class Error : uint8_t { struct ShardError {
SERIALIZATION_ERROR, ShardError(common::ErrorCode code, std::string message, const std::experimental::source_location location)
NONEXISTENT_OBJECT, : code{code}, message{std::move(message)}, source{fmt::format("{}:{}", location.file_name(), location.line())} {}
DELETED_OBJECT,
VERTEX_HAS_EDGES, ShardError(common::ErrorCode code, const std::experimental::source_location location)
PROPERTIES_DISABLED, : code{code}, source{fmt::format("{}:{}", location.file_name(), location.line())} {}
VERTEX_ALREADY_INSERTED
common::ErrorCode code;
std::string message;
std::string source;
inline friend bool operator==(const ShardError &lhs, const ShardError &rhs) { return lhs.code == rhs.code; }
inline friend bool operator==(const ShardError &lhs, const common::ErrorCode rhs) { return lhs.code == rhs; }
}; };
// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
#define SHARD_ERROR(error, ...) \
({ \
using ErrorCode = memgraph::common::ErrorCode; \
memgraph::storage::v3::ShardError(error, GET_MESSAGE(__VA_ARGS__), std::experimental::source_location::current()); \
})
template <class TValue> template <class TValue>
using Result = utils::BasicResult<Error, TValue>; using ShardResult = utils::BasicResult<ShardError, TValue>;
} // namespace memgraph::storage::v3 } // namespace memgraph::storage::v3

View File

@ -16,67 +16,58 @@
#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} {} ShardResult<void> SchemaValidator::ValidateVertexCreate(LabelId primary_label, const std::vector<LabelId> &labels,
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,
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, "Schema not defined for label :{}",
name_id_mapper_->IdToName(primary_label.AsInt()));
} }
// 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,
"Cannot add label :{}, since it is defined as a primary label",
name_id_mapper_->IdToName(secondary_label.AsInt()));
} }
} }
// 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,
"Not all primary properties have been specified for :{} vertex",
name_id_mapper_->IdToName(primary_label.AsInt()));
} }
// 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(ErrorCode::SCHEMA_VERTEX_PROPERTY_WRONG_TYPE,
schema->second[i], primary_properties[i]); "Property {} is of wrong type, expected {}, actual {}",
name_id_mapper_->IdToName(schema->second[i].property_id.AsInt()),
SchemaTypeToString(schema->second[i].type), SchemaTypeToString(*property_schema_type));
} }
} }
return std::nullopt; return {};
} }
std::optional<SchemaViolation> SchemaValidator::ValidatePropertyUpdate(const LabelId primary_label, ShardResult<void> 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,34 +75,37 @@ 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(ErrorCode::SCHEMA_VERTEX_UPDATE_PRIMARY_KEY,
*schema_property); "Cannot update primary property {} of schema on label :{}",
name_id_mapper_->IdToName(schema_property->property_id.AsInt()),
name_id_mapper_->IdToName(primary_label.AsInt()));
} }
return std::nullopt; return {};
} }
std::optional<SchemaViolation> SchemaValidator::ValidateLabelUpdate(const LabelId label) const { ShardResult<void> 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, "Cannot add/remove primary label :{}",
name_id_mapper_->IdToName(label.AsInt()));
} }
return std::nullopt; return {};
} }
const Schemas::Schema *SchemaValidator::GetSchema(LabelId label) const { return schemas_.GetSchema(label); } const Schemas::Schema *SchemaValidator::GetSchema(LabelId label) const { return schemas_->GetSchema(label); }
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 { ShardResult<void> 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 { ShardResult<void> VertexValidator::ValidateAddLabel(LabelId label) const {
return schema_validator->ValidateLabelUpdate(label); return schema_validator->ValidateLabelUpdate(label);
} }
std::optional<SchemaViolation> VertexValidator::ValidateRemoveLabel(LabelId label) const { ShardResult<void> VertexValidator::ValidateRemoveLabel(LabelId label) const {
return schema_validator->ValidateLabelUpdate(label); return schema_validator->ValidateLabelUpdate(label);
} }

View File

@ -11,68 +11,43 @@
#pragma once #pragma once
#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]] ShardResult<void> 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]] ShardResult<void> ValidatePropertyUpdate(LabelId primary_label, PropertyId property_id) const;
PropertyId property_id) const;
[[nodiscard]] std::optional<SchemaViolation> ValidateLabelUpdate(LabelId label) const; [[nodiscard]] ShardResult<void> 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]] ShardResult<void> ValidatePropertyUpdate(PropertyId property_id) const;
[[nodiscard]] std::optional<SchemaViolation> ValidateAddLabel(LabelId label) const; [[nodiscard]] ShardResult<void> ValidateAddLabel(LabelId label) const;
[[nodiscard]] std::optional<SchemaViolation> ValidateRemoveLabel(LabelId label) const; [[nodiscard]] ShardResult<void> ValidateRemoveLabel(LabelId label) const;
const SchemaValidator *schema_validator; const SchemaValidator *schema_validator;

View File

@ -31,9 +31,10 @@
#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/result.hpp"
#include "storage/v3/schema_validator.hpp" #include "storage/v3/schema_validator.hpp"
#include "storage/v3/shard_operation_result.hpp"
#include "storage/v3/transaction.hpp" #include "storage/v3/transaction.hpp"
#include "storage/v3/vertex.hpp" #include "storage/v3/vertex.hpp"
#include "storage/v3/vertex_accessor.hpp" #include "storage/v3/vertex_accessor.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},
@ -344,7 +345,7 @@ Shard::~Shard() {}
Shard::Accessor::Accessor(Shard &shard, Transaction &transaction) Shard::Accessor::Accessor(Shard &shard, Transaction &transaction)
: shard_(&shard), transaction_(&transaction), config_(shard_->config_.items) {} : shard_(&shard), transaction_(&transaction), config_(shard_->config_.items) {}
ShardOperationResult<VertexAccessor> Shard::Accessor::CreateVertexAndValidate( ShardResult<VertexAccessor> Shard::Accessor::CreateVertexAndValidate(
const std::vector<LabelId> &labels, const std::vector<PropertyValue> &primary_properties, const std::vector<LabelId> &labels, const std::vector<PropertyValue> &primary_properties,
const std::vector<std::pair<PropertyId, PropertyValue>> &properties) { const std::vector<std::pair<PropertyId, PropertyValue>> &properties) {
OOMExceptionEnabler oom_exception; OOMExceptionEnabler oom_exception;
@ -352,8 +353,8 @@ ShardOperationResult<VertexAccessor> Shard::Accessor::CreateVertexAndValidate(
auto maybe_schema_violation = auto maybe_schema_violation =
GetSchemaValidator().ValidateVertexCreate(shard_->primary_label_, labels, primary_properties); GetSchemaValidator().ValidateVertexCreate(shard_->primary_label_, labels, primary_properties);
if (maybe_schema_violation) { if (maybe_schema_violation.HasError()) {
return {std::move(*maybe_schema_violation)}; return {std::move(maybe_schema_violation.GetError())};
} }
auto acc = shard_->vertices_.access(); auto acc = shard_->vertices_.access();
@ -363,7 +364,7 @@ ShardOperationResult<VertexAccessor> Shard::Accessor::CreateVertexAndValidate(
VertexAccessor vertex_acc{&it->vertex, transaction_, &shard_->indices_, config_, shard_->vertex_validator_}; VertexAccessor vertex_acc{&it->vertex, transaction_, &shard_->indices_, config_, shard_->vertex_validator_};
if (!inserted) { if (!inserted) {
return {Error::VERTEX_ALREADY_INSERTED}; return SHARD_ERROR(ErrorCode::VERTEX_ALREADY_INSERTED);
} }
MG_ASSERT(it != acc.end(), "Invalid Vertex accessor!"); MG_ASSERT(it != acc.end(), "Invalid Vertex accessor!");
@ -394,19 +395,19 @@ std::optional<VertexAccessor> Shard::Accessor::FindVertex(std::vector<PropertyVa
return VertexAccessor::Create(&it->vertex, transaction_, &shard_->indices_, config_, shard_->vertex_validator_, view); return VertexAccessor::Create(&it->vertex, transaction_, &shard_->indices_, config_, shard_->vertex_validator_, view);
} }
Result<std::optional<VertexAccessor>> Shard::Accessor::DeleteVertex(VertexAccessor *vertex) { ShardResult<std::optional<VertexAccessor>> Shard::Accessor::DeleteVertex(VertexAccessor *vertex) {
MG_ASSERT(vertex->transaction_ == transaction_, MG_ASSERT(vertex->transaction_ == transaction_,
"VertexAccessor must be from the same transaction as the storage " "VertexAccessor must be from the same transaction as the storage "
"accessor when deleting a vertex!"); "accessor when deleting a vertex!");
auto *vertex_ptr = vertex->vertex_; auto *vertex_ptr = vertex->vertex_;
if (!PrepareForWrite(transaction_, vertex_ptr)) return Error::SERIALIZATION_ERROR; if (!PrepareForWrite(transaction_, vertex_ptr)) return SHARD_ERROR(ErrorCode::SERIALIZATION_ERROR);
if (vertex_ptr->deleted) { if (vertex_ptr->deleted) {
return std::optional<VertexAccessor>{}; return std::optional<VertexAccessor>{};
} }
if (!vertex_ptr->in_edges.empty() || !vertex_ptr->out_edges.empty()) return Error::VERTEX_HAS_EDGES; if (!vertex_ptr->in_edges.empty() || !vertex_ptr->out_edges.empty()) return SHARD_ERROR(ErrorCode::VERTEX_HAS_EDGES);
CreateAndLinkDelta(transaction_, vertex_ptr, Delta::RecreateObjectTag()); CreateAndLinkDelta(transaction_, vertex_ptr, Delta::RecreateObjectTag());
vertex_ptr->deleted = true; vertex_ptr->deleted = true;
@ -415,7 +416,7 @@ Result<std::optional<VertexAccessor>> Shard::Accessor::DeleteVertex(VertexAccess
shard_->vertex_validator_, true); shard_->vertex_validator_, true);
} }
Result<std::optional<std::pair<VertexAccessor, std::vector<EdgeAccessor>>>> Shard::Accessor::DetachDeleteVertex( ShardResult<std::optional<std::pair<VertexAccessor, std::vector<EdgeAccessor>>>> Shard::Accessor::DetachDeleteVertex(
VertexAccessor *vertex) { VertexAccessor *vertex) {
using ReturnType = std::pair<VertexAccessor, std::vector<EdgeAccessor>>; using ReturnType = std::pair<VertexAccessor, std::vector<EdgeAccessor>>;
@ -428,7 +429,7 @@ Result<std::optional<std::pair<VertexAccessor, std::vector<EdgeAccessor>>>> Shar
std::vector<Vertex::EdgeLink> out_edges; std::vector<Vertex::EdgeLink> out_edges;
{ {
if (!PrepareForWrite(transaction_, vertex_ptr)) return Error::SERIALIZATION_ERROR; if (!PrepareForWrite(transaction_, vertex_ptr)) return SHARD_ERROR(ErrorCode::SERIALIZATION_ERROR);
if (vertex_ptr->deleted) return std::optional<ReturnType>{}; if (vertex_ptr->deleted) return std::optional<ReturnType>{};
@ -441,9 +442,9 @@ 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_id, transaction_, &shard_->indices_, config_); EdgeAccessor e(edge, edge_type, from_vertex, vertex_id, transaction_, &shard_->indices_, config_);
auto ret = DeleteEdge(e.FromVertex(), e.ToVertex(), e.Gid()); auto ret = DeleteEdge(e.From(), e.To(), e.Gid());
if (ret.HasError()) { if (ret.HasError()) {
MG_ASSERT(ret.GetError() == Error::SERIALIZATION_ERROR, "Invalid database state!"); MG_ASSERT(ret.GetError() == common::ErrorCode::SERIALIZATION_ERROR, "Invalid database state!");
return ret.GetError(); return ret.GetError();
} }
@ -454,9 +455,9 @@ 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_id, to_vertex, transaction_, &shard_->indices_, config_); EdgeAccessor e(edge, edge_type, vertex_id, to_vertex, transaction_, &shard_->indices_, config_);
auto ret = DeleteEdge(e.FromVertex(), e.ToVertex(), e.Gid()); auto ret = DeleteEdge(e.From(), e.To(), e.Gid());
if (ret.HasError()) { if (ret.HasError()) {
MG_ASSERT(ret.GetError() == Error::SERIALIZATION_ERROR, "Invalid database state!"); MG_ASSERT(ret.GetError() == common::ErrorCode::SERIALIZATION_ERROR, "Invalid database state!");
return ret.GetError(); return ret.GetError();
} }
@ -469,7 +470,7 @@ Result<std::optional<std::pair<VertexAccessor, std::vector<EdgeAccessor>>>> Shar
// vertex. Some other transaction could have modified the vertex in the // vertex. Some other transaction could have modified the vertex in the
// meantime if we didn't have any edges to delete. // meantime if we didn't have any edges to delete.
if (!PrepareForWrite(transaction_, vertex_ptr)) return Error::SERIALIZATION_ERROR; if (!PrepareForWrite(transaction_, vertex_ptr)) return SHARD_ERROR(ErrorCode::SERIALIZATION_ERROR);
MG_ASSERT(!vertex_ptr->deleted, "Invalid database state!"); MG_ASSERT(!vertex_ptr->deleted, "Invalid database state!");
@ -481,7 +482,7 @@ Result<std::optional<std::pair<VertexAccessor, std::vector<EdgeAccessor>>>> Shar
std::move(deleted_edges)); std::move(deleted_edges));
} }
Result<EdgeAccessor> Shard::Accessor::CreateEdge(VertexId from_vertex_id, VertexId to_vertex_id, ShardResult<EdgeAccessor> Shard::Accessor::CreateEdge(VertexId from_vertex_id, VertexId to_vertex_id,
const EdgeTypeId edge_type, const Gid gid) { const EdgeTypeId edge_type, const Gid gid) {
OOMExceptionEnabler oom_exception; OOMExceptionEnabler oom_exception;
Vertex *from_vertex{nullptr}; Vertex *from_vertex{nullptr};
@ -506,12 +507,12 @@ Result<EdgeAccessor> Shard::Accessor::CreateEdge(VertexId from_vertex_id, Vertex
} }
if (from_is_local) { if (from_is_local) {
if (!PrepareForWrite(transaction_, from_vertex)) return Error::SERIALIZATION_ERROR; if (!PrepareForWrite(transaction_, from_vertex)) return SHARD_ERROR(ErrorCode::SERIALIZATION_ERROR);
if (from_vertex->deleted) return Error::DELETED_OBJECT; if (from_vertex->deleted) return SHARD_ERROR(ErrorCode::DELETED_OBJECT);
} }
if (to_is_local && to_vertex != from_vertex) { if (to_is_local && to_vertex != from_vertex) {
if (!PrepareForWrite(transaction_, to_vertex)) return Error::SERIALIZATION_ERROR; if (!PrepareForWrite(transaction_, to_vertex)) return SHARD_ERROR(ErrorCode::SERIALIZATION_ERROR);
if (to_vertex->deleted) return Error::DELETED_OBJECT; if (to_vertex->deleted) return SHARD_ERROR(ErrorCode::DELETED_OBJECT);
} }
EdgeRef edge(gid); EdgeRef edge(gid);
@ -540,7 +541,7 @@ Result<EdgeAccessor> Shard::Accessor::CreateEdge(VertexId from_vertex_id, Vertex
&shard_->indices_, config_); &shard_->indices_, config_);
} }
Result<std::optional<EdgeAccessor>> Shard::Accessor::DeleteEdge(VertexId from_vertex_id, VertexId to_vertex_id, ShardResult<std::optional<EdgeAccessor>> Shard::Accessor::DeleteEdge(VertexId from_vertex_id, VertexId to_vertex_id,
const Gid edge_id) { const Gid edge_id) {
Vertex *from_vertex{nullptr}; Vertex *from_vertex{nullptr};
Vertex *to_vertex{nullptr}; Vertex *to_vertex{nullptr};
@ -566,13 +567,13 @@ Result<std::optional<EdgeAccessor>> Shard::Accessor::DeleteEdge(VertexId from_ve
if (from_is_local) { if (from_is_local) {
if (!PrepareForWrite(transaction_, from_vertex)) { if (!PrepareForWrite(transaction_, from_vertex)) {
return Error::SERIALIZATION_ERROR; return SHARD_ERROR(ErrorCode::SERIALIZATION_ERROR);
} }
MG_ASSERT(!from_vertex->deleted, "Invalid database state!"); MG_ASSERT(!from_vertex->deleted, "Invalid database state!");
} }
if (to_is_local && to_vertex != from_vertex) { if (to_is_local && to_vertex != from_vertex) {
if (!PrepareForWrite(transaction_, to_vertex)) { if (!PrepareForWrite(transaction_, to_vertex)) {
return Error::SERIALIZATION_ERROR; return SHARD_ERROR(ErrorCode::SERIALIZATION_ERROR);
} }
MG_ASSERT(!to_vertex->deleted, "Invalid database state!"); MG_ASSERT(!to_vertex->deleted, "Invalid database state!");
} }

View File

@ -38,7 +38,6 @@
#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/schemas.hpp" #include "storage/v3/schemas.hpp"
#include "storage/v3/shard_operation_result.hpp"
#include "storage/v3/transaction.hpp" #include "storage/v3/transaction.hpp"
#include "storage/v3/vertex.hpp" #include "storage/v3/vertex.hpp"
#include "storage/v3/vertex_accessor.hpp" #include "storage/v3/vertex_accessor.hpp"
@ -207,7 +206,7 @@ class Shard final {
public: public:
/// @throw std::bad_alloc /// @throw std::bad_alloc
ShardOperationResult<VertexAccessor> CreateVertexAndValidate( ShardResult<VertexAccessor> CreateVertexAndValidate(
const std::vector<LabelId> &labels, const std::vector<PropertyValue> &primary_properties, const std::vector<LabelId> &labels, const std::vector<PropertyValue> &primary_properties,
const std::vector<std::pair<PropertyId, PropertyValue>> &properties); const std::vector<std::pair<PropertyId, PropertyValue>> &properties);
@ -262,19 +261,19 @@ class Shard final {
/// @return Accessor to the deleted vertex if a deletion took place, std::nullopt otherwise /// @return Accessor to the deleted vertex if a deletion took place, std::nullopt otherwise
/// @throw std::bad_alloc /// @throw std::bad_alloc
Result<std::optional<VertexAccessor>> DeleteVertex(VertexAccessor *vertex); ShardResult<std::optional<VertexAccessor>> DeleteVertex(VertexAccessor *vertex);
/// @return Accessor to the deleted vertex and deleted edges if a deletion took place, std::nullopt otherwise /// @return Accessor to the deleted vertex and deleted edges if a deletion took place, std::nullopt otherwise
/// @throw std::bad_alloc /// @throw std::bad_alloc
Result<std::optional<std::pair<VertexAccessor, std::vector<EdgeAccessor>>>> DetachDeleteVertex( ShardResult<std::optional<std::pair<VertexAccessor, std::vector<EdgeAccessor>>>> DetachDeleteVertex(
VertexAccessor *vertex); VertexAccessor *vertex);
/// @throw std::bad_alloc /// @throw std::bad_alloc
Result<EdgeAccessor> CreateEdge(VertexId from_vertex_id, VertexId to_vertex_id, EdgeTypeId edge_type, Gid gid); ShardResult<EdgeAccessor> CreateEdge(VertexId from_vertex_id, VertexId to_vertex_id, EdgeTypeId edge_type, Gid gid);
/// Accessor to the deleted edge if a deletion took place, std::nullopt otherwise /// Accessor to the deleted edge if a deletion took place, std::nullopt otherwise
/// @throw std::bad_alloc /// @throw std::bad_alloc
Result<std::optional<EdgeAccessor>> DeleteEdge(VertexId from_vertex_id, VertexId to_vertex_id, Gid edge_id); ShardResult<std::optional<EdgeAccessor>> DeleteEdge(VertexId from_vertex_id, VertexId to_vertex_id, Gid edge_id);
LabelId NameToLabel(std::string_view name) const; LabelId NameToLabel(std::string_view name) const;

View File

@ -1,26 +0,0 @@
// Copyright 2022 Memgraph Ltd.
//
// Use of this software is governed by the Business Source License
// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
// License, and you may not use this file except in compliance with the Business Source License.
//
// As of the Change Date specified in that file, in accordance with
// the Business Source License, use of this software will be governed
// by the Apache License, Version 2.0, included in the file
// licenses/APL.txt.
#pragma once
#include <variant>
#include "storage/v3/result.hpp"
#include "storage/v3/schema_validator.hpp"
namespace memgraph::storage::v3 {
using ResultErrorType = std::variant<SchemaViolation, Error>;
template <typename TValue>
using ShardOperationResult = utils::BasicResult<ResultErrorType, TValue>;
} // namespace memgraph::storage::v3

View File

@ -34,6 +34,7 @@
#include "storage/v3/key_store.hpp" #include "storage/v3/key_store.hpp"
#include "storage/v3/property_value.hpp" #include "storage/v3/property_value.hpp"
#include "storage/v3/request_helper.hpp" #include "storage/v3/request_helper.hpp"
#include "storage/v3/result.hpp"
#include "storage/v3/schemas.hpp" #include "storage/v3/schemas.hpp"
#include "storage/v3/shard.hpp" #include "storage/v3/shard.hpp"
#include "storage/v3/shard_rsm.hpp" #include "storage/v3/shard_rsm.hpp"
@ -56,10 +57,17 @@ using conversions::FromPropertyValueToValue;
using conversions::ToMsgsVertexId; using conversions::ToMsgsVertexId;
using conversions::ToPropertyValue; using conversions::ToPropertyValue;
auto CreateErrorResponse(const ShardError &shard_error, const auto transaction_id, const std::string_view action) {
msgs::ShardError message_shard_error{shard_error.code, shard_error.message};
spdlog::debug("{} In transaction {} {} failed: {}: {}", shard_error.source, transaction_id.logical_id, action,
ErrorCodeToString(shard_error.code), shard_error.message);
return message_shard_error;
}
msgs::WriteResponses ShardRsm::ApplyWrite(msgs::CreateVerticesRequest &&req) { msgs::WriteResponses ShardRsm::ApplyWrite(msgs::CreateVerticesRequest &&req) {
auto acc = shard_->Access(req.transaction_id); auto acc = shard_->Access(req.transaction_id);
bool action_successful = true; std::optional<msgs::ShardError> shard_error;
for (auto &new_vertex : req.new_vertices) { for (auto &new_vertex : req.new_vertices) {
/// TODO(gvolfing) Consider other methods than converting. Change either /// TODO(gvolfing) Consider other methods than converting. Change either
@ -77,48 +85,39 @@ msgs::WriteResponses ShardRsm::ApplyWrite(msgs::CreateVerticesRequest &&req) {
PrimaryKey transformed_pk; PrimaryKey transformed_pk;
std::transform(new_vertex.primary_key.begin(), new_vertex.primary_key.end(), std::back_inserter(transformed_pk), std::transform(new_vertex.primary_key.begin(), new_vertex.primary_key.end(), std::back_inserter(transformed_pk),
[](msgs::Value &val) { return ToPropertyValue(std::move(val)); }); [](msgs::Value &val) { return ToPropertyValue(std::move(val)); });
auto result_schema = acc.CreateVertexAndValidate(converted_label_ids, transformed_pk, converted_property_map);
if (auto result_schema = acc.CreateVertexAndValidate(converted_label_ids, transformed_pk, converted_property_map); if (result_schema.HasError()) {
result_schema.HasError()) { shard_error.emplace(CreateErrorResponse(result_schema.GetError(), req.transaction_id, "creating vertices"));
LogResultError(result_schema.GetError(), "Creating Vertex");
action_successful = false;
break; break;
} }
} }
return msgs::CreateVerticesResponse{.success = action_successful}; return msgs::CreateVerticesResponse{std::move(shard_error)};
} }
msgs::WriteResponses ShardRsm::ApplyWrite(msgs::UpdateVerticesRequest &&req) { msgs::WriteResponses ShardRsm::ApplyWrite(msgs::UpdateVerticesRequest &&req) {
auto acc = shard_->Access(req.transaction_id); auto acc = shard_->Access(req.transaction_id);
bool action_successful = true; std::optional<msgs::ShardError> shard_error;
for (auto &vertex : req.update_vertices) { for (auto &vertex : req.update_vertices) {
if (!action_successful) {
break;
}
auto vertex_to_update = acc.FindVertex(ConvertPropertyVector(std::move(vertex.primary_key)), View::OLD); auto vertex_to_update = acc.FindVertex(ConvertPropertyVector(std::move(vertex.primary_key)), View::OLD);
if (!vertex_to_update) { if (!vertex_to_update) {
action_successful = false; shard_error.emplace(msgs::ShardError{common::ErrorCode::OBJECT_NOT_FOUND});
spdlog::debug("Vertex could not be found while trying to update its properties. Transaction id: {}", spdlog::debug("In transaction {} vertex could not be found while trying to update its properties.",
req.transaction_id.logical_id); req.transaction_id.logical_id);
continue; break;
} }
for (const auto label : vertex.add_labels) { for (const auto label : vertex.add_labels) {
if (const auto maybe_error = vertex_to_update->AddLabelAndValidate(label); maybe_error.HasError()) { if (const auto maybe_error = vertex_to_update->AddLabelAndValidate(label); maybe_error.HasError()) {
LogResultError(maybe_error.GetError(), "Add vertex labels"); shard_error.emplace(CreateErrorResponse(maybe_error.GetError(), req.transaction_id, "adding label"));
action_successful = false;
break; break;
} }
} }
for (const auto label : vertex.remove_labels) { for (const auto label : vertex.remove_labels) {
if (const auto maybe_error = vertex_to_update->RemoveLabelAndValidate(label); maybe_error.HasError()) { if (const auto maybe_error = vertex_to_update->RemoveLabelAndValidate(label); maybe_error.HasError()) {
LogResultError(maybe_error.GetError(), "Remove vertex labels"); shard_error.emplace(CreateErrorResponse(maybe_error.GetError(), req.transaction_id, "adding label"));
action_successful = false;
break; break;
} }
} }
@ -127,32 +126,28 @@ msgs::WriteResponses ShardRsm::ApplyWrite(msgs::UpdateVerticesRequest &&req) {
if (const auto result_schema = vertex_to_update->SetPropertyAndValidate( if (const auto result_schema = vertex_to_update->SetPropertyAndValidate(
update_prop.first, ToPropertyValue(std::move(update_prop.second))); update_prop.first, ToPropertyValue(std::move(update_prop.second)));
result_schema.HasError()) { result_schema.HasError()) {
action_successful = false; shard_error.emplace(CreateErrorResponse(result_schema.GetError(), req.transaction_id, "adding label"));
LogResultError(result_schema.GetError(), "Update vertex properties");
break; break;
} }
} }
} }
return msgs::UpdateVerticesResponse{.success = action_successful}; return msgs::UpdateVerticesResponse{std::move(shard_error)};
} }
msgs::WriteResponses ShardRsm::ApplyWrite(msgs::DeleteVerticesRequest &&req) { msgs::WriteResponses ShardRsm::ApplyWrite(msgs::DeleteVerticesRequest &&req) {
bool action_successful = true; std::optional<msgs::ShardError> shard_error;
auto acc = shard_->Access(req.transaction_id); auto acc = shard_->Access(req.transaction_id);
for (auto &propval : req.primary_keys) { for (auto &propval : req.primary_keys) {
if (!action_successful) {
break;
}
auto vertex_acc = acc.FindVertex(ConvertPropertyVector(std::move(propval)), View::OLD); auto vertex_acc = acc.FindVertex(ConvertPropertyVector(std::move(propval)), View::OLD);
if (!vertex_acc) { if (!vertex_acc) {
spdlog::debug("Error while trying to delete vertex. Vertex to delete does not exist. Transaction id: {}", shard_error.emplace(msgs::ShardError{common::ErrorCode::OBJECT_NOT_FOUND});
spdlog::debug("In transaction {} vertex could not be found while trying to delete it.",
req.transaction_id.logical_id); req.transaction_id.logical_id);
action_successful = false; break;
} else { }
// TODO(gvolfing) // TODO(gvolfing)
// Since we will not have different kinds of deletion types in one transaction, // Since we will not have different kinds of deletion types in one transaction,
// we dont have to enter the switch statement on every iteration. Optimize this. // we dont have to enter the switch statement on every iteration. Optimize this.
@ -160,32 +155,29 @@ msgs::WriteResponses ShardRsm::ApplyWrite(msgs::DeleteVerticesRequest &&req) {
case msgs::DeleteVerticesRequest::DeletionType::DELETE: { case msgs::DeleteVerticesRequest::DeletionType::DELETE: {
auto result = acc.DeleteVertex(&vertex_acc.value()); auto result = acc.DeleteVertex(&vertex_acc.value());
if (result.HasError() || !(result.GetValue().has_value())) { if (result.HasError() || !(result.GetValue().has_value())) {
action_successful = false; shard_error.emplace(CreateErrorResponse(result.GetError(), req.transaction_id, "deleting vertices"));
spdlog::debug("Error while trying to delete vertex. Transaction id: {}", req.transaction_id.logical_id);
} }
break; break;
} }
case msgs::DeleteVerticesRequest::DeletionType::DETACH_DELETE: { case msgs::DeleteVerticesRequest::DeletionType::DETACH_DELETE: {
auto result = acc.DetachDeleteVertex(&vertex_acc.value()); auto result = acc.DetachDeleteVertex(&vertex_acc.value());
if (result.HasError() || !(result.GetValue().has_value())) { if (result.HasError() || !(result.GetValue().has_value())) {
action_successful = false; shard_error.emplace(CreateErrorResponse(result.GetError(), req.transaction_id, "deleting vertices"));
spdlog::debug("Error while trying to detach and delete vertex. Transaction id: {}",
req.transaction_id.logical_id);
} }
break; break;
} }
} }
if (shard_error) {
break;
} }
} }
return msgs::DeleteVerticesResponse{.success = action_successful}; return msgs::DeleteVerticesResponse{std::move(shard_error)};
} }
msgs::WriteResponses ShardRsm::ApplyWrite(msgs::CreateExpandRequest &&req) { msgs::WriteResponses ShardRsm::ApplyWrite(msgs::CreateExpandRequest &&req) {
auto acc = shard_->Access(req.transaction_id); auto acc = shard_->Access(req.transaction_id);
bool action_successful = true; std::optional<msgs::ShardError> shard_error;
for (auto &new_expand : req.new_expands) { for (auto &new_expand : req.new_expands) {
const auto from_vertex_id = const auto from_vertex_id =
@ -195,7 +187,8 @@ msgs::WriteResponses ShardRsm::ApplyWrite(msgs::CreateExpandRequest &&req) {
VertexId{new_expand.dest_vertex.first.id, ConvertPropertyVector(std::move(new_expand.dest_vertex.second))}; VertexId{new_expand.dest_vertex.first.id, ConvertPropertyVector(std::move(new_expand.dest_vertex.second))};
if (!(shard_->IsVertexBelongToShard(from_vertex_id) || shard_->IsVertexBelongToShard(to_vertex_id))) { if (!(shard_->IsVertexBelongToShard(from_vertex_id) || shard_->IsVertexBelongToShard(to_vertex_id))) {
action_successful = false; shard_error = msgs::ShardError{common::ErrorCode::OBJECT_NOT_FOUND,
"Error while trying to insert edge, none of the vertices belong to this shard"};
spdlog::debug("Error while trying to insert edge, none of the vertices belong to this shard. Transaction id: {}", spdlog::debug("Error while trying to insert edge, none of the vertices belong to this shard. Transaction id: {}",
req.transaction_id.logical_id); req.transaction_id.logical_id);
break; break;
@ -207,18 +200,18 @@ msgs::WriteResponses ShardRsm::ApplyWrite(msgs::CreateExpandRequest &&req) {
if (!new_expand.properties.empty()) { if (!new_expand.properties.empty()) {
for (const auto &[property, value] : new_expand.properties) { for (const auto &[property, value] : new_expand.properties) {
if (const auto maybe_error = edge.SetProperty(property, ToPropertyValue(value)); maybe_error.HasError()) { if (const auto maybe_error = edge.SetProperty(property, ToPropertyValue(value)); maybe_error.HasError()) {
action_successful = false; shard_error.emplace(
spdlog::debug("Setting edge property was not successful. Transaction id: {}", CreateErrorResponse(maybe_error.GetError(), req.transaction_id, "setting edge property"));
req.transaction_id.logical_id);
break; break;
} }
if (!action_successful) {
break;
} }
if (shard_error) {
break;
} }
} }
} else { } else {
action_successful = false; // TODO Code for this
shard_error = msgs::ShardError{common::ErrorCode::OBJECT_NOT_FOUND};
spdlog::debug("Creating edge was not successful. Transaction id: {}", req.transaction_id.logical_id); spdlog::debug("Creating edge was not successful. Transaction id: {}", req.transaction_id.logical_id);
break; break;
} }
@ -228,24 +221,22 @@ msgs::WriteResponses ShardRsm::ApplyWrite(msgs::CreateExpandRequest &&req) {
for (auto &[edge_prop_key, edge_prop_val] : new_expand.properties) { for (auto &[edge_prop_key, edge_prop_val] : new_expand.properties) {
auto set_result = edge_acc->SetProperty(edge_prop_key, ToPropertyValue(std::move(edge_prop_val))); auto set_result = edge_acc->SetProperty(edge_prop_key, ToPropertyValue(std::move(edge_prop_val)));
if (set_result.HasError()) { if (set_result.HasError()) {
action_successful = false; shard_error.emplace(CreateErrorResponse(set_result.GetError(), req.transaction_id, "adding edge property"));
spdlog::debug("Adding property to edge was not successful. Transaction id: {}",
req.transaction_id.logical_id);
break; break;
} }
} }
} }
} }
return msgs::CreateExpandResponse{.success = action_successful}; return msgs::CreateExpandResponse{std::move(shard_error)};
} }
msgs::WriteResponses ShardRsm::ApplyWrite(msgs::DeleteEdgesRequest &&req) { msgs::WriteResponses ShardRsm::ApplyWrite(msgs::DeleteEdgesRequest &&req) {
bool action_successful = true; std::optional<msgs::ShardError> shard_error;
auto acc = shard_->Access(req.transaction_id); auto acc = shard_->Access(req.transaction_id);
for (auto &edge : req.edges) { for (auto &edge : req.edges) {
if (!action_successful) { if (shard_error) {
break; break;
} }
@ -253,41 +244,38 @@ msgs::WriteResponses ShardRsm::ApplyWrite(msgs::DeleteEdgesRequest &&req) {
VertexId(edge.dst.first.id, ConvertPropertyVector(std::move(edge.dst.second))), VertexId(edge.dst.first.id, ConvertPropertyVector(std::move(edge.dst.second))),
Gid::FromUint(edge.id.gid)); Gid::FromUint(edge.id.gid));
if (edge_acc.HasError() || !edge_acc.HasValue()) { if (edge_acc.HasError() || !edge_acc.HasValue()) {
spdlog::debug("Error while trying to delete edge. Transaction id: {}", req.transaction_id.logical_id); shard_error.emplace(CreateErrorResponse(edge_acc.GetError(), req.transaction_id, "delete edge"));
action_successful = false;
continue; continue;
} }
} }
return msgs::DeleteEdgesResponse{.success = action_successful}; return msgs::DeleteEdgesResponse{std::move(shard_error)};
} }
msgs::WriteResponses ShardRsm::ApplyWrite(msgs::UpdateEdgesRequest &&req) { msgs::WriteResponses ShardRsm::ApplyWrite(msgs::UpdateEdgesRequest &&req) {
// TODO(antaljanosbenjamin): handle when the vertex is the destination vertex // TODO(antaljanosbenjamin): handle when the vertex is the destination vertex
auto acc = shard_->Access(req.transaction_id); auto acc = shard_->Access(req.transaction_id);
bool action_successful = true; std::optional<msgs::ShardError> shard_error;
for (auto &edge : req.new_properties) { for (auto &edge : req.new_properties) {
if (!action_successful) { if (shard_error) {
break; break;
} }
auto vertex_acc = acc.FindVertex(ConvertPropertyVector(std::move(edge.src.second)), View::OLD); auto vertex_acc = acc.FindVertex(ConvertPropertyVector(std::move(edge.src.second)), View::OLD);
if (!vertex_acc) { if (!vertex_acc) {
action_successful = false; shard_error = msgs::ShardError{common::ErrorCode::OBJECT_NOT_FOUND, "Source vertex was not found"};
spdlog::debug("Encountered an error while trying to acquire VertexAccessor with transaction id: {}", spdlog::debug("Encountered an error while trying to acquire VertexAccessor with transaction id: {}",
req.transaction_id.logical_id); req.transaction_id.logical_id);
continue; continue;
} }
// Since we are using the source vertex of the edge we are only intrested // Since we are using the source vertex of the edge we are only interested
// in the vertex's out-going edges // in the vertex's out-going edges
auto edges_res = vertex_acc->OutEdges(View::OLD); auto edges_res = vertex_acc->OutEdges(View::OLD);
if (edges_res.HasError()) { if (edges_res.HasError()) {
action_successful = false; shard_error.emplace(CreateErrorResponse(edges_res.GetError(), req.transaction_id, "update edge"));
spdlog::debug("Encountered an error while trying to acquire EdgeAccessor with transaction id: {}",
req.transaction_id.logical_id);
continue; continue;
} }
@ -303,27 +291,28 @@ msgs::WriteResponses ShardRsm::ApplyWrite(msgs::UpdateEdgesRequest &&req) {
// Check if the property was set if SetProperty does not do that itself. // Check if the property was set if SetProperty does not do that itself.
auto res = edge_accessor.SetProperty(key, ToPropertyValue(std::move(value))); auto res = edge_accessor.SetProperty(key, ToPropertyValue(std::move(value)));
if (res.HasError()) { if (res.HasError()) {
spdlog::debug("Encountered an error while trying to set the property of an Edge with transaction id: {}", // TODO(jbajic) why not set action unsuccessful here?
req.transaction_id.logical_id); shard_error.emplace(CreateErrorResponse(edges_res.GetError(), req.transaction_id, "update edge"));
} }
} }
} }
} }
if (!edge_accessor_did_match) { if (!edge_accessor_did_match) {
action_successful = false; // TODO(jbajic) Do we need this
shard_error = msgs::ShardError{common::ErrorCode::OBJECT_NOT_FOUND, "Edge was not found"};
spdlog::debug("Could not find the Edge with the specified Gid. Transaction id: {}", spdlog::debug("Could not find the Edge with the specified Gid. Transaction id: {}",
req.transaction_id.logical_id); req.transaction_id.logical_id);
continue; continue;
} }
} }
return msgs::UpdateEdgesResponse{.success = action_successful}; return msgs::UpdateEdgesResponse{std::move(shard_error)};
} }
msgs::ReadResponses ShardRsm::HandleRead(msgs::ScanVerticesRequest &&req) { msgs::ReadResponses ShardRsm::HandleRead(msgs::ScanVerticesRequest &&req) {
auto acc = shard_->Access(req.transaction_id); auto acc = shard_->Access(req.transaction_id);
bool action_successful = true; std::optional<msgs::ShardError> shard_error;
std::vector<msgs::ScanResultRow> results; std::vector<msgs::ScanResultRow> results;
if (req.batch_limit) { if (req.batch_limit) {
@ -348,25 +337,24 @@ msgs::ReadResponses ShardRsm::HandleRead(msgs::ScanVerticesRequest &&req) {
EvaluateVertexExpressions(dba, vertex, req.vertex_expressions, expr::identifier_node_symbol)); EvaluateVertexExpressions(dba, vertex, req.vertex_expressions, expr::identifier_node_symbol));
} }
std::optional<std::map<PropertyId, Value>> found_props; auto found_props = std::invoke([&]() {
if (req.props_to_return) { if (req.props_to_return) {
found_props = CollectSpecificPropertiesFromAccessor(vertex, req.props_to_return.value(), view); return CollectSpecificPropertiesFromAccessor(vertex, req.props_to_return.value(), view);
} else { }
const auto *schema = shard_->GetSchema(shard_->PrimaryLabel()); const auto *schema = shard_->GetSchema(shard_->PrimaryLabel());
MG_ASSERT(schema); MG_ASSERT(schema);
found_props = CollectAllPropertiesFromAccessor(vertex, view, *schema); return CollectAllPropertiesFromAccessor(vertex, view, *schema);
} });
// TODO(gvolfing) -VERIFY- // TODO(gvolfing) -VERIFY-
// Vertex is separated from the properties in the response. // Vertex is separated from the properties in the response.
// Is it useful to return just a vertex without the properties? // Is it useful to return just a vertex without the properties?
if (!found_props) { if (found_props.HasError()) {
action_successful = false; shard_error = msgs::ShardError{common::ErrorCode::OBJECT_NOT_FOUND, "Requested properties were not found!"};
} }
results.emplace_back(msgs::ScanResultRow{.vertex = ConstructValueVertex(vertex, view).vertex_v, results.emplace_back(msgs::ScanResultRow{.vertex = ConstructValueVertex(vertex, view).vertex_v,
.props = FromMap(found_props.value()), .props = FromMap(found_props.GetValue()),
.evaluated_vertex_expressions = std::move(expression_results)}); .evaluated_vertex_expressions = std::move(expression_results)});
}; };
@ -410,10 +398,8 @@ msgs::ReadResponses ShardRsm::HandleRead(msgs::ScanVerticesRequest &&req) {
} }
} }
msgs::ScanVerticesResponse resp{}; msgs::ScanVerticesResponse resp{.error = std::move(shard_error)};
resp.success = action_successful; if (!resp.error) {
if (action_successful) {
resp.next_start_id = next_start_id; resp.next_start_id = next_start_id;
resp.results = std::move(results); resp.results = std::move(results);
} }
@ -423,13 +409,13 @@ msgs::ReadResponses ShardRsm::HandleRead(msgs::ScanVerticesRequest &&req) {
msgs::ReadResponses ShardRsm::HandleRead(msgs::ExpandOneRequest &&req) { msgs::ReadResponses ShardRsm::HandleRead(msgs::ExpandOneRequest &&req) {
auto acc = shard_->Access(req.transaction_id); auto acc = shard_->Access(req.transaction_id);
bool action_successful = true; std::optional<msgs::ShardError> shard_error;
std::vector<msgs::ExpandOneResultRow> results; std::vector<msgs::ExpandOneResultRow> results;
const auto batch_limit = req.limit; const auto batch_limit = req.limit;
auto dba = DbAccessor{&acc}; auto dba = DbAccessor{&acc};
auto maybe_filter_based_on_edge_uniquness = InitializeEdgeUniqunessFunction(req.only_unique_neighbor_rows); auto maybe_filter_based_on_edge_uniqueness = InitializeEdgeUniquenessFunction(req.only_unique_neighbor_rows);
auto edge_filler = InitializeEdgeFillerFunction(req); auto edge_filler = InitializeEdgeFillerFunction(req);
std::vector<VertexAccessor> vertex_accessors; std::vector<VertexAccessor> vertex_accessors;
@ -438,7 +424,7 @@ msgs::ReadResponses ShardRsm::HandleRead(msgs::ExpandOneRequest &&req) {
// Get Vertex acc // Get Vertex acc
auto src_vertex_acc_opt = acc.FindVertex(ConvertPropertyVector((src_vertex.second)), View::NEW); auto src_vertex_acc_opt = acc.FindVertex(ConvertPropertyVector((src_vertex.second)), View::NEW);
if (!src_vertex_acc_opt) { if (!src_vertex_acc_opt) {
action_successful = false; shard_error = msgs::ShardError{common::ErrorCode::OBJECT_NOT_FOUND, "Source vertex was not found."};
spdlog::debug("Encountered an error while trying to obtain VertexAccessor. Transaction id: {}", spdlog::debug("Encountered an error while trying to obtain VertexAccessor. Transaction id: {}",
req.transaction_id.logical_id); req.transaction_id.logical_id);
break; break;
@ -466,27 +452,23 @@ msgs::ReadResponses ShardRsm::HandleRead(msgs::ExpandOneRequest &&req) {
for (const auto &src_vertex_acc : vertex_accessors) { for (const auto &src_vertex_acc : vertex_accessors) {
auto label_id = src_vertex_acc.PrimaryLabel(View::NEW); auto label_id = src_vertex_acc.PrimaryLabel(View::NEW);
if (label_id.HasError()) { if (label_id.HasError()) {
action_successful = false; shard_error.emplace(CreateErrorResponse(label_id.GetError(), req.transaction_id, "getting label"));
break;
} }
auto primary_key = src_vertex_acc.PrimaryKey(View::NEW); auto primary_key = src_vertex_acc.PrimaryKey(View::NEW);
if (primary_key.HasError()) { if (primary_key.HasError()) {
action_successful = false; shard_error.emplace(CreateErrorResponse(primary_key.GetError(), req.transaction_id, "getting primary key"));
break; break;
} }
msgs::VertexId src_vertex(msgs::Label{.id = *label_id}, conversions::ConvertValueVector(*primary_key)); msgs::VertexId src_vertex(msgs::Label{.id = *label_id}, conversions::ConvertValueVector(*primary_key));
std::optional<msgs::ExpandOneResultRow> maybe_result; auto maybe_result = std::invoke([&]() {
if (req.order_by_edges.empty()) { if (req.order_by_edges.empty()) {
const auto *schema = shard_->GetSchema(shard_->PrimaryLabel()); const auto *schema = shard_->GetSchema(shard_->PrimaryLabel());
MG_ASSERT(schema); MG_ASSERT(schema);
maybe_result = return GetExpandOneResult(acc, src_vertex, req, maybe_filter_based_on_edge_uniqueness, edge_filler, *schema);
GetExpandOneResult(acc, src_vertex, req, maybe_filter_based_on_edge_uniquness, edge_filler, *schema); }
} else {
auto [in_edge_accessors, out_edge_accessors] = GetEdgesFromVertex(src_vertex_acc, req.direction); auto [in_edge_accessors, out_edge_accessors] = GetEdgesFromVertex(src_vertex_acc, req.direction);
const auto in_ordered_edges = OrderByEdges(dba, in_edge_accessors, req.order_by_edges, src_vertex_acc); const auto in_ordered_edges = OrderByEdges(dba, in_edge_accessors, req.order_by_edges, src_vertex_acc);
const auto out_ordered_edges = OrderByEdges(dba, out_edge_accessors, req.order_by_edges, src_vertex_acc); const auto out_ordered_edges = OrderByEdges(dba, out_edge_accessors, req.order_by_edges, src_vertex_acc);
@ -500,25 +482,23 @@ msgs::ReadResponses ShardRsm::HandleRead(msgs::ExpandOneRequest &&req) {
[](const auto &edge_element) { return edge_element.object_acc; }); [](const auto &edge_element) { return edge_element.object_acc; });
const auto *schema = shard_->GetSchema(shard_->PrimaryLabel()); const auto *schema = shard_->GetSchema(shard_->PrimaryLabel());
MG_ASSERT(schema); MG_ASSERT(schema);
maybe_result = return GetExpandOneResult(src_vertex_acc, src_vertex, req, in_edge_ordered_accessors, out_edge_ordered_accessors,
GetExpandOneResult(src_vertex_acc, src_vertex, req, in_edge_ordered_accessors, out_edge_ordered_accessors, maybe_filter_based_on_edge_uniqueness, edge_filler, *schema);
maybe_filter_based_on_edge_uniquness, edge_filler, *schema); });
}
if (!maybe_result) { if (maybe_result.HasError()) {
action_successful = false; shard_error.emplace(CreateErrorResponse(primary_key.GetError(), req.transaction_id, "getting primary key"));
break; break;
} }
results.emplace_back(std::move(maybe_result.value())); results.emplace_back(std::move(maybe_result.GetValue()));
if (batch_limit.has_value() && results.size() >= batch_limit.value()) { if (batch_limit.has_value() && results.size() >= batch_limit.value()) {
break; break;
} }
} }
msgs::ExpandOneResponse resp{}; msgs::ExpandOneResponse resp{.error = std::move(shard_error)};
resp.success = action_successful; if (!resp.error) {
if (action_successful) {
resp.result = std::move(results); resp.result = std::move(results);
} }
@ -527,7 +507,7 @@ msgs::ReadResponses ShardRsm::HandleRead(msgs::ExpandOneRequest &&req) {
msgs::WriteResponses ShardRsm::ApplyWrite(msgs::CommitRequest &&req) { msgs::WriteResponses ShardRsm::ApplyWrite(msgs::CommitRequest &&req) {
shard_->Access(req.transaction_id).Commit(req.commit_timestamp); shard_->Access(req.transaction_id).Commit(req.commit_timestamp);
return msgs::CommitResponse{true}; return msgs::CommitResponse{};
}; };
// NOLINTNEXTLINE(readability-convert-member-functions-to-static) // NOLINTNEXTLINE(readability-convert-member-functions-to-static)

View File

@ -21,8 +21,8 @@
#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/property_value.hpp" #include "storage/v3/property_value.hpp"
#include "storage/v3/result.hpp"
#include "storage/v3/shard.hpp" #include "storage/v3/shard.hpp"
#include "storage/v3/shard_operation_result.hpp"
#include "storage/v3/vertex.hpp" #include "storage/v3/vertex.hpp"
#include "utils/logging.hpp" #include "utils/logging.hpp"
#include "utils/memory_tracker.hpp" #include "utils/memory_tracker.hpp"
@ -80,12 +80,12 @@ bool VertexAccessor::IsVisible(View view) const {
return exists && (for_deleted_ || !deleted); return exists && (for_deleted_ || !deleted);
} }
Result<bool> VertexAccessor::AddLabel(LabelId label) { ShardResult<bool> VertexAccessor::AddLabel(LabelId label) {
utils::MemoryTracker::OutOfMemoryExceptionEnabler oom_exception; utils::MemoryTracker::OutOfMemoryExceptionEnabler oom_exception;
if (!PrepareForWrite(transaction_, vertex_)) return Error::SERIALIZATION_ERROR; if (!PrepareForWrite(transaction_, vertex_)) return SHARD_ERROR(ErrorCode::SERIALIZATION_ERROR);
if (vertex_->deleted) return Error::DELETED_OBJECT; if (vertex_->deleted) return SHARD_ERROR(ErrorCode::DELETED_OBJECT);
if (std::find(vertex_->labels.begin(), vertex_->labels.end(), label) != vertex_->labels.end()) return false; if (std::find(vertex_->labels.begin(), vertex_->labels.end(), label) != vertex_->labels.end()) return false;
@ -98,15 +98,15 @@ Result<bool> VertexAccessor::AddLabel(LabelId label) {
return true; return true;
} }
ShardOperationResult<bool> VertexAccessor::AddLabelAndValidate(LabelId label) { ShardResult<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.HasError()) {
return {*maybe_violation_error}; return {maybe_violation_error.GetError()};
} }
utils::MemoryTracker::OutOfMemoryExceptionEnabler oom_exception; utils::MemoryTracker::OutOfMemoryExceptionEnabler oom_exception;
if (!PrepareForWrite(transaction_, vertex_)) return {Error::SERIALIZATION_ERROR}; if (!PrepareForWrite(transaction_, vertex_)) return SHARD_ERROR(ErrorCode::SERIALIZATION_ERROR);
if (vertex_->deleted) return {Error::DELETED_OBJECT}; if (vertex_->deleted) return SHARD_ERROR(ErrorCode::DELETED_OBJECT);
if (std::find(vertex_->labels.begin(), vertex_->labels.end(), label) != vertex_->labels.end()) return false; if (std::find(vertex_->labels.begin(), vertex_->labels.end(), label) != vertex_->labels.end()) return false;
@ -119,10 +119,10 @@ ShardOperationResult<bool> VertexAccessor::AddLabelAndValidate(LabelId label) {
return true; return true;
} }
Result<bool> VertexAccessor::RemoveLabel(LabelId label) { ShardResult<bool> VertexAccessor::RemoveLabel(LabelId label) {
if (!PrepareForWrite(transaction_, vertex_)) return Error::SERIALIZATION_ERROR; if (!PrepareForWrite(transaction_, vertex_)) return SHARD_ERROR(ErrorCode::SERIALIZATION_ERROR);
if (vertex_->deleted) return Error::DELETED_OBJECT; if (vertex_->deleted) return SHARD_ERROR(ErrorCode::DELETED_OBJECT);
auto it = std::find(vertex_->labels.begin(), vertex_->labels.end(), label); auto it = std::find(vertex_->labels.begin(), vertex_->labels.end(), label);
if (it == vertex_->labels.end()) return false; if (it == vertex_->labels.end()) return false;
@ -134,14 +134,15 @@ Result<bool> VertexAccessor::RemoveLabel(LabelId label) {
return true; return true;
} }
ShardOperationResult<bool> VertexAccessor::RemoveLabelAndValidate(LabelId label) { ShardResult<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);
return {*maybe_violation_error}; maybe_violation_error.HasError()) {
return {maybe_violation_error.GetError()};
} }
if (!PrepareForWrite(transaction_, vertex_)) return {Error::SERIALIZATION_ERROR}; if (!PrepareForWrite(transaction_, vertex_)) return SHARD_ERROR(ErrorCode::SERIALIZATION_ERROR);
if (vertex_->deleted) return {Error::DELETED_OBJECT}; if (vertex_->deleted) return SHARD_ERROR(ErrorCode::DELETED_OBJECT);
auto it = std::find(vertex_->labels.begin(), vertex_->labels.end(), label); auto it = std::find(vertex_->labels.begin(), vertex_->labels.end(), label);
if (it == vertex_->labels.end()) return false; if (it == vertex_->labels.end()) return false;
@ -153,9 +154,9 @@ ShardOperationResult<bool> VertexAccessor::RemoveLabelAndValidate(LabelId label)
return true; return true;
} }
Result<bool> VertexAccessor::HasLabel(View view, LabelId label) const { return HasLabel(label, view); } ShardResult<bool> VertexAccessor::HasLabel(View view, LabelId label) const { return HasLabel(label, view); }
Result<bool> VertexAccessor::HasLabel(LabelId label, View view) const { ShardResult<bool> VertexAccessor::HasLabel(LabelId label, View view) const {
bool exists = true; bool exists = true;
bool deleted = false; bool deleted = false;
bool has_label = false; bool has_label = false;
@ -197,12 +198,12 @@ Result<bool> VertexAccessor::HasLabel(LabelId label, View view) const {
break; break;
} }
}); });
if (!exists) return Error::NONEXISTENT_OBJECT; if (!exists) return SHARD_ERROR(ErrorCode::NONEXISTENT_OBJECT);
if (!for_deleted_ && deleted) return Error::DELETED_OBJECT; if (!for_deleted_ && deleted) return SHARD_ERROR(ErrorCode::DELETED_OBJECT);
return has_label; return has_label;
} }
Result<LabelId> VertexAccessor::PrimaryLabel(const View view) const { ShardResult<LabelId> VertexAccessor::PrimaryLabel(const View view) const {
if (const auto result = CheckVertexExistence(view); result.HasError()) { if (const auto result = CheckVertexExistence(view); result.HasError()) {
return result.GetError(); return result.GetError();
} }
@ -210,21 +211,21 @@ Result<LabelId> VertexAccessor::PrimaryLabel(const View view) const {
return vertex_validator_->primary_label_; return vertex_validator_->primary_label_;
} }
Result<PrimaryKey> VertexAccessor::PrimaryKey(const View view) const { ShardResult<PrimaryKey> VertexAccessor::PrimaryKey(const View view) const {
if (const auto result = CheckVertexExistence(view); result.HasError()) { if (const auto result = CheckVertexExistence(view); result.HasError()) {
return result.GetError(); return result.GetError();
} }
return vertex_->keys.Keys(); return vertex_->keys.Keys();
} }
Result<VertexId> VertexAccessor::Id(View view) const { ShardResult<VertexId> VertexAccessor::Id(View view) const {
if (const auto result = CheckVertexExistence(view); result.HasError()) { if (const auto result = CheckVertexExistence(view); result.HasError()) {
return result.GetError(); return result.GetError();
} }
return VertexId{vertex_validator_->primary_label_, vertex_->keys.Keys()}; return VertexId{vertex_validator_->primary_label_, vertex_->keys.Keys()};
}; };
Result<std::vector<LabelId>> VertexAccessor::Labels(View view) const { ShardResult<std::vector<LabelId>> VertexAccessor::Labels(View view) const {
bool exists = true; bool exists = true;
bool deleted = false; bool deleted = false;
std::vector<LabelId> labels; std::vector<LabelId> labels;
@ -267,17 +268,17 @@ Result<std::vector<LabelId>> VertexAccessor::Labels(View view) const {
break; break;
} }
}); });
if (!exists) return Error::NONEXISTENT_OBJECT; if (!exists) return SHARD_ERROR(ErrorCode::NONEXISTENT_OBJECT);
if (!for_deleted_ && deleted) return Error::DELETED_OBJECT; if (!for_deleted_ && deleted) return SHARD_ERROR(ErrorCode::DELETED_OBJECT);
return std::move(labels); return std::move(labels);
} }
Result<PropertyValue> VertexAccessor::SetProperty(PropertyId property, const PropertyValue &value) { ShardResult<PropertyValue> VertexAccessor::SetProperty(PropertyId property, const PropertyValue &value) {
utils::MemoryTracker::OutOfMemoryExceptionEnabler oom_exception; utils::MemoryTracker::OutOfMemoryExceptionEnabler oom_exception;
if (!PrepareForWrite(transaction_, vertex_)) return Error::SERIALIZATION_ERROR; if (!PrepareForWrite(transaction_, vertex_)) return SHARD_ERROR(ErrorCode::SERIALIZATION_ERROR);
if (vertex_->deleted) return Error::DELETED_OBJECT; if (vertex_->deleted) return SHARD_ERROR(ErrorCode::DELETED_OBJECT);
auto current_value = vertex_->properties.GetProperty(property); auto current_value = vertex_->properties.GetProperty(property);
// We could skip setting the value if the previous one is the same to the new // We could skip setting the value if the previous one is the same to the new
@ -294,7 +295,7 @@ Result<PropertyValue> VertexAccessor::SetProperty(PropertyId property, const Pro
return std::move(current_value); return std::move(current_value);
} }
Result<void> VertexAccessor::CheckVertexExistence(View view) const { ShardResult<void> VertexAccessor::CheckVertexExistence(View view) const {
bool exists = true; bool exists = true;
bool deleted = false; bool deleted = false;
Delta *delta = nullptr; Delta *delta = nullptr;
@ -323,27 +324,27 @@ Result<void> VertexAccessor::CheckVertexExistence(View view) const {
} }
}); });
if (!exists) { if (!exists) {
return Error::NONEXISTENT_OBJECT; return SHARD_ERROR(ErrorCode::NONEXISTENT_OBJECT);
} }
if (!for_deleted_ && deleted) { if (!for_deleted_ && deleted) {
return Error::DELETED_OBJECT; return SHARD_ERROR(ErrorCode::DELETED_OBJECT);
} }
return {}; return {};
} }
ShardOperationResult<PropertyValue> VertexAccessor::SetPropertyAndValidate(PropertyId property, ShardResult<PropertyValue> VertexAccessor::SetPropertyAndValidate(PropertyId property, const PropertyValue &value) {
const PropertyValue &value) { if (auto maybe_violation_error = vertex_validator_->ValidatePropertyUpdate(property);
if (auto maybe_violation_error = vertex_validator_->ValidatePropertyUpdate(property); maybe_violation_error) { maybe_violation_error.HasError()) {
return {*maybe_violation_error}; return {maybe_violation_error.GetError()};
} }
utils::MemoryTracker::OutOfMemoryExceptionEnabler oom_exception; utils::MemoryTracker::OutOfMemoryExceptionEnabler oom_exception;
if (!PrepareForWrite(transaction_, vertex_)) { if (!PrepareForWrite(transaction_, vertex_)) {
return {Error::SERIALIZATION_ERROR}; return SHARD_ERROR(ErrorCode::SERIALIZATION_ERROR);
} }
if (vertex_->deleted) { if (vertex_->deleted) {
return {Error::DELETED_OBJECT}; return SHARD_ERROR(ErrorCode::DELETED_OBJECT);
} }
auto current_value = vertex_->properties.GetProperty(property); auto current_value = vertex_->properties.GetProperty(property);
@ -361,10 +362,10 @@ ShardOperationResult<PropertyValue> VertexAccessor::SetPropertyAndValidate(Prope
return std::move(current_value); return std::move(current_value);
} }
Result<std::map<PropertyId, PropertyValue>> VertexAccessor::ClearProperties() { ShardResult<std::map<PropertyId, PropertyValue>> VertexAccessor::ClearProperties() {
if (!PrepareForWrite(transaction_, vertex_)) return Error::SERIALIZATION_ERROR; if (!PrepareForWrite(transaction_, vertex_)) return SHARD_ERROR(ErrorCode::SERIALIZATION_ERROR);
if (vertex_->deleted) return Error::DELETED_OBJECT; if (vertex_->deleted) return SHARD_ERROR(ErrorCode::DELETED_OBJECT);
auto properties = vertex_->properties.Properties(); auto properties = vertex_->properties.Properties();
for (const auto &property : properties) { for (const auto &property : properties) {
@ -377,7 +378,7 @@ Result<std::map<PropertyId, PropertyValue>> VertexAccessor::ClearProperties() {
return std::move(properties); return std::move(properties);
} }
Result<PropertyValue> VertexAccessor::GetProperty(View view, PropertyId property) const { ShardResult<PropertyValue> VertexAccessor::GetProperty(View view, PropertyId property) const {
return GetProperty(property, view).GetValue(); return GetProperty(property, view).GetValue();
} }
@ -407,7 +408,7 @@ PropertyValue VertexAccessor::GetPropertyValue(PropertyId property, View view) c
return value; return value;
} }
Result<PropertyValue> VertexAccessor::GetProperty(PropertyId property, View view) const { ShardResult<PropertyValue> VertexAccessor::GetProperty(PropertyId property, View view) const {
bool exists = true; bool exists = true;
bool deleted = false; bool deleted = false;
PropertyValue value; PropertyValue value;
@ -442,12 +443,12 @@ Result<PropertyValue> VertexAccessor::GetProperty(PropertyId property, View view
break; break;
} }
}); });
if (!exists) return Error::NONEXISTENT_OBJECT; if (!exists) return SHARD_ERROR(ErrorCode::NONEXISTENT_OBJECT);
if (!for_deleted_ && deleted) return Error::DELETED_OBJECT; if (!for_deleted_ && deleted) return SHARD_ERROR(ErrorCode::DELETED_OBJECT);
return std::move(value); return std::move(value);
} }
Result<std::map<PropertyId, PropertyValue>> VertexAccessor::Properties(View view) const { ShardResult<std::map<PropertyId, PropertyValue>> VertexAccessor::Properties(View view) const {
bool exists = true; bool exists = true;
bool deleted = false; bool deleted = false;
std::map<PropertyId, PropertyValue> properties; std::map<PropertyId, PropertyValue> properties;
@ -492,12 +493,12 @@ Result<std::map<PropertyId, PropertyValue>> VertexAccessor::Properties(View view
break; break;
} }
}); });
if (!exists) return Error::NONEXISTENT_OBJECT; if (!exists) return SHARD_ERROR(ErrorCode::NONEXISTENT_OBJECT);
if (!for_deleted_ && deleted) return Error::DELETED_OBJECT; if (!for_deleted_ && deleted) return SHARD_ERROR(ErrorCode::DELETED_OBJECT);
return std::move(properties); return std::move(properties);
} }
Result<std::vector<EdgeAccessor>> VertexAccessor::InEdges(View view, const std::vector<EdgeTypeId> &edge_types, ShardResult<std::vector<EdgeAccessor>> VertexAccessor::InEdges(View view, const std::vector<EdgeTypeId> &edge_types,
const VertexId *destination_id) const { const VertexId *destination_id) const {
bool exists = true; bool exists = true;
bool deleted = false; bool deleted = false;
@ -564,8 +565,8 @@ Result<std::vector<EdgeAccessor>> VertexAccessor::InEdges(View view, const std::
break; break;
} }
}); });
if (!exists) return Error::NONEXISTENT_OBJECT; if (!exists) return SHARD_ERROR(ErrorCode::NONEXISTENT_OBJECT);
if (deleted) return Error::DELETED_OBJECT; if (deleted) return SHARD_ERROR(ErrorCode::DELETED_OBJECT);
std::vector<EdgeAccessor> ret; std::vector<EdgeAccessor> ret;
if (in_edges.empty()) { if (in_edges.empty()) {
return ret; return ret;
@ -579,7 +580,7 @@ Result<std::vector<EdgeAccessor>> VertexAccessor::InEdges(View view, const std::
return ret; return ret;
} }
Result<std::vector<EdgeAccessor>> VertexAccessor::OutEdges(View view, const std::vector<EdgeTypeId> &edge_types, ShardResult<std::vector<EdgeAccessor>> VertexAccessor::OutEdges(View view, const std::vector<EdgeTypeId> &edge_types,
const VertexId *destination_id) const { const VertexId *destination_id) const {
bool exists = true; bool exists = true;
bool deleted = false; bool deleted = false;
@ -644,8 +645,8 @@ Result<std::vector<EdgeAccessor>> VertexAccessor::OutEdges(View view, const std:
break; break;
} }
}); });
if (!exists) return Error::NONEXISTENT_OBJECT; if (!exists) return SHARD_ERROR(ErrorCode::NONEXISTENT_OBJECT);
if (deleted) return Error::DELETED_OBJECT; if (deleted) return SHARD_ERROR(ErrorCode::DELETED_OBJECT);
std::vector<EdgeAccessor> ret; std::vector<EdgeAccessor> ret;
if (out_edges.empty()) { if (out_edges.empty()) {
return ret; return ret;
@ -659,7 +660,7 @@ Result<std::vector<EdgeAccessor>> VertexAccessor::OutEdges(View view, const std:
return ret; return ret;
} }
Result<size_t> VertexAccessor::InDegree(View view) const { ShardResult<size_t> VertexAccessor::InDegree(View view) const {
bool exists = true; bool exists = true;
bool deleted = false; bool deleted = false;
size_t degree = 0; size_t degree = 0;
@ -691,12 +692,12 @@ Result<size_t> VertexAccessor::InDegree(View view) const {
break; break;
} }
}); });
if (!exists) return Error::NONEXISTENT_OBJECT; if (!exists) return SHARD_ERROR(ErrorCode::NONEXISTENT_OBJECT);
if (!for_deleted_ && deleted) return Error::DELETED_OBJECT; if (!for_deleted_ && deleted) return SHARD_ERROR(ErrorCode::DELETED_OBJECT);
return degree; return degree;
} }
Result<size_t> VertexAccessor::OutDegree(View view) const { ShardResult<size_t> VertexAccessor::OutDegree(View view) const {
bool exists = true; bool exists = true;
bool deleted = false; bool deleted = false;
size_t degree = 0; size_t degree = 0;
@ -728,8 +729,8 @@ Result<size_t> VertexAccessor::OutDegree(View view) const {
break; break;
} }
}); });
if (!exists) return Error::NONEXISTENT_OBJECT; if (!exists) return SHARD_ERROR(ErrorCode::NONEXISTENT_OBJECT);
if (!for_deleted_ && deleted) return Error::DELETED_OBJECT; if (!for_deleted_ && deleted) return SHARD_ERROR(ErrorCode::DELETED_OBJECT);
return degree; return degree;
} }

View File

@ -17,7 +17,7 @@
#include "storage/v3/id_types.hpp" #include "storage/v3/id_types.hpp"
#include "storage/v3/key_store.hpp" #include "storage/v3/key_store.hpp"
#include "storage/v3/result.hpp" #include "storage/v3/result.hpp"
#include "storage/v3/shard_operation_result.hpp" #include "storage/v3/schema_validator.hpp"
#include "storage/v3/transaction.hpp" #include "storage/v3/transaction.hpp"
#include "storage/v3/vertex.hpp" #include "storage/v3/vertex.hpp"
#include "storage/v3/vertex_id.hpp" #include "storage/v3/vertex_id.hpp"
@ -55,61 +55,61 @@ class VertexAccessor final {
/// `false` is returned if the label already existed, or SchemaViolation /// `false` is returned if the label already existed, or SchemaViolation
/// if adding the label has violated one of the schema constraints. /// if adding the label has violated one of the schema constraints.
/// @throw std::bad_alloc /// @throw std::bad_alloc
ShardOperationResult<bool> AddLabelAndValidate(LabelId label); ShardResult<bool> AddLabelAndValidate(LabelId label);
/// Remove a label and return `true` if deletion took place. /// Remove a label and return `true` if deletion took place.
/// `false` is returned if the vertex did not have a label already. or SchemaViolation /// `false` is returned if the vertex did not have a label already. or SchemaViolation
/// if adding the label has violated one of the schema constraints. /// if adding the label has violated one of the schema constraints.
/// @throw std::bad_alloc /// @throw std::bad_alloc
ShardOperationResult<bool> RemoveLabelAndValidate(LabelId label); ShardResult<bool> RemoveLabelAndValidate(LabelId label);
Result<bool> HasLabel(View view, LabelId label) const; ShardResult<bool> HasLabel(View view, LabelId label) const;
Result<bool> HasLabel(LabelId label, View view) const; ShardResult<bool> HasLabel(LabelId label, View view) const;
/// @throw std::bad_alloc /// @throw std::bad_alloc
/// @throw std::length_error if the resulting vector exceeds /// @throw std::length_error if the resulting vector exceeds
/// std::vector::max_size(). /// std::vector::max_size().
Result<std::vector<LabelId>> Labels(View view) const; ShardResult<std::vector<LabelId>> Labels(View view) const;
Result<LabelId> PrimaryLabel(View view) const; ShardResult<LabelId> PrimaryLabel(View view) const;
Result<PrimaryKey> PrimaryKey(View view) const; ShardResult<PrimaryKey> PrimaryKey(View view) const;
Result<VertexId> Id(View view) const; ShardResult<VertexId> Id(View view) const;
/// Set a property value and return the old value or error. /// Set a property value and return the old value or error.
/// @throw std::bad_alloc /// @throw std::bad_alloc
ShardOperationResult<PropertyValue> SetPropertyAndValidate(PropertyId property, const PropertyValue &value); ShardResult<PropertyValue> SetPropertyAndValidate(PropertyId property, const PropertyValue &value);
/// Remove all properties and return the values of the removed properties. /// Remove all properties and return the values of the removed properties.
/// @throw std::bad_alloc /// @throw std::bad_alloc
Result<std::map<PropertyId, PropertyValue>> ClearProperties(); ShardResult<std::map<PropertyId, PropertyValue>> ClearProperties();
/// @throw std::bad_alloc /// @throw std::bad_alloc
Result<PropertyValue> GetProperty(PropertyId property, View view) const; ShardResult<PropertyValue> GetProperty(PropertyId property, View view) const;
// TODO Remove this // TODO Remove this
Result<PropertyValue> GetProperty(View view, PropertyId property) const; ShardResult<PropertyValue> GetProperty(View view, PropertyId property) const;
/// @throw std::bad_alloc /// @throw std::bad_alloc
Result<std::map<PropertyId, PropertyValue>> Properties(View view) const; ShardResult<std::map<PropertyId, PropertyValue>> Properties(View view) const;
/// @throw std::bad_alloc /// @throw std::bad_alloc
/// @throw std::length_error if the resulting vector exceeds /// @throw std::length_error if the resulting vector exceeds
/// std::vector::max_size(). /// std::vector::max_size().
Result<std::vector<EdgeAccessor>> InEdges(View view, const std::vector<EdgeTypeId> &edge_types = {}, ShardResult<std::vector<EdgeAccessor>> InEdges(View view, const std::vector<EdgeTypeId> &edge_types = {},
const VertexId *destination_id = nullptr) const; const VertexId *destination_id = nullptr) const;
/// @throw std::bad_alloc /// @throw std::bad_alloc
/// @throw std::length_error if the resulting vector exceeds /// @throw std::length_error if the resulting vector exceeds
/// std::vector::max_size(). /// std::vector::max_size().
Result<std::vector<EdgeAccessor>> OutEdges(View view, const std::vector<EdgeTypeId> &edge_types = {}, ShardResult<std::vector<EdgeAccessor>> OutEdges(View view, const std::vector<EdgeTypeId> &edge_types = {},
const VertexId *destination_id = nullptr) const; const VertexId *destination_id = nullptr) const;
Result<size_t> InDegree(View view) const; ShardResult<size_t> InDegree(View view) const;
Result<size_t> OutDegree(View view) const; ShardResult<size_t> OutDegree(View view) const;
const SchemaValidator *GetSchemaValidator() const; const SchemaValidator *GetSchemaValidator() const;
@ -122,20 +122,20 @@ class VertexAccessor final {
/// Add a label and return `true` if insertion took place. /// Add a label and return `true` if insertion took place.
/// `false` is returned if the label already existed. /// `false` is returned if the label already existed.
/// @throw std::bad_alloc /// @throw std::bad_alloc
Result<bool> AddLabel(LabelId label); ShardResult<bool> AddLabel(LabelId label);
/// Remove a label and return `true` if deletion took place. /// Remove a label and return `true` if deletion took place.
/// `false` is returned if the vertex did not have a label already. /// `false` is returned if the vertex did not have a label already.
/// @throw std::bad_alloc /// @throw std::bad_alloc
Result<bool> RemoveLabel(LabelId label); ShardResult<bool> RemoveLabel(LabelId label);
/// Set a property value and return the old value. /// Set a property value and return the old value.
/// @throw std::bad_alloc /// @throw std::bad_alloc
Result<PropertyValue> SetProperty(PropertyId property, const PropertyValue &value); ShardResult<PropertyValue> SetProperty(PropertyId property, const PropertyValue &value);
PropertyValue GetPropertyValue(PropertyId property, View view) const; PropertyValue GetPropertyValue(PropertyId property, View view) const;
Result<void> CheckVertexExistence(View view) const; ShardResult<void> CheckVertexExistence(View view) const;
Vertex *vertex_; Vertex *vertex_;
Transaction *transaction_; Transaction *transaction_;

View File

@ -9,3 +9,4 @@ distributed_queries_e2e_python_files(order_by_and_limit.py)
distributed_queries_e2e_python_files(distinct.py) distributed_queries_e2e_python_files(distinct.py)
distributed_queries_e2e_python_files(optional_match.py) distributed_queries_e2e_python_files(optional_match.py)
distributed_queries_e2e_python_files(common.py) distributed_queries_e2e_python_files(common.py)
distributed_queries_e2e_python_files(awesome_memgraph_functions.py)

View File

@ -0,0 +1,93 @@
# Copyright 2022 Memgraph Ltd.
#
# Use of this software is governed by the Business Source License
# included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
# License, and you may not use this file except in compliance with the Business Source License.
#
# As of the Change Date specified in that file, in accordance with
# the Business Source License, use of this software will be governed
# by the Apache License, Version 2.0, included in the file
# licenses/APL.txt.
import sys
import mgclient
import pytest
from common import (
connection,
execute_and_fetch_all,
has_n_result_row,
wait_for_shard_manager_to_initialize,
)
def test_awesome_memgraph_functions(connection):
wait_for_shard_manager_to_initialize()
cursor = connection.cursor()
assert has_n_result_row(cursor, "CREATE (n :label {property:1})", 0)
assert has_n_result_row(cursor, "CREATE (n :label {property:2})", 0)
assert has_n_result_row(cursor, "CREATE (n :label {property:3})", 0)
assert has_n_result_row(cursor, "CREATE (n :label {property:4})", 0)
assert has_n_result_row(cursor, "CREATE (n :label {property:10})", 0)
results = execute_and_fetch_all(cursor, "MATCH (n) WITH COLLECT(n) as nn RETURN SIZE(nn)")
assert len(results) == 1
assert results[0][0] == 5
results = execute_and_fetch_all(cursor, "MATCH (n) WITH COLLECT(n.property) as nn RETURN ALL(i IN nn WHERE i > 0)")
assert len(results) == 1
assert results[0][0] == True
results = execute_and_fetch_all(cursor, """RETURN CONTAINS("Pineapple", "P")""")
assert len(results) == 1
assert results[0][0] == True
results = execute_and_fetch_all(cursor, """RETURN ENDSWITH("Pineapple", "e")""")
assert len(results) == 1
assert results[0][0] == True
results = execute_and_fetch_all(cursor, """RETURN LEFT("Pineapple", 1)""")
assert len(results) == 1
assert results[0][0] == "P"
results = execute_and_fetch_all(cursor, """RETURN RIGHT("Pineapple", 1)""")
assert len(results) == 1
assert results[0][0] == "e"
results = execute_and_fetch_all(cursor, """RETURN REVERSE("Apple")""")
assert len(results) == 1
assert results[0][0] == "elppA"
results = execute_and_fetch_all(cursor, """RETURN REPLACE("Apple", "A", "a")""")
assert len(results) == 1
assert results[0][0] == "apple"
results = execute_and_fetch_all(cursor, """RETURN TOLOWER("Apple")""")
assert len(results) == 1
assert results[0][0] == "apple"
results = execute_and_fetch_all(cursor, """RETURN TOUPPER("Apple")""")
assert len(results) == 1
assert results[0][0] == "APPLE"
results = execute_and_fetch_all(cursor, """RETURN TRIM(" Apple")""")
assert len(results) == 1
assert results[0][0] == "Apple"
results = execute_and_fetch_all(cursor, """RETURN SPLIT("Apple.Apple", ".")""")
assert len(results) == 1
assert results[0][0] == ["Apple", "Apple"]
results = execute_and_fetch_all(cursor, """RETURN LOG10(100)""")
assert len(results) == 1
assert results[0][0] == 2
results = execute_and_fetch_all(cursor, """RETURN SQRT(4)""")
assert len(results) == 1
assert results[0][0] == 2
if __name__ == "__main__":
sys.exit(pytest.main([__file__, "-rA"]))

View File

@ -36,3 +36,8 @@ workloads:
binary: "tests/e2e/pytest_runner.sh" binary: "tests/e2e/pytest_runner.sh"
args: ["distributed_queries/optional_match.py"] args: ["distributed_queries/optional_match.py"]
<<: *template_cluster <<: *template_cluster
- name: "Awesome memgraph functions"
binary: "tests/e2e/pytest_runner.sh"
args: ["distributed_queries/awesome_memgraph_functions.py"]
<<: *template_cluster

View File

@ -151,7 +151,7 @@ void RunStorageRaft(Raft<IoImpl, MockedShardRsm, WriteRequests, WriteResponses,
server.Run(); server.Run();
} }
void TestScanVertices(msgs::ShardRequestManagerInterface &io) { void TestScanVertices(query::v2::ShardRequestManagerInterface &io) {
msgs::ExecutionState<ScanVerticesRequest> state{.label = "test_label"}; msgs::ExecutionState<ScanVerticesRequest> state{.label = "test_label"};
auto result = io.Request(state); auto result = io.Request(state);
@ -171,7 +171,7 @@ void TestScanVertices(msgs::ShardRequestManagerInterface &io) {
} }
} }
void TestCreateVertices(msgs::ShardRequestManagerInterface &io) { void TestCreateVertices(query::v2::ShardRequestManagerInterface &io) {
using PropVal = msgs::Value; using PropVal = msgs::Value;
msgs::ExecutionState<CreateVerticesRequest> state; msgs::ExecutionState<CreateVerticesRequest> state;
std::vector<msgs::NewVertex> new_vertices; std::vector<msgs::NewVertex> new_vertices;
@ -187,7 +187,7 @@ void TestCreateVertices(msgs::ShardRequestManagerInterface &io) {
MG_ASSERT(result.size() == 2); MG_ASSERT(result.size() == 2);
} }
void TestCreateExpand(msgs::ShardRequestManagerInterface &io) { void TestCreateExpand(query::v2::ShardRequestManagerInterface &io) {
using PropVal = msgs::Value; using PropVal = msgs::Value;
msgs::ExecutionState<msgs::CreateExpandRequest> state; msgs::ExecutionState<msgs::CreateExpandRequest> state;
std::vector<msgs::NewExpand> new_expands; std::vector<msgs::NewExpand> new_expands;
@ -209,7 +209,7 @@ void TestCreateExpand(msgs::ShardRequestManagerInterface &io) {
MG_ASSERT(responses[1].success); MG_ASSERT(responses[1].success);
} }
void TestExpandOne(msgs::ShardRequestManagerInterface &shard_request_manager) { void TestExpandOne(query::v2::ShardRequestManagerInterface &shard_request_manager) {
msgs::ExecutionState<msgs::ExpandOneRequest> state{}; msgs::ExecutionState<msgs::ExpandOneRequest> state{};
msgs::ExpandOneRequest request; msgs::ExpandOneRequest request;
const auto edge_type_id = shard_request_manager.NameToEdgeType("edge_type"); const auto edge_type_id = shard_request_manager.NameToEdgeType("edge_type");
@ -337,7 +337,7 @@ void DoTest() {
// also get the current shard map // also get the current shard map
CoordinatorClient<SimulatorTransport> coordinator_client(cli_io, c_addrs[0], c_addrs); CoordinatorClient<SimulatorTransport> coordinator_client(cli_io, c_addrs[0], c_addrs);
msgs::ShardRequestManager<SimulatorTransport> io(std::move(coordinator_client), std::move(cli_io)); query::v2::ShardRequestManager<SimulatorTransport> io(std::move(coordinator_client), std::move(cli_io));
io.StartTransaction(); io.StartTransaction();
TestScanVertices(io); TestScanVertices(io);

View File

@ -137,7 +137,7 @@ void Commit(ShardClient &client, const coordinator::Hlc &transaction_timestamp)
auto write_response_result = write_res.GetValue(); auto write_response_result = write_res.GetValue();
auto write_response = std::get<msgs::CommitResponse>(write_response_result); auto write_response = std::get<msgs::CommitResponse>(write_response_result);
MG_ASSERT(write_response.success, "Commit expected to be successful, but it is failed"); MG_ASSERT(!write_response.error.has_value(), "Commit expected to be successful, but it is failed");
break; break;
} }
@ -156,7 +156,7 @@ bool AttemptToCreateVertex(ShardClient &client, int64_t value) {
create_req.transaction_id.logical_id = GetTransactionId(); create_req.transaction_id.logical_id = GetTransactionId();
auto write_res = client.SendWriteRequest(create_req); auto write_res = client.SendWriteRequest(create_req);
MG_ASSERT(write_res.HasValue() && std::get<msgs::CreateVerticesResponse>(write_res.GetValue()).success, MG_ASSERT(write_res.HasValue() && !std::get<msgs::CreateVerticesResponse>(write_res.GetValue()).error.has_value(),
"Unexpected failure"); "Unexpected failure");
Commit(client, create_req.transaction_id); Commit(client, create_req.transaction_id);
@ -179,7 +179,7 @@ bool AttemptToDeleteVertex(ShardClient &client, int64_t value) {
auto write_response = std::get<msgs::DeleteVerticesResponse>(write_response_result); auto write_response = std::get<msgs::DeleteVerticesResponse>(write_response_result);
Commit(client, delete_req.transaction_id); Commit(client, delete_req.transaction_id);
return write_response.success; return !write_response.error.has_value();
} }
} }
@ -210,7 +210,7 @@ bool AttemptToUpdateVertex(ShardClient &client, int64_t vertex_primary_key, std:
auto write_response = std::get<msgs::UpdateVerticesResponse>(write_response_result); auto write_response = std::get<msgs::UpdateVerticesResponse>(write_response_result);
Commit(client, update_req.transaction_id); Commit(client, update_req.transaction_id);
return write_response.success; return !write_response.error.has_value();
} }
} }
@ -241,7 +241,7 @@ bool AttemptToRemoveVertexProperty(ShardClient &client, int64_t primary_key, std
auto write_response = std::get<msgs::UpdateVerticesResponse>(write_response_result); auto write_response = std::get<msgs::UpdateVerticesResponse>(write_response_result);
Commit(client, update_req.transaction_id); Commit(client, update_req.transaction_id);
return write_response.success; return !write_response.error.has_value();
} }
} }
@ -278,7 +278,7 @@ bool AttemptToAddEdge(ShardClient &client, int64_t value_of_vertex_1, int64_t va
Commit(client, create_req.transaction_id); Commit(client, create_req.transaction_id);
return write_response.success; return !write_response.error.has_value();
} }
return true; return true;
} }
@ -310,7 +310,7 @@ bool AttemptToAddEdgeWithProperties(ShardClient &client, int64_t value_of_vertex
create_req.transaction_id.logical_id = GetTransactionId(); create_req.transaction_id.logical_id = GetTransactionId();
auto write_res = client.SendWriteRequest(create_req); auto write_res = client.SendWriteRequest(create_req);
MG_ASSERT(write_res.HasValue() && std::get<msgs::CreateExpandResponse>(write_res.GetValue()).success, MG_ASSERT(write_res.HasValue() && !std::get<msgs::CreateExpandResponse>(write_res.GetValue()).error.has_value(),
"Unexpected failure"); "Unexpected failure");
Commit(client, create_req.transaction_id); Commit(client, create_req.transaction_id);
@ -350,7 +350,7 @@ bool AttemptToDeleteEdge(ShardClient &client, int64_t value_of_vertex_1, int64_t
auto write_response = std::get<msgs::DeleteEdgesResponse>(write_response_result); auto write_response = std::get<msgs::DeleteEdgesResponse>(write_response_result);
Commit(client, delete_req.transaction_id); Commit(client, delete_req.transaction_id);
return write_response.success; return !write_response.error.has_value();
} }
} }
@ -390,7 +390,7 @@ bool AttemptToUpdateEdge(ShardClient &client, int64_t value_of_vertex_1, int64_t
auto write_response = std::get<msgs::UpdateEdgesResponse>(write_response_result); auto write_response = std::get<msgs::UpdateEdgesResponse>(write_response_result);
Commit(client, update_req.transaction_id); Commit(client, update_req.transaction_id);
return write_response.success; return !write_response.error.has_value();
} }
} }
@ -413,7 +413,7 @@ std::tuple<size_t, std::optional<msgs::VertexId>> AttemptToScanAllWithoutBatchLi
auto write_response_result = read_res.GetValue(); auto write_response_result = read_res.GetValue();
auto write_response = std::get<msgs::ScanVerticesResponse>(write_response_result); auto write_response = std::get<msgs::ScanVerticesResponse>(write_response_result);
MG_ASSERT(write_response.success); MG_ASSERT(write_response.error == std::nullopt);
return {write_response.results.size(), write_response.next_start_id}; return {write_response.results.size(), write_response.next_start_id};
} }
@ -439,7 +439,7 @@ std::tuple<size_t, std::optional<msgs::VertexId>> AttemptToScanAllWithBatchLimit
auto write_response_result = read_res.GetValue(); auto write_response_result = read_res.GetValue();
auto write_response = std::get<msgs::ScanVerticesResponse>(write_response_result); auto write_response = std::get<msgs::ScanVerticesResponse>(write_response_result);
MG_ASSERT(write_response.success); MG_ASSERT(!write_response.error.has_value());
return {write_response.results.size(), write_response.next_start_id}; return {write_response.results.size(), write_response.next_start_id};
} }
@ -473,7 +473,7 @@ std::tuple<size_t, std::optional<msgs::VertexId>> AttemptToScanAllWithExpression
auto write_response_result = read_res.GetValue(); auto write_response_result = read_res.GetValue();
auto write_response = std::get<msgs::ScanVerticesResponse>(write_response_result); auto write_response = std::get<msgs::ScanVerticesResponse>(write_response_result);
MG_ASSERT(write_response.success); MG_ASSERT(!write_response.error.has_value());
MG_ASSERT(!write_response.results.empty(), "There are no results!"); MG_ASSERT(!write_response.results.empty(), "There are no results!");
MG_ASSERT(write_response.results[0].evaluated_vertex_expressions[0].int_v == 4); MG_ASSERT(write_response.results[0].evaluated_vertex_expressions[0].int_v == 4);
return {write_response.results.size(), write_response.next_start_id}; return {write_response.results.size(), write_response.next_start_id};
@ -498,7 +498,7 @@ void AttemptToScanAllWithOrderByOnPrimaryProperty(ShardClient &client, msgs::Ver
auto write_response_result = read_res.GetValue(); auto write_response_result = read_res.GetValue();
auto write_response = std::get<msgs::ScanVerticesResponse>(write_response_result); auto write_response = std::get<msgs::ScanVerticesResponse>(write_response_result);
MG_ASSERT(write_response.success); MG_ASSERT(!write_response.error.has_value());
MG_ASSERT(write_response.results.size() == 5, "Expecting 5 results!"); MG_ASSERT(write_response.results.size() == 5, "Expecting 5 results!");
for (int64_t i{0}; i < 5; ++i) { for (int64_t i{0}; i < 5; ++i) {
const auto expected_primary_key = std::vector{msgs::Value(1023 - i)}; const auto expected_primary_key = std::vector{msgs::Value(1023 - i)};
@ -528,7 +528,7 @@ void AttemptToScanAllWithOrderByOnSecondaryProperty(ShardClient &client, msgs::V
auto write_response_result = read_res.GetValue(); auto write_response_result = read_res.GetValue();
auto write_response = std::get<msgs::ScanVerticesResponse>(write_response_result); auto write_response = std::get<msgs::ScanVerticesResponse>(write_response_result);
MG_ASSERT(write_response.success); MG_ASSERT(!write_response.error.has_value());
MG_ASSERT(write_response.results.size() == 5, "Expecting 5 results!"); MG_ASSERT(write_response.results.size() == 5, "Expecting 5 results!");
for (int64_t i{0}; i < 5; ++i) { for (int64_t i{0}; i < 5; ++i) {
const auto expected_prop4 = std::vector{msgs::Value(1023 - i)}; const auto expected_prop4 = std::vector{msgs::Value(1023 - i)};

View File

@ -151,7 +151,7 @@ ShardMap TestShardMap(int n_splits, int replication_factor) {
return sm; return sm;
} }
void ExecuteOp(msgs::ShardRequestManager<SimulatorTransport> &shard_request_manager, void ExecuteOp(query::v2::ShardRequestManager<SimulatorTransport> &shard_request_manager,
std::set<CompoundKey> &correctness_model, CreateVertex create_vertex) { std::set<CompoundKey> &correctness_model, CreateVertex create_vertex) {
const auto key1 = memgraph::storage::v3::PropertyValue(create_vertex.first); const auto key1 = memgraph::storage::v3::PropertyValue(create_vertex.first);
const auto key2 = memgraph::storage::v3::PropertyValue(create_vertex.second); const auto key2 = memgraph::storage::v3::PropertyValue(create_vertex.second);
@ -164,7 +164,7 @@ void ExecuteOp(msgs::ShardRequestManager<SimulatorTransport> &shard_request_mana
return; return;
} }
msgs::ExecutionState<msgs::CreateVerticesRequest> state; query::v2::ExecutionState<msgs::CreateVerticesRequest> state;
auto label_id = shard_request_manager.NameToLabel("test_label"); auto label_id = shard_request_manager.NameToLabel("test_label");
@ -177,14 +177,14 @@ void ExecuteOp(msgs::ShardRequestManager<SimulatorTransport> &shard_request_mana
auto result = shard_request_manager.Request(state, std::move(new_vertices)); auto result = shard_request_manager.Request(state, std::move(new_vertices));
RC_ASSERT(result.size() == 1); RC_ASSERT(result.size() == 1);
RC_ASSERT(result[0].success); RC_ASSERT(!result[0].error.has_value());
correctness_model.emplace(std::make_pair(create_vertex.first, create_vertex.second)); correctness_model.emplace(std::make_pair(create_vertex.first, create_vertex.second));
} }
void ExecuteOp(msgs::ShardRequestManager<SimulatorTransport> &shard_request_manager, void ExecuteOp(query::v2::ShardRequestManager<SimulatorTransport> &shard_request_manager,
std::set<CompoundKey> &correctness_model, ScanAll scan_all) { std::set<CompoundKey> &correctness_model, ScanAll scan_all) {
msgs::ExecutionState<msgs::ScanVerticesRequest> request{.label = "test_label"}; query::v2::ExecutionState<msgs::ScanVerticesRequest> request{.label = "test_label"};
auto results = shard_request_manager.Request(request); auto results = shard_request_manager.Request(request);
@ -247,7 +247,8 @@ std::pair<SimulatorStats, LatencyHistogramSummaries> RunClusterSimulation(const
CoordinatorClient<SimulatorTransport> coordinator_client(cli_io, coordinator_address, {coordinator_address}); CoordinatorClient<SimulatorTransport> coordinator_client(cli_io, coordinator_address, {coordinator_address});
WaitForShardsToInitialize(coordinator_client); WaitForShardsToInitialize(coordinator_client);
msgs::ShardRequestManager<SimulatorTransport> shard_request_manager(std::move(coordinator_client), std::move(cli_io)); query::v2::ShardRequestManager<SimulatorTransport> shard_request_manager(std::move(coordinator_client),
std::move(cli_io));
shard_request_manager.StartTransaction(); shard_request_manager.StartTransaction();

View File

@ -406,3 +406,7 @@ target_link_libraries(${test_prefix}coordinator_shard_map mg-coordinator)
# Tests for many shards, many creates, scan # Tests for many shards, many creates, scan
add_unit_test(high_density_shard_create_scan.cpp) add_unit_test(high_density_shard_create_scan.cpp)
target_link_libraries(${test_prefix}high_density_shard_create_scan mg-io mg-coordinator mg-storage-v3 mg-query-v2) target_link_libraries(${test_prefix}high_density_shard_create_scan mg-io mg-coordinator mg-storage-v3 mg-query-v2)
# Tests for awesome_memgraph_functions
add_unit_test(query_v2_expression_evaluator.cpp)
target_link_libraries(${test_prefix}query_v2_expression_evaluator mg-query-v2)

View File

@ -161,7 +161,7 @@ ShardMap TestShardMap(int shards, int replication_factor, int gap_between_shards
return sm; return sm;
} }
void ExecuteOp(msgs::ShardRequestManager<LocalTransport> &shard_request_manager, void ExecuteOp(query::v2::ShardRequestManager<LocalTransport> &shard_request_manager,
std::set<CompoundKey> &correctness_model, CreateVertex create_vertex) { std::set<CompoundKey> &correctness_model, CreateVertex create_vertex) {
const auto key1 = memgraph::storage::v3::PropertyValue(create_vertex.first); const auto key1 = memgraph::storage::v3::PropertyValue(create_vertex.first);
const auto key2 = memgraph::storage::v3::PropertyValue(create_vertex.second); const auto key2 = memgraph::storage::v3::PropertyValue(create_vertex.second);
@ -174,7 +174,7 @@ void ExecuteOp(msgs::ShardRequestManager<LocalTransport> &shard_request_manager,
return; return;
} }
msgs::ExecutionState<msgs::CreateVerticesRequest> state; query::v2::ExecutionState<msgs::CreateVerticesRequest> state;
auto label_id = shard_request_manager.NameToLabel("test_label"); auto label_id = shard_request_manager.NameToLabel("test_label");
@ -187,14 +187,14 @@ void ExecuteOp(msgs::ShardRequestManager<LocalTransport> &shard_request_manager,
auto result = shard_request_manager.Request(state, std::move(new_vertices)); auto result = shard_request_manager.Request(state, std::move(new_vertices));
MG_ASSERT(result.size() == 1); MG_ASSERT(result.size() == 1);
MG_ASSERT(result[0].success); MG_ASSERT(!result[0].error.has_value());
correctness_model.emplace(std::make_pair(create_vertex.first, create_vertex.second)); correctness_model.emplace(std::make_pair(create_vertex.first, create_vertex.second));
} }
void ExecuteOp(msgs::ShardRequestManager<LocalTransport> &shard_request_manager, void ExecuteOp(query::v2::ShardRequestManager<LocalTransport> &shard_request_manager,
std::set<CompoundKey> &correctness_model, ScanAll scan_all) { std::set<CompoundKey> &correctness_model, ScanAll scan_all) {
msgs::ExecutionState<msgs::ScanVerticesRequest> request{.label = "test_label"}; query::v2::ExecutionState<msgs::ScanVerticesRequest> request{.label = "test_label"};
auto results = shard_request_manager.Request(request); auto results = shard_request_manager.Request(request);
@ -245,7 +245,8 @@ void RunWorkload(int shards, int replication_factor, int create_ops, int scan_op
WaitForShardsToInitialize(coordinator_client); WaitForShardsToInitialize(coordinator_client);
auto time_after_shard_stabilization = cli_io_2.Now(); auto time_after_shard_stabilization = cli_io_2.Now();
msgs::ShardRequestManager<LocalTransport> shard_request_manager(std::move(coordinator_client), std::move(cli_io)); query::v2::ShardRequestManager<LocalTransport> shard_request_manager(std::move(coordinator_client),
std::move(cli_io));
shard_request_manager.StartTransaction(); shard_request_manager.StartTransaction();

View File

@ -111,15 +111,15 @@ ShardMap TestShardMap() {
template <typename ShardRequestManager> template <typename ShardRequestManager>
void TestScanAll(ShardRequestManager &shard_request_manager) { void TestScanAll(ShardRequestManager &shard_request_manager) {
msgs::ExecutionState<msgs::ScanVerticesRequest> state{.label = kLabelName}; query::v2::ExecutionState<msgs::ScanVerticesRequest> state{.label = kLabelName};
auto result = shard_request_manager.Request(state); auto result = shard_request_manager.Request(state);
EXPECT_EQ(result.size(), 2); EXPECT_EQ(result.size(), 2);
} }
void TestCreateVertices(msgs::ShardRequestManagerInterface &shard_request_manager) { void TestCreateVertices(query::v2::ShardRequestManagerInterface &shard_request_manager) {
using PropVal = msgs::Value; using PropVal = msgs::Value;
msgs::ExecutionState<msgs::CreateVerticesRequest> state; query::v2::ExecutionState<msgs::CreateVerticesRequest> state;
std::vector<msgs::NewVertex> new_vertices; std::vector<msgs::NewVertex> new_vertices;
auto label_id = shard_request_manager.NameToLabel(kLabelName); auto label_id = shard_request_manager.NameToLabel(kLabelName);
msgs::NewVertex a1{.primary_key = {PropVal(int64_t(0)), PropVal(int64_t(0))}}; msgs::NewVertex a1{.primary_key = {PropVal(int64_t(0)), PropVal(int64_t(0))}};
@ -131,11 +131,12 @@ void TestCreateVertices(msgs::ShardRequestManagerInterface &shard_request_manage
auto result = shard_request_manager.Request(state, std::move(new_vertices)); auto result = shard_request_manager.Request(state, std::move(new_vertices));
EXPECT_EQ(result.size(), 1); EXPECT_EQ(result.size(), 1);
EXPECT_FALSE(result[0].error.has_value()) << result[0].error->message;
} }
void TestCreateExpand(msgs::ShardRequestManagerInterface &shard_request_manager) { void TestCreateExpand(query::v2::ShardRequestManagerInterface &shard_request_manager) {
using PropVal = msgs::Value; using PropVal = msgs::Value;
msgs::ExecutionState<msgs::CreateExpandRequest> state; query::v2::ExecutionState<msgs::CreateExpandRequest> state;
std::vector<msgs::NewExpand> new_expands; std::vector<msgs::NewExpand> new_expands;
const auto edge_type_id = shard_request_manager.NameToEdgeType("edge_type"); const auto edge_type_id = shard_request_manager.NameToEdgeType("edge_type");
@ -151,11 +152,11 @@ void TestCreateExpand(msgs::ShardRequestManagerInterface &shard_request_manager)
auto responses = shard_request_manager.Request(state, std::move(new_expands)); auto responses = shard_request_manager.Request(state, std::move(new_expands));
MG_ASSERT(responses.size() == 1); MG_ASSERT(responses.size() == 1);
MG_ASSERT(responses[0].success); MG_ASSERT(!responses[0].error.has_value());
} }
void TestExpandOne(msgs::ShardRequestManagerInterface &shard_request_manager) { void TestExpandOne(query::v2::ShardRequestManagerInterface &shard_request_manager) {
msgs::ExecutionState<msgs::ExpandOneRequest> state{}; query::v2::ExecutionState<msgs::ExpandOneRequest> state{};
msgs::ExpandOneRequest request; msgs::ExpandOneRequest request;
const auto edge_type_id = shard_request_manager.NameToEdgeType("edge_type"); const auto edge_type_id = shard_request_manager.NameToEdgeType("edge_type");
const auto label = msgs::Label{shard_request_manager.NameToLabel("test_label")}; const auto label = msgs::Label{shard_request_manager.NameToLabel("test_label")};
@ -225,7 +226,8 @@ TEST(MachineManager, BasicFunctionality) {
CoordinatorClient<LocalTransport> coordinator_client(cli_io, coordinator_address, {coordinator_address}); CoordinatorClient<LocalTransport> coordinator_client(cli_io, coordinator_address, {coordinator_address});
msgs::ShardRequestManager<LocalTransport> shard_request_manager(std::move(coordinator_client), std::move(cli_io)); query::v2::ShardRequestManager<LocalTransport> shard_request_manager(std::move(coordinator_client),
std::move(cli_io));
shard_request_manager.StartTransaction(); shard_request_manager.StartTransaction();
TestCreateVertices(shard_request_manager); TestCreateVertices(shard_request_manager);

File diff suppressed because it is too large Load Diff

View File

@ -17,6 +17,7 @@
#include <gtest/gtest-death-test.h> #include <gtest/gtest-death-test.h>
#include <gtest/gtest.h> #include <gtest/gtest.h>
#include "common/errors.hpp"
#include "coordinator/hybrid_logical_clock.hpp" #include "coordinator/hybrid_logical_clock.hpp"
#include "io/time.hpp" #include "io/time.hpp"
#include "storage/v3/delta.hpp" #include "storage/v3/delta.hpp"
@ -579,7 +580,7 @@ TEST_P(StorageV3, VertexDeleteSerializationError) {
EXPECT_EQ(CountVertices(acc2, View::NEW), 1U); EXPECT_EQ(CountVertices(acc2, View::NEW), 1U);
auto res = acc2.DeleteVertex(&*vertex); auto res = acc2.DeleteVertex(&*vertex);
ASSERT_TRUE(res.HasError()); ASSERT_TRUE(res.HasError());
ASSERT_EQ(res.GetError(), Error::SERIALIZATION_ERROR); ASSERT_EQ(res.GetError(), SHARD_ERROR(ErrorCode::SERIALIZATION_ERROR));
EXPECT_EQ(CountVertices(acc2, View::OLD), 1U); EXPECT_EQ(CountVertices(acc2, View::OLD), 1U);
EXPECT_EQ(CountVertices(acc2, View::NEW), 1U); EXPECT_EQ(CountVertices(acc2, View::NEW), 1U);
acc2.AdvanceCommand(); acc2.AdvanceCommand();
@ -660,12 +661,11 @@ TEST_P(StorageV3, VertexDeleteSpecialCases) {
} }
} }
template <typename TError, typename TResultHolder> template <typename T>
void AssertErrorInVariant(TResultHolder &holder, TError error_type) { void AssertShardErrorEqual(const ShardResult<T> &lhs, const ShardError &rhs) {
ASSERT_TRUE(holder.HasError()); ASSERT_TRUE(lhs.HasError());
const auto error = holder.GetError(); const auto error = lhs.GetError();
ASSERT_TRUE(std::holds_alternative<TError>(error)); ASSERT_EQ(error, rhs);
ASSERT_EQ(std::get<TError>(error), error_type);
} }
// NOLINTNEXTLINE(hicpp-special-member-functions) // NOLINTNEXTLINE(hicpp-special-member-functions)
@ -711,20 +711,20 @@ TEST_P(StorageV3, VertexDeleteLabel) {
// Check whether label 5 exists // Check whether label 5 exists
ASSERT_FALSE(vertex->HasLabel(label5, View::OLD).GetValue()); ASSERT_FALSE(vertex->HasLabel(label5, View::OLD).GetValue());
ASSERT_EQ(vertex->HasLabel(label5, View::NEW).GetError(), Error::DELETED_OBJECT); ASSERT_EQ(vertex->HasLabel(label5, View::NEW).GetError(), SHARD_ERROR(ErrorCode::DELETED_OBJECT));
ASSERT_EQ(vertex->Labels(View::OLD)->size(), 0); ASSERT_EQ(vertex->Labels(View::OLD)->size(), 0);
ASSERT_EQ(vertex->Labels(View::NEW).GetError(), Error::DELETED_OBJECT); ASSERT_EQ(vertex->Labels(View::NEW).GetError(), SHARD_ERROR(ErrorCode::DELETED_OBJECT));
// Try to add the label // Try to add the label
{ {
auto ret = vertex->AddLabelAndValidate(label5); auto ret = vertex->AddLabelAndValidate(label5);
AssertErrorInVariant(ret, Error::DELETED_OBJECT); AssertShardErrorEqual(ret, SHARD_ERROR(ErrorCode::DELETED_OBJECT));
} }
// Try to remove the label // Try to remove the label
{ {
auto ret = vertex->RemoveLabelAndValidate(label5); auto ret = vertex->RemoveLabelAndValidate(label5);
AssertErrorInVariant(ret, Error::DELETED_OBJECT); AssertShardErrorEqual(ret, SHARD_ERROR(ErrorCode::DELETED_OBJECT));
} }
acc.Abort(); acc.Abort();
@ -779,33 +779,33 @@ TEST_P(StorageV3, VertexDeleteLabel) {
// Check whether label 5 exists // Check whether label 5 exists
ASSERT_TRUE(vertex->HasLabel(label5, View::OLD).GetValue()); ASSERT_TRUE(vertex->HasLabel(label5, View::OLD).GetValue());
ASSERT_EQ(vertex->HasLabel(label5, View::NEW).GetError(), Error::DELETED_OBJECT); ASSERT_EQ(vertex->HasLabel(label5, View::NEW).GetError(), SHARD_ERROR(ErrorCode::DELETED_OBJECT));
{ {
auto labels = vertex->Labels(View::OLD).GetValue(); auto labels = vertex->Labels(View::OLD).GetValue();
ASSERT_EQ(labels.size(), 1); ASSERT_EQ(labels.size(), 1);
ASSERT_EQ(labels[0], label5); ASSERT_EQ(labels[0], label5);
} }
ASSERT_EQ(vertex->Labels(View::NEW).GetError(), Error::DELETED_OBJECT); ASSERT_EQ(vertex->Labels(View::NEW).GetError(), SHARD_ERROR(ErrorCode::DELETED_OBJECT));
// Advance command // Advance command
acc.AdvanceCommand(); acc.AdvanceCommand();
// Check whether label 5 exists // Check whether label 5 exists
ASSERT_EQ(vertex->HasLabel(label5, View::OLD).GetError(), Error::DELETED_OBJECT); ASSERT_EQ(vertex->HasLabel(label5, View::OLD).GetError(), SHARD_ERROR(ErrorCode::DELETED_OBJECT));
ASSERT_EQ(vertex->HasLabel(label5, View::NEW).GetError(), Error::DELETED_OBJECT); ASSERT_EQ(vertex->HasLabel(label5, View::NEW).GetError(), SHARD_ERROR(ErrorCode::DELETED_OBJECT));
ASSERT_EQ(vertex->Labels(View::OLD).GetError(), Error::DELETED_OBJECT); ASSERT_EQ(vertex->Labels(View::OLD).GetError(), SHARD_ERROR(ErrorCode::DELETED_OBJECT));
ASSERT_EQ(vertex->Labels(View::NEW).GetError(), Error::DELETED_OBJECT); ASSERT_EQ(vertex->Labels(View::NEW).GetError(), SHARD_ERROR(ErrorCode::DELETED_OBJECT));
// Try to add the label // Try to add the label
{ {
auto ret = vertex->AddLabelAndValidate(label5); auto ret = vertex->AddLabelAndValidate(label5);
AssertErrorInVariant(ret, Error::DELETED_OBJECT); AssertShardErrorEqual(ret, SHARD_ERROR(ErrorCode::DELETED_OBJECT));
} }
// Try to remove the label // Try to remove the label
{ {
auto ret = vertex->RemoveLabelAndValidate(label5); auto ret = vertex->RemoveLabelAndValidate(label5);
AssertErrorInVariant(ret, Error::DELETED_OBJECT); AssertShardErrorEqual(ret, SHARD_ERROR(ErrorCode::DELETED_OBJECT));
} }
acc.Abort(); acc.Abort();
@ -855,14 +855,14 @@ TEST_P(StorageV3, VertexDeleteProperty) {
// Check whether label 5 exists // Check whether label 5 exists
ASSERT_TRUE(vertex->GetProperty(property5, View::OLD)->IsNull()); ASSERT_TRUE(vertex->GetProperty(property5, View::OLD)->IsNull());
ASSERT_EQ(vertex->GetProperty(property5, View::NEW).GetError(), Error::DELETED_OBJECT); ASSERT_EQ(vertex->GetProperty(property5, View::NEW).GetError(), SHARD_ERROR(ErrorCode::DELETED_OBJECT));
ASSERT_EQ(vertex->Properties(View::OLD)->size(), 0); ASSERT_EQ(vertex->Properties(View::OLD)->size(), 0);
ASSERT_EQ(vertex->Properties(View::NEW).GetError(), Error::DELETED_OBJECT); ASSERT_EQ(vertex->Properties(View::NEW).GetError(), SHARD_ERROR(ErrorCode::DELETED_OBJECT));
// Try to set the property5 // Try to set the property5
{ {
auto ret = vertex->SetPropertyAndValidate(property5, PropertyValue("haihai")); auto ret = vertex->SetPropertyAndValidate(property5, PropertyValue("haihai"));
AssertErrorInVariant(ret, Error::DELETED_OBJECT); AssertShardErrorEqual(ret, SHARD_ERROR(ErrorCode::DELETED_OBJECT));
} }
acc.Abort(); acc.Abort();
@ -918,27 +918,27 @@ TEST_P(StorageV3, VertexDeleteProperty) {
// Check whether property 5 exists // Check whether property 5 exists
ASSERT_EQ(vertex->GetProperty(property5, View::OLD)->ValueString(), "nandare"); ASSERT_EQ(vertex->GetProperty(property5, View::OLD)->ValueString(), "nandare");
ASSERT_EQ(vertex->GetProperty(property5, View::NEW).GetError(), Error::DELETED_OBJECT); ASSERT_EQ(vertex->GetProperty(property5, View::NEW).GetError(), SHARD_ERROR(ErrorCode::DELETED_OBJECT));
{ {
auto properties = vertex->Properties(View::OLD).GetValue(); auto properties = vertex->Properties(View::OLD).GetValue();
ASSERT_EQ(properties.size(), 1); ASSERT_EQ(properties.size(), 1);
ASSERT_EQ(properties[property5].ValueString(), "nandare"); ASSERT_EQ(properties[property5].ValueString(), "nandare");
} }
ASSERT_EQ(vertex->Properties(View::NEW).GetError(), Error::DELETED_OBJECT); ASSERT_EQ(vertex->Properties(View::NEW).GetError(), SHARD_ERROR(ErrorCode::DELETED_OBJECT));
// Advance command // Advance command
acc.AdvanceCommand(); acc.AdvanceCommand();
// Check whether property 5 exists // Check whether property 5 exists
ASSERT_EQ(vertex->GetProperty(property5, View::OLD).GetError(), Error::DELETED_OBJECT); ASSERT_EQ(vertex->GetProperty(property5, View::OLD).GetError(), SHARD_ERROR(ErrorCode::DELETED_OBJECT));
ASSERT_EQ(vertex->GetProperty(property5, View::NEW).GetError(), Error::DELETED_OBJECT); ASSERT_EQ(vertex->GetProperty(property5, View::NEW).GetError(), SHARD_ERROR(ErrorCode::DELETED_OBJECT));
ASSERT_EQ(vertex->Properties(View::OLD).GetError(), Error::DELETED_OBJECT); ASSERT_EQ(vertex->Properties(View::OLD).GetError(), SHARD_ERROR(ErrorCode::DELETED_OBJECT));
ASSERT_EQ(vertex->Properties(View::NEW).GetError(), Error::DELETED_OBJECT); ASSERT_EQ(vertex->Properties(View::NEW).GetError(), SHARD_ERROR(ErrorCode::DELETED_OBJECT));
// Try to set the property // Try to set the property
{ {
auto ret = vertex->SetPropertyAndValidate(property5, PropertyValue("haihai")); auto ret = vertex->SetPropertyAndValidate(property5, PropertyValue("haihai"));
AssertErrorInVariant(ret, Error::DELETED_OBJECT); AssertShardErrorEqual(ret, SHARD_ERROR(ErrorCode::DELETED_OBJECT));
} }
acc.Abort(); acc.Abort();
@ -1371,7 +1371,7 @@ TEST_P(StorageV3, VertexLabelSerializationError) {
{ {
auto res = vertex->AddLabelAndValidate(label1); auto res = vertex->AddLabelAndValidate(label1);
AssertErrorInVariant(res, Error::SERIALIZATION_ERROR); AssertShardErrorEqual(res, SHARD_ERROR(ErrorCode::SERIALIZATION_ERROR));
} }
} }
@ -1865,7 +1865,7 @@ TEST_P(StorageV3, VertexPropertySerializationError) {
{ {
auto res = vertex->SetPropertyAndValidate(property2, PropertyValue("nandare")); auto res = vertex->SetPropertyAndValidate(property2, PropertyValue("nandare"));
AssertErrorInVariant(res, Error::SERIALIZATION_ERROR); AssertShardErrorEqual(res, SHARD_ERROR(ErrorCode::SERIALIZATION_ERROR));
} }
} }
@ -2255,14 +2255,14 @@ TEST_P(StorageV3, VertexNonexistentLabelPropertyEdgeAPI) {
auto vertex = CreateVertexAndValidate(acc, {}, PropertyValue{0}, {}); auto vertex = CreateVertexAndValidate(acc, {}, PropertyValue{0}, {});
// Check state before (OLD view). // Check state before (OLD view).
ASSERT_EQ(vertex.Labels(View::OLD).GetError(), Error::NONEXISTENT_OBJECT); ASSERT_EQ(vertex.Labels(View::OLD).GetError(), SHARD_ERROR(ErrorCode::NONEXISTENT_OBJECT));
ASSERT_EQ(vertex.HasLabel(label1, View::OLD).GetError(), Error::NONEXISTENT_OBJECT); ASSERT_EQ(vertex.HasLabel(label1, View::OLD).GetError(), SHARD_ERROR(ErrorCode::NONEXISTENT_OBJECT));
ASSERT_EQ(vertex.Properties(View::OLD).GetError(), Error::NONEXISTENT_OBJECT); ASSERT_EQ(vertex.Properties(View::OLD).GetError(), SHARD_ERROR(ErrorCode::NONEXISTENT_OBJECT));
ASSERT_EQ(vertex.GetProperty(property1, View::OLD).GetError(), Error::NONEXISTENT_OBJECT); ASSERT_EQ(vertex.GetProperty(property1, View::OLD).GetError(), SHARD_ERROR(ErrorCode::NONEXISTENT_OBJECT));
ASSERT_EQ(vertex.InEdges(View::OLD).GetError(), Error::NONEXISTENT_OBJECT); ASSERT_EQ(vertex.InEdges(View::OLD).GetError(), SHARD_ERROR(ErrorCode::NONEXISTENT_OBJECT));
ASSERT_EQ(vertex.OutEdges(View::OLD).GetError(), Error::NONEXISTENT_OBJECT); ASSERT_EQ(vertex.OutEdges(View::OLD).GetError(), SHARD_ERROR(ErrorCode::NONEXISTENT_OBJECT));
ASSERT_EQ(vertex.InDegree(View::OLD).GetError(), Error::NONEXISTENT_OBJECT); ASSERT_EQ(vertex.InDegree(View::OLD).GetError(), SHARD_ERROR(ErrorCode::NONEXISTENT_OBJECT));
ASSERT_EQ(vertex.OutDegree(View::OLD).GetError(), Error::NONEXISTENT_OBJECT); ASSERT_EQ(vertex.OutDegree(View::OLD).GetError(), SHARD_ERROR(ErrorCode::NONEXISTENT_OBJECT));
// Check state before (NEW view). // Check state before (NEW view).
ASSERT_EQ(vertex.Labels(View::NEW)->size(), 0); ASSERT_EQ(vertex.Labels(View::NEW)->size(), 0);
@ -2282,14 +2282,14 @@ TEST_P(StorageV3, VertexNonexistentLabelPropertyEdgeAPI) {
.HasValue()); .HasValue());
// Check state after (OLD view). // Check state after (OLD view).
ASSERT_EQ(vertex.Labels(View::OLD).GetError(), Error::NONEXISTENT_OBJECT); ASSERT_EQ(vertex.Labels(View::OLD).GetError(), SHARD_ERROR(ErrorCode::NONEXISTENT_OBJECT));
ASSERT_EQ(vertex.HasLabel(label1, View::OLD).GetError(), Error::NONEXISTENT_OBJECT); ASSERT_EQ(vertex.HasLabel(label1, View::OLD).GetError(), SHARD_ERROR(ErrorCode::NONEXISTENT_OBJECT));
ASSERT_EQ(vertex.Properties(View::OLD).GetError(), Error::NONEXISTENT_OBJECT); ASSERT_EQ(vertex.Properties(View::OLD).GetError(), SHARD_ERROR(ErrorCode::NONEXISTENT_OBJECT));
ASSERT_EQ(vertex.GetProperty(property1, View::OLD).GetError(), Error::NONEXISTENT_OBJECT); ASSERT_EQ(vertex.GetProperty(property1, View::OLD).GetError(), SHARD_ERROR(ErrorCode::NONEXISTENT_OBJECT));
ASSERT_EQ(vertex.InEdges(View::OLD).GetError(), Error::NONEXISTENT_OBJECT); ASSERT_EQ(vertex.InEdges(View::OLD).GetError(), SHARD_ERROR(ErrorCode::NONEXISTENT_OBJECT));
ASSERT_EQ(vertex.OutEdges(View::OLD).GetError(), Error::NONEXISTENT_OBJECT); ASSERT_EQ(vertex.OutEdges(View::OLD).GetError(), SHARD_ERROR(ErrorCode::NONEXISTENT_OBJECT));
ASSERT_EQ(vertex.InDegree(View::OLD).GetError(), Error::NONEXISTENT_OBJECT); ASSERT_EQ(vertex.InDegree(View::OLD).GetError(), SHARD_ERROR(ErrorCode::NONEXISTENT_OBJECT));
ASSERT_EQ(vertex.OutDegree(View::OLD).GetError(), Error::NONEXISTENT_OBJECT); ASSERT_EQ(vertex.OutDegree(View::OLD).GetError(), SHARD_ERROR(ErrorCode::NONEXISTENT_OBJECT));
// Check state after (NEW view). // Check state after (NEW view).
ASSERT_EQ(vertex.Labels(View::NEW)->size(), 1); ASSERT_EQ(vertex.Labels(View::NEW)->size(), 1);
@ -2657,42 +2657,31 @@ TEST_P(StorageV3, TestCreateVertexAndValidate) {
ASSERT_TRUE(vertex2.HasError()); ASSERT_TRUE(vertex2.HasError());
auto error = vertex2.GetError(); auto error = vertex2.GetError();
auto error_ptr = std::get_if<memgraph::storage::v3::Error>(&error); ASSERT_TRUE(error == common::ErrorCode::VERTEX_ALREADY_INSERTED);
ASSERT_TRUE(error_ptr);
ASSERT_TRUE(*error_ptr == storage::v3::Error::VERTEX_ALREADY_INSERTED);
} }
{ {
auto acc = store.Access(GetNextHlc()); auto acc = store.Access(GetNextHlc());
auto vertex = acc.CreateVertexAndValidate({primary_label}, {PropertyValue{0}}, {}); auto vertex = acc.CreateVertexAndValidate({primary_label}, {PropertyValue{0}}, {});
ASSERT_TRUE(vertex.HasError()); ASSERT_TRUE(vertex.HasError());
ASSERT_TRUE(std::holds_alternative<SchemaViolation>(vertex.GetError())); EXPECT_EQ(vertex.GetError(), SHARD_ERROR(ErrorCode::SCHEMA_VERTEX_SECONDARY_LABEL_IS_PRIMARY));
EXPECT_EQ(std::get<SchemaViolation>(vertex.GetError()),
SchemaViolation(SchemaViolation::ValidationStatus::VERTEX_SECONDARY_LABEL_IS_PRIMARY, primary_label));
} }
{ {
auto acc = store.Access(GetNextHlc()); auto acc = store.Access(GetNextHlc());
auto vertex = acc.CreateVertexAndValidate({primary_label}, {PropertyValue{0}}, {}); auto vertex = acc.CreateVertexAndValidate({primary_label}, {PropertyValue{0}}, {});
ASSERT_TRUE(vertex.HasError()); ASSERT_TRUE(vertex.HasError());
ASSERT_TRUE(std::holds_alternative<SchemaViolation>(vertex.GetError())); EXPECT_EQ(vertex.GetError(), SHARD_ERROR(ErrorCode::SCHEMA_VERTEX_SECONDARY_LABEL_IS_PRIMARY));
EXPECT_EQ(std::get<SchemaViolation>(vertex.GetError()),
SchemaViolation(SchemaViolation::ValidationStatus::VERTEX_SECONDARY_LABEL_IS_PRIMARY, primary_label));
} }
{ {
auto acc = store.Access(GetNextHlc()); auto acc = store.Access(GetNextHlc());
auto vertex = acc.CreateVertexAndValidate({}, {}, {}); auto vertex = acc.CreateVertexAndValidate({}, {}, {});
ASSERT_TRUE(vertex.HasError()); ASSERT_TRUE(vertex.HasError());
ASSERT_TRUE(std::holds_alternative<SchemaViolation>(vertex.GetError())); EXPECT_EQ(vertex.GetError(), SHARD_ERROR(ErrorCode::SCHEMA_VERTEX_PRIMARY_PROPERTIES_UNDEFINED));
EXPECT_EQ(std::get<SchemaViolation>(vertex.GetError()),
SchemaViolation(SchemaViolation::ValidationStatus::VERTEX_PRIMARY_PROPERTIES_UNDEFINED, primary_label));
} }
{ {
auto acc = store.Access(GetNextHlc()); auto acc = store.Access(GetNextHlc());
auto vertex = acc.CreateVertexAndValidate({}, {PropertyValue{"test"}}, {}); auto vertex = acc.CreateVertexAndValidate({}, {PropertyValue{"test"}}, {});
ASSERT_TRUE(vertex.HasError()); ASSERT_TRUE(vertex.HasError());
ASSERT_TRUE(std::holds_alternative<SchemaViolation>(vertex.GetError())); EXPECT_EQ(vertex.GetError(), SHARD_ERROR(ErrorCode::SCHEMA_VERTEX_PROPERTY_WRONG_TYPE));
EXPECT_EQ(std::get<SchemaViolation>(vertex.GetError()),
SchemaViolation(SchemaViolation::ValidationStatus::VERTEX_PROPERTY_WRONG_TYPE, primary_label,
{primary_property, common::SchemaType::INT}, PropertyValue("test")));
} }
} }
} // namespace memgraph::storage::v3::tests } // namespace memgraph::storage::v3::tests

File diff suppressed because it is too large Load Diff

View File

@ -14,10 +14,10 @@
#include <gtest/gtest.h> #include <gtest/gtest.h>
#include <fmt/format.h> #include <fmt/format.h>
#include <optional>
#include <string> #include <string>
#include <vector> #include <vector>
#include "common/errors.hpp"
#include "common/types.hpp" #include "common/types.hpp"
#include "storage/v3/id_types.hpp" #include "storage/v3/id_types.hpp"
#include "storage/v3/property_value.hpp" #include "storage/v3/property_value.hpp"
@ -150,7 +150,15 @@ TEST_F(SchemaTest, TestSchemaDrop) {
class SchemaValidatorTest : public testing::Test { class SchemaValidatorTest : public testing::Test {
private: private:
NameIdMapper id_mapper_{{{1, "label1"}, {2, "label2"}, {3, "prop1"}, {4, "prop2"}, {5, "prop3"}}}; NameIdMapper id_mapper_{{{1, "label1"},
{2, "label2"},
{3, "prop1"},
{4, "prop2"},
{5, "prop3"},
{6, "label4"},
{7, "label5"},
{8, "label6"},
{9, "test"}}};
protected: protected:
void SetUp() override { void SetUp() override {
@ -162,9 +170,8 @@ class SchemaValidatorTest : public testing::Test {
PropertyId NameToProperty(const std::string &name) { return PropertyId::FromUint(id_mapper_.NameToId(name)); } PropertyId NameToProperty(const std::string &name) { return PropertyId::FromUint(id_mapper_.NameToId(name)); }
protected:
Schemas schemas; Schemas schemas;
SchemaValidator schema_validator{schemas}; SchemaValidator schema_validator{schemas, id_mapper_};
PropertyId prop_string{NameToProperty("prop1")}; PropertyId prop_string{NameToProperty("prop1")};
PropertyId prop_int{NameToProperty("prop2")}; PropertyId prop_int{NameToProperty("prop2")};
PropertyId prop_duration{NameToProperty("prop3")}; PropertyId prop_duration{NameToProperty("prop3")};
@ -179,100 +186,92 @@ TEST_F(SchemaValidatorTest, TestSchemaValidateVertexCreate) {
// Validate against secondary label // Validate against secondary label
{ {
const auto schema_violation = schema_validator.ValidateVertexCreate(NameToLabel("test"), {}, {PropertyValue(1)}); const auto schema_violation = schema_validator.ValidateVertexCreate(NameToLabel("test"), {}, {PropertyValue(1)});
ASSERT_NE(schema_violation, std::nullopt); ASSERT_TRUE(schema_violation.HasError());
EXPECT_EQ(*schema_violation, EXPECT_EQ(schema_violation.GetError(), SHARD_ERROR(ErrorCode::SCHEMA_NO_SCHEMA_DEFINED_FOR_LABEL));
SchemaViolation(SchemaViolation::ValidationStatus::NO_SCHEMA_DEFINED_FOR_LABEL, NameToLabel("test")));
} }
{ {
const auto schema_violation = schema_validator.ValidateVertexCreate(label2, {}, {}); const auto schema_violation = schema_validator.ValidateVertexCreate(label2, {}, {});
ASSERT_NE(schema_violation, std::nullopt); ASSERT_TRUE(schema_violation.HasError());
EXPECT_EQ(*schema_violation, EXPECT_EQ(schema_violation.GetError(), SHARD_ERROR(ErrorCode::SCHEMA_VERTEX_PRIMARY_PROPERTIES_UNDEFINED));
SchemaViolation(SchemaViolation::ValidationStatus::VERTEX_PRIMARY_PROPERTIES_UNDEFINED, label2));
} }
// Validate wrong secondary label // Validate wrong secondary label
{ {
const auto schema_violation = schema_validator.ValidateVertexCreate(label1, {label1}, {PropertyValue("test")}); const auto schema_violation = schema_validator.ValidateVertexCreate(label1, {label1}, {PropertyValue("test")});
ASSERT_NE(schema_violation, std::nullopt); ASSERT_TRUE(schema_violation.HasError());
EXPECT_EQ(*schema_violation, EXPECT_EQ(schema_violation.GetError(), SHARD_ERROR(ErrorCode::SCHEMA_VERTEX_SECONDARY_LABEL_IS_PRIMARY));
SchemaViolation(SchemaViolation::ValidationStatus::VERTEX_SECONDARY_LABEL_IS_PRIMARY, label1));
} }
{ {
const auto schema_violation = schema_validator.ValidateVertexCreate(label1, {label2}, {PropertyValue("test")}); const auto schema_violation = schema_validator.ValidateVertexCreate(label1, {label2}, {PropertyValue("test")});
ASSERT_NE(schema_violation, std::nullopt); ASSERT_TRUE(schema_violation.HasError());
EXPECT_EQ(*schema_violation, EXPECT_EQ(schema_violation.GetError(), SHARD_ERROR(ErrorCode::SCHEMA_VERTEX_SECONDARY_LABEL_IS_PRIMARY));
SchemaViolation(SchemaViolation::ValidationStatus::VERTEX_SECONDARY_LABEL_IS_PRIMARY, label2));
} }
// Validate wrong property type // Validate wrong property type
{ {
const auto schema_violation = schema_validator.ValidateVertexCreate(label1, {}, {PropertyValue(1)}); const auto schema_violation = schema_validator.ValidateVertexCreate(label1, {}, {PropertyValue(1)});
ASSERT_NE(schema_violation, std::nullopt); ASSERT_TRUE(schema_violation.HasError());
EXPECT_EQ(*schema_violation, SchemaViolation(SchemaViolation::ValidationStatus::VERTEX_PROPERTY_WRONG_TYPE, label1, EXPECT_EQ(schema_violation.GetError(), SHARD_ERROR(ErrorCode::SCHEMA_VERTEX_PROPERTY_WRONG_TYPE));
schema_prop_string, PropertyValue(1)));
} }
{ {
const auto schema_violation = const auto schema_violation =
schema_validator.ValidateVertexCreate(label2, {}, {PropertyValue("test"), PropertyValue(12), PropertyValue(1)}); schema_validator.ValidateVertexCreate(label2, {}, {PropertyValue("test"), PropertyValue(12), PropertyValue(1)});
ASSERT_NE(schema_violation, std::nullopt); ASSERT_TRUE(schema_violation.HasError());
EXPECT_EQ(*schema_violation, SchemaViolation(SchemaViolation::ValidationStatus::VERTEX_PROPERTY_WRONG_TYPE, label2, EXPECT_EQ(schema_violation.GetError(), SHARD_ERROR(ErrorCode::SCHEMA_VERTEX_PROPERTY_WRONG_TYPE));
schema_prop_duration, PropertyValue(1)));
} }
{ {
const auto wrong_prop = PropertyValue(TemporalData(TemporalType::Date, 1234)); const auto wrong_prop = PropertyValue(TemporalData(TemporalType::Date, 1234));
const auto schema_violation = const auto schema_violation =
schema_validator.ValidateVertexCreate(label2, {}, {PropertyValue("test"), PropertyValue(12), wrong_prop}); schema_validator.ValidateVertexCreate(label2, {}, {PropertyValue("test"), PropertyValue(12), wrong_prop});
ASSERT_NE(schema_violation, std::nullopt); ASSERT_TRUE(schema_violation.HasError());
EXPECT_EQ(*schema_violation, SchemaViolation(SchemaViolation::ValidationStatus::VERTEX_PROPERTY_WRONG_TYPE, label2, EXPECT_EQ(schema_violation.GetError(), SHARD_ERROR(ErrorCode::SCHEMA_VERTEX_PROPERTY_WRONG_TYPE));
schema_prop_duration, wrong_prop));
} }
// Passing validations // Passing validations
EXPECT_EQ(schema_validator.ValidateVertexCreate(label1, {}, {PropertyValue("test")}), std::nullopt); EXPECT_FALSE(schema_validator.ValidateVertexCreate(label1, {}, {PropertyValue("test")}).HasError());
EXPECT_EQ(schema_validator.ValidateVertexCreate(label1, {NameToLabel("label3"), NameToLabel("label4")}, EXPECT_FALSE(
{PropertyValue("test")}), schema_validator
std::nullopt); .ValidateVertexCreate(label1, {NameToLabel("label3"), NameToLabel("label4")}, {PropertyValue("test")})
EXPECT_EQ(schema_validator.ValidateVertexCreate( .HasError());
label2, {}, EXPECT_FALSE(schema_validator
{PropertyValue("test"), PropertyValue(122), PropertyValue(TemporalData(TemporalType::Duration, 1234))}), .ValidateVertexCreate(label2, {},
std::nullopt); {PropertyValue("test"), PropertyValue(122),
EXPECT_EQ(schema_validator.ValidateVertexCreate(label2, {NameToLabel("label5"), NameToLabel("label6")}, PropertyValue(TemporalData(TemporalType::Duration, 1234))})
.HasError());
EXPECT_FALSE(schema_validator
.ValidateVertexCreate(label2, {NameToLabel("label5"), NameToLabel("label6")},
{PropertyValue("test123"), PropertyValue(122221), {PropertyValue("test123"), PropertyValue(122221),
PropertyValue(TemporalData(TemporalType::Duration, 12344321))}), PropertyValue(TemporalData(TemporalType::Duration, 12344321))})
std::nullopt); .HasError());
} }
TEST_F(SchemaValidatorTest, TestSchemaValidatePropertyUpdate) { TEST_F(SchemaValidatorTest, TestSchemaValidatePropertyUpdate) {
// Validate updating of primary key // Validate updating of primary key
{ {
const auto schema_violation = schema_validator.ValidatePropertyUpdate(label1, prop_string); const auto schema_violation = schema_validator.ValidatePropertyUpdate(label1, prop_string);
ASSERT_NE(schema_violation, std::nullopt); ASSERT_TRUE(schema_violation.HasError());
EXPECT_EQ(*schema_violation, SchemaViolation(SchemaViolation::ValidationStatus::VERTEX_UPDATE_PRIMARY_KEY, label1, EXPECT_EQ(schema_violation.GetError(), SHARD_ERROR(ErrorCode::SCHEMA_VERTEX_UPDATE_PRIMARY_KEY));
schema_prop_string));
} }
{ {
const auto schema_violation = schema_validator.ValidatePropertyUpdate(label2, prop_duration); const auto schema_violation = schema_validator.ValidatePropertyUpdate(label2, prop_duration);
ASSERT_NE(schema_violation, std::nullopt); ASSERT_TRUE(schema_violation.HasError());
EXPECT_EQ(*schema_violation, SchemaViolation(SchemaViolation::ValidationStatus::VERTEX_UPDATE_PRIMARY_KEY, label2, EXPECT_EQ(schema_violation.GetError(), SHARD_ERROR(ErrorCode::SCHEMA_VERTEX_UPDATE_PRIMARY_KEY));
schema_prop_duration));
} }
EXPECT_EQ(schema_validator.ValidatePropertyUpdate(label1, prop_int), std::nullopt); EXPECT_FALSE(schema_validator.ValidatePropertyUpdate(label1, prop_int).HasError());
EXPECT_EQ(schema_validator.ValidatePropertyUpdate(label1, prop_duration), std::nullopt); EXPECT_FALSE(schema_validator.ValidatePropertyUpdate(label1, prop_duration).HasError());
EXPECT_EQ(schema_validator.ValidatePropertyUpdate(label2, NameToProperty("test")), std::nullopt); EXPECT_FALSE(schema_validator.ValidatePropertyUpdate(label2, NameToProperty("test")).HasError());
} }
TEST_F(SchemaValidatorTest, TestSchemaValidatePropertyUpdateLabel) { TEST_F(SchemaValidatorTest, TestSchemaValidatePropertyUpdateLabel) {
// Validate adding primary label // Validate adding primary label
{ {
const auto schema_violation = schema_validator.ValidateLabelUpdate(label1); const auto schema_violation = schema_validator.ValidateLabelUpdate(label1);
ASSERT_NE(schema_violation, std::nullopt); ASSERT_TRUE(schema_violation.HasError());
EXPECT_EQ(*schema_violation, EXPECT_EQ(schema_violation.GetError(), SHARD_ERROR(ErrorCode::SCHEMA_VERTEX_UPDATE_PRIMARY_LABEL));
SchemaViolation(SchemaViolation::ValidationStatus::VERTEX_UPDATE_PRIMARY_LABEL, label1));
} }
{ {
const auto schema_violation = schema_validator.ValidateLabelUpdate(label2); const auto schema_violation = schema_validator.ValidateLabelUpdate(label2);
ASSERT_NE(schema_violation, std::nullopt); ASSERT_TRUE(schema_violation.HasError());
EXPECT_EQ(*schema_violation, EXPECT_EQ(schema_violation.GetError(), SHARD_ERROR(ErrorCode::SCHEMA_VERTEX_UPDATE_PRIMARY_LABEL));
SchemaViolation(SchemaViolation::ValidationStatus::VERTEX_UPDATE_PRIMARY_LABEL, label2));
} }
EXPECT_EQ(schema_validator.ValidateLabelUpdate(NameToLabel("test")), std::nullopt); EXPECT_FALSE(schema_validator.ValidateLabelUpdate(NameToLabel("test")).HasError());
} }
} // namespace memgraph::storage::v3::tests } // namespace memgraph::storage::v3::tests

View File

@ -94,7 +94,7 @@ class ShardRSMTest : public testing::Test {
auto commit_res = Commit(create_req); auto commit_res = Commit(create_req);
ASSERT_TRUE(std::holds_alternative<msgs::CommitResponse>(commit_res)); ASSERT_TRUE(std::holds_alternative<msgs::CommitResponse>(commit_res));
ASSERT_TRUE(std::get<msgs::CommitResponse>(commit_res).success); ASSERT_FALSE(std::get<msgs::CommitResponse>(commit_res).error.has_value());
} }
void AssertVertexExists(const msgs::PrimaryKey &primary_key, const std::vector<msgs::Label> &labels, void AssertVertexExists(const msgs::PrimaryKey &primary_key, const std::vector<msgs::Label> &labels,
@ -109,7 +109,7 @@ class ShardRSMTest : public testing::Test {
auto maybe_read_res = shard_rsm->Read(scan_req); auto maybe_read_res = shard_rsm->Read(scan_req);
ASSERT_TRUE(std::holds_alternative<msgs::ScanVerticesResponse>(maybe_read_res)); ASSERT_TRUE(std::holds_alternative<msgs::ScanVerticesResponse>(maybe_read_res));
const auto read_res = std::get<msgs::ScanVerticesResponse>(maybe_read_res); const auto read_res = std::get<msgs::ScanVerticesResponse>(maybe_read_res);
EXPECT_TRUE(read_res.success); EXPECT_FALSE(read_res.error.has_value());
EXPECT_EQ(read_res.results.size(), 1); EXPECT_EQ(read_res.results.size(), 1);
// Read results // Read results
@ -148,11 +148,11 @@ TEST_F(ShardRSMTest, TestUpdateVertexSecondaryProperty) {
const auto write_res = shard_rsm->Apply(update_req); const auto write_res = shard_rsm->Apply(update_req);
ASSERT_TRUE(std::holds_alternative<msgs::UpdateVerticesResponse>(write_res)); ASSERT_TRUE(std::holds_alternative<msgs::UpdateVerticesResponse>(write_res));
EXPECT_TRUE(std::get<msgs::UpdateVerticesResponse>(write_res).success); EXPECT_FALSE(std::get<msgs::UpdateVerticesResponse>(write_res).error.has_value());
const auto commit_res = Commit(update_req); const auto commit_res = Commit(update_req);
ASSERT_TRUE(std::holds_alternative<msgs::CommitResponse>(commit_res)); ASSERT_TRUE(std::holds_alternative<msgs::CommitResponse>(commit_res));
EXPECT_TRUE(std::get<msgs::CommitResponse>(commit_res).success); EXPECT_FALSE(std::get<msgs::CommitResponse>(commit_res).error.has_value());
} }
AssertVertexExists(pk, {}, {{primary_property1, primary_key_val}, {prop, msgs::Value(updated_vertex_id)}}); AssertVertexExists(pk, {}, {{primary_property1, primary_key_val}, {prop, msgs::Value(updated_vertex_id)}});
@ -167,11 +167,11 @@ TEST_F(ShardRSMTest, TestUpdateVertexSecondaryProperty) {
const auto write_res = shard_rsm->Apply(update_req); const auto write_res = shard_rsm->Apply(update_req);
ASSERT_TRUE(std::holds_alternative<msgs::UpdateVerticesResponse>(write_res)); ASSERT_TRUE(std::holds_alternative<msgs::UpdateVerticesResponse>(write_res));
ASSERT_TRUE(std::get<msgs::UpdateVerticesResponse>(write_res).success); EXPECT_FALSE(std::get<msgs::UpdateVerticesResponse>(write_res).error.has_value());
const auto commit_res = Commit(update_req); const auto commit_res = Commit(update_req);
ASSERT_TRUE(std::holds_alternative<msgs::CommitResponse>(commit_res)); ASSERT_TRUE(std::holds_alternative<msgs::CommitResponse>(commit_res));
EXPECT_TRUE(std::get<msgs::CommitResponse>(commit_res).success); EXPECT_FALSE(std::get<msgs::CommitResponse>(commit_res).error.has_value());
AssertVertexExists(pk, {}, {{primary_property1, primary_key_val}, {prop, msgs::Value(updated_vertex_id_2)}}); AssertVertexExists(pk, {}, {{primary_property1, primary_key_val}, {prop, msgs::Value(updated_vertex_id_2)}});
} }
AssertVertexExists(pk, {}, {{primary_property1, primary_key_val}, {prop, msgs::Value(updated_vertex_id_2)}}); AssertVertexExists(pk, {}, {{primary_property1, primary_key_val}, {prop, msgs::Value(updated_vertex_id_2)}});
@ -186,11 +186,11 @@ TEST_F(ShardRSMTest, TestUpdateVertexSecondaryProperty) {
const auto write_res = shard_rsm->Apply(update_req); const auto write_res = shard_rsm->Apply(update_req);
ASSERT_TRUE(std::holds_alternative<msgs::UpdateVerticesResponse>(write_res)); ASSERT_TRUE(std::holds_alternative<msgs::UpdateVerticesResponse>(write_res));
EXPECT_TRUE(std::get<msgs::UpdateVerticesResponse>(write_res).success); EXPECT_FALSE(std::get<msgs::UpdateVerticesResponse>(write_res).error.has_value());
const auto commit_res = Commit(update_req); const auto commit_res = Commit(update_req);
ASSERT_TRUE(std::holds_alternative<msgs::CommitResponse>(commit_res)); ASSERT_TRUE(std::holds_alternative<msgs::CommitResponse>(commit_res));
EXPECT_TRUE(std::get<msgs::CommitResponse>(commit_res).success); EXPECT_FALSE(std::get<msgs::CommitResponse>(commit_res).error.has_value());
} }
AssertVertexExists(pk, {}, {{primary_property1, primary_key_val}}); AssertVertexExists(pk, {}, {{primary_property1, primary_key_val}});
} }
@ -213,7 +213,7 @@ TEST_F(ShardRSMTest, TestUpdateVertexPrimaryProperty) {
const auto write_res = shard_rsm->Apply(update_req); const auto write_res = shard_rsm->Apply(update_req);
ASSERT_TRUE(std::holds_alternative<msgs::UpdateVerticesResponse>(write_res)); ASSERT_TRUE(std::holds_alternative<msgs::UpdateVerticesResponse>(write_res));
EXPECT_FALSE(std::get<msgs::UpdateVerticesResponse>(write_res).success); EXPECT_TRUE(std::get<msgs::UpdateVerticesResponse>(write_res).error.has_value());
} }
AssertVertexExists(pk, {}, {{primary_property1, primary_key_val}}); AssertVertexExists(pk, {}, {{primary_property1, primary_key_val}});
// Try to update primary property of another schema // Try to update primary property of another schema
@ -226,11 +226,11 @@ TEST_F(ShardRSMTest, TestUpdateVertexPrimaryProperty) {
const auto write_res = shard_rsm->Apply(update_req); const auto write_res = shard_rsm->Apply(update_req);
ASSERT_TRUE(std::holds_alternative<msgs::UpdateVerticesResponse>(write_res)); ASSERT_TRUE(std::holds_alternative<msgs::UpdateVerticesResponse>(write_res));
EXPECT_TRUE(std::get<msgs::UpdateVerticesResponse>(write_res).success); EXPECT_FALSE(std::get<msgs::UpdateVerticesResponse>(write_res).error.has_value());
const auto commit_res = Commit(update_req); const auto commit_res = Commit(update_req);
ASSERT_TRUE(std::holds_alternative<msgs::CommitResponse>(commit_res)); ASSERT_TRUE(std::holds_alternative<msgs::CommitResponse>(commit_res));
EXPECT_TRUE(std::get<msgs::CommitResponse>(commit_res).success); EXPECT_FALSE(std::get<msgs::CommitResponse>(commit_res).error.has_value());
} }
AssertVertexExists(pk, {}, AssertVertexExists(pk, {},
{{primary_property1, primary_key_val}, {primary_property2, msgs::Value(updated_vertex_id)}}); {{primary_property1, primary_key_val}, {primary_property2, msgs::Value(updated_vertex_id)}});
@ -253,11 +253,11 @@ TEST_F(ShardRSMTest, TestUpdateSecondaryLabel) {
const auto write_res = shard_rsm->Apply(update_req); const auto write_res = shard_rsm->Apply(update_req);
ASSERT_TRUE(std::holds_alternative<msgs::UpdateVerticesResponse>(write_res)); ASSERT_TRUE(std::holds_alternative<msgs::UpdateVerticesResponse>(write_res));
ASSERT_TRUE(std::get<msgs::UpdateVerticesResponse>(write_res).success); EXPECT_FALSE(std::get<msgs::UpdateVerticesResponse>(write_res).error.has_value());
const auto commit_res = Commit(update_req); const auto commit_res = Commit(update_req);
ASSERT_TRUE(std::holds_alternative<msgs::CommitResponse>(commit_res)); ASSERT_TRUE(std::holds_alternative<msgs::CommitResponse>(commit_res));
EXPECT_TRUE(std::get<msgs::CommitResponse>(commit_res).success); EXPECT_FALSE(std::get<msgs::CommitResponse>(commit_res).error.has_value());
} }
AssertVertexExists(pk, {secondary_label}, {{primary_property1, primary_key_val}}); AssertVertexExists(pk, {secondary_label}, {{primary_property1, primary_key_val}});
@ -270,11 +270,11 @@ TEST_F(ShardRSMTest, TestUpdateSecondaryLabel) {
const auto write_res = shard_rsm->Apply(update_req); const auto write_res = shard_rsm->Apply(update_req);
ASSERT_TRUE(std::holds_alternative<msgs::UpdateVerticesResponse>(write_res)); ASSERT_TRUE(std::holds_alternative<msgs::UpdateVerticesResponse>(write_res));
EXPECT_TRUE(std::get<msgs::UpdateVerticesResponse>(write_res).success); EXPECT_FALSE(std::get<msgs::UpdateVerticesResponse>(write_res).error.has_value());
const auto commit_res = Commit(update_req); const auto commit_res = Commit(update_req);
ASSERT_TRUE(std::holds_alternative<msgs::CommitResponse>(commit_res)); ASSERT_TRUE(std::holds_alternative<msgs::CommitResponse>(commit_res));
EXPECT_TRUE(std::get<msgs::CommitResponse>(commit_res).success); EXPECT_FALSE(std::get<msgs::CommitResponse>(commit_res).error.has_value());
} }
AssertVertexExists(pk, {}, {{primary_property1, primary_key_val}}); AssertVertexExists(pk, {}, {{primary_property1, primary_key_val}});
} }
@ -295,7 +295,7 @@ TEST_F(ShardRSMTest, TestUpdatePrimaryLabel) {
const auto write_res = shard_rsm->Apply(update_req); const auto write_res = shard_rsm->Apply(update_req);
ASSERT_TRUE(std::holds_alternative<msgs::UpdateVerticesResponse>(write_res)); ASSERT_TRUE(std::holds_alternative<msgs::UpdateVerticesResponse>(write_res));
EXPECT_FALSE(std::get<msgs::UpdateVerticesResponse>(write_res).success); EXPECT_TRUE(std::get<msgs::UpdateVerticesResponse>(write_res).error.has_value());
} }
AssertVertexExists(pk, {}, {{primary_property1, primary_key_val}}); AssertVertexExists(pk, {}, {{primary_property1, primary_key_val}});
@ -308,7 +308,7 @@ TEST_F(ShardRSMTest, TestUpdatePrimaryLabel) {
const auto write_res = shard_rsm->Apply(update_req); const auto write_res = shard_rsm->Apply(update_req);
ASSERT_TRUE(std::holds_alternative<msgs::UpdateVerticesResponse>(write_res)); ASSERT_TRUE(std::holds_alternative<msgs::UpdateVerticesResponse>(write_res));
EXPECT_FALSE(std::get<msgs::UpdateVerticesResponse>(write_res).success); EXPECT_TRUE(std::get<msgs::UpdateVerticesResponse>(write_res).error.has_value());
} }
AssertVertexExists(pk, {}, {{primary_property1, primary_key_val}}); AssertVertexExists(pk, {}, {{primary_property1, primary_key_val}});
} }

View File

@ -16,6 +16,7 @@
#include <gmock/gmock.h> #include <gmock/gmock.h>
#include <gtest/gtest.h> #include <gtest/gtest.h>
#include "common/errors.hpp"
#include "common/types.hpp" #include "common/types.hpp"
#include "storage/v3/delta.hpp" #include "storage/v3/delta.hpp"
#include "storage/v3/id_types.hpp" #include "storage/v3/id_types.hpp"
@ -76,7 +77,7 @@ TEST_F(StorageV3Accessor, TestPrimaryLabel) {
ASSERT_TRUE(vertex.PrimaryLabel(View::OLD).HasError()); ASSERT_TRUE(vertex.PrimaryLabel(View::OLD).HasError());
const auto error_primary_label = vertex.PrimaryLabel(View::OLD).GetError(); const auto error_primary_label = vertex.PrimaryLabel(View::OLD).GetError();
ASSERT_FALSE(vertex.PrimaryLabel(View::NEW).HasError()); ASSERT_FALSE(vertex.PrimaryLabel(View::NEW).HasError());
EXPECT_EQ(error_primary_label, Error::NONEXISTENT_OBJECT); EXPECT_EQ(error_primary_label, SHARD_ERROR(ErrorCode::NONEXISTENT_OBJECT));
} }
{ {
auto acc = storage.Access(GetNextHlc()); auto acc = storage.Access(GetNextHlc());
@ -127,9 +128,7 @@ TEST_F(StorageV3Accessor, TestAddLabels) {
const auto label1 = NameToLabelId("label"); const auto label1 = NameToLabelId("label");
auto vertex = acc.CreateVertexAndValidate({label1}, {PropertyValue{2}}, {}); auto vertex = acc.CreateVertexAndValidate({label1}, {PropertyValue{2}}, {});
ASSERT_TRUE(vertex.HasError()); ASSERT_TRUE(vertex.HasError());
ASSERT_TRUE(std::holds_alternative<SchemaViolation>(vertex.GetError())); EXPECT_EQ(vertex.GetError(), SHARD_ERROR(ErrorCode::SCHEMA_VERTEX_SECONDARY_LABEL_IS_PRIMARY));
EXPECT_EQ(std::get<SchemaViolation>(vertex.GetError()),
SchemaViolation(SchemaViolation::ValidationStatus::VERTEX_SECONDARY_LABEL_IS_PRIMARY, label1));
} }
{ {
auto acc = storage.Access(GetNextHlc()); auto acc = storage.Access(GetNextHlc());
@ -138,9 +137,7 @@ TEST_F(StorageV3Accessor, TestAddLabels) {
ASSERT_TRUE(vertex.HasValue()); ASSERT_TRUE(vertex.HasValue());
const auto schema_violation = vertex->AddLabelAndValidate(label1); const auto schema_violation = vertex->AddLabelAndValidate(label1);
ASSERT_TRUE(schema_violation.HasError()); ASSERT_TRUE(schema_violation.HasError());
ASSERT_TRUE(std::holds_alternative<SchemaViolation>(schema_violation.GetError())); EXPECT_EQ(schema_violation.GetError(), SHARD_ERROR(ErrorCode::SCHEMA_VERTEX_UPDATE_PRIMARY_LABEL));
EXPECT_EQ(std::get<SchemaViolation>(schema_violation.GetError()),
SchemaViolation(SchemaViolation::ValidationStatus::VERTEX_UPDATE_PRIMARY_LABEL, label1));
} }
} }
@ -184,9 +181,7 @@ TEST_F(StorageV3Accessor, TestRemoveLabels) {
auto vertex = CreateVertexAndValidate(acc, {}, PropertyValue{2}); auto vertex = CreateVertexAndValidate(acc, {}, PropertyValue{2});
const auto res1 = vertex.RemoveLabelAndValidate(primary_label); const auto res1 = vertex.RemoveLabelAndValidate(primary_label);
ASSERT_TRUE(res1.HasError()); ASSERT_TRUE(res1.HasError());
ASSERT_TRUE(std::holds_alternative<SchemaViolation>(res1.GetError())); EXPECT_EQ(res1.GetError(), SHARD_ERROR(ErrorCode::SCHEMA_VERTEX_UPDATE_PRIMARY_LABEL));
EXPECT_EQ(std::get<SchemaViolation>(res1.GetError()),
SchemaViolation(SchemaViolation::ValidationStatus::VERTEX_UPDATE_PRIMARY_LABEL, primary_label));
} }
} }
@ -205,20 +200,14 @@ TEST_F(StorageV3Accessor, TestSetKeysAndProperties) {
auto vertex = CreateVertexAndValidate(acc, {}, PropertyValue{1}); auto vertex = CreateVertexAndValidate(acc, {}, PropertyValue{1});
const auto res = vertex.SetPropertyAndValidate(primary_property, PropertyValue(1)); const auto res = vertex.SetPropertyAndValidate(primary_property, PropertyValue(1));
ASSERT_TRUE(res.HasError()); ASSERT_TRUE(res.HasError());
ASSERT_TRUE(std::holds_alternative<SchemaViolation>(res.GetError())); EXPECT_EQ(res.GetError(), SHARD_ERROR(ErrorCode::SCHEMA_VERTEX_UPDATE_PRIMARY_KEY));
EXPECT_EQ(std::get<SchemaViolation>(res.GetError()),
SchemaViolation(SchemaViolation::ValidationStatus::VERTEX_UPDATE_PRIMARY_KEY, primary_label,
SchemaProperty{primary_property, common::SchemaType::INT}));
} }
{ {
auto acc = storage.Access(GetNextHlc()); auto acc = storage.Access(GetNextHlc());
auto vertex = CreateVertexAndValidate(acc, {}, PropertyValue{2}); auto vertex = CreateVertexAndValidate(acc, {}, PropertyValue{2});
const auto res = vertex.SetPropertyAndValidate(primary_property, PropertyValue()); const auto res = vertex.SetPropertyAndValidate(primary_property, PropertyValue());
ASSERT_TRUE(res.HasError()); ASSERT_TRUE(res.HasError());
ASSERT_TRUE(std::holds_alternative<SchemaViolation>(res.GetError())); EXPECT_EQ(res.GetError(), SHARD_ERROR(ErrorCode::SCHEMA_VERTEX_UPDATE_PRIMARY_KEY));
EXPECT_EQ(std::get<SchemaViolation>(res.GetError()),
SchemaViolation(SchemaViolation::ValidationStatus::VERTEX_UPDATE_PRIMARY_KEY, primary_label,
SchemaProperty{primary_property, common::SchemaType::INT}));
} }
} }