From 02ef954e5134d79e0831d28796bec50c96721de8 Mon Sep 17 00:00:00 2001
From: Kostas Kyrimis <kostaskyrim@gmail.com>
Date: Mon, 7 Nov 2022 18:28:35 +0200
Subject: [PATCH 01/26] Add mg-functions lib and integrated with SE and QE

---
 src/CMakeLists.txt                            |    1 +
 src/expr/CMakeLists.txt                       |    2 +-
 src/expr/interpret/eval.hpp                   |    3 +-
 src/functions/CMakeLists.txt                  |    2 +
 src/functions/awesome_memgraph_functions.hpp  | 1463 +++++++++++++++++
 src/query/v2/CMakeLists.txt                   |    3 +-
 src/query/v2/accessors.hpp                    |   19 +-
 src/query/v2/conversions.hpp                  |    4 +
 src/query/v2/frontend/ast/ast.lcp             |   13 +-
 .../interpret/awesome_memgraph_functions.cpp  | 1108 -------------
 .../interpret/awesome_memgraph_functions.hpp  |   55 -
 src/query/v2/plan/preprocess.cpp              |    2 +-
 src/storage/v3/CMakeLists.txt                 |    2 +-
 src/storage/v3/bindings/ast/ast.lcp           |   28 +-
 src/storage/v3/bindings/db_accessor.hpp       |    2 +-
 src/storage/v3/conversions.hpp                |    4 +
 src/storage/v3/edge_accessor.cpp              |    7 +-
 src/storage/v3/edge_accessor.hpp              |    7 +-
 src/storage/v3/expr.cpp                       |    9 +-
 src/storage/v3/shard.cpp                      |    4 +-
 src/storage/v3/shard_rsm.cpp                  |   10 +-
 src/storage/v3/vertex_accessor.cpp            |    3 +
 src/storage/v3/vertex_accessor.hpp            |    3 +
 tests/unit/storage_v3_edge.cpp                |  846 +++++-----
 24 files changed, 1970 insertions(+), 1630 deletions(-)
 create mode 100644 src/functions/CMakeLists.txt
 create mode 100644 src/functions/awesome_memgraph_functions.hpp
 delete mode 100644 src/query/v2/interpret/awesome_memgraph_functions.cpp
 delete mode 100644 src/query/v2/interpret/awesome_memgraph_functions.hpp

diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 8b84bb26a..81fc61836 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -21,6 +21,7 @@ add_subdirectory(auth)
 add_subdirectory(parser)
 add_subdirectory(expr)
 add_subdirectory(coordinator)
+add_subdirectory(functions)
 
 if (MG_ENTERPRISE)
   add_subdirectory(audit)
diff --git a/src/expr/CMakeLists.txt b/src/expr/CMakeLists.txt
index e529512b7..31cbfa493 100644
--- a/src/expr/CMakeLists.txt
+++ b/src/expr/CMakeLists.txt
@@ -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}/interpret)
 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)
diff --git a/src/expr/interpret/eval.hpp b/src/expr/interpret/eval.hpp
index 70127c023..139e37514 100644
--- a/src/expr/interpret/eval.hpp
+++ b/src/expr/interpret/eval.hpp
@@ -24,6 +24,7 @@
 #include "expr/exceptions.hpp"
 #include "expr/interpret/frame.hpp"
 #include "expr/semantic/symbol_table.hpp"
+#include "functions/awesome_memgraph_functions.hpp"
 #include "utils/exceptions.hpp"
 
 namespace memgraph::expr {
@@ -479,7 +480,7 @@ class ExpressionEvaluator : public ExpressionVisitor<TypedValue> {
   }
 
   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.
     if (function.arguments_.size() <= 8) {
       TypedValue arguments[8] = {TypedValue(ctx_->memory), TypedValue(ctx_->memory), TypedValue(ctx_->memory),
diff --git a/src/functions/CMakeLists.txt b/src/functions/CMakeLists.txt
new file mode 100644
index 000000000..09720c862
--- /dev/null
+++ b/src/functions/CMakeLists.txt
@@ -0,0 +1,2 @@
+add_library(mg-functions INTERFACE)
+target_include_directories(mg-functions INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})
diff --git a/src/functions/awesome_memgraph_functions.hpp b/src/functions/awesome_memgraph_functions.hpp
new file mode 100644
index 000000000..ca415c69b
--- /dev/null
+++ b/src/functions/awesome_memgraph_functions.hpp
@@ -0,0 +1,1463 @@
+// 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 <functional>
+#include <string>
+#include <type_traits>
+#include <unordered_map>
+
+#include "storage/v3/result.hpp"
+#include "storage/v3/view.hpp"
+#include "utils/algorithm.hpp"
+#include "utils/cast.hpp"
+#include "utils/concepts.hpp"
+#include "utils/memory.hpp"
+#include "utils/pmr/string.hpp"
+#include "utils/string.hpp"
+#include "utils/temporal.hpp"
+
+namespace memgraph::functions {
+
+class FunctionRuntimeException : public utils::BasicException {
+  using utils::BasicException::BasicException;
+};
+
+template <typename TAccessor>
+struct FunctionContext {
+  TAccessor *db_accessor;
+  utils::MemoryResource *memory;
+  int64_t timestamp;
+  std::unordered_map<std::string, int64_t> *counters;
+  storage::v3::View view;
+};
+
+// Tags for the NameToFunction() function template
+struct StorageEngineTag {};
+struct QueryEngineTag {};
+
+namespace impl {
+struct SinkCallable {
+  void operator()() {}
+};
+}  // namespace impl
+
+/// Return the function implementation with the given name.
+///
+/// Note, returned function signature uses C-style access to an array to allow
+/// having an array stored anywhere the caller likes, as long as it is
+/// contiguous in memory. Since most functions don't take many arguments, it's
+/// convenient to have them stored in the calling stack frame.
+template <typename TypedValueT, typename FunctionContextT, typename Tag, typename Conv = impl::SinkCallable>
+std::function<TypedValueT(const TypedValueT *arguments, int64_t num_arguments, const FunctionContextT &context)>
+NameToFunction(const std::string &function_name);
+
+namespace {
+const char kStartsWith[] = "STARTSWITH";
+const char kEndsWith[] = "ENDSWITH";
+const char kContains[] = "CONTAINS";
+const char kId[] = "ID";
+}  // namespace
+
+}  // namespace memgraph::functions
+
+namespace memgraph::functions::impl {
+
+////////////////////////////////////////////////////////////////////////////////
+// eDSL using template magic for describing a type of an awesome memgraph
+// function and checking if the passed in arguments match the description.
+//
+// To use the type checking eDSL, you should put a `FType` invocation in the
+// body of your awesome Memgraph function. `FType` takes type arguments as the
+// description of the function type signature. Each runtime argument will be
+// checked in order corresponding to given compile time type arguments. These
+// type arguments can come in two forms:
+//
+//   * final, primitive type descriptor and
+//   * combinator type descriptor.
+//
+// The primitive type descriptors are defined as empty structs, they are right
+// below this documentation.
+//
+// Combinator type descriptors are defined as structs taking additional type
+// parameters, you can find these further below in the implementation. Of
+// primary interest are `Or` and `Optional` type combinators.
+//
+// With `Or` you can describe that an argument can be any of the types listed in
+// `Or`. For example, `Or<Null, Bool, Integer>` allows an argument to be either
+// `Null` or a boolean or an integer.
+//
+// The `Optional` combinator is used to define optional arguments to a function.
+// These must come as the last positional arguments. Naturally, you can use `Or`
+// inside `Optional`. So for example, `Optional<Or<Null, Bool>, Integer>`
+// describes that a function takes 2 optional arguments. The 1st one must be
+// either a `Null` or a boolean, while the 2nd one must be an integer. The type
+// signature check will succeed in the following cases.
+//
+//   * No optional arguments were supplied.
+//   * One argument was supplied and it passes `Or<Null, Bool>` check.
+//   * Two arguments were supplied, the 1st one passes `Or<Null, Bool>` check
+//     and the 2nd one passes `Integer` check.
+//
+// Runtime arguments to `FType` are: function name, pointer to arguments and the
+// number of received arguments.
+//
+// Full example.
+//
+//     FType<Or<Null, String>, NonNegativeInteger,
+//           Optional<NonNegativeInteger>>("substring", args, nargs);
+//
+// The above will check that `substring` function received the 2 required
+// arguments. Optionally, the function may take a 3rd argument. The 1st argument
+// must be either a `Null` or a character string. The 2nd argument is required
+// to be a non-negative integer. If the 3rd argument was supplied, it will also
+// be checked that it is a non-negative integer. If any of these checks fail,
+// `FType` will throw a `FunctionRuntimeException` with an appropriate error
+// message.
+////////////////////////////////////////////////////////////////////////////////
+
+struct Null {};
+struct Bool {};
+struct Integer {};
+struct PositiveInteger {};
+struct NonZeroInteger {};
+struct NonNegativeInteger {};
+struct Double {};
+struct Number {};
+struct List {};
+struct String {};
+struct Map {};
+struct Edge {};
+struct Vertex {};
+struct Path {};
+struct Date {};
+struct LocalTime {};
+struct LocalDateTime {};
+struct Duration {};
+
+template <typename ArgType, typename TypedValueT>
+bool ArgIsType(const TypedValueT &arg) {
+  if constexpr (std::is_same_v<ArgType, Null>) {
+    return arg.IsNull();
+  } else if constexpr (std::is_same_v<ArgType, Bool>) {
+    return arg.IsBool();
+  } else if constexpr (std::is_same_v<ArgType, Integer>) {
+    return arg.IsInt();
+  } else if constexpr (std::is_same_v<ArgType, PositiveInteger>) {
+    return arg.IsInt() && arg.ValueInt() > 0;
+  } else if constexpr (std::is_same_v<ArgType, NonZeroInteger>) {
+    return arg.IsInt() && arg.ValueInt() != 0;
+  } else if constexpr (std::is_same_v<ArgType, NonNegativeInteger>) {
+    return arg.IsInt() && arg.ValueInt() >= 0;
+  } else if constexpr (std::is_same_v<ArgType, Double>) {
+    return arg.IsDouble();
+  } else if constexpr (std::is_same_v<ArgType, Number>) {
+    return arg.IsNumeric();
+  } else if constexpr (std::is_same_v<ArgType, List>) {
+    return arg.IsList();
+  } else if constexpr (std::is_same_v<ArgType, String>) {
+    return arg.IsString();
+  } else if constexpr (std::is_same_v<ArgType, Map>) {
+    return arg.IsMap();
+  } else if constexpr (std::is_same_v<ArgType, Vertex>) {
+    return arg.IsVertex();
+  } else if constexpr (std::is_same_v<ArgType, Edge>) {
+    return arg.IsEdge();
+  } else if constexpr (std::is_same_v<ArgType, Path>) {
+    return arg.IsPath();
+  } else if constexpr (std::is_same_v<ArgType, Date>) {
+    return arg.IsDate();
+  } else if constexpr (std::is_same_v<ArgType, LocalTime>) {
+    return arg.IsLocalTime();
+  } else if constexpr (std::is_same_v<ArgType, LocalDateTime>) {
+    return arg.IsLocalDateTime();
+  } else if constexpr (std::is_same_v<ArgType, Duration>) {
+    return arg.IsDuration();
+  } else if constexpr (std::is_same_v<ArgType, void>) {
+    return true;
+  } else {
+    static_assert(std::is_same_v<ArgType, Null>, "Unknown ArgType");
+  }
+  return false;
+}
+
+template <typename ArgType>
+constexpr const char *ArgTypeName() {
+  // The type names returned should be standardized openCypher type names.
+  // https://github.com/opencypher/openCypher/blob/master/docs/openCypher9.pdf
+  if constexpr (std::is_same_v<ArgType, Null>) {
+    return "null";
+  } else if constexpr (std::is_same_v<ArgType, Bool>) {
+    return "boolean";
+  } else if constexpr (std::is_same_v<ArgType, Integer>) {
+    return "integer";
+  } else if constexpr (std::is_same_v<ArgType, PositiveInteger>) {
+    return "positive integer";
+  } else if constexpr (std::is_same_v<ArgType, NonZeroInteger>) {
+    return "non-zero integer";
+  } else if constexpr (std::is_same_v<ArgType, NonNegativeInteger>) {
+    return "non-negative integer";
+  } else if constexpr (std::is_same_v<ArgType, Double>) {
+    return "float";
+  } else if constexpr (std::is_same_v<ArgType, Number>) {
+    return "number";
+  } else if constexpr (std::is_same_v<ArgType, List>) {
+    return "list";
+  } else if constexpr (std::is_same_v<ArgType, String>) {
+    return "string";
+  } else if constexpr (std::is_same_v<ArgType, Map>) {
+    return "map";
+  } else if constexpr (std::is_same_v<ArgType, Vertex>) {
+    return "node";
+  } else if constexpr (std::is_same_v<ArgType, Edge>) {
+    return "relationship";
+  } else if constexpr (std::is_same_v<ArgType, Path>) {
+    return "path";
+  } else if constexpr (std::is_same_v<ArgType, void>) {
+    return "void";
+  } else if constexpr (std::is_same_v<ArgType, Date>) {
+    return "Date";
+  } else if constexpr (std::is_same_v<ArgType, LocalTime>) {
+    return "LocalTime";
+  } else if constexpr (std::is_same_v<ArgType, LocalDateTime>) {
+    return "LocalDateTime";
+  } else if constexpr (std::is_same_v<ArgType, Duration>) {
+    return "Duration";
+  } else {
+    static_assert(std::is_same_v<ArgType, Null>, "Unknown ArgType");
+  }
+  return "<unknown-type>";
+}
+
+template <typename... ArgType>
+struct Or;
+
+template <typename ArgType>
+struct Or<ArgType> {
+  template <typename TypedValueT>
+  static bool Check(const TypedValueT &arg) {
+    return ArgIsType<ArgType>(arg);
+  }
+
+  static std::string TypeNames() { return ArgTypeName<ArgType>(); }
+};
+
+template <typename ArgType, typename... ArgTypes>
+struct Or<ArgType, ArgTypes...> {
+  template <typename TypedValueT>
+  static bool Check(const TypedValueT &arg) {
+    if (ArgIsType<ArgType>(arg)) return true;
+    return Or<ArgTypes...>::Check(arg);
+  }
+
+  static std::string TypeNames() {
+    if constexpr (sizeof...(ArgTypes) > 1) {
+      return fmt::format("'{}', {}", ArgTypeName<ArgType>(), Or<ArgTypes...>::TypeNames());
+    } else {
+      return fmt::format("'{}' or '{}'", ArgTypeName<ArgType>(), Or<ArgTypes...>::TypeNames());
+    }
+  }
+};
+
+template <class T>
+struct IsOrType {
+  static constexpr bool value = false;
+};
+
+template <class... ArgTypes>
+struct IsOrType<Or<ArgTypes...>> {
+  static constexpr bool value = true;
+};
+
+template <typename... ArgTypes>
+struct Optional;
+
+template <typename ArgType>
+struct Optional<ArgType> {
+  static constexpr size_t size = 1;
+
+  template <typename TypedValueT>
+  static void Check(const char *name, const TypedValueT *args, int64_t nargs, int64_t pos) {
+    if (nargs == 0) return;
+    const TypedValueT &arg = args[0];
+    if constexpr (IsOrType<ArgType>::value) {
+      if (!ArgType::Check(arg)) {
+        throw FunctionRuntimeException("Optional '{}' argument at position {} must be either {}.", name, pos,
+                                       ArgType::TypeNames());
+      }
+    } else {
+      if (!ArgIsType<ArgType>(arg))
+        throw FunctionRuntimeException("Optional '{}' argument at position {} must be '{}'.", name, pos,
+                                       ArgTypeName<ArgType>());
+    }
+  }
+};
+
+template <class ArgType, class... ArgTypes>
+struct Optional<ArgType, ArgTypes...> {
+  static constexpr size_t size = 1 + sizeof...(ArgTypes);
+
+  template <typename TypedValueT>
+  static void Check(const char *name, const TypedValueT *args, int64_t nargs, int64_t pos) {
+    if (nargs == 0) return;
+    Optional<ArgType>::Check(name, args, nargs, pos);
+    Optional<ArgTypes...>::Check(name, args + 1, nargs - 1, pos + 1);
+  }
+};
+
+template <class T>
+struct IsOptional {
+  static constexpr bool value = false;
+};
+
+template <class... ArgTypes>
+struct IsOptional<Optional<ArgTypes...>> {
+  static constexpr bool value = true;
+};
+
+template <class ArgType, class... ArgTypes>
+constexpr size_t FTypeRequiredArgs() {
+  if constexpr (IsOptional<ArgType>::value) {
+    static_assert(sizeof...(ArgTypes) == 0, "Optional arguments must be last!");
+    return 0;
+  } else if constexpr (sizeof...(ArgTypes) == 0) {
+    return 1;
+  } else {
+    return 1U + FTypeRequiredArgs<ArgTypes...>();
+  }
+}
+
+template <class ArgType, class... ArgTypes>
+constexpr size_t FTypeOptionalArgs() {
+  if constexpr (IsOptional<ArgType>::value) {
+    static_assert(sizeof...(ArgTypes) == 0, "Optional arguments must be last!");
+    return ArgType::size;
+  } else if constexpr (sizeof...(ArgTypes) == 0) {
+    return 0;
+  } else {
+    return FTypeOptionalArgs<ArgTypes...>();
+  }
+}
+
+template <typename TypedValueT, typename ArgType, typename... ArgTypes>
+void FType(const char *name, const TypedValueT *args, int64_t nargs, int64_t pos = 1) {
+  if constexpr (std::is_same_v<ArgType, void>) {
+    if (nargs != 0) {
+      throw FunctionRuntimeException("'{}' requires no arguments.", name);
+    }
+    return;
+  }
+  static constexpr int64_t required_args = FTypeRequiredArgs<ArgType, ArgTypes...>();
+  static constexpr int64_t optional_args = FTypeOptionalArgs<ArgType, ArgTypes...>();
+  static constexpr int64_t total_args = required_args + optional_args;
+  if constexpr (optional_args > 0) {
+    if (nargs < required_args || nargs > total_args) {
+      throw FunctionRuntimeException("'{}' requires between {} and {} arguments.", name, required_args, total_args);
+    }
+  } else {
+    if (nargs != required_args) {
+      throw FunctionRuntimeException("'{}' requires exactly {} {}.", name, required_args,
+                                     required_args == 1 ? "argument" : "arguments");
+    }
+  }
+  const TypedValueT &arg = args[0];
+  if constexpr (IsOrType<ArgType>::value) {
+    if (!ArgType::Check(arg)) {
+      throw FunctionRuntimeException("'{}' argument at position {} must be either {}.", name, pos,
+                                     ArgType::TypeNames());
+    }
+  } else if constexpr (IsOptional<ArgType>::value) {
+    static_assert(sizeof...(ArgTypes) == 0, "Optional arguments must be last!");
+    ArgType::Check(name, args, nargs, pos);
+  } else {
+    if (!ArgIsType<ArgType>(arg)) {
+      throw FunctionRuntimeException("'{}' argument at position {} must be '{}'", name, pos, ArgTypeName<ArgType>());
+    }
+  }
+  if constexpr (sizeof...(ArgTypes) > 0) {
+    FType<TypedValueT, ArgTypes...>(name, args + 1, nargs - 1, pos + 1);
+  }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// END function type description eDSL
+////////////////////////////////////////////////////////////////////////////////
+
+// Predicate functions.
+// Neo4j has all, any, exists, none, single
+// Those functions are a little bit different since they take a filterExpression
+// as an argument.
+// There is all, any, none and single productions in opencypher grammar, but it
+// will be trivial to also add exists.
+// TODO: Implement this.
+
+// Scalar functions.
+// We don't have a way to implement id function since we don't store any. If it
+// is really neccessary we could probably map vlist* to id.
+// TODO: Implement length (it works on a path, but we didn't define path
+// structure yet).
+// TODO: Implement size(pattern), for example size((a)-[:X]-()) should return
+// number of results of this pattern. I don't think we will ever do this.
+// TODO: Implement rest of the list functions.
+// TODO: Implement degrees, haversin, radians
+// TODO: Implement spatial functions
+
+template <typename TypedValueT, typename FunctionContextT, typename Tag>
+TypedValueT EndNode(const TypedValueT *args, int64_t nargs, const FunctionContextT &ctx) {
+  FType<TypedValueT, Or<Null, Edge>>("endNode", args, nargs);
+  if (args[0].IsNull()) return TypedValueT(ctx.memory);
+  if constexpr (std::is_same_v<Tag, StorageEngineTag>) {
+    const auto to = args[0].ValueEdge().To();
+    auto pk = to.primary_key;
+    auto maybe_vertex_accessor = ctx.db_accessor->FindVertex(pk, ctx.view);
+    if (!maybe_vertex_accessor) {
+      throw functions::FunctionRuntimeException("Trying to get properties from a deleted object.");
+    }
+    return TypedValueT(*maybe_vertex_accessor, ctx.memory);
+  } else {
+    return TypedValueT(args[0].ValueEdge().To(), ctx.memory);
+  }
+}
+
+template <typename TypedValueT, typename FunctionContextT>
+TypedValueT Head(const TypedValueT *args, int64_t nargs, const FunctionContextT &ctx) {
+  FType<TypedValueT, Or<Null, List>>("head", args, nargs);
+  if (args[0].IsNull()) return TypedValueT(ctx.memory);
+  const auto &list = args[0].ValueList();
+  if (list.empty()) return TypedValueT(ctx.memory);
+  return TypedValueT(list[0], ctx.memory);
+}
+
+template <typename TypedValueT, typename FunctionContextT>
+TypedValueT Last(const TypedValueT *args, int64_t nargs, const FunctionContextT &ctx) {
+  FType<TypedValueT, Or<Null, List>>("last", args, nargs);
+  if (args[0].IsNull()) return TypedValueT(ctx.memory);
+  const auto &list = args[0].ValueList();
+  if (list.empty()) return TypedValueT(ctx.memory);
+  return TypedValueT(list.back(), ctx.memory);
+}
+
+template <typename TypedValueT, typename FunctionContextT, typename Tag, typename Conv>
+TypedValueT Properties(const TypedValueT *args, int64_t nargs, const FunctionContextT &ctx) {
+  FType<TypedValueT, Or<Null, Vertex, Edge>>("properties", args, nargs);
+  auto *dba = ctx.db_accessor;
+  auto get_properties = [&](const auto &record_accessor) {
+    typename TypedValueT::TMap properties(ctx.memory);
+    if constexpr (std::is_same_v<Tag, StorageEngineTag>) {
+      auto maybe_props = record_accessor.Properties(ctx.view);
+      if (maybe_props.HasError()) {
+        switch (maybe_props.GetError()) {
+          case storage::v3::Error::DELETED_OBJECT:
+            throw functions::FunctionRuntimeException("Trying to get properties from a deleted object.");
+          case storage::v3::Error::NONEXISTENT_OBJECT:
+            throw functions::FunctionRuntimeException("Trying to get properties from an object that doesn't exist.");
+          case storage::v3::Error::SERIALIZATION_ERROR:
+          case storage::v3::Error::VERTEX_HAS_EDGES:
+          case storage::v3::Error::PROPERTIES_DISABLED:
+          case storage::v3::Error::VERTEX_ALREADY_INSERTED:
+            throw functions::FunctionRuntimeException("Unexpected error when getting properties.");
+        }
+      }
+      for (const auto &property : *maybe_props) {
+        Conv conv;
+        properties.emplace(dba->PropertyToName(property.first), conv(property.second));
+      }
+    } else {
+      Conv conv;
+      for (const auto &property : record_accessor.Properties()) {
+        properties.emplace(utils::pmr::string(dba->PropertyToName(property.first), ctx.memory),
+                           conv(property.second, dba));
+      }
+    }
+    return TypedValueT(std::move(properties));
+  };
+
+  const auto &value = args[0];
+  if (value.IsNull()) {
+    return TypedValueT(ctx.memory);
+  } else if (value.IsVertex()) {
+    return get_properties(value.ValueVertex());
+  } else {
+    return get_properties(value.ValueEdge());
+  }
+}
+
+template <typename TypedValueT, typename FunctionContextT>
+TypedValueT Size(const TypedValueT *args, int64_t nargs, const FunctionContextT &ctx) {
+  FType<TypedValueT, Or<Null, List, String, Map, Path>>("size", args, nargs);
+  const auto &value = args[0];
+  if (value.IsNull()) {
+    return TypedValueT(ctx.memory);
+  } else if (value.IsList()) {
+    return TypedValueT(static_cast<int64_t>(value.ValueList().size()), ctx.memory);
+  } else if (value.IsString()) {
+    return TypedValueT(static_cast<int64_t>(value.ValueString().size()), ctx.memory);
+  } else if (value.IsMap()) {
+    // neo4j doesn't implement size for map, but I don't see a good reason not
+    // to do it.
+    return TypedValueT(static_cast<int64_t>(value.ValueMap().size()), ctx.memory);
+  } else {
+    return TypedValueT(static_cast<int64_t>(value.ValuePath().edges().size()), ctx.memory);
+  }
+}
+
+template <typename TypedValueT, typename FunctionContextT, typename Tag, typename Conv>
+TypedValueT StartNode(const TypedValueT *args, int64_t nargs, const FunctionContextT &ctx) {
+  FType<TypedValueT, Or<Null, Edge>>("startNode", args, nargs);
+  if (args[0].IsNull()) return TypedValueT(ctx.memory);
+  if constexpr (std::is_same_v<Tag, StorageEngineTag>) {
+    const auto to = args[0].ValueEdge().From();
+    auto pk = to.primary_key;
+    auto maybe_vertex_accessor = ctx.db_accessor->FindVertex(pk, ctx.view);
+    if (!maybe_vertex_accessor) {
+      throw functions::FunctionRuntimeException("Trying to get properties from a deleted object.");
+    }
+    return TypedValueT(*maybe_vertex_accessor, ctx.memory);
+  } else {
+    return TypedValueT(args[0].ValueEdge().From(), ctx.memory);
+  }
+}
+
+namespace {
+
+size_t UnwrapDegreeResult(storage::v3::Result<size_t> maybe_degree) {
+  if (maybe_degree.HasError()) {
+    switch (maybe_degree.GetError()) {
+      case storage::v3::Error::DELETED_OBJECT:
+        throw functions::FunctionRuntimeException("Trying to get degree of a deleted node.");
+      case storage::v3::Error::NONEXISTENT_OBJECT:
+        throw functions::FunctionRuntimeException("Trying to get degree of a node that doesn't exist.");
+      case storage::v3::Error::SERIALIZATION_ERROR:
+      case storage::v3::Error::VERTEX_HAS_EDGES:
+      case storage::v3::Error::PROPERTIES_DISABLED:
+      case storage::v3::Error::VERTEX_ALREADY_INSERTED:
+        throw functions::FunctionRuntimeException("Unexpected error when getting node degree.");
+    }
+  }
+  return *maybe_degree;
+}
+
+}  // namespace
+
+template <typename TypedValueT, typename FunctionContextT, typename Tag>
+TypedValueT Degree(const TypedValueT *args, int64_t nargs, const FunctionContextT &ctx) {
+  FType<TypedValueT, Or<Null, Vertex>>("degree", args, nargs);
+  if (args[0].IsNull()) return TypedValueT(ctx.memory);
+  const auto &vertex = args[0].ValueVertex();
+  size_t out_degree = 0;
+  size_t in_degree = 0;
+  if constexpr (std::same_as<Tag, StorageEngineTag>) {
+    out_degree = UnwrapDegreeResult(vertex.OutDegree(ctx.view));
+    in_degree = UnwrapDegreeResult(vertex.InDegree(ctx.view));
+  } else {
+    out_degree = vertex.OutDegree();
+    in_degree = vertex.InDegree();
+  }
+  return TypedValueT(static_cast<int64_t>(out_degree + in_degree), ctx.memory);
+}
+
+template <typename TypedValueT, typename FunctionContextT, typename Tag>
+TypedValueT InDegree(const TypedValueT *args, int64_t nargs, const FunctionContextT &ctx) {
+  FType<TypedValueT, Or<Null, Vertex>>("inDegree", args, nargs);
+  if (args[0].IsNull()) return TypedValueT(ctx.memory);
+  const auto &vertex = args[0].ValueVertex();
+  size_t in_degree = 0;
+  if constexpr (std::same_as<Tag, StorageEngineTag>) {
+    in_degree = UnwrapDegreeResult(vertex.InDegree(ctx.view));
+  } else {
+    in_degree = vertex.InDegree();
+  }
+  return TypedValueT(static_cast<int64_t>(in_degree), ctx.memory);
+}
+
+template <typename TypedValueT, typename FunctionContextT, typename Tag>
+TypedValueT OutDegree(const TypedValueT *args, int64_t nargs, const FunctionContextT &ctx) {
+  FType<TypedValueT, Or<Null, Vertex>>("outDegree", args, nargs);
+  if (args[0].IsNull()) return TypedValueT(ctx.memory);
+  const auto &vertex = args[0].ValueVertex();
+  size_t out_degree = 0;
+  if constexpr (std::same_as<Tag, StorageEngineTag>) {
+    out_degree = UnwrapDegreeResult(vertex.OutDegree(ctx.view));
+  } else {
+    out_degree = vertex.OutDegree();
+  }
+  return TypedValueT(static_cast<int64_t>(out_degree), ctx.memory);
+}
+
+template <typename TypedValueT, typename FunctionContextT>
+TypedValueT ToBoolean(const TypedValueT *args, int64_t nargs, const FunctionContextT &ctx) {
+  FType<TypedValueT, Or<Null, Bool, Integer, String>>("toBoolean", args, nargs);
+  const auto &value = args[0];
+  if (value.IsNull()) {
+    return TypedValueT(ctx.memory);
+  } else if (value.IsBool()) {
+    return TypedValueT(value.ValueBool(), ctx.memory);
+  } else if (value.IsInt()) {
+    return TypedValueT(value.ValueInt() != 0L, ctx.memory);
+  } else {
+    auto s = utils::ToUpperCase(utils::Trim(value.ValueString()));
+    if (s == "TRUE") return TypedValueT(true, ctx.memory);
+    if (s == "FALSE") return TypedValueT(false, ctx.memory);
+    // I think this is just stupid and that exception should be thrown, but
+    // neo4j does it this way...
+    return TypedValueT(ctx.memory);
+  }
+}
+
+template <typename TypedValueT, typename FunctionContextT>
+TypedValueT ToFloat(const TypedValueT *args, int64_t nargs, const FunctionContextT &ctx) {
+  FType<TypedValueT, Or<Null, Number, String>>("toFloat", args, nargs);
+  const auto &value = args[0];
+  if (value.IsNull()) {
+    return TypedValueT(ctx.memory);
+  } else if (value.IsInt()) {
+    return TypedValueT(static_cast<double>(value.ValueInt()), ctx.memory);
+  } else if (value.IsDouble()) {
+    return TypedValueT(value, ctx.memory);
+  } else {
+    try {
+      return TypedValueT(utils::ParseDouble(utils::Trim(value.ValueString())), ctx.memory);
+    } catch (const utils::BasicException &) {
+      return TypedValueT(ctx.memory);
+    }
+  }
+}
+
+template <typename TypedValueT, typename FunctionContextT>
+TypedValueT ToInteger(const TypedValueT *args, int64_t nargs, const FunctionContextT &ctx) {
+  FType<TypedValueT, Or<Null, Bool, Number, String>>("toInteger", args, nargs);
+  const auto &value = args[0];
+  if (value.IsNull()) {
+    return TypedValueT(ctx.memory);
+  } else if (value.IsBool()) {
+    return TypedValueT(value.ValueBool() ? 1L : 0L, ctx.memory);
+  } else if (value.IsInt()) {
+    return TypedValueT(value, ctx.memory);
+  } else if (value.IsDouble()) {
+    return TypedValueT(static_cast<int64_t>(value.ValueDouble()), ctx.memory);
+  } else {
+    try {
+      // Yup, this is correct. String is valid if it has floating point
+      // number, then it is parsed and converted to int.
+      return TypedValueT(static_cast<int64_t>(utils::ParseDouble(utils::Trim(value.ValueString()))), ctx.memory);
+    } catch (const utils::BasicException &) {
+      return TypedValueT(ctx.memory);
+    }
+  }
+}
+
+template <typename TypedValueT, typename FunctionContextT>
+TypedValueT Type(const TypedValueT *args, int64_t nargs, const FunctionContextT &ctx) {
+  FType<TypedValueT, Or<Null, Edge>>("type", args, nargs);
+  auto *dba = ctx.db_accessor;
+  if (args[0].IsNull()) return TypedValueT(ctx.memory);
+  return TypedValueT(dba->EdgeTypeToName(args[0].ValueEdge().EdgeType()), ctx.memory);
+}
+
+template <typename TypedValueT, typename FunctionContextT>
+TypedValueT ValueType(const TypedValueT *args, int64_t nargs, const FunctionContextT &ctx) {
+  FType<TypedValueT, Or<Null, Bool, Integer, Double, String, List, Map, Vertex, Edge, Path>>("type", args, nargs);
+  // The type names returned should be standardized openCypher type names.
+  // https://github.com/opencypher/openCypher/blob/master/docs/openCypher9.pdf
+  switch (args[0].type()) {
+    case TypedValueT::Type::Null:
+      return TypedValueT("NULL", ctx.memory);
+    case TypedValueT::Type::Bool:
+      return TypedValueT("BOOLEAN", ctx.memory);
+    case TypedValueT::Type::Int:
+      return TypedValueT("INTEGER", ctx.memory);
+    case TypedValueT::Type::Double:
+      return TypedValueT("FLOAT", ctx.memory);
+    case TypedValueT::Type::String:
+      return TypedValueT("STRING", ctx.memory);
+    case TypedValueT::Type::List:
+      return TypedValueT("LIST", ctx.memory);
+    case TypedValueT::Type::Map:
+      return TypedValueT("MAP", ctx.memory);
+    case TypedValueT::Type::Vertex:
+      return TypedValueT("NODE", ctx.memory);
+    case TypedValueT::Type::Edge:
+      return TypedValueT("RELATIONSHIP", ctx.memory);
+    case TypedValueT::Type::Path:
+      return TypedValueT("PATH", ctx.memory);
+    case TypedValueT::Type::Date:
+      return TypedValueT("DATE", ctx.memory);
+    case TypedValueT::Type::LocalTime:
+      return TypedValueT("LOCAL_TIME", ctx.memory);
+    case TypedValueT::Type::LocalDateTime:
+      return TypedValueT("LOCAL_DATE_TIME", ctx.memory);
+    case TypedValueT::Type::Duration:
+      return TypedValueT("DURATION", ctx.memory);
+  }
+}
+
+// TODO: How is Keys different from Properties function?
+template <typename TypedValueT, typename FunctionContextT, typename Tag>
+TypedValueT Keys(const TypedValueT *args, int64_t nargs, const FunctionContextT &ctx) {
+  FType<TypedValueT, Or<Null, Vertex, Edge>>("keys", args, nargs);
+  auto *dba = ctx.db_accessor;
+  auto get_keys = [&](const auto &record_accessor) {
+    typename TypedValueT::TVector keys(ctx.memory);
+    if constexpr (std::same_as<Tag, StorageEngineTag>) {
+      auto maybe_props = record_accessor.Properties(ctx.view);
+      if (maybe_props.HasError()) {
+        switch (maybe_props.GetError()) {
+          case storage::v3::Error::DELETED_OBJECT:
+            throw functions::FunctionRuntimeException("Trying to get keys from a deleted object.");
+          case storage::v3::Error::NONEXISTENT_OBJECT:
+            throw functions::FunctionRuntimeException("Trying to get keys from an object that doesn't exist.");
+          case storage::v3::Error::SERIALIZATION_ERROR:
+          case storage::v3::Error::VERTEX_HAS_EDGES:
+          case storage::v3::Error::PROPERTIES_DISABLED:
+          case storage::v3::Error::VERTEX_ALREADY_INSERTED:
+            throw functions::FunctionRuntimeException("Unexpected error when getting keys.");
+        }
+      }
+      for (const auto &property : *maybe_props) {
+        keys.emplace_back(dba->PropertyToName(property.first));
+      }
+    } else {
+      for (const auto &property : record_accessor.Properties()) {
+        keys.emplace_back(dba->PropertyToName(property.first));
+      }
+    }
+    return TypedValueT(std::move(keys));
+  };
+
+  const auto &value = args[0];
+  if (value.IsNull()) {
+    return TypedValueT(ctx.memory);
+  } else if (value.IsVertex()) {
+    return get_keys(value.ValueVertex());
+  } else {
+    return get_keys(value.ValueEdge());
+  }
+}
+
+template <typename TypedValueT, typename FunctionContextT, typename Tag>
+TypedValueT Labels(const TypedValueT *args, int64_t nargs, const FunctionContextT &ctx) {
+  FType<TypedValueT, Or<Null, Vertex>>("labels", args, nargs);
+  auto *dba = ctx.db_accessor;
+  if (args[0].IsNull()) return TypedValueT(ctx.memory);
+  typename TypedValueT::TVector labels(ctx.memory);
+  if constexpr (std::is_same_v<Tag, StorageEngineTag>) {
+    auto maybe_labels = args[0].ValueVertex().Labels(ctx.view);
+    if (maybe_labels.HasError()) {
+      switch (maybe_labels.GetError()) {
+        case storage::v3::Error::DELETED_OBJECT:
+          throw functions::FunctionRuntimeException("Trying to get labels from a deleted node.");
+        case storage::v3::Error::NONEXISTENT_OBJECT:
+          throw functions::FunctionRuntimeException("Trying to get labels from a node that doesn't exist.");
+        case storage::v3::Error::SERIALIZATION_ERROR:
+        case storage::v3::Error::VERTEX_HAS_EDGES:
+        case storage::v3::Error::PROPERTIES_DISABLED:
+        case storage::v3::Error::VERTEX_ALREADY_INSERTED:
+          throw functions::FunctionRuntimeException("Unexpected error when getting labels.");
+      }
+    }
+    for (const auto &label : *maybe_labels) {
+      labels.emplace_back(dba->LabelToName(label));
+    }
+  } else {
+    auto vertex = args[0].ValueVertex();
+    for (const auto &label : vertex.Labels()) {
+      labels.emplace_back(dba->LabelToName(label.id));
+    }
+  }
+  return TypedValueT(std::move(labels));
+}
+
+template <typename TypedValueT, typename FunctionContextT>
+TypedValueT Nodes(const TypedValueT *args, int64_t nargs, const FunctionContextT &ctx) {
+  FType<TypedValueT, Or<Null, Path>>("nodes", args, nargs);
+  if (args[0].IsNull()) return TypedValueT(ctx.memory);
+  const auto &vertices = args[0].ValuePath().vertices();
+  typename TypedValueT::TVector values(ctx.memory);
+  values.reserve(vertices.size());
+  for (const auto &v : vertices) values.emplace_back(v);
+  return TypedValueT(std::move(values));
+}
+
+template <typename TypedValueT, typename FunctionContextT>
+TypedValueT Relationships(const TypedValueT *args, int64_t nargs, const FunctionContextT &ctx) {
+  FType<TypedValueT, Or<Null, Path>>("relationships", args, nargs);
+  if (args[0].IsNull()) return TypedValueT(ctx.memory);
+  const auto &edges = args[0].ValuePath().edges();
+  typename TypedValueT::TVector values(ctx.memory);
+  values.reserve(edges.size());
+  for (const auto &e : edges) values.emplace_back(e);
+  return TypedValueT(std::move(values));
+}
+
+template <typename TypedValueT, typename FunctionContextT>
+TypedValueT Range(const TypedValueT *args, int64_t nargs, const FunctionContextT &ctx) {
+  FType<TypedValueT, Or<Null, Integer>, Or<Null, Integer>, Optional<Or<Null, NonZeroInteger>>>("range", args, nargs);
+  for (int64_t i = 0; i < nargs; ++i)
+    if (args[i].IsNull()) return TypedValueT(ctx.memory);
+  auto lbound = args[0].ValueInt();
+  auto rbound = args[1].ValueInt();
+  int64_t step = nargs == 3 ? args[2].ValueInt() : 1;
+  typename TypedValueT::TVector list(ctx.memory);
+  if (lbound <= rbound && step > 0) {
+    for (auto i = lbound; i <= rbound; i += step) {
+      list.emplace_back(i);
+    }
+  } else if (lbound >= rbound && step < 0) {
+    for (auto i = lbound; i >= rbound; i += step) {
+      list.emplace_back(i);
+    }
+  }
+  return TypedValueT(std::move(list));
+}
+
+template <typename TypedValueT, typename FunctionContextT>
+TypedValueT Tail(const TypedValueT *args, int64_t nargs, const FunctionContextT &ctx) {
+  FType<TypedValueT, Or<Null, List>>("tail", args, nargs);
+  if (args[0].IsNull()) return TypedValueT(ctx.memory);
+  typename TypedValueT::TVector list(args[0].ValueList(), ctx.memory);
+  if (list.empty()) return TypedValueT(std::move(list));
+  list.erase(list.begin());
+  return TypedValueT(std::move(list));
+}
+
+template <typename TypedValueT, typename FunctionContextT>
+TypedValueT UniformSample(const TypedValueT *args, int64_t nargs, const FunctionContextT &ctx) {
+  FType<TypedValueT, Or<Null, List>, Or<Null, NonNegativeInteger>>("uniformSample", args, nargs);
+  static thread_local std::mt19937 pseudo_rand_gen_{std::random_device{}()};
+  if (args[0].IsNull() || args[1].IsNull()) return TypedValueT(ctx.memory);
+  const auto &population = args[0].ValueList();
+  auto population_size = population.size();
+  if (population_size == 0) return TypedValueT(ctx.memory);
+  auto desired_length = args[1].ValueInt();
+  std::uniform_int_distribution<uint64_t> rand_dist{0, population_size - 1};
+  typename TypedValueT::TVector sampled(ctx.memory);
+  sampled.reserve(desired_length);
+  for (int64_t i = 0; i < desired_length; ++i) {
+    sampled.emplace_back(population[rand_dist(pseudo_rand_gen_)]);
+  }
+  return TypedValueT(std::move(sampled));
+}
+
+template <typename TypedValueT, typename FunctionContextT>
+TypedValueT Abs(const TypedValueT *args, int64_t nargs, const FunctionContextT &ctx) {
+  FType<TypedValueT, Or<Null, Number>>("abs", args, nargs);
+  const auto &value = args[0];
+  if (value.IsNull()) {
+    return TypedValueT(ctx.memory);
+  } else if (value.IsInt()) {
+    return TypedValueT(std::abs(value.ValueInt()), ctx.memory);
+  } else {
+    return TypedValueT(std::abs(value.ValueDouble()), ctx.memory);
+  }
+}
+
+#define WRAP_CMATH_FLOAT_FUNCTION(name, lowercased_name)                                  \
+  template <typename TypedValueT, typename FunctionContextT>                              \
+  TypedValueT name(const TypedValueT *args, int64_t nargs, const FunctionContextT &ctx) { \
+    FType<TypedValueT, Or<Null, Number>>(#lowercased_name, args, nargs);                  \
+    const auto &value = args[0];                                                          \
+    if (value.IsNull()) {                                                                 \
+      return TypedValueT(ctx.memory);                                                     \
+    } else if (value.IsInt()) {                                                           \
+      return TypedValueT(lowercased_name(value.ValueInt()), ctx.memory);                  \
+    } else {                                                                              \
+      return TypedValueT(lowercased_name(value.ValueDouble()), ctx.memory);               \
+    }                                                                                     \
+  }
+
+WRAP_CMATH_FLOAT_FUNCTION(Ceil, ceil)
+WRAP_CMATH_FLOAT_FUNCTION(Floor, floor)
+// We are not completely compatible with neoj4 in this function because,
+// neo4j rounds -0.5, -1.5, -2.5... to 0, -1, -2...
+WRAP_CMATH_FLOAT_FUNCTION(Round, round)
+WRAP_CMATH_FLOAT_FUNCTION(Exp, exp)
+WRAP_CMATH_FLOAT_FUNCTION(Log, log)
+WRAP_CMATH_FLOAT_FUNCTION(Log10, log10)
+WRAP_CMATH_FLOAT_FUNCTION(Sqrt, sqrt)
+WRAP_CMATH_FLOAT_FUNCTION(Acos, acos)
+WRAP_CMATH_FLOAT_FUNCTION(Asin, asin)
+WRAP_CMATH_FLOAT_FUNCTION(Atan, atan)
+WRAP_CMATH_FLOAT_FUNCTION(Cos, cos)
+WRAP_CMATH_FLOAT_FUNCTION(Sin, sin)
+WRAP_CMATH_FLOAT_FUNCTION(Tan, tan)
+
+#undef WRAP_CMATH_FLOAT_FUNCTION
+
+template <typename TypedValueT, typename FunctionContextT>
+TypedValueT Atan2(const TypedValueT *args, int64_t nargs, const FunctionContextT &ctx) {
+  FType<TypedValueT, Or<Null, Number>, Or<Null, Number>>("atan2", args, nargs);
+  if (args[0].IsNull() || args[1].IsNull()) return TypedValueT(ctx.memory);
+  auto to_double = [](const TypedValueT &t) -> double {
+    if (t.IsInt()) {
+      return t.ValueInt();
+    } else {
+      return t.ValueDouble();
+    }
+  };
+  double y = to_double(args[0]);
+  double x = to_double(args[1]);
+  return TypedValueT(atan2(y, x), ctx.memory);
+}
+
+template <typename TypedValueT, typename FunctionContextT>
+TypedValueT Sign(const TypedValueT *args, int64_t nargs, const FunctionContextT &ctx) {
+  FType<TypedValueT, Or<Null, Number>>("sign", args, nargs);
+  auto sign = [&](auto x) { return TypedValueT((0 < x) - (x < 0), ctx.memory); };
+  const auto &value = args[0];
+  if (value.IsNull()) {
+    return TypedValueT(ctx.memory);
+  } else if (value.IsInt()) {
+    return sign(value.ValueInt());
+  } else {
+    return sign(value.ValueDouble());
+  }
+}
+
+template <typename TypedValueT, typename FunctionContextT>
+TypedValueT E(const TypedValueT *args, int64_t nargs, const FunctionContextT &ctx) {
+  FType<TypedValueT, void>("e", args, nargs);
+  return TypedValueT(M_E, ctx.memory);
+}
+
+template <typename TypedValueT, typename FunctionContextT>
+TypedValueT Pi(const TypedValueT *args, int64_t nargs, const FunctionContextT &ctx) {
+  FType<TypedValueT, void>("pi", args, nargs);
+  return TypedValueT(M_PI, ctx.memory);
+}
+
+template <typename TypedValueT, typename FunctionContextT>
+TypedValueT Rand(const TypedValueT *args, int64_t nargs, const FunctionContextT &ctx) {
+  FType<TypedValueT, void>("rand", args, nargs);
+  static thread_local std::mt19937 pseudo_rand_gen_{std::random_device{}()};
+  static thread_local std::uniform_real_distribution<> rand_dist_{0, 1};
+  return TypedValueT(rand_dist_(pseudo_rand_gen_), ctx.memory);
+}
+
+template <class TPredicate, typename TypedValueT, typename FunctionContextT>
+TypedValueT StringMatchOperator(const TypedValueT *args, int64_t nargs, const FunctionContextT &ctx) {
+  FType<TypedValueT, Or<Null, String>, Or<Null, String>>(TPredicate::name, args, nargs);
+  if (args[0].IsNull() || args[1].IsNull()) return TypedValueT(ctx.memory);
+  const auto &s1 = args[0].ValueString();
+  const auto &s2 = args[1].ValueString();
+  return TypedValueT(TPredicate{}(s1, s2), ctx.memory);
+}
+
+// Check if s1 starts with s2.
+template <typename TypedValueT>
+struct StartsWithPredicate {
+  static constexpr const char *name = "startsWith";
+  bool operator()(const typename TypedValueT::TString &s1, const typename TypedValueT::TString &s2) const {
+    if (s1.size() < s2.size()) return false;
+    return std::equal(s2.begin(), s2.end(), s1.begin());
+  }
+};
+
+template <typename TypedValueT, typename FunctionContextT>
+inline auto StartsWith = StringMatchOperator<StartsWithPredicate<TypedValueT>, TypedValueT, FunctionContextT>;
+
+// Check if s1 ends with s2.
+template <typename TypedValueT>
+struct EndsWithPredicate {
+  static constexpr const char *name = "endsWith";
+  bool operator()(const typename TypedValueT::TString &s1, const typename TypedValueT::TString &s2) const {
+    if (s1.size() < s2.size()) return false;
+    return std::equal(s2.rbegin(), s2.rend(), s1.rbegin());
+  }
+};
+
+template <typename TypedValueT, typename FunctionContextT>
+inline auto EndsWith = StringMatchOperator<EndsWithPredicate<TypedValueT>, TypedValueT, FunctionContextT>;
+
+// Check if s1 contains s2.
+template <typename TypedValueT>
+struct ContainsPredicate {
+  static constexpr const char *name = "contains";
+  bool operator()(const typename TypedValueT::TString &s1, const typename TypedValueT::TString &s2) const {
+    if (s1.size() < s2.size()) return false;
+    return s1.find(s2) != std::string::npos;
+  }
+};
+
+template <typename TypedValueT, typename FunctionContextT>
+inline auto Contains = StringMatchOperator<ContainsPredicate<TypedValueT>, TypedValueT, FunctionContextT>;
+
+template <typename TypedValueT, typename FunctionContextT>
+TypedValueT Assert(const TypedValueT *args, int64_t nargs, const FunctionContextT &ctx) {
+  FType<TypedValueT, Bool, Optional<String>>("assert", args, nargs);
+  if (!args[0].ValueBool()) {
+    std::string message("Assertion failed");
+    if (nargs == 2) {
+      message += ": ";
+      message += args[1].ValueString();
+    }
+    message += ".";
+    throw FunctionRuntimeException(message);
+  }
+  return TypedValueT(args[0], ctx.memory);
+}
+
+template <typename TypedValueT, typename FunctionContextT>
+TypedValueT Counter(const TypedValueT *args, int64_t nargs, const FunctionContextT &context) {
+  FType<TypedValueT, String, Integer, Optional<NonZeroInteger>>("counter", args, nargs);
+  int64_t step = 1;
+  if (nargs == 3) {
+    step = args[2].ValueInt();
+  }
+
+  auto [it, inserted] = context.counters->emplace(args[0].ValueString(), args[1].ValueInt());
+  auto value = it->second;
+  it->second += step;
+
+  return TypedValueT(value, context.memory);
+}
+
+template <typename TypedValueT, typename FunctionContextT>
+TypedValueT Id(const TypedValueT *args, int64_t nargs, const FunctionContextT &ctx) {
+  FType<TypedValueT, Or<Null, Vertex, Edge>>("id", args, nargs);
+  const auto &arg = args[0];
+  if (arg.IsNull()) {
+    return TypedValueT(ctx.memory);
+  } else if (arg.IsVertex()) {
+    return TypedValueT(static_cast<int64_t>(arg.ValueVertex().CypherId()), ctx.memory);
+  } else {
+    return TypedValueT(static_cast<int64_t>(arg.ValueEdge().CypherId()), ctx.memory);
+  }
+}
+
+template <typename TypedValueT, typename FunctionContextT>
+TypedValueT ToString(const TypedValueT *args, int64_t nargs, const FunctionContextT &ctx) {
+  FType<TypedValueT, Or<Null, String, Number, Date, LocalTime, LocalDateTime, Duration, Bool>>("toString", args, nargs);
+  const auto &arg = args[0];
+  if (arg.IsNull()) {
+    return TypedValueT(ctx.memory);
+  }
+  if (arg.IsString()) {
+    return TypedValueT(arg, ctx.memory);
+  }
+  if (arg.IsInt()) {
+    // TODO: This is making a pointless copy of std::string, we may want to
+    // use a different conversion to string
+    return TypedValueT(std::to_string(arg.ValueInt()), ctx.memory);
+  }
+  if (arg.IsDouble()) {
+    return TypedValueT(std::to_string(arg.ValueDouble()), ctx.memory);
+  }
+  if (arg.IsDate()) {
+    return TypedValueT(arg.ValueDate().ToString(), ctx.memory);
+  }
+  if (arg.IsLocalTime()) {
+    return TypedValueT(arg.ValueLocalTime().ToString(), ctx.memory);
+  }
+  if (arg.IsLocalDateTime()) {
+    return TypedValueT(arg.ValueLocalDateTime().ToString(), ctx.memory);
+  }
+  if (arg.IsDuration()) {
+    return TypedValueT(arg.ValueDuration().ToString(), ctx.memory);
+  }
+
+  return TypedValueT(arg.ValueBool() ? "true" : "false", ctx.memory);
+}
+
+template <typename TypedValueT, typename FunctionContextT>
+TypedValueT Timestamp(const TypedValueT *args, int64_t nargs, const FunctionContextT &ctx) {
+  FType<TypedValueT, Optional<Or<Date, LocalTime, LocalDateTime, Duration>>>("timestamp", args, nargs);
+  const auto &arg = *args;
+  if (arg.IsDate()) {
+    return TypedValueT(arg.ValueDate().MicrosecondsSinceEpoch(), ctx.memory);
+  }
+  if (arg.IsLocalTime()) {
+    return TypedValueT(arg.ValueLocalTime().MicrosecondsSinceEpoch(), ctx.memory);
+  }
+  if (arg.IsLocalDateTime()) {
+    return TypedValueT(arg.ValueLocalDateTime().MicrosecondsSinceEpoch(), ctx.memory);
+  }
+  if (arg.IsDuration()) {
+    return TypedValueT(arg.ValueDuration().microseconds, ctx.memory);
+  }
+  return TypedValueT(ctx.timestamp, ctx.memory);
+}
+
+template <typename TypedValueT, typename FunctionContextT>
+TypedValueT Left(const TypedValueT *args, int64_t nargs, const FunctionContextT &ctx) {
+  FType<TypedValueT, Or<Null, String>, Or<Null, NonNegativeInteger>>("left", args, nargs);
+  if (args[0].IsNull() || args[1].IsNull()) return TypedValueT(ctx.memory);
+  return TypedValueT(utils::Substr(args[0].ValueString(), 0, args[1].ValueInt()), ctx.memory);
+}
+
+template <typename TypedValueT, typename FunctionContextT>
+TypedValueT Right(const TypedValueT *args, int64_t nargs, const FunctionContextT &ctx) {
+  FType<TypedValueT, Or<Null, String>, Or<Null, NonNegativeInteger>>("right", args, nargs);
+  if (args[0].IsNull() || args[1].IsNull()) return TypedValueT(ctx.memory);
+  const auto &str = args[0].ValueString();
+  auto len = args[1].ValueInt();
+  return len <= str.size() ? TypedValueT(utils::Substr(str, str.size() - len, len), ctx.memory)
+                           : TypedValueT(str, ctx.memory);
+}
+
+template <typename TypedValueT, typename FunctionContextT>
+TypedValueT CallStringFunction(
+    const TypedValueT *args, int64_t nargs, utils::MemoryResource *memory, const char *name,
+    std::function<typename TypedValueT::TString(const typename TypedValueT::TString &)> fun) {
+  FType<TypedValueT, Or<Null, String>>(name, args, nargs);
+  if (args[0].IsNull()) return TypedValueT(memory);
+  return TypedValueT(fun(args[0].ValueString()), memory);
+}
+
+template <typename TypedValueT, typename FunctionContextT>
+TypedValueT LTrim(const TypedValueT *args, int64_t nargs, const FunctionContextT &ctx) {
+  return CallStringFunction<TypedValueT, FunctionContextT>(args, nargs, ctx.memory, "lTrim", [&](const auto &str) {
+    return typename TypedValueT::TString(utils::LTrim(str), ctx.memory);
+  });
+}
+
+template <typename TypedValueT, typename FunctionContextT>
+TypedValueT RTrim(const TypedValueT *args, int64_t nargs, const FunctionContextT &ctx) {
+  return CallStringFunction<TypedValueT, FunctionContextT>(args, nargs, ctx.memory, "rTrim", [&](const auto &str) {
+    return typename TypedValueT::TString(utils::RTrim(str), ctx.memory);
+  });
+}
+
+template <typename TypedValueT, typename FunctionContextT>
+TypedValueT Trim(const TypedValueT *args, int64_t nargs, const FunctionContextT &ctx) {
+  return CallStringFunction<TypedValueT, FunctionContextT>(args, nargs, ctx.memory, "trim", [&](const auto &str) {
+    return typename TypedValueT::TString(utils::Trim(str), ctx.memory);
+  });
+}
+
+template <typename TypedValueT, typename FunctionContextT>
+TypedValueT Reverse(const TypedValueT *args, int64_t nargs, const FunctionContextT &ctx) {
+  return CallStringFunction<TypedValueT, FunctionContextT>(
+      args, nargs, ctx.memory, "reverse", [&](const auto &str) { return utils::Reversed(str, ctx.memory); });
+}
+
+template <typename TypedValueT, typename FunctionContextT>
+TypedValueT ToLower(const TypedValueT *args, int64_t nargs, const FunctionContextT &ctx) {
+  return CallStringFunction<TypedValueT, FunctionContextT>(args, nargs, ctx.memory, "toLower", [&](const auto &str) {
+    typename TypedValueT::TString res(ctx.memory);
+    utils::ToLowerCase(&res, str);
+    return res;
+  });
+}
+
+template <typename TypedValueT, typename FunctionContextT>
+TypedValueT ToUpper(const TypedValueT *args, int64_t nargs, const FunctionContextT &ctx) {
+  return CallStringFunction<TypedValueT, FunctionContextT>(args, nargs, ctx.memory, "toUpper", [&](const auto &str) {
+    typename TypedValueT::TString res(ctx.memory);
+    utils::ToUpperCase(&res, str);
+    return res;
+  });
+}
+
+template <typename TypedValueT, typename FunctionContextT>
+TypedValueT Replace(const TypedValueT *args, int64_t nargs, const FunctionContextT &ctx) {
+  FType<TypedValueT, Or<Null, String>, Or<Null, String>, Or<Null, String>>("replace", args, nargs);
+  if (args[0].IsNull() || args[1].IsNull() || args[2].IsNull()) {
+    return TypedValueT(ctx.memory);
+  }
+  typename TypedValueT::TString replaced(ctx.memory);
+  utils::Replace(&replaced, args[0].ValueString(), args[1].ValueString(), args[2].ValueString());
+  return TypedValueT(std::move(replaced));
+}
+
+template <typename TypedValueT, typename FunctionContextT>
+TypedValueT Split(const TypedValueT *args, int64_t nargs, const FunctionContextT &ctx) {
+  FType<TypedValueT, Or<Null, String>, Or<Null, String>>("split", args, nargs);
+  if (args[0].IsNull() || args[1].IsNull()) {
+    return TypedValueT(ctx.memory);
+  }
+  typename TypedValueT::TVector result(ctx.memory);
+  utils::Split(&result, args[0].ValueString(), args[1].ValueString());
+  return TypedValueT(std::move(result));
+}
+
+template <typename TypedValueT, typename FunctionContextT>
+TypedValueT Substring(const TypedValueT *args, int64_t nargs, const FunctionContextT &ctx) {
+  FType<TypedValueT, Or<Null, String>, NonNegativeInteger, Optional<NonNegativeInteger>>("substring", args, nargs);
+  if (args[0].IsNull()) return TypedValueT(ctx.memory);
+  const auto &str = args[0].ValueString();
+  auto start = args[1].ValueInt();
+  if (nargs == 2) return TypedValueT(utils::Substr(str, start), ctx.memory);
+  auto len = args[2].ValueInt();
+  return TypedValueT(utils::Substr(str, start, len), ctx.memory);
+}
+
+template <typename TypedValueT, typename FunctionContextT>
+TypedValueT ToByteString(const TypedValueT *args, int64_t nargs, const FunctionContextT &ctx) {
+  FType<TypedValueT, String>("toByteString", args, nargs);
+  const auto &str = args[0].ValueString();
+  if (str.empty()) return TypedValueT("", ctx.memory);
+  if (!utils::StartsWith(str, "0x") && !utils::StartsWith(str, "0X")) {
+    throw FunctionRuntimeException("'toByteString' argument must start with '0x'");
+  }
+  const auto &hex_str = utils::Substr(str, 2);
+  auto read_hex = [](const char ch) -> unsigned char {
+    if (ch >= '0' && ch <= '9') return ch - '0';
+    if (ch >= 'a' && ch <= 'f') return ch - 'a' + 10;
+    if (ch >= 'A' && ch <= 'F') return ch - 'A' + 10;
+    throw FunctionRuntimeException("'toByteString' argument has an invalid character '{}'", ch);
+  };
+  utils::pmr::string bytes(ctx.memory);
+  bytes.reserve((1 + hex_str.size()) / 2);
+  size_t i = 0;
+  // Treat odd length hex string as having a leading zero.
+  if (hex_str.size() % 2) bytes.append(1, read_hex(hex_str[i++]));
+  for (; i < hex_str.size(); i += 2) {
+    unsigned char byte = read_hex(hex_str[i]) * 16U + read_hex(hex_str[i + 1]);
+    // MemcpyCast in case we are converting to a signed value, so as to avoid
+    // undefined behaviour.
+    bytes.append(1, utils::MemcpyCast<decltype(bytes)::value_type>(byte));
+  }
+  return TypedValueT(std::move(bytes));
+}
+
+template <typename TypedValueT, typename FunctionContextT>
+TypedValueT FromByteString(const TypedValueT *args, int64_t nargs, const FunctionContextT &ctx) {
+  FType<TypedValueT, String, Optional<PositiveInteger>>("fromByteString", args, nargs);
+  const auto &bytes = args[0].ValueString();
+  if (bytes.empty()) return TypedValueT("", ctx.memory);
+  size_t min_length = bytes.size();
+  if (nargs == 2) min_length = std::max(min_length, static_cast<size_t>(args[1].ValueInt()));
+  utils::pmr::string str(ctx.memory);
+  str.reserve(min_length * 2 + 2);
+  str.append("0x");
+  for (size_t pad = 0; pad < min_length - bytes.size(); ++pad) str.append(2, '0');
+  // Convert the bytes to a character string in hex representation.
+  // Unfortunately, we don't know whether the default `char` is signed or
+  // unsigned, so we have to work around any potential undefined behaviour when
+  // conversions between the 2 occur. That's why this function is more
+  // complicated than it should be.
+  auto to_hex = [](const unsigned char val) -> char {
+    unsigned char ch = val < 10U ? static_cast<unsigned char>('0') + val : static_cast<unsigned char>('a') + val - 10U;
+    return utils::MemcpyCast<char>(ch);
+  };
+  for (unsigned char byte : bytes) {
+    str.append(1, to_hex(byte / 16U));
+    str.append(1, to_hex(byte % 16U));
+  }
+  return TypedValueT(std::move(str));
+}
+
+template <typename T>
+concept IsNumberOrInteger = utils::SameAsAnyOf<T, Number, Integer>;
+
+template <IsNumberOrInteger ArgType>
+void MapNumericParameters(auto &parameter_mappings, const auto &input_parameters) {
+  for (const auto &[key, value] : input_parameters) {
+    if (auto it = parameter_mappings.find(key); it != parameter_mappings.end()) {
+      if (value.IsInt()) {
+        *it->second = value.ValueInt();
+      } else if (std::is_same_v<ArgType, Number> && value.IsDouble()) {
+        *it->second = value.ValueDouble();
+      } else {
+        std::string_view error = std::is_same_v<ArgType, Integer> ? "an integer." : "a numeric value.";
+        throw FunctionRuntimeException("Invalid value for key '{}'. Expected {}", key, error);
+      }
+    } else {
+      throw FunctionRuntimeException("Unknown key '{}'.", key);
+    }
+  }
+}
+
+template <typename TypedValueT, typename FunctionContextT>
+TypedValueT Date(const TypedValueT *args, int64_t nargs, const FunctionContextT &ctx) {
+  FType<TypedValueT, Optional<Or<String, Map>>>("date", args, nargs);
+  if (nargs == 0) {
+    return TypedValueT(utils::LocalDateTime(ctx.timestamp).date, ctx.memory);
+  }
+
+  if (args[0].IsString()) {
+    const auto &[date_parameters, is_extended] = utils::ParseDateParameters(args[0].ValueString());
+    return TypedValueT(utils::Date(date_parameters), ctx.memory);
+  }
+
+  utils::DateParameters date_parameters;
+
+  using namespace std::literals;
+  std::unordered_map parameter_mappings = {std::pair{"year"sv, &date_parameters.year},
+                                           std::pair{"month"sv, &date_parameters.month},
+                                           std::pair{"day"sv, &date_parameters.day}};
+
+  MapNumericParameters<Integer>(parameter_mappings, args[0].ValueMap());
+  return TypedValueT(utils::Date(date_parameters), ctx.memory);
+}
+
+template <typename TypedValueT, typename FunctionContextT>
+TypedValueT LocalTime(const TypedValueT *args, int64_t nargs, const FunctionContextT &ctx) {
+  FType<TypedValueT, Optional<Or<String, Map>>>("localtime", args, nargs);
+
+  if (nargs == 0) {
+    return TypedValueT(utils::LocalDateTime(ctx.timestamp).local_time, ctx.memory);
+  }
+
+  if (args[0].IsString()) {
+    const auto &[local_time_parameters, is_extended] = utils::ParseLocalTimeParameters(args[0].ValueString());
+    return TypedValueT(utils::LocalTime(local_time_parameters), ctx.memory);
+  }
+
+  utils::LocalTimeParameters local_time_parameters;
+
+  using namespace std::literals;
+  std::unordered_map parameter_mappings{
+      std::pair{"hour"sv, &local_time_parameters.hour},
+      std::pair{"minute"sv, &local_time_parameters.minute},
+      std::pair{"second"sv, &local_time_parameters.second},
+      std::pair{"millisecond"sv, &local_time_parameters.millisecond},
+      std::pair{"microsecond"sv, &local_time_parameters.microsecond},
+  };
+
+  MapNumericParameters<Integer>(parameter_mappings, args[0].ValueMap());
+  return TypedValueT(utils::LocalTime(local_time_parameters), ctx.memory);
+}
+
+template <typename TypedValueT, typename FunctionContextT>
+TypedValueT LocalDateTime(const TypedValueT *args, int64_t nargs, const FunctionContextT &ctx) {
+  FType<TypedValueT, Optional<Or<String, Map>>>("localdatetime", args, nargs);
+
+  if (nargs == 0) {
+    return TypedValueT(utils::LocalDateTime(ctx.timestamp), ctx.memory);
+  }
+
+  if (args[0].IsString()) {
+    const auto &[date_parameters, local_time_parameters] = ParseLocalDateTimeParameters(args[0].ValueString());
+    return TypedValueT(utils::LocalDateTime(date_parameters, local_time_parameters), ctx.memory);
+  }
+
+  utils::DateParameters date_parameters;
+  utils::LocalTimeParameters local_time_parameters;
+  using namespace std::literals;
+  std::unordered_map parameter_mappings{
+      std::pair{"year"sv, &date_parameters.year},
+      std::pair{"month"sv, &date_parameters.month},
+      std::pair{"day"sv, &date_parameters.day},
+      std::pair{"hour"sv, &local_time_parameters.hour},
+      std::pair{"minute"sv, &local_time_parameters.minute},
+      std::pair{"second"sv, &local_time_parameters.second},
+      std::pair{"millisecond"sv, &local_time_parameters.millisecond},
+      std::pair{"microsecond"sv, &local_time_parameters.microsecond},
+  };
+
+  MapNumericParameters<Integer>(parameter_mappings, args[0].ValueMap());
+  return TypedValueT(utils::LocalDateTime(date_parameters, local_time_parameters), ctx.memory);
+}
+
+template <typename TypedValueT, typename FunctionContextT>
+TypedValueT Duration(const TypedValueT *args, int64_t nargs, const FunctionContextT &ctx) {
+  FType<TypedValueT, Or<String, Map>>("duration", args, nargs);
+
+  if (args[0].IsString()) {
+    return TypedValueT(utils::Duration(ParseDurationParameters(args[0].ValueString())), ctx.memory);
+  }
+
+  utils::DurationParameters duration_parameters;
+  using namespace std::literals;
+  std::unordered_map parameter_mappings{std::pair{"day"sv, &duration_parameters.day},
+                                        std::pair{"hour"sv, &duration_parameters.hour},
+                                        std::pair{"minute"sv, &duration_parameters.minute},
+                                        std::pair{"second"sv, &duration_parameters.second},
+                                        std::pair{"millisecond"sv, &duration_parameters.millisecond},
+                                        std::pair{"microsecond"sv, &duration_parameters.microsecond}};
+  MapNumericParameters<Number>(parameter_mappings, args[0].ValueMap());
+  return TypedValueT(utils::Duration(duration_parameters), ctx.memory);
+}
+
+}  // namespace memgraph::functions::impl
+
+namespace memgraph::functions {
+
+template <typename TypedValueT, typename FunctionContextT, typename Tag, typename Conv>
+std::function<TypedValueT(const TypedValueT *arguments, int64_t num_arguments, const FunctionContextT &context)>
+NameToFunction(const std::string &function_name) {
+  // Scalar functions
+  if (function_name == "DEGREE") return functions::impl::Degree<TypedValueT, FunctionContextT, Tag>;
+  if (function_name == "INDEGREE") return functions::impl::InDegree<TypedValueT, FunctionContextT, Tag>;
+  if (function_name == "OUTDEGREE") return functions::impl::OutDegree<TypedValueT, FunctionContextT, Tag>;
+  if (function_name == "ENDNODE") return functions::impl::EndNode<TypedValueT, FunctionContextT, Tag>;
+  if (function_name == "HEAD") return functions::impl::Head<TypedValueT, FunctionContextT>;
+  if (function_name == kId) return functions::impl::Id<TypedValueT, FunctionContextT>;
+  if (function_name == "LAST") return functions::impl::Last<TypedValueT, FunctionContextT>;
+  if (function_name == "PROPERTIES") return functions::impl::Properties<TypedValueT, FunctionContextT, Tag, Conv>;
+  if (function_name == "SIZE") return functions::impl::Size<TypedValueT, FunctionContextT>;
+  if (function_name == "STARTNODE") return functions::impl::StartNode<TypedValueT, FunctionContextT, Tag, Conv>;
+  if (function_name == "TIMESTAMP") return functions::impl::Timestamp<TypedValueT, FunctionContextT>;
+  if (function_name == "TOBOOLEAN") return functions::impl::ToBoolean<TypedValueT, FunctionContextT>;
+  if (function_name == "TOFLOAT") return functions::impl::ToFloat<TypedValueT, FunctionContextT>;
+  if (function_name == "TOINTEGER") return functions::impl::ToInteger<TypedValueT, FunctionContextT>;
+  if (function_name == "TYPE") return functions::impl::Type<TypedValueT, FunctionContextT>;
+  if (function_name == "VALUETYPE") return functions::impl::ValueType<TypedValueT, FunctionContextT>;
+
+  // List functions
+  if (function_name == "KEYS") return functions::impl::Keys<TypedValueT, FunctionContextT, Tag>;
+  if (function_name == "LABELS") return functions::impl::Labels<TypedValueT, FunctionContextT, Tag>;
+  if (function_name == "NODES") return functions::impl::Nodes<TypedValueT, FunctionContextT>;
+  if (function_name == "RANGE") return functions::impl::Range<TypedValueT, FunctionContextT>;
+  if (function_name == "RELATIONSHIPS") return functions::impl::Relationships<TypedValueT, FunctionContextT>;
+  if (function_name == "TAIL") return functions::impl::Tail<TypedValueT, FunctionContextT>;
+  if (function_name == "UNIFORMSAMPLE") return functions::impl::UniformSample<TypedValueT, FunctionContextT>;
+
+  // Mathematical functions - numeric
+  if (function_name == "ABS") return functions::impl::Abs<TypedValueT, FunctionContextT>;
+  if (function_name == "CEIL") return functions::impl::Ceil<TypedValueT, FunctionContextT>;
+  if (function_name == "FLOOR") return functions::impl::Floor<TypedValueT, FunctionContextT>;
+  if (function_name == "RAND") return functions::impl::Rand<TypedValueT, FunctionContextT>;
+  if (function_name == "ROUND") return functions::impl::Round<TypedValueT, FunctionContextT>;
+  if (function_name == "SIGN") return functions::impl::Sign<TypedValueT, FunctionContextT>;
+
+  // Mathematical functions - logarithmic
+  if (function_name == "E") return functions::impl::E<TypedValueT, FunctionContextT>;
+  if (function_name == "EXP") return functions::impl::Exp<TypedValueT, FunctionContextT>;
+  if (function_name == "LOG") return functions::impl::Log<TypedValueT, FunctionContextT>;
+  if (function_name == "LOG10") return functions::impl::Log10<TypedValueT, FunctionContextT>;
+  if (function_name == "SQRT") return functions::impl::Sqrt<TypedValueT, FunctionContextT>;
+
+  // Mathematical functions - trigonometric
+  if (function_name == "ACOS") return functions::impl::Acos<TypedValueT, FunctionContextT>;
+  if (function_name == "ASIN") return functions::impl::Asin<TypedValueT, FunctionContextT>;
+  if (function_name == "ATAN") return functions::impl::Atan<TypedValueT, FunctionContextT>;
+  if (function_name == "ATAN2") return functions::impl::Atan2<TypedValueT, FunctionContextT>;
+  if (function_name == "COS") return functions::impl::Cos<TypedValueT, FunctionContextT>;
+  if (function_name == "PI") return functions::impl::Pi<TypedValueT, FunctionContextT>;
+  if (function_name == "SIN") return functions::impl::Sin<TypedValueT, FunctionContextT>;
+  if (function_name == "TAN") return functions::impl::Tan<TypedValueT, FunctionContextT>;
+
+  // String functions
+  if (function_name == kContains) return functions::impl::Contains<TypedValueT, FunctionContextT>;
+  if (function_name == kEndsWith) return functions::impl::EndsWith<TypedValueT, FunctionContextT>;
+  if (function_name == "LEFT") return functions::impl::Left<TypedValueT, FunctionContextT>;
+  if (function_name == "LTRIM") return functions::impl::LTrim<TypedValueT, FunctionContextT>;
+  if (function_name == "REPLACE") return functions::impl::Replace<TypedValueT, FunctionContextT>;
+  if (function_name == "REVERSE") return functions::impl::Reverse<TypedValueT, FunctionContextT>;
+  if (function_name == "RIGHT") return functions::impl::Right<TypedValueT, FunctionContextT>;
+  if (function_name == "RTRIM") return functions::impl::RTrim<TypedValueT, FunctionContextT>;
+  if (function_name == "SPLIT") return functions::impl::Split<TypedValueT, FunctionContextT>;
+  if (function_name == kStartsWith) return functions::impl::StartsWith<TypedValueT, FunctionContextT>;
+  if (function_name == "SUBSTRING") return functions::impl::Substring<TypedValueT, FunctionContextT>;
+  if (function_name == "TOLOWER") return functions::impl::ToLower<TypedValueT, FunctionContextT>;
+  if (function_name == "TOSTRING") return functions::impl::ToString<TypedValueT, FunctionContextT>;
+  if (function_name == "TOUPPER") return functions::impl::ToUpper<TypedValueT, FunctionContextT>;
+  if (function_name == "TRIM") return functions::impl::Trim<TypedValueT, FunctionContextT>;
+
+  // Memgraph specific functions
+  if (function_name == "ASSERT") return functions::impl::Assert<TypedValueT, FunctionContextT>;
+  if (function_name == "COUNTER") return functions::impl::Counter<TypedValueT, FunctionContextT>;
+  if (function_name == "TOBYTESTRING") return functions::impl::ToByteString<TypedValueT, FunctionContextT>;
+  if (function_name == "FROMBYTESTRING") return functions::impl::FromByteString<TypedValueT, FunctionContextT>;
+
+  // Functions for temporal types
+  if (function_name == "DATE") return functions::impl::Date<TypedValueT, FunctionContextT>;
+  if (function_name == "LOCALTIME") return functions::impl::LocalTime<TypedValueT, FunctionContextT>;
+  if (function_name == "LOCALDATETIME") return functions::impl::LocalDateTime<TypedValueT, FunctionContextT>;
+  if (function_name == "DURATION") return functions::impl::Duration<TypedValueT, FunctionContextT>;
+
+  return nullptr;
+}
+
+}  // namespace memgraph::functions
diff --git a/src/query/v2/CMakeLists.txt b/src/query/v2/CMakeLists.txt
index 3c3f780c8..3ecaf63f9 100644
--- a/src/query/v2/CMakeLists.txt
+++ b/src/query/v2/CMakeLists.txt
@@ -11,7 +11,6 @@ set(mg_query_v2_sources
     cypher_query_interpreter.cpp
     frontend/semantic/required_privileges.cpp
     frontend/stripped.cpp
-    interpret/awesome_memgraph_functions.cpp
     interpreter.cpp
     metadata.cpp
     plan/operator.cpp
@@ -34,7 +33,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_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-expr)
+target_link_libraries(mg-query-v2 mg-expr mg-functions)
 
 if(NOT "${MG_PYTHON_PATH}" STREQUAL "")
     set(Python3_ROOT_DIR "${MG_PYTHON_PATH}")
diff --git a/src/query/v2/accessors.hpp b/src/query/v2/accessors.hpp
index 8e10c865d..73cc24ba2 100644
--- a/src/query/v2/accessors.hpp
+++ b/src/query/v2/accessors.hpp
@@ -136,9 +136,11 @@ class VertexAccessor final {
   //    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); }
+  // NOLINTNEXTLINE(readability-convert-member-functions-to-static)
+  [[nodiscard]] size_t InDegree() const { return 0; }
+
+  // NOLINTNEXTLINE(readability-convert-member-functions-to-static)
+  [[nodiscard]] size_t OutDegree() const { return 0; }
   //
 
   friend bool operator==(const VertexAccessor &lhs, const VertexAccessor &rhs) {
@@ -153,10 +155,6 @@ class VertexAccessor final {
   const msgs::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.
 class Path {
  public:
@@ -197,7 +195,14 @@ class Path {
   friend bool operator==(const Path & /*lhs*/, const Path & /*rhs*/) { return true; };
   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:
+  std::vector<VertexAccessor> vertices_;
+  std::vector<EdgeAccessor> edges_;
   utils::MemoryResource *mem = utils::NewDeleteResource();
 };
 }  // namespace memgraph::query::v2::accessors
diff --git a/src/query/v2/conversions.hpp b/src/query/v2/conversions.hpp
index 10299c919..4556e46bc 100644
--- a/src/query/v2/conversions.hpp
+++ b/src/query/v2/conversions.hpp
@@ -56,6 +56,10 @@ inline TypedValue ValueToTypedValue(const msgs::Value &value, msgs::ShardRequest
   throw std::runtime_error("Incorrect type in conversion");
 }
 
+inline const auto ValueToTypedValueFunctor = [](const msgs::Value &value, msgs::ShardRequestManagerInterface *manager) {
+  return ValueToTypedValue(value, manager);
+};
+
 inline msgs::Value TypedValueToValue(const TypedValue &value) {
   using Value = msgs::Value;
   switch (value.type()) {
diff --git a/src/query/v2/frontend/ast/ast.lcp b/src/query/v2/frontend/ast/ast.lcp
index e30e623ea..209bdfd50 100644
--- a/src/query/v2/frontend/ast/ast.lcp
+++ b/src/query/v2/frontend/ast/ast.lcp
@@ -20,11 +20,13 @@
 #include "query/v2/bindings/ast_visitor.hpp"
 #include "common/types.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/db_accessor.hpp"
 #include "query/v2/path.hpp"
+#include "query/v2/shard_request_manager.hpp"
 #include "utils/typeinfo.hpp"
+#include "query/v2/conversions.hpp"
 
 cpp<#
 
@@ -836,13 +838,15 @@ cpp<#
               :slk-load (slk-load-ast-vector "Expression"))
    (function-name "std::string" :scope :public)
    (function "std::function<TypedValue(const TypedValue *, int64_t,
-                                       const FunctionContext &)>"
+                                       const functions::FunctionContext<msgs::ShardRequestManagerInterface> &)>"
              :scope :public
              :dont-save t
              :clone :copy
              :slk-load (lambda (member)
                         #>cpp
-                        self->${member} = query::v2::NameToFunction(self->function_name_);
+                        self->${member} = functions::NameToFunction<TypedValue,
+                                            functions::FunctionContext<msgs::ShardRequestManagerInterface>,
+                                            functions::QueryEngineTag, decltype(ValueToTypedValueFunctor)>(self->function_name_);
                         cpp<#)))
   (:public
     #>cpp
@@ -865,7 +869,8 @@ cpp<#
              const std::vector<Expression *> &arguments)
         : arguments_(arguments),
           function_name_(function_name),
-          function_(NameToFunction(function_name_)) {
+          function_(functions::NameToFunction<TypedValue, functions::FunctionContext<msgs::ShardRequestManagerInterface>,
+                                              functions::QueryEngineTag, decltype(ValueToTypedValueFunctor)>(function_name_)) {
       if (!function_) {
         throw SemanticException("Function '{}' doesn't exist.", function_name);
       }
diff --git a/src/query/v2/interpret/awesome_memgraph_functions.cpp b/src/query/v2/interpret/awesome_memgraph_functions.cpp
deleted file mode 100644
index 8768736b2..000000000
--- a/src/query/v2/interpret/awesome_memgraph_functions.cpp
+++ /dev/null
@@ -1,1108 +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.
-
-#include "query/v2/interpret/awesome_memgraph_functions.hpp"
-
-#include <algorithm>
-#include <cctype>
-#include <cmath>
-#include <cstdlib>
-#include <functional>
-#include <random>
-#include <string_view>
-#include <type_traits>
-
-#include "query/v2/bindings/typed_value.hpp"
-#include "query/v2/conversions.hpp"
-#include "query/v2/exceptions.hpp"
-#include "query/v2/shard_request_manager.hpp"
-#include "storage/v3/conversions.hpp"
-#include "utils/string.hpp"
-#include "utils/temporal.hpp"
-
-namespace memgraph::query::v2 {
-namespace {
-
-////////////////////////////////////////////////////////////////////////////////
-// eDSL using template magic for describing a type of an awesome memgraph
-// function and checking if the passed in arguments match the description.
-//
-// To use the type checking eDSL, you should put a `FType` invocation in the
-// body of your awesome Memgraph function. `FType` takes type arguments as the
-// description of the function type signature. Each runtime argument will be
-// checked in order corresponding to given compile time type arguments. These
-// type arguments can come in two forms:
-//
-//   * final, primitive type descriptor and
-//   * combinator type descriptor.
-//
-// The primitive type descriptors are defined as empty structs, they are right
-// below this documentation.
-//
-// Combinator type descriptors are defined as structs taking additional type
-// parameters, you can find these further below in the implementation. Of
-// primary interest are `Or` and `Optional` type combinators.
-//
-// With `Or` you can describe that an argument can be any of the types listed in
-// `Or`. For example, `Or<Null, Bool, Integer>` allows an argument to be either
-// `Null` or a boolean or an integer.
-//
-// The `Optional` combinator is used to define optional arguments to a function.
-// These must come as the last positional arguments. Naturally, you can use `Or`
-// inside `Optional`. So for example, `Optional<Or<Null, Bool>, Integer>`
-// describes that a function takes 2 optional arguments. The 1st one must be
-// either a `Null` or a boolean, while the 2nd one must be an integer. The type
-// signature check will succeed in the following cases.
-//
-//   * No optional arguments were supplied.
-//   * One argument was supplied and it passes `Or<Null, Bool>` check.
-//   * Two arguments were supplied, the 1st one passes `Or<Null, Bool>` check
-//     and the 2nd one passes `Integer` check.
-//
-// Runtime arguments to `FType` are: function name, pointer to arguments and the
-// number of received arguments.
-//
-// Full example.
-//
-//     FType<Or<Null, String>, NonNegativeInteger,
-//           Optional<NonNegativeInteger>>("substring", args, nargs);
-//
-// The above will check that `substring` function received the 2 required
-// arguments. Optionally, the function may take a 3rd argument. The 1st argument
-// must be either a `Null` or a character string. The 2nd argument is required
-// to be a non-negative integer. If the 3rd argument was supplied, it will also
-// be checked that it is a non-negative integer. If any of these checks fail,
-// `FType` will throw a `QueryRuntimeException` with an appropriate error
-// message.
-////////////////////////////////////////////////////////////////////////////////
-
-struct Null {};
-struct Bool {};
-struct Integer {};
-struct PositiveInteger {};
-struct NonZeroInteger {};
-struct NonNegativeInteger {};
-struct Double {};
-struct Number {};
-struct List {};
-struct String {};
-struct Map {};
-struct Edge {};
-struct Vertex {};
-struct Path {};
-struct Date {};
-struct LocalTime {};
-struct LocalDateTime {};
-struct Duration {};
-
-template <class ArgType>
-bool ArgIsType(const TypedValue &arg) {
-  if constexpr (std::is_same_v<ArgType, Null>) {
-    return arg.IsNull();
-  } else if constexpr (std::is_same_v<ArgType, Bool>) {
-    return arg.IsBool();
-  } else if constexpr (std::is_same_v<ArgType, Integer>) {
-    return arg.IsInt();
-  } else if constexpr (std::is_same_v<ArgType, PositiveInteger>) {
-    return arg.IsInt() && arg.ValueInt() > 0;
-  } else if constexpr (std::is_same_v<ArgType, NonZeroInteger>) {
-    return arg.IsInt() && arg.ValueInt() != 0;
-  } else if constexpr (std::is_same_v<ArgType, NonNegativeInteger>) {
-    return arg.IsInt() && arg.ValueInt() >= 0;
-  } else if constexpr (std::is_same_v<ArgType, Double>) {
-    return arg.IsDouble();
-  } else if constexpr (std::is_same_v<ArgType, Number>) {
-    return arg.IsNumeric();
-  } else if constexpr (std::is_same_v<ArgType, List>) {
-    return arg.IsList();
-  } else if constexpr (std::is_same_v<ArgType, String>) {
-    return arg.IsString();
-  } else if constexpr (std::is_same_v<ArgType, Map>) {
-    return arg.IsMap();
-  } else if constexpr (std::is_same_v<ArgType, Vertex>) {
-    return arg.IsVertex();
-  } else if constexpr (std::is_same_v<ArgType, Edge>) {
-    return arg.IsEdge();
-  } else if constexpr (std::is_same_v<ArgType, Path>) {
-    return arg.IsPath();
-  } else if constexpr (std::is_same_v<ArgType, Date>) {
-    return arg.IsDate();
-  } else if constexpr (std::is_same_v<ArgType, LocalTime>) {
-    return arg.IsLocalTime();
-  } else if constexpr (std::is_same_v<ArgType, LocalDateTime>) {
-    return arg.IsLocalDateTime();
-  } else if constexpr (std::is_same_v<ArgType, Duration>) {
-    return arg.IsDuration();
-  } else if constexpr (std::is_same_v<ArgType, void>) {
-    return true;
-  } else {
-    static_assert(std::is_same_v<ArgType, Null>, "Unknown ArgType");
-  }
-  return false;
-}
-
-template <class ArgType>
-constexpr const char *ArgTypeName() {
-  // The type names returned should be standardized openCypher type names.
-  // https://github.com/opencypher/openCypher/blob/master/docs/openCypher9.pdf
-  if constexpr (std::is_same_v<ArgType, Null>) {
-    return "null";
-  } else if constexpr (std::is_same_v<ArgType, Bool>) {
-    return "boolean";
-  } else if constexpr (std::is_same_v<ArgType, Integer>) {
-    return "integer";
-  } else if constexpr (std::is_same_v<ArgType, PositiveInteger>) {
-    return "positive integer";
-  } else if constexpr (std::is_same_v<ArgType, NonZeroInteger>) {
-    return "non-zero integer";
-  } else if constexpr (std::is_same_v<ArgType, NonNegativeInteger>) {
-    return "non-negative integer";
-  } else if constexpr (std::is_same_v<ArgType, Double>) {
-    return "float";
-  } else if constexpr (std::is_same_v<ArgType, Number>) {
-    return "number";
-  } else if constexpr (std::is_same_v<ArgType, List>) {
-    return "list";
-  } else if constexpr (std::is_same_v<ArgType, String>) {
-    return "string";
-  } else if constexpr (std::is_same_v<ArgType, Map>) {
-    return "map";
-  } else if constexpr (std::is_same_v<ArgType, Vertex>) {
-    return "node";
-  } else if constexpr (std::is_same_v<ArgType, Edge>) {
-    return "relationship";
-  } else if constexpr (std::is_same_v<ArgType, Path>) {
-    return "path";
-  } else if constexpr (std::is_same_v<ArgType, void>) {
-    return "void";
-  } else if constexpr (std::is_same_v<ArgType, Date>) {
-    return "Date";
-  } else if constexpr (std::is_same_v<ArgType, LocalTime>) {
-    return "LocalTime";
-  } else if constexpr (std::is_same_v<ArgType, LocalDateTime>) {
-    return "LocalDateTime";
-  } else if constexpr (std::is_same_v<ArgType, Duration>) {
-    return "Duration";
-  } else {
-    static_assert(std::is_same_v<ArgType, Null>, "Unknown ArgType");
-  }
-  return "<unknown-type>";
-}
-
-template <class... ArgType>
-struct Or;
-
-template <class ArgType>
-struct Or<ArgType> {
-  static bool Check(const TypedValue &arg) { return ArgIsType<ArgType>(arg); }
-
-  static std::string TypeNames() { return ArgTypeName<ArgType>(); }
-};
-
-template <class ArgType, class... ArgTypes>
-struct Or<ArgType, ArgTypes...> {
-  static bool Check(const TypedValue &arg) {
-    if (ArgIsType<ArgType>(arg)) return true;
-    return Or<ArgTypes...>::Check(arg);
-  }
-
-  static std::string TypeNames() {
-    if constexpr (sizeof...(ArgTypes) > 1) {
-      return fmt::format("'{}', {}", ArgTypeName<ArgType>(), Or<ArgTypes...>::TypeNames());
-    } else {
-      return fmt::format("'{}' or '{}'", ArgTypeName<ArgType>(), Or<ArgTypes...>::TypeNames());
-    }
-  }
-};
-
-template <class T>
-struct IsOrType {
-  static constexpr bool value = false;
-};
-
-template <class... ArgTypes>
-struct IsOrType<Or<ArgTypes...>> {
-  static constexpr bool value = true;
-};
-
-template <class... ArgTypes>
-struct Optional;
-
-template <class ArgType>
-struct Optional<ArgType> {
-  static constexpr size_t size = 1;
-
-  static void Check(const char *name, const TypedValue *args, int64_t nargs, int64_t pos) {
-    if (nargs == 0) return;
-    const TypedValue &arg = args[0];
-    if constexpr (IsOrType<ArgType>::value) {
-      if (!ArgType::Check(arg)) {
-        throw QueryRuntimeException("Optional '{}' argument at position {} must be either {}.", name, pos,
-                                    ArgType::TypeNames());
-      }
-    } else {
-      if (!ArgIsType<ArgType>(arg))
-        throw QueryRuntimeException("Optional '{}' argument at position {} must be '{}'.", name, pos,
-                                    ArgTypeName<ArgType>());
-    }
-  }
-};
-
-template <class ArgType, class... ArgTypes>
-struct Optional<ArgType, ArgTypes...> {
-  static constexpr size_t size = 1 + sizeof...(ArgTypes);
-
-  static void Check(const char *name, const TypedValue *args, int64_t nargs, int64_t pos) {
-    if (nargs == 0) return;
-    Optional<ArgType>::Check(name, args, nargs, pos);
-    Optional<ArgTypes...>::Check(name, args + 1, nargs - 1, pos + 1);
-  }
-};
-
-template <class T>
-struct IsOptional {
-  static constexpr bool value = false;
-};
-
-template <class... ArgTypes>
-struct IsOptional<Optional<ArgTypes...>> {
-  static constexpr bool value = true;
-};
-
-template <class ArgType, class... ArgTypes>
-constexpr size_t FTypeRequiredArgs() {
-  if constexpr (IsOptional<ArgType>::value) {
-    static_assert(sizeof...(ArgTypes) == 0, "Optional arguments must be last!");
-    return 0;
-  } else if constexpr (sizeof...(ArgTypes) == 0) {
-    return 1;
-  } else {
-    return 1U + FTypeRequiredArgs<ArgTypes...>();
-  }
-}
-
-template <class ArgType, class... ArgTypes>
-constexpr size_t FTypeOptionalArgs() {
-  if constexpr (IsOptional<ArgType>::value) {
-    static_assert(sizeof...(ArgTypes) == 0, "Optional arguments must be last!");
-    return ArgType::size;
-  } else if constexpr (sizeof...(ArgTypes) == 0) {
-    return 0;
-  } else {
-    return FTypeOptionalArgs<ArgTypes...>();
-  }
-}
-
-template <class ArgType, class... ArgTypes>
-void FType(const char *name, const TypedValue *args, int64_t nargs, int64_t pos = 1) {
-  if constexpr (std::is_same_v<ArgType, void>) {
-    if (nargs != 0) {
-      throw QueryRuntimeException("'{}' requires no arguments.", name);
-    }
-    return;
-  }
-  static constexpr int64_t required_args = FTypeRequiredArgs<ArgType, ArgTypes...>();
-  static constexpr int64_t optional_args = FTypeOptionalArgs<ArgType, ArgTypes...>();
-  static constexpr int64_t total_args = required_args + optional_args;
-  if constexpr (optional_args > 0) {
-    if (nargs < required_args || nargs > total_args) {
-      throw QueryRuntimeException("'{}' requires between {} and {} arguments.", name, required_args, total_args);
-    }
-  } else {
-    if (nargs != required_args) {
-      throw QueryRuntimeException("'{}' requires exactly {} {}.", name, required_args,
-                                  required_args == 1 ? "argument" : "arguments");
-    }
-  }
-  const TypedValue &arg = args[0];
-  if constexpr (IsOrType<ArgType>::value) {
-    if (!ArgType::Check(arg)) {
-      throw QueryRuntimeException("'{}' argument at position {} must be either {}.", name, pos, ArgType::TypeNames());
-    }
-  } else if constexpr (IsOptional<ArgType>::value) {
-    static_assert(sizeof...(ArgTypes) == 0, "Optional arguments must be last!");
-    ArgType::Check(name, args, nargs, pos);
-  } else {
-    if (!ArgIsType<ArgType>(arg)) {
-      throw QueryRuntimeException("'{}' argument at position {} must be '{}'", name, pos, ArgTypeName<ArgType>());
-    }
-  }
-  if constexpr (sizeof...(ArgTypes) > 0) {
-    FType<ArgTypes...>(name, args + 1, nargs - 1, pos + 1);
-  }
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// END function type description eDSL
-////////////////////////////////////////////////////////////////////////////////
-
-// Predicate functions.
-// Neo4j has all, any, exists, none, single
-// Those functions are a little bit different since they take a filterExpression
-// as an argument.
-// There is all, any, none and single productions in opencypher grammar, but it
-// will be trivial to also add exists.
-// TODO: Implement this.
-
-// Scalar functions.
-// We don't have a way to implement id function since we don't store any. If it
-// is really neccessary we could probably map vlist* to id.
-// TODO: Implement length (it works on a path, but we didn't define path
-// structure yet).
-// TODO: Implement size(pattern), for example size((a)-[:X]-()) should return
-// number of results of this pattern. I don't think we will ever do this.
-// TODO: Implement rest of the list functions.
-// TODO: Implement degrees, haversin, radians
-// TODO: Implement spatial functions
-
-TypedValue EndNode(const TypedValue *args, int64_t nargs, const FunctionContext &ctx) {
-  FType<Or<Null, Edge>>("endNode", args, nargs);
-  if (args[0].IsNull()) return TypedValue(ctx.memory);
-  return TypedValue(args[0].ValueEdge().To(), ctx.memory);
-}
-
-TypedValue Head(const TypedValue *args, int64_t nargs, const FunctionContext &ctx) {
-  FType<Or<Null, List>>("head", args, nargs);
-  if (args[0].IsNull()) return TypedValue(ctx.memory);
-  const auto &list = args[0].ValueList();
-  if (list.empty()) return TypedValue(ctx.memory);
-  return TypedValue(list[0], ctx.memory);
-}
-
-TypedValue Last(const TypedValue *args, int64_t nargs, const FunctionContext &ctx) {
-  FType<Or<Null, List>>("last", args, nargs);
-  if (args[0].IsNull()) return TypedValue(ctx.memory);
-  const auto &list = args[0].ValueList();
-  if (list.empty()) return TypedValue(ctx.memory);
-  return TypedValue(list.back(), ctx.memory);
-}
-
-TypedValue Properties(const TypedValue * /*args*/, int64_t /*nargs*/, const FunctionContext & /*ctx*/) { return {}; }
-
-TypedValue Size(const TypedValue *args, int64_t nargs, const FunctionContext &ctx) {
-  FType<Or<Null, List, String, Map, Path>>("size", args, nargs);
-  const auto &value = args[0];
-  if (value.IsNull()) {
-    return TypedValue(ctx.memory);
-  } else if (value.IsList()) {
-    return TypedValue(static_cast<int64_t>(value.ValueList().size()), ctx.memory);
-  } else if (value.IsString()) {
-    return TypedValue(static_cast<int64_t>(value.ValueString().size()), ctx.memory);
-  } else if (value.IsMap()) {
-    // neo4j doesn't implement size for map, but I don't see a good reason not
-    // to do it.
-    return TypedValue(static_cast<int64_t>(value.ValueMap().size()), ctx.memory);
-  } else {
-    // TODO(kostasrim) Fix the dummy return
-    return TypedValue(int64_t(0), ctx.memory);
-  }
-}
-
-TypedValue StartNode(const TypedValue *args, int64_t nargs, const FunctionContext &ctx) {
-  FType<Or<Null, Edge>>("startNode", args, nargs);
-  if (args[0].IsNull()) return TypedValue(ctx.memory);
-  return TypedValue(args[0].ValueEdge().From(), ctx.memory);
-}
-
-TypedValue ToBoolean(const TypedValue *args, int64_t nargs, const FunctionContext &ctx) {
-  FType<Or<Null, Bool, Integer, String>>("toBoolean", args, nargs);
-  const auto &value = args[0];
-  if (value.IsNull()) {
-    return TypedValue(ctx.memory);
-  } else if (value.IsBool()) {
-    return TypedValue(value.ValueBool(), ctx.memory);
-  } else if (value.IsInt()) {
-    return TypedValue(value.ValueInt() != 0L, ctx.memory);
-  } else {
-    auto s = utils::ToUpperCase(utils::Trim(value.ValueString()));
-    if (s == "TRUE") return TypedValue(true, ctx.memory);
-    if (s == "FALSE") return TypedValue(false, ctx.memory);
-    // I think this is just stupid and that exception should be thrown, but
-    // neo4j does it this way...
-    return TypedValue(ctx.memory);
-  }
-}
-
-TypedValue ToFloat(const TypedValue *args, int64_t nargs, const FunctionContext &ctx) {
-  FType<Or<Null, Number, String>>("toFloat", args, nargs);
-  const auto &value = args[0];
-  if (value.IsNull()) {
-    return TypedValue(ctx.memory);
-  } else if (value.IsInt()) {
-    return TypedValue(static_cast<double>(value.ValueInt()), ctx.memory);
-  } else if (value.IsDouble()) {
-    return TypedValue(value, ctx.memory);
-  } else {
-    try {
-      return TypedValue(utils::ParseDouble(utils::Trim(value.ValueString())), ctx.memory);
-    } catch (const utils::BasicException &) {
-      return TypedValue(ctx.memory);
-    }
-  }
-}
-
-TypedValue ToInteger(const TypedValue *args, int64_t nargs, const FunctionContext &ctx) {
-  FType<Or<Null, Bool, Number, String>>("toInteger", args, nargs);
-  const auto &value = args[0];
-  if (value.IsNull()) {
-    return TypedValue(ctx.memory);
-  } else if (value.IsBool()) {
-    return TypedValue(value.ValueBool() ? 1L : 0L, ctx.memory);
-  } else if (value.IsInt()) {
-    return TypedValue(value, ctx.memory);
-  } else if (value.IsDouble()) {
-    return TypedValue(static_cast<int64_t>(value.ValueDouble()), ctx.memory);
-  } else {
-    try {
-      // Yup, this is correct. String is valid if it has floating point
-      // number, then it is parsed and converted to int.
-      return TypedValue(static_cast<int64_t>(utils::ParseDouble(utils::Trim(value.ValueString()))), ctx.memory);
-    } catch (const utils::BasicException &) {
-      return TypedValue(ctx.memory);
-    }
-  }
-}
-
-TypedValue Type(const TypedValue *args, int64_t nargs, const FunctionContext &ctx) {
-  FType<Or<Null, Edge>>("type", args, nargs);
-  if (args[0].IsNull()) return TypedValue(ctx.memory);
-  return TypedValue(args[0].ValueEdge().EdgeType().AsInt(), ctx.memory);
-}
-
-TypedValue ValueType(const TypedValue *args, int64_t nargs, const FunctionContext &ctx) {
-  FType<Or<Null, Bool, Integer, Double, String, List, Map, Vertex, Edge, Path>>("type", args, nargs);
-  // The type names returned should be standardized openCypher type names.
-  // https://github.com/opencypher/openCypher/blob/master/docs/openCypher9.pdf
-  switch (args[0].type()) {
-    case TypedValue::Type::Null:
-      return TypedValue("NULL", ctx.memory);
-    case TypedValue::Type::Bool:
-      return TypedValue("BOOLEAN", ctx.memory);
-    case TypedValue::Type::Int:
-      return TypedValue("INTEGER", ctx.memory);
-    case TypedValue::Type::Double:
-      return TypedValue("FLOAT", ctx.memory);
-    case TypedValue::Type::String:
-      return TypedValue("STRING", ctx.memory);
-    case TypedValue::Type::List:
-      return TypedValue("LIST", ctx.memory);
-    case TypedValue::Type::Map:
-      return TypedValue("MAP", ctx.memory);
-    case TypedValue::Type::Vertex:
-      return TypedValue("NODE", ctx.memory);
-    case TypedValue::Type::Edge:
-      return TypedValue("RELATIONSHIP", ctx.memory);
-    case TypedValue::Type::Path:
-      return TypedValue("PATH", ctx.memory);
-    case TypedValue::Type::Date:
-      return TypedValue("DATE", ctx.memory);
-    case TypedValue::Type::LocalTime:
-      return TypedValue("LOCAL_TIME", ctx.memory);
-    case TypedValue::Type::LocalDateTime:
-      return TypedValue("LOCAL_DATE_TIME", ctx.memory);
-    case TypedValue::Type::Duration:
-      return TypedValue("DURATION", ctx.memory);
-  }
-}
-
-TypedValue Range(const TypedValue *args, int64_t nargs, const FunctionContext &ctx) {
-  FType<Or<Null, Integer>, Or<Null, Integer>, Optional<Or<Null, NonZeroInteger>>>("range", args, nargs);
-  for (int64_t i = 0; i < nargs; ++i)
-    if (args[i].IsNull()) return TypedValue(ctx.memory);
-  auto lbound = args[0].ValueInt();
-  auto rbound = args[1].ValueInt();
-  int64_t step = nargs == 3 ? args[2].ValueInt() : 1;
-  TypedValue::TVector list(ctx.memory);
-  if (lbound <= rbound && step > 0) {
-    for (auto i = lbound; i <= rbound; i += step) {
-      list.emplace_back(i);
-    }
-  } else if (lbound >= rbound && step < 0) {
-    for (auto i = lbound; i >= rbound; i += step) {
-      list.emplace_back(i);
-    }
-  }
-  return TypedValue(std::move(list));
-}
-
-TypedValue Tail(const TypedValue *args, int64_t nargs, const FunctionContext &ctx) {
-  FType<Or<Null, List>>("tail", args, nargs);
-  if (args[0].IsNull()) return TypedValue(ctx.memory);
-  TypedValue::TVector list(args[0].ValueList(), ctx.memory);
-  if (list.empty()) return TypedValue(std::move(list));
-  list.erase(list.begin());
-  return TypedValue(std::move(list));
-}
-
-TypedValue UniformSample(const TypedValue *args, int64_t nargs, const FunctionContext &ctx) {
-  FType<Or<Null, List>, Or<Null, NonNegativeInteger>>("uniformSample", args, nargs);
-  static thread_local std::mt19937 pseudo_rand_gen_{std::random_device{}()};
-  if (args[0].IsNull() || args[1].IsNull()) return TypedValue(ctx.memory);
-  const auto &population = args[0].ValueList();
-  auto population_size = population.size();
-  if (population_size == 0) return TypedValue(ctx.memory);
-  auto desired_length = args[1].ValueInt();
-  std::uniform_int_distribution<uint64_t> rand_dist{0, population_size - 1};
-  TypedValue::TVector sampled(ctx.memory);
-  sampled.reserve(desired_length);
-  for (int64_t i = 0; i < desired_length; ++i) {
-    sampled.emplace_back(population[rand_dist(pseudo_rand_gen_)]);
-  }
-  return TypedValue(std::move(sampled));
-}
-
-TypedValue Abs(const TypedValue *args, int64_t nargs, const FunctionContext &ctx) {
-  FType<Or<Null, Number>>("abs", args, nargs);
-  const auto &value = args[0];
-  if (value.IsNull()) {
-    return TypedValue(ctx.memory);
-  } else if (value.IsInt()) {
-    return TypedValue(std::abs(value.ValueInt()), ctx.memory);
-  } else {
-    return TypedValue(std::abs(value.ValueDouble()), ctx.memory);
-  }
-}
-
-#define WRAP_CMATH_FLOAT_FUNCTION(name, lowercased_name)                               \
-  TypedValue name(const TypedValue *args, int64_t nargs, const FunctionContext &ctx) { \
-    FType<Or<Null, Number>>(#lowercased_name, args, nargs);                            \
-    const auto &value = args[0];                                                       \
-    if (value.IsNull()) {                                                              \
-      return TypedValue(ctx.memory);                                                   \
-    } else if (value.IsInt()) {                                                        \
-      return TypedValue(lowercased_name(value.ValueInt()), ctx.memory);                \
-    } else {                                                                           \
-      return TypedValue(lowercased_name(value.ValueDouble()), ctx.memory);             \
-    }                                                                                  \
-  }
-
-WRAP_CMATH_FLOAT_FUNCTION(Ceil, ceil)
-WRAP_CMATH_FLOAT_FUNCTION(Floor, floor)
-// We are not completely compatible with neoj4 in this function because,
-// neo4j rounds -0.5, -1.5, -2.5... to 0, -1, -2...
-WRAP_CMATH_FLOAT_FUNCTION(Round, round)
-WRAP_CMATH_FLOAT_FUNCTION(Exp, exp)
-WRAP_CMATH_FLOAT_FUNCTION(Log, log)
-WRAP_CMATH_FLOAT_FUNCTION(Log10, log10)
-WRAP_CMATH_FLOAT_FUNCTION(Sqrt, sqrt)
-WRAP_CMATH_FLOAT_FUNCTION(Acos, acos)
-WRAP_CMATH_FLOAT_FUNCTION(Asin, asin)
-WRAP_CMATH_FLOAT_FUNCTION(Atan, atan)
-WRAP_CMATH_FLOAT_FUNCTION(Cos, cos)
-WRAP_CMATH_FLOAT_FUNCTION(Sin, sin)
-WRAP_CMATH_FLOAT_FUNCTION(Tan, tan)
-
-#undef WRAP_CMATH_FLOAT_FUNCTION
-
-TypedValue Atan2(const TypedValue *args, int64_t nargs, const FunctionContext &ctx) {
-  FType<Or<Null, Number>, Or<Null, Number>>("atan2", args, nargs);
-  if (args[0].IsNull() || args[1].IsNull()) return TypedValue(ctx.memory);
-  auto to_double = [](const TypedValue &t) -> double {
-    if (t.IsInt()) {
-      return t.ValueInt();
-    } else {
-      return t.ValueDouble();
-    }
-  };
-  double y = to_double(args[0]);
-  double x = to_double(args[1]);
-  return TypedValue(atan2(y, x), ctx.memory);
-}
-
-TypedValue Sign(const TypedValue *args, int64_t nargs, const FunctionContext &ctx) {
-  FType<Or<Null, Number>>("sign", args, nargs);
-  auto sign = [&](auto x) { return TypedValue((0 < x) - (x < 0), ctx.memory); };
-  const auto &value = args[0];
-  if (value.IsNull()) {
-    return TypedValue(ctx.memory);
-  } else if (value.IsInt()) {
-    return sign(value.ValueInt());
-  } else {
-    return sign(value.ValueDouble());
-  }
-}
-
-TypedValue E(const TypedValue *args, int64_t nargs, const FunctionContext &ctx) {
-  FType<void>("e", args, nargs);
-  return TypedValue(M_E, ctx.memory);
-}
-
-TypedValue Pi(const TypedValue *args, int64_t nargs, const FunctionContext &ctx) {
-  FType<void>("pi", args, nargs);
-  return TypedValue(M_PI, ctx.memory);
-}
-
-TypedValue Rand(const TypedValue *args, int64_t nargs, const FunctionContext &ctx) {
-  FType<void>("rand", args, nargs);
-  static thread_local std::mt19937 pseudo_rand_gen_{std::random_device{}()};
-  static thread_local std::uniform_real_distribution<> rand_dist_{0, 1};
-  return TypedValue(rand_dist_(pseudo_rand_gen_), ctx.memory);
-}
-
-template <class TPredicate>
-TypedValue StringMatchOperator(const TypedValue *args, int64_t nargs, const FunctionContext &ctx) {
-  FType<Or<Null, String>, Or<Null, String>>(TPredicate::name, args, nargs);
-  if (args[0].IsNull() || args[1].IsNull()) return TypedValue(ctx.memory);
-  const auto &s1 = args[0].ValueString();
-  const auto &s2 = args[1].ValueString();
-  return TypedValue(TPredicate{}(s1, s2), ctx.memory);
-}
-
-// Check if s1 starts with s2.
-struct StartsWithPredicate {
-  static constexpr const char *name = "startsWith";
-  bool operator()(const TypedValue::TString &s1, const TypedValue::TString &s2) const {
-    if (s1.size() < s2.size()) return false;
-    return std::equal(s2.begin(), s2.end(), s1.begin());
-  }
-};
-auto StartsWith = StringMatchOperator<StartsWithPredicate>;
-
-// Check if s1 ends with s2.
-struct EndsWithPredicate {
-  static constexpr const char *name = "endsWith";
-  bool operator()(const TypedValue::TString &s1, const TypedValue::TString &s2) const {
-    if (s1.size() < s2.size()) return false;
-    return std::equal(s2.rbegin(), s2.rend(), s1.rbegin());
-  }
-};
-auto EndsWith = StringMatchOperator<EndsWithPredicate>;
-
-// Check if s1 contains s2.
-struct ContainsPredicate {
-  static constexpr const char *name = "contains";
-  bool operator()(const TypedValue::TString &s1, const TypedValue::TString &s2) const {
-    if (s1.size() < s2.size()) return false;
-    return s1.find(s2) != std::string::npos;
-  }
-};
-auto Contains = StringMatchOperator<ContainsPredicate>;
-
-TypedValue Assert(const TypedValue *args, int64_t nargs, const FunctionContext &ctx) {
-  FType<Bool, Optional<String>>("assert", args, nargs);
-  if (!args[0].ValueBool()) {
-    std::string message("Assertion failed");
-    if (nargs == 2) {
-      message += ": ";
-      message += args[1].ValueString();
-    }
-    message += ".";
-    throw QueryRuntimeException(message);
-  }
-  return TypedValue(args[0], ctx.memory);
-}
-
-TypedValue Counter(const TypedValue *args, int64_t nargs, const FunctionContext &context) {
-  FType<String, Integer, Optional<NonZeroInteger>>("counter", args, nargs);
-  int64_t step = 1;
-  if (nargs == 3) {
-    step = args[2].ValueInt();
-  }
-
-  auto [it, inserted] = context.counters->emplace(args[0].ValueString(), args[1].ValueInt());
-  auto value = it->second;
-  it->second += step;
-
-  return TypedValue(value, context.memory);
-}
-
-TypedValue Id(const TypedValue *args, int64_t nargs, const FunctionContext &ctx) {
-  FType<Or<Null, Vertex, Edge>>("id", args, nargs);
-  const auto &arg = args[0];
-  if (arg.IsNull()) {
-    return TypedValue(ctx.memory);
-  } else if (arg.IsVertex()) {
-    return TypedValue(int64_t(arg.ValueVertex().CypherId()), ctx.memory);
-  } else {
-    return TypedValue(int64_t(arg.ValueEdge().CypherId()), ctx.memory);
-  }
-}
-
-TypedValue ToString(const TypedValue *args, int64_t nargs, const FunctionContext &ctx) {
-  FType<Or<Null, String, Number, Bool>>("toString", args, nargs);
-  const auto &arg = args[0];
-  if (arg.IsNull()) {
-    return TypedValue(ctx.memory);
-  } else if (arg.IsString()) {
-    return TypedValue(arg, ctx.memory);
-  } else if (arg.IsInt()) {
-    // TODO: This is making a pointless copy of std::string, we may want to
-    // use a different conversion to string
-    return TypedValue(std::to_string(arg.ValueInt()), ctx.memory);
-  } else if (arg.IsDouble()) {
-    return TypedValue(std::to_string(arg.ValueDouble()), ctx.memory);
-  } else {
-    return TypedValue(arg.ValueBool() ? "true" : "false", ctx.memory);
-  }
-}
-
-TypedValue Timestamp(const TypedValue *args, int64_t nargs, const FunctionContext &ctx) {
-  FType<Optional<Or<Date, LocalTime, LocalDateTime, Duration>>>("timestamp", args, nargs);
-  const auto &arg = *args;
-  if (arg.IsDate()) {
-    return TypedValue(arg.ValueDate().MicrosecondsSinceEpoch(), ctx.memory);
-  }
-  if (arg.IsLocalTime()) {
-    return TypedValue(arg.ValueLocalTime().MicrosecondsSinceEpoch(), ctx.memory);
-  }
-  if (arg.IsLocalDateTime()) {
-    return TypedValue(arg.ValueLocalDateTime().MicrosecondsSinceEpoch(), ctx.memory);
-  }
-  if (arg.IsDuration()) {
-    return TypedValue(arg.ValueDuration().microseconds, ctx.memory);
-  }
-  return TypedValue(ctx.timestamp, ctx.memory);
-}
-
-TypedValue Left(const TypedValue *args, int64_t nargs, const FunctionContext &ctx) {
-  FType<Or<Null, String>, Or<Null, NonNegativeInteger>>("left", args, nargs);
-  if (args[0].IsNull() || args[1].IsNull()) return TypedValue(ctx.memory);
-  return TypedValue(utils::Substr(args[0].ValueString(), 0, args[1].ValueInt()), ctx.memory);
-}
-
-TypedValue Right(const TypedValue *args, int64_t nargs, const FunctionContext &ctx) {
-  FType<Or<Null, String>, Or<Null, NonNegativeInteger>>("right", args, nargs);
-  if (args[0].IsNull() || args[1].IsNull()) return TypedValue(ctx.memory);
-  const auto &str = args[0].ValueString();
-  auto len = args[1].ValueInt();
-  return len <= str.size() ? TypedValue(utils::Substr(str, str.size() - len, len), ctx.memory)
-                           : TypedValue(str, ctx.memory);
-}
-
-TypedValue CallStringFunction(const TypedValue *args, int64_t nargs, utils::MemoryResource *memory, const char *name,
-                              std::function<TypedValue::TString(const TypedValue::TString &)> fun) {
-  FType<Or<Null, String>>(name, args, nargs);
-  if (args[0].IsNull()) return TypedValue(memory);
-  return TypedValue(fun(args[0].ValueString()), memory);
-}
-
-TypedValue LTrim(const TypedValue *args, int64_t nargs, const FunctionContext &ctx) {
-  return CallStringFunction(args, nargs, ctx.memory, "lTrim",
-                            [&](const auto &str) { return TypedValue::TString(utils::LTrim(str), ctx.memory); });
-}
-
-TypedValue RTrim(const TypedValue *args, int64_t nargs, const FunctionContext &ctx) {
-  return CallStringFunction(args, nargs, ctx.memory, "rTrim",
-                            [&](const auto &str) { return TypedValue::TString(utils::RTrim(str), ctx.memory); });
-}
-
-TypedValue Trim(const TypedValue *args, int64_t nargs, const FunctionContext &ctx) {
-  return CallStringFunction(args, nargs, ctx.memory, "trim",
-                            [&](const auto &str) { return TypedValue::TString(utils::Trim(str), ctx.memory); });
-}
-
-TypedValue Reverse(const TypedValue *args, int64_t nargs, const FunctionContext &ctx) {
-  return CallStringFunction(args, nargs, ctx.memory, "reverse",
-                            [&](const auto &str) { return utils::Reversed(str, ctx.memory); });
-}
-
-TypedValue ToLower(const TypedValue *args, int64_t nargs, const FunctionContext &ctx) {
-  return CallStringFunction(args, nargs, ctx.memory, "toLower", [&](const auto &str) {
-    TypedValue::TString res(ctx.memory);
-    utils::ToLowerCase(&res, str);
-    return res;
-  });
-}
-
-TypedValue ToUpper(const TypedValue *args, int64_t nargs, const FunctionContext &ctx) {
-  return CallStringFunction(args, nargs, ctx.memory, "toUpper", [&](const auto &str) {
-    TypedValue::TString res(ctx.memory);
-    utils::ToUpperCase(&res, str);
-    return res;
-  });
-}
-
-TypedValue Replace(const TypedValue *args, int64_t nargs, const FunctionContext &ctx) {
-  FType<Or<Null, String>, Or<Null, String>, Or<Null, String>>("replace", args, nargs);
-  if (args[0].IsNull() || args[1].IsNull() || args[2].IsNull()) {
-    return TypedValue(ctx.memory);
-  }
-  TypedValue::TString replaced(ctx.memory);
-  utils::Replace(&replaced, args[0].ValueString(), args[1].ValueString(), args[2].ValueString());
-  return TypedValue(std::move(replaced));
-}
-
-TypedValue Split(const TypedValue *args, int64_t nargs, const FunctionContext &ctx) {
-  FType<Or<Null, String>, Or<Null, String>>("split", args, nargs);
-  if (args[0].IsNull() || args[1].IsNull()) {
-    return TypedValue(ctx.memory);
-  }
-  TypedValue::TVector result(ctx.memory);
-  utils::Split(&result, args[0].ValueString(), args[1].ValueString());
-  return TypedValue(std::move(result));
-}
-
-TypedValue Substring(const TypedValue *args, int64_t nargs, const FunctionContext &ctx) {
-  FType<Or<Null, String>, NonNegativeInteger, Optional<NonNegativeInteger>>("substring", args, nargs);
-  if (args[0].IsNull()) return TypedValue(ctx.memory);
-  const auto &str = args[0].ValueString();
-  auto start = args[1].ValueInt();
-  if (nargs == 2) return TypedValue(utils::Substr(str, start), ctx.memory);
-  auto len = args[2].ValueInt();
-  return TypedValue(utils::Substr(str, start, len), ctx.memory);
-}
-
-TypedValue ToByteString(const TypedValue *args, int64_t nargs, const FunctionContext &ctx) {
-  FType<String>("toByteString", args, nargs);
-  const auto &str = args[0].ValueString();
-  if (str.empty()) return TypedValue("", ctx.memory);
-  if (!utils::StartsWith(str, "0x") && !utils::StartsWith(str, "0X")) {
-    throw QueryRuntimeException("'toByteString' argument must start with '0x'");
-  }
-  const auto &hex_str = utils::Substr(str, 2);
-  auto read_hex = [](const char ch) -> unsigned char {
-    if (ch >= '0' && ch <= '9') return ch - '0';
-    if (ch >= 'a' && ch <= 'f') return ch - 'a' + 10;
-    if (ch >= 'A' && ch <= 'F') return ch - 'A' + 10;
-    throw QueryRuntimeException("'toByteString' argument has an invalid character '{}'", ch);
-  };
-  utils::pmr::string bytes(ctx.memory);
-  bytes.reserve((1 + hex_str.size()) / 2);
-  size_t i = 0;
-  // Treat odd length hex string as having a leading zero.
-  if (hex_str.size() % 2) bytes.append(1, read_hex(hex_str[i++]));
-  for (; i < hex_str.size(); i += 2) {
-    unsigned char byte = read_hex(hex_str[i]) * 16U + read_hex(hex_str[i + 1]);
-    // MemcpyCast in case we are converting to a signed value, so as to avoid
-    // undefined behaviour.
-    bytes.append(1, utils::MemcpyCast<decltype(bytes)::value_type>(byte));
-  }
-  return TypedValue(std::move(bytes));
-}
-
-TypedValue FromByteString(const TypedValue *args, int64_t nargs, const FunctionContext &ctx) {
-  FType<String, Optional<PositiveInteger>>("fromByteString", args, nargs);
-  const auto &bytes = args[0].ValueString();
-  if (bytes.empty()) return TypedValue("", ctx.memory);
-  size_t min_length = bytes.size();
-  if (nargs == 2) min_length = std::max(min_length, static_cast<size_t>(args[1].ValueInt()));
-  utils::pmr::string str(ctx.memory);
-  str.reserve(min_length * 2 + 2);
-  str.append("0x");
-  for (size_t pad = 0; pad < min_length - bytes.size(); ++pad) str.append(2, '0');
-  // Convert the bytes to a character string in hex representation.
-  // Unfortunately, we don't know whether the default `char` is signed or
-  // unsigned, so we have to work around any potential undefined behaviour when
-  // conversions between the 2 occur. That's why this function is more
-  // complicated than it should be.
-  auto to_hex = [](const unsigned char val) -> char {
-    unsigned char ch = val < 10U ? static_cast<unsigned char>('0') + val : static_cast<unsigned char>('a') + val - 10U;
-    return utils::MemcpyCast<char>(ch);
-  };
-  for (unsigned char byte : bytes) {
-    str.append(1, to_hex(byte / 16U));
-    str.append(1, to_hex(byte % 16U));
-  }
-  return TypedValue(std::move(str));
-}
-
-template <typename T>
-concept IsNumberOrInteger = utils::SameAsAnyOf<T, Number, Integer>;
-
-template <IsNumberOrInteger ArgType>
-void MapNumericParameters(auto &parameter_mappings, const auto &input_parameters) {
-  for (const auto &[key, value] : input_parameters) {
-    if (auto it = parameter_mappings.find(key); it != parameter_mappings.end()) {
-      if (value.IsInt()) {
-        *it->second = value.ValueInt();
-      } else if (std::is_same_v<ArgType, Number> && value.IsDouble()) {
-        *it->second = value.ValueDouble();
-      } else {
-        std::string_view error = std::is_same_v<ArgType, Integer> ? "an integer." : "a numeric value.";
-        throw QueryRuntimeException("Invalid value for key '{}'. Expected {}", key, error);
-      }
-    } else {
-      throw QueryRuntimeException("Unknown key '{}'.", key);
-    }
-  }
-}
-
-TypedValue Date(const TypedValue *args, int64_t nargs, const FunctionContext &ctx) {
-  FType<Optional<Or<String, Map>>>("date", args, nargs);
-  if (nargs == 0) {
-    return TypedValue(utils::LocalDateTime(ctx.timestamp).date, ctx.memory);
-  }
-
-  if (args[0].IsString()) {
-    const auto &[date_parameters, is_extended] = utils::ParseDateParameters(args[0].ValueString());
-    return TypedValue(utils::Date(date_parameters), ctx.memory);
-  }
-
-  utils::DateParameters date_parameters;
-
-  using namespace std::literals;
-  std::unordered_map parameter_mappings = {std::pair{"year"sv, &date_parameters.year},
-                                           std::pair{"month"sv, &date_parameters.month},
-                                           std::pair{"day"sv, &date_parameters.day}};
-
-  MapNumericParameters<Integer>(parameter_mappings, args[0].ValueMap());
-  return TypedValue(utils::Date(date_parameters), ctx.memory);
-}
-
-TypedValue LocalTime(const TypedValue *args, int64_t nargs, const FunctionContext &ctx) {
-  FType<Optional<Or<String, Map>>>("localtime", args, nargs);
-
-  if (nargs == 0) {
-    return TypedValue(utils::LocalDateTime(ctx.timestamp).local_time, ctx.memory);
-  }
-
-  if (args[0].IsString()) {
-    const auto &[local_time_parameters, is_extended] = utils::ParseLocalTimeParameters(args[0].ValueString());
-    return TypedValue(utils::LocalTime(local_time_parameters), ctx.memory);
-  }
-
-  utils::LocalTimeParameters local_time_parameters;
-
-  using namespace std::literals;
-  std::unordered_map parameter_mappings{
-      std::pair{"hour"sv, &local_time_parameters.hour},
-      std::pair{"minute"sv, &local_time_parameters.minute},
-      std::pair{"second"sv, &local_time_parameters.second},
-      std::pair{"millisecond"sv, &local_time_parameters.millisecond},
-      std::pair{"microsecond"sv, &local_time_parameters.microsecond},
-  };
-
-  MapNumericParameters<Integer>(parameter_mappings, args[0].ValueMap());
-  return TypedValue(utils::LocalTime(local_time_parameters), ctx.memory);
-}
-
-TypedValue LocalDateTime(const TypedValue *args, int64_t nargs, const FunctionContext &ctx) {
-  FType<Optional<Or<String, Map>>>("localdatetime", args, nargs);
-
-  if (nargs == 0) {
-    return TypedValue(utils::LocalDateTime(ctx.timestamp), ctx.memory);
-  }
-
-  if (args[0].IsString()) {
-    const auto &[date_parameters, local_time_parameters] = ParseLocalDateTimeParameters(args[0].ValueString());
-    return TypedValue(utils::LocalDateTime(date_parameters, local_time_parameters), ctx.memory);
-  }
-
-  utils::DateParameters date_parameters;
-  utils::LocalTimeParameters local_time_parameters;
-  using namespace std::literals;
-  std::unordered_map parameter_mappings{
-      std::pair{"year"sv, &date_parameters.year},
-      std::pair{"month"sv, &date_parameters.month},
-      std::pair{"day"sv, &date_parameters.day},
-      std::pair{"hour"sv, &local_time_parameters.hour},
-      std::pair{"minute"sv, &local_time_parameters.minute},
-      std::pair{"second"sv, &local_time_parameters.second},
-      std::pair{"millisecond"sv, &local_time_parameters.millisecond},
-      std::pair{"microsecond"sv, &local_time_parameters.microsecond},
-  };
-
-  MapNumericParameters<Integer>(parameter_mappings, args[0].ValueMap());
-  return TypedValue(utils::LocalDateTime(date_parameters, local_time_parameters), ctx.memory);
-}
-
-TypedValue Duration(const TypedValue *args, int64_t nargs, const FunctionContext &ctx) {
-  FType<Or<String, Map>>("duration", args, nargs);
-
-  if (args[0].IsString()) {
-    return TypedValue(utils::Duration(ParseDurationParameters(args[0].ValueString())), ctx.memory);
-  }
-
-  utils::DurationParameters duration_parameters;
-  using namespace std::literals;
-  std::unordered_map parameter_mappings{std::pair{"day"sv, &duration_parameters.day},
-                                        std::pair{"hour"sv, &duration_parameters.hour},
-                                        std::pair{"minute"sv, &duration_parameters.minute},
-                                        std::pair{"second"sv, &duration_parameters.second},
-                                        std::pair{"millisecond"sv, &duration_parameters.millisecond},
-                                        std::pair{"microsecond"sv, &duration_parameters.microsecond}};
-  MapNumericParameters<Number>(parameter_mappings, args[0].ValueMap());
-  return TypedValue(utils::Duration(duration_parameters), ctx.memory);
-}
-
-}  // namespace
-
-std::function<TypedValue(const TypedValue *, int64_t, const FunctionContext &ctx)> NameToFunction(
-    const std::string &function_name) {
-  // Scalar functions
-  if (function_name == "ENDNODE") return EndNode;
-  if (function_name == "HEAD") return Head;
-  if (function_name == kId) return Id;
-  if (function_name == "LAST") return Last;
-  if (function_name == "PROPERTIES") return Properties;
-  if (function_name == "SIZE") return Size;
-  if (function_name == "STARTNODE") return StartNode;
-  if (function_name == "TIMESTAMP") return Timestamp;
-  if (function_name == "TOBOOLEAN") return ToBoolean;
-  if (function_name == "TOFLOAT") return ToFloat;
-  if (function_name == "TOINTEGER") return ToInteger;
-  if (function_name == "TYPE") return Type;
-  if (function_name == "VALUETYPE") return ValueType;
-
-  // List functions
-  if (function_name == "RANGE") return Range;
-  if (function_name == "TAIL") return Tail;
-  if (function_name == "UNIFORMSAMPLE") return UniformSample;
-
-  // Mathematical functions - numeric
-  if (function_name == "ABS") return Abs;
-  if (function_name == "CEIL") return Ceil;
-  if (function_name == "FLOOR") return Floor;
-  if (function_name == "RAND") return Rand;
-  if (function_name == "ROUND") return Round;
-  if (function_name == "SIGN") return Sign;
-
-  // Mathematical functions - logarithmic
-  if (function_name == "E") return E;
-  if (function_name == "EXP") return Exp;
-  if (function_name == "LOG") return Log;
-  if (function_name == "LOG10") return Log10;
-  if (function_name == "SQRT") return Sqrt;
-
-  // Mathematical functions - trigonometric
-  if (function_name == "ACOS") return Acos;
-  if (function_name == "ASIN") return Asin;
-  if (function_name == "ATAN") return Atan;
-  if (function_name == "ATAN2") return Atan2;
-  if (function_name == "COS") return Cos;
-  if (function_name == "PI") return Pi;
-  if (function_name == "SIN") return Sin;
-  if (function_name == "TAN") return Tan;
-
-  // String functions
-  if (function_name == kContains) return Contains;
-  if (function_name == kEndsWith) return EndsWith;
-  if (function_name == "LEFT") return Left;
-  if (function_name == "LTRIM") return LTrim;
-  if (function_name == "REPLACE") return Replace;
-  if (function_name == "REVERSE") return Reverse;
-  if (function_name == "RIGHT") return Right;
-  if (function_name == "RTRIM") return RTrim;
-  if (function_name == "SPLIT") return Split;
-  if (function_name == kStartsWith) return StartsWith;
-  if (function_name == "SUBSTRING") return Substring;
-  if (function_name == "TOLOWER") return ToLower;
-  // TODO(kostasrim) fix function lookup here
-  if (function_name == "TOSTRING") return ToString;
-  if (function_name == "TOUPPER") return ToUpper;
-  if (function_name == "TRIM") return Trim;
-
-  // Memgraph specific functions
-  if (function_name == "ASSERT") return Assert;
-  if (function_name == "COUNTER") return Counter;
-  if (function_name == "TOBYTESTRING") return ToByteString;
-  if (function_name == "FROMBYTESTRING") return FromByteString;
-
-  // Functions for temporal types
-  if (function_name == "DATE") return Date;
-  if (function_name == "LOCALTIME") return LocalTime;
-  if (function_name == "LOCALDATETIME") return LocalDateTime;
-  if (function_name == "DURATION") return Duration;
-
-  return nullptr;
-}
-
-}  // namespace memgraph::query::v2
diff --git a/src/query/v2/interpret/awesome_memgraph_functions.hpp b/src/query/v2/interpret/awesome_memgraph_functions.hpp
deleted file mode 100644
index 134f05d7d..000000000
--- a/src/query/v2/interpret/awesome_memgraph_functions.hpp
+++ /dev/null
@@ -1,55 +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 <functional>
-#include <string>
-#include <unordered_map>
-
-#include "query/v2/bindings/typed_value.hpp"
-#include "query/v2/db_accessor.hpp"
-#include "storage/v3/view.hpp"
-#include "utils/memory.hpp"
-
-namespace memgraph::msgs {
-class ShardRequestManagerInterface;
-} // namespace memgraph::msgs
-
-namespace memgraph::query::v2 {
-
-namespace {
-const char kStartsWith[] = "STARTSWITH";
-const char kEndsWith[] = "ENDSWITH";
-const char kContains[] = "CONTAINS";
-const char kId[] = "ID";
-}  // namespace
-
-struct FunctionContext {
-  // TODO(kostasrim) consider optional here. ShardRequestManager does not exist on the storage.
-  // DbAccessor *db_accessor;
-  msgs::ShardRequestManagerInterface *manager;
-  utils::MemoryResource *memory;
-  int64_t timestamp;
-  std::unordered_map<std::string, int64_t> *counters;
-  storage::v3::View view;
-};
-
-/// Return the function implementation with the given name.
-///
-/// Note, returned function signature uses C-style access to an array to allow
-/// having an array stored anywhere the caller likes, as long as it is
-/// contiguous in memory. Since most functions don't take many arguments, it's
-/// convenient to have them stored in the calling stack frame.
-std::function<TypedValue(const TypedValue *arguments, int64_t num_arguments, const FunctionContext &context)>
-NameToFunction(const std::string &function_name);
-
-}  // namespace memgraph::query::v2
diff --git a/src/query/v2/plan/preprocess.cpp b/src/query/v2/plan/preprocess.cpp
index 1037f3fe6..765066079 100644
--- a/src/query/v2/plan/preprocess.cpp
+++ b/src/query/v2/plan/preprocess.cpp
@@ -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 *id_fun = utils::Downcast<Function>(maybe_id_fun);
     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;
     auto *ident = utils::Downcast<Identifier>(id_fun->arguments_.front());
     if (!ident) return false;
diff --git a/src/storage/v3/CMakeLists.txt b/src/storage/v3/CMakeLists.txt
index 0f359c702..dccbe2356 100644
--- a/src/storage/v3/CMakeLists.txt
+++ b/src/storage/v3/CMakeLists.txt
@@ -33,4 +33,4 @@ target_link_libraries(mg-storage-v3 Threads::Threads mg-utils gflags)
 target_include_directories(mg-storage-v3 PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/bindings)
 
 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)
diff --git a/src/storage/v3/bindings/ast/ast.lcp b/src/storage/v3/bindings/ast/ast.lcp
index 3be1830ae..8a3484a58 100644
--- a/src/storage/v3/bindings/ast/ast.lcp
+++ b/src/storage/v3/bindings/ast/ast.lcp
@@ -24,6 +24,8 @@
 #include "storage/v3/conversions.hpp"
 #include "storage/v3/path.hpp"
 #include "utils/typeinfo.hpp"
+#include "utils/exceptions.hpp"
+#include "functions/awesome_memgraph_functions.hpp"
 
 cpp<#
 
@@ -178,14 +180,6 @@ cpp<#
   (:serialize (:slk :load-args '((storage "storage::v3::AstStorage *")))))
 
 #>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) {
   return a.ix == b.ix && a.name == b.name;
 }
@@ -845,16 +839,24 @@ cpp<#
               :slk-load (slk-load-ast-vector "Expression"))
    (function-name "std::string" :scope :public)
    (function "std::function<TypedValue(const TypedValue *, int64_t,
-                                       const FunctionContext &)>"
+                                       const functions::FunctionContext<memgraph::storage::v3::DbAccessor> &)>"
              :scope :public
              :dont-save t
              :clone :copy
              :slk-load (lambda (member)
                         #>cpp
+                        self->${member} = functions::NameToFunction<memgraph::storage::v3::TypedValue,
+                                            functions::FunctionContext<memgraph::storage::v3::DbAccessor>,
+                                            functions::StorageEngineTag, Conv>(self->function_name_);
                         cpp<#)))
   (:public
     #>cpp
     Function() = default;
+    using Conv = decltype(PropertyToTypedValueFunctor<TypedValue>);
+    class SemanticException : public memgraph::utils::BasicException {
+      using utils::BasicException::BasicException;
+    };
+
 
     DEFVISITABLE(ExpressionVisitor<TypedValue>);
     DEFVISITABLE(ExpressionVisitor<void>);
@@ -872,7 +874,13 @@ cpp<#
     Function(const std::string &function_name,
              const std::vector<Expression *> &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<#)
   (:private
diff --git a/src/storage/v3/bindings/db_accessor.hpp b/src/storage/v3/bindings/db_accessor.hpp
index 186a1b5c5..2a4f91fe0 100644
--- a/src/storage/v3/bindings/db_accessor.hpp
+++ b/src/storage/v3/bindings/db_accessor.hpp
@@ -88,7 +88,7 @@ class DbAccessor final {
   }
 
   storage::v3::Result<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()) {
       return res.GetError();
     }
diff --git a/src/storage/v3/conversions.hpp b/src/storage/v3/conversions.hpp
index 3ff804b6a..dfb190ac1 100644
--- a/src/storage/v3/conversions.hpp
+++ b/src/storage/v3/conversions.hpp
@@ -69,6 +69,10 @@ TTypedValue PropertyToTypedValue(const PropertyValue &value) {
   LOG_FATAL("Unsupported type");
 }
 
+template <typename TypedValueT>
+inline const auto PropertyToTypedValueFunctor =
+    [](const PropertyValue &value) { return PropertyToTypedValue<TypedValueT>(value); };
+
 template <typename TTypedValue>
 TTypedValue PropertyToTypedValue(const PropertyValue &value, utils::MemoryResource *mem) {
   switch (value.type()) {
diff --git a/src/storage/v3/edge_accessor.cpp b/src/storage/v3/edge_accessor.cpp
index ed4abd1fe..d60cdeebc 100644
--- a/src/storage/v3/edge_accessor.cpp
+++ b/src/storage/v3/edge_accessor.cpp
@@ -50,9 +50,9 @@ bool EdgeAccessor::IsVisible(const View view) const {
   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) {
   utils::MemoryTracker::OutOfMemoryExceptionEnabler oom_exception;
@@ -179,4 +179,7 @@ Result<std::map<PropertyId, PropertyValue>> EdgeAccessor::Properties(View view)
   return std::move(properties);
 }
 
+// NOLINTNEXTLINE(readability-convert-member-functions-to-static)
+size_t EdgeAccessor::CypherId() const { return 10; }
+
 }  // namespace memgraph::storage::v3
diff --git a/src/storage/v3/edge_accessor.hpp b/src/storage/v3/edge_accessor.hpp
index 546a09200..0c9235b14 100644
--- a/src/storage/v3/edge_accessor.hpp
+++ b/src/storage/v3/edge_accessor.hpp
@@ -48,9 +48,9 @@ class EdgeAccessor final {
   /// @return true if the object is visible from the current transaction
   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_; }
 
@@ -84,6 +84,9 @@ class EdgeAccessor final {
   }
   bool operator!=(const EdgeAccessor &other) const noexcept { return !(*this == other); }
 
+  // Dummy function
+  size_t CypherId() const;
+
  private:
   EdgeRef edge_;
   EdgeTypeId edge_type_;
diff --git a/src/storage/v3/expr.cpp b/src/storage/v3/expr.cpp
index 1d6739433..074e9f15f 100644
--- a/src/storage/v3/expr.cpp
+++ b/src/storage/v3/expr.cpp
@@ -52,13 +52,12 @@ msgs::Value ConstructValueEdge(const EdgeAccessor &acc, View view) {
   msgs::EdgeType type = {.id = acc.EdgeType()};
   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 =
-      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::VertexId dst_vertex =
-      std::make_pair(dst_prim_label, conversions::ConvertValueVector(acc.ToVertex().primary_key));
+  msgs::Label dst_prim_label = {.id = acc.To().primary_label};
+  msgs::VertexId dst_vertex = std::make_pair(dst_prim_label, conversions::ConvertValueVector(acc.To().primary_key));
 
   auto properties = acc.Properties(view);
 
diff --git a/src/storage/v3/shard.cpp b/src/storage/v3/shard.cpp
index 0e596172d..49c692134 100644
--- a/src/storage/v3/shard.cpp
+++ b/src/storage/v3/shard.cpp
@@ -441,7 +441,7 @@ Result<std::optional<std::pair<VertexAccessor, std::vector<EdgeAccessor>>>> Shar
   for (const auto &item : in_edges) {
     auto [edge_type, from_vertex, edge] = item;
     EdgeAccessor e(edge, edge_type, from_vertex, vertex_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()) {
       MG_ASSERT(ret.GetError() == Error::SERIALIZATION_ERROR, "Invalid database state!");
       return ret.GetError();
@@ -454,7 +454,7 @@ Result<std::optional<std::pair<VertexAccessor, std::vector<EdgeAccessor>>>> Shar
   for (const auto &item : out_edges) {
     auto [edge_type, to_vertex, edge] = item;
     EdgeAccessor e(edge, edge_type, vertex_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()) {
       MG_ASSERT(ret.GetError() == Error::SERIALIZATION_ERROR, "Invalid database state!");
       return ret.GetError();
diff --git a/src/storage/v3/shard_rsm.cpp b/src/storage/v3/shard_rsm.cpp
index f288e5e27..781ab67ed 100644
--- a/src/storage/v3/shard_rsm.cpp
+++ b/src/storage/v3/shard_rsm.cpp
@@ -376,7 +376,7 @@ EdgeUniqunessFunction InitializeEdgeUniqunessFunction(bool only_unique_neighbor_
         case msgs::EdgeDirection::OUT: {
           is_edge_unique = [](std::set<const storage::v3::VertexId *, VertexIdCmpr> &other_vertex_set,
                               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;
           };
           break;
@@ -384,7 +384,7 @@ EdgeUniqunessFunction InitializeEdgeUniqunessFunction(bool only_unique_neighbor_
         case msgs::EdgeDirection::IN: {
           is_edge_unique = [](std::set<const storage::v3::VertexId *, VertexIdCmpr> &other_vertex_set,
                               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;
           };
           break;
@@ -429,8 +429,8 @@ EdgeFiller InitializeEdgeFillerFunction(const msgs::ExpandOneRequest &req) {
         value_properties.insert(std::make_pair(prop_key, FromPropertyValueToValue(std::move(prop_val))));
       }
       using EdgeWithAllProperties = msgs::ExpandOneResultRow::EdgeWithAllProperties;
-      EdgeWithAllProperties edges{ToMsgsVertexId(edge.FromVertex()), msgs::EdgeType{edge.EdgeType()},
-                                  edge.Gid().AsUint(), std::move(value_properties)};
+      EdgeWithAllProperties edges{ToMsgsVertexId(edge.From()), msgs::EdgeType{edge.EdgeType()}, edge.Gid().AsUint(),
+                                  std::move(value_properties)};
       if (is_in_edge) {
         result_row.in_edges_with_all_properties.push_back(std::move(edges));
       } else {
@@ -454,7 +454,7 @@ EdgeFiller InitializeEdgeFillerFunction(const msgs::ExpandOneRequest &req) {
         value_properties.emplace_back(FromPropertyValueToValue(std::move(property_result.GetValue())));
       }
       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)};
       if (is_in_edge) {
         result_row.in_edges_with_specific_properties.push_back(std::move(edges));
diff --git a/src/storage/v3/vertex_accessor.cpp b/src/storage/v3/vertex_accessor.cpp
index 543caa88a..10c39dba6 100644
--- a/src/storage/v3/vertex_accessor.cpp
+++ b/src/storage/v3/vertex_accessor.cpp
@@ -733,4 +733,7 @@ Result<size_t> VertexAccessor::OutDegree(View view) const {
   return degree;
 }
 
+// NOLINTNEXTLINE(readability-convert-member-functions-to-static)
+size_t VertexAccessor::CypherId() const { return 10; }
+
 }  // namespace memgraph::storage::v3
diff --git a/src/storage/v3/vertex_accessor.hpp b/src/storage/v3/vertex_accessor.hpp
index 682a04e39..d708f723e 100644
--- a/src/storage/v3/vertex_accessor.hpp
+++ b/src/storage/v3/vertex_accessor.hpp
@@ -118,6 +118,9 @@ class VertexAccessor final {
   }
   bool operator!=(const VertexAccessor &other) const noexcept { return !(*this == other); }
 
+  // Dummy function
+  size_t CypherId() const;
+
  private:
   /// Add a label and return `true` if insertion took place.
   /// `false` is returned if the label already existed.
diff --git a/tests/unit/storage_v3_edge.cpp b/tests/unit/storage_v3_edge.cpp
index 21c4214ce..5c0759e98 100644
--- a/tests/unit/storage_v3_edge.cpp
+++ b/tests/unit/storage_v3_edge.cpp
@@ -98,8 +98,8 @@ TEST_P(StorageEdgeTest, EdgeCreateFromSmallerCommit) {
     auto edge = res.GetValue();
     ASSERT_EQ(edge.EdgeType(), et);
     ASSERT_EQ(edge.Gid(), edge_id);
-    ASSERT_EQ(edge.FromVertex(), from_id);
-    ASSERT_EQ(edge.ToVertex(), to_id);
+    ASSERT_EQ(edge.From(), from_id);
+    ASSERT_EQ(edge.To(), to_id);
 
     // Check edges without filters
     ASSERT_EQ(vertex_from->InEdges(View::OLD)->size(), 0);
@@ -117,8 +117,8 @@ TEST_P(StorageEdgeTest, EdgeCreateFromSmallerCommit) {
       auto e = edges[0];
       ASSERT_EQ(e.EdgeType(), et);
       ASSERT_EQ(e.Gid(), edge_id);
-      ASSERT_EQ(e.FromVertex(), from_id);
-      ASSERT_EQ(e.ToVertex(), to_id);
+      ASSERT_EQ(e.From(), from_id);
+      ASSERT_EQ(e.To(), to_id);
     }
     ASSERT_EQ(vertex_to->InEdges(View::OLD)->size(), 0);
     ASSERT_EQ(*vertex_to->InDegree(View::OLD), 0);
@@ -131,8 +131,8 @@ TEST_P(StorageEdgeTest, EdgeCreateFromSmallerCommit) {
       auto e = edges[0];
       ASSERT_EQ(e.EdgeType(), et);
       ASSERT_EQ(e.Gid(), edge_id);
-      ASSERT_EQ(e.FromVertex(), from_id);
-      ASSERT_EQ(e.ToVertex(), to_id);
+      ASSERT_EQ(e.From(), from_id);
+      ASSERT_EQ(e.To(), to_id);
     }
     ASSERT_EQ(vertex_to->OutEdges(View::OLD)->size(), 0);
     ASSERT_EQ(*vertex_to->OutDegree(View::OLD), 0);
@@ -188,8 +188,8 @@ TEST_P(StorageEdgeTest, EdgeCreateFromSmallerCommit) {
       auto e = edges[0];
       ASSERT_EQ(e.EdgeType(), et);
       ASSERT_EQ(e.Gid(), edge_id);
-      ASSERT_EQ(e.FromVertex(), from_id);
-      ASSERT_EQ(e.ToVertex(), to_id);
+      ASSERT_EQ(e.From(), from_id);
+      ASSERT_EQ(e.To(), to_id);
     }
     {
       auto ret = vertex_from->OutEdges(View::NEW);
@@ -200,8 +200,8 @@ TEST_P(StorageEdgeTest, EdgeCreateFromSmallerCommit) {
       auto e = edges[0];
       ASSERT_EQ(e.EdgeType(), et);
       ASSERT_EQ(e.Gid(), edge_id);
-      ASSERT_EQ(e.FromVertex(), from_id);
-      ASSERT_EQ(e.ToVertex(), to_id);
+      ASSERT_EQ(e.From(), from_id);
+      ASSERT_EQ(e.To(), to_id);
     }
     {
       auto ret = vertex_to->InEdges(View::OLD);
@@ -212,8 +212,8 @@ TEST_P(StorageEdgeTest, EdgeCreateFromSmallerCommit) {
       auto e = edges[0];
       ASSERT_EQ(e.EdgeType(), et);
       ASSERT_EQ(e.Gid(), edge_id);
-      ASSERT_EQ(e.FromVertex(), from_id);
-      ASSERT_EQ(e.ToVertex(), to_id);
+      ASSERT_EQ(e.From(), from_id);
+      ASSERT_EQ(e.To(), to_id);
     }
     {
       auto ret = vertex_to->InEdges(View::NEW);
@@ -224,8 +224,8 @@ TEST_P(StorageEdgeTest, EdgeCreateFromSmallerCommit) {
       auto e = edges[0];
       ASSERT_EQ(e.EdgeType(), et);
       ASSERT_EQ(e.Gid(), edge_id);
-      ASSERT_EQ(e.FromVertex(), from_id);
-      ASSERT_EQ(e.ToVertex(), to_id);
+      ASSERT_EQ(e.From(), from_id);
+      ASSERT_EQ(e.To(), to_id);
     }
     ASSERT_EQ(vertex_to->OutEdges(View::OLD)->size(), 0);
     ASSERT_EQ(*vertex_to->OutDegree(View::OLD), 0);
@@ -309,8 +309,8 @@ TEST_P(StorageEdgeTest, EdgeCreateFromSmallerCommit) {
 //     ASSERT_TRUE(res.HasValue());
 //     auto edge = res.GetValue();
 //     ASSERT_EQ(edge.EdgeType(), et);
-//     ASSERT_EQ(edge.FromVertex(), *vertex_from);
-//     ASSERT_EQ(edge.ToVertex(), *vertex_to);
+//     ASSERT_EQ(edge.From(), *vertex_from);
+//     ASSERT_EQ(edge.To(), *vertex_to);
 
 //     // Check edges without filters
 //     ASSERT_EQ(vertex_from->InEdges(View::OLD)->size(), 0);
@@ -327,8 +327,8 @@ TEST_P(StorageEdgeTest, EdgeCreateFromSmallerCommit) {
 //       ASSERT_EQ(*vertex_from->OutDegree(View::NEW), 1);
 //       auto e = edges[0];
 //       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.FromVertex(), *vertex_from);
-//       ASSERT_EQ(e.ToVertex(), *vertex_to);
+//       ASSERT_EQ(e.From(), *vertex_from);
+//       ASSERT_EQ(e.To(), *vertex_to);
 //     }
 //     ASSERT_EQ(vertex_to->InEdges(View::OLD)->size(), 0);
 //     ASSERT_EQ(*vertex_to->InDegree(View::OLD), 0);
@@ -340,8 +340,8 @@ TEST_P(StorageEdgeTest, EdgeCreateFromSmallerCommit) {
 //       ASSERT_EQ(*vertex_to->InDegree(View::NEW), 1);
 //       auto e = edges[0];
 //       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.FromVertex(), *vertex_from);
-//       ASSERT_EQ(e.ToVertex(), *vertex_to);
+//       ASSERT_EQ(e.From(), *vertex_from);
+//       ASSERT_EQ(e.To(), *vertex_to);
 //     }
 //     ASSERT_EQ(vertex_to->OutEdges(View::OLD)->size(), 0);
 //     ASSERT_EQ(*vertex_to->OutDegree(View::OLD), 0);
@@ -386,8 +386,8 @@ TEST_P(StorageEdgeTest, EdgeCreateFromSmallerCommit) {
 //       ASSERT_EQ(*vertex_from->OutDegree(View::OLD), 1);
 //       auto e = edges[0];
 //       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.FromVertex(), *vertex_from);
-//       ASSERT_EQ(e.ToVertex(), *vertex_to);
+//       ASSERT_EQ(e.From(), *vertex_from);
+//       ASSERT_EQ(e.To(), *vertex_to);
 //     }
 //     {
 //       auto ret = vertex_from->OutEdges(View::NEW);
@@ -397,8 +397,8 @@ TEST_P(StorageEdgeTest, EdgeCreateFromSmallerCommit) {
 //       ASSERT_EQ(*vertex_from->OutDegree(View::NEW), 1);
 //       auto e = edges[0];
 //       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.FromVertex(), *vertex_from);
-//       ASSERT_EQ(e.ToVertex(), *vertex_to);
+//       ASSERT_EQ(e.From(), *vertex_from);
+//       ASSERT_EQ(e.To(), *vertex_to);
 //     }
 //     {
 //       auto ret = vertex_to->InEdges(View::OLD);
@@ -408,8 +408,8 @@ TEST_P(StorageEdgeTest, EdgeCreateFromSmallerCommit) {
 //       ASSERT_EQ(*vertex_to->InDegree(View::OLD), 1);
 //       auto e = edges[0];
 //       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.FromVertex(), *vertex_from);
-//       ASSERT_EQ(e.ToVertex(), *vertex_to);
+//       ASSERT_EQ(e.From(), *vertex_from);
+//       ASSERT_EQ(e.To(), *vertex_to);
 //     }
 //     {
 //       auto ret = vertex_to->InEdges(View::NEW);
@@ -419,8 +419,8 @@ TEST_P(StorageEdgeTest, EdgeCreateFromSmallerCommit) {
 //       ASSERT_EQ(*vertex_to->InDegree(View::NEW), 1);
 //       auto e = edges[0];
 //       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.FromVertex(), *vertex_from);
-//       ASSERT_EQ(e.ToVertex(), *vertex_to);
+//       ASSERT_EQ(e.From(), *vertex_from);
+//       ASSERT_EQ(e.To(), *vertex_to);
 //     }
 //     ASSERT_EQ(vertex_to->OutEdges(View::OLD)->size(), 0);
 //     ASSERT_EQ(*vertex_to->OutDegree(View::OLD), 0);
@@ -476,8 +476,8 @@ TEST_P(StorageEdgeTest, EdgeCreateFromSmallerCommit) {
 //     ASSERT_TRUE(res.HasValue());
 //     auto edge = res.GetValue();
 //     ASSERT_EQ(edge.EdgeType(), et);
-//     ASSERT_EQ(edge.FromVertex(), *vertex);
-//     ASSERT_EQ(edge.ToVertex(), *vertex);
+//     ASSERT_EQ(edge.From(), *vertex);
+//     ASSERT_EQ(edge.To(), *vertex);
 
 //     // Check edges without filters
 //     ASSERT_EQ(vertex->InEdges(View::OLD)->size(), 0);
@@ -490,8 +490,8 @@ TEST_P(StorageEdgeTest, EdgeCreateFromSmallerCommit) {
 //       ASSERT_EQ(*vertex->InDegree(View::NEW), 1);
 //       auto e = edges[0];
 //       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.FromVertex(), *vertex);
-//       ASSERT_EQ(e.ToVertex(), *vertex);
+//       ASSERT_EQ(e.From(), *vertex);
+//       ASSERT_EQ(e.To(), *vertex);
 //     }
 //     ASSERT_EQ(vertex->OutEdges(View::OLD)->size(), 0);
 //     ASSERT_EQ(*vertex->OutDegree(View::OLD), 0);
@@ -503,8 +503,8 @@ TEST_P(StorageEdgeTest, EdgeCreateFromSmallerCommit) {
 //       ASSERT_EQ(*vertex->OutDegree(View::NEW), 1);
 //       auto e = edges[0];
 //       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.FromVertex(), *vertex);
-//       ASSERT_EQ(e.ToVertex(), *vertex);
+//       ASSERT_EQ(e.From(), *vertex);
+//       ASSERT_EQ(e.To(), *vertex);
 //     }
 
 //     auto other_et = acc.NameToEdgeType("other");
@@ -539,8 +539,8 @@ TEST_P(StorageEdgeTest, EdgeCreateFromSmallerCommit) {
 //       ASSERT_EQ(*vertex->InDegree(View::OLD), 1);
 //       auto e = edges[0];
 //       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.FromVertex(), *vertex);
-//       ASSERT_EQ(e.ToVertex(), *vertex);
+//       ASSERT_EQ(e.From(), *vertex);
+//       ASSERT_EQ(e.To(), *vertex);
 //     }
 //     {
 //       auto ret = vertex->InEdges(View::NEW);
@@ -550,8 +550,8 @@ TEST_P(StorageEdgeTest, EdgeCreateFromSmallerCommit) {
 //       ASSERT_EQ(*vertex->InDegree(View::NEW), 1);
 //       auto e = edges[0];
 //       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.FromVertex(), *vertex);
-//       ASSERT_EQ(e.ToVertex(), *vertex);
+//       ASSERT_EQ(e.From(), *vertex);
+//       ASSERT_EQ(e.To(), *vertex);
 //     }
 //     {
 //       auto ret = vertex->OutEdges(View::OLD);
@@ -561,8 +561,8 @@ TEST_P(StorageEdgeTest, EdgeCreateFromSmallerCommit) {
 //       ASSERT_EQ(*vertex->OutDegree(View::OLD), 1);
 //       auto e = edges[0];
 //       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.FromVertex(), *vertex);
-//       ASSERT_EQ(e.ToVertex(), *vertex);
+//       ASSERT_EQ(e.From(), *vertex);
+//       ASSERT_EQ(e.To(), *vertex);
 //     }
 //     {
 //       auto ret = vertex->OutEdges(View::NEW);
@@ -572,8 +572,8 @@ TEST_P(StorageEdgeTest, EdgeCreateFromSmallerCommit) {
 //       ASSERT_EQ(*vertex->OutDegree(View::NEW), 1);
 //       auto e = edges[0];
 //       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.FromVertex(), *vertex);
-//       ASSERT_EQ(e.ToVertex(), *vertex);
+//       ASSERT_EQ(e.From(), *vertex);
+//       ASSERT_EQ(e.To(), *vertex);
 //     }
 
 //     auto other_et = acc.NameToEdgeType("other");
@@ -626,8 +626,8 @@ TEST_P(StorageEdgeTest, EdgeCreateFromSmallerCommit) {
 //     ASSERT_TRUE(res.HasValue());
 //     auto edge = res.GetValue();
 //     ASSERT_EQ(edge.EdgeType(), et);
-//     ASSERT_EQ(edge.FromVertex(), *vertex_from);
-//     ASSERT_EQ(edge.ToVertex(), *vertex_to);
+//     ASSERT_EQ(edge.From(), *vertex_from);
+//     ASSERT_EQ(edge.To(), *vertex_to);
 
 //     // Check edges without filters
 //     ASSERT_EQ(vertex_from->InEdges(View::OLD)->size(), 0);
@@ -644,8 +644,8 @@ TEST_P(StorageEdgeTest, EdgeCreateFromSmallerCommit) {
 //       ASSERT_EQ(*vertex_from->OutDegree(View::NEW), 1);
 //       auto e = edges[0];
 //       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.FromVertex(), *vertex_from);
-//       ASSERT_EQ(e.ToVertex(), *vertex_to);
+//       ASSERT_EQ(e.From(), *vertex_from);
+//       ASSERT_EQ(e.To(), *vertex_to);
 //     }
 //     ASSERT_EQ(vertex_to->InEdges(View::OLD)->size(), 0);
 //     ASSERT_EQ(*vertex_to->InDegree(View::OLD), 0);
@@ -657,8 +657,8 @@ TEST_P(StorageEdgeTest, EdgeCreateFromSmallerCommit) {
 //       ASSERT_EQ(*vertex_to->InDegree(View::NEW), 1);
 //       auto e = edges[0];
 //       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.FromVertex(), *vertex_from);
-//       ASSERT_EQ(e.ToVertex(), *vertex_to);
+//       ASSERT_EQ(e.From(), *vertex_from);
+//       ASSERT_EQ(e.To(), *vertex_to);
 //     }
 //     ASSERT_EQ(vertex_to->OutEdges(View::OLD)->size(), 0);
 //     ASSERT_EQ(*vertex_to->OutDegree(View::OLD), 0);
@@ -723,8 +723,8 @@ TEST_P(StorageEdgeTest, EdgeCreateFromSmallerCommit) {
 //     ASSERT_TRUE(res.HasValue());
 //     auto edge = res.GetValue();
 //     ASSERT_EQ(edge.EdgeType(), et);
-//     ASSERT_EQ(edge.FromVertex(), *vertex_from);
-//     ASSERT_EQ(edge.ToVertex(), *vertex_to);
+//     ASSERT_EQ(edge.From(), *vertex_from);
+//     ASSERT_EQ(edge.To(), *vertex_to);
 
 //     // Check edges without filters
 //     ASSERT_EQ(vertex_from->InEdges(View::OLD)->size(), 0);
@@ -741,8 +741,8 @@ TEST_P(StorageEdgeTest, EdgeCreateFromSmallerCommit) {
 //       ASSERT_EQ(*vertex_from->OutDegree(View::NEW), 1);
 //       auto e = edges[0];
 //       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.FromVertex(), *vertex_from);
-//       ASSERT_EQ(e.ToVertex(), *vertex_to);
+//       ASSERT_EQ(e.From(), *vertex_from);
+//       ASSERT_EQ(e.To(), *vertex_to);
 //     }
 //     ASSERT_EQ(vertex_to->InEdges(View::OLD)->size(), 0);
 //     ASSERT_EQ(*vertex_to->InDegree(View::OLD), 0);
@@ -754,8 +754,8 @@ TEST_P(StorageEdgeTest, EdgeCreateFromSmallerCommit) {
 //       ASSERT_EQ(*vertex_to->InDegree(View::NEW), 1);
 //       auto e = edges[0];
 //       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.FromVertex(), *vertex_from);
-//       ASSERT_EQ(e.ToVertex(), *vertex_to);
+//       ASSERT_EQ(e.From(), *vertex_from);
+//       ASSERT_EQ(e.To(), *vertex_to);
 //     }
 //     ASSERT_EQ(vertex_to->OutEdges(View::OLD)->size(), 0);
 //     ASSERT_EQ(*vertex_to->OutDegree(View::OLD), 0);
@@ -800,8 +800,8 @@ TEST_P(StorageEdgeTest, EdgeCreateFromSmallerCommit) {
 //       ASSERT_EQ(*vertex_from->OutDegree(View::OLD), 1);
 //       auto e = edges[0];
 //       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.FromVertex(), *vertex_from);
-//       ASSERT_EQ(e.ToVertex(), *vertex_to);
+//       ASSERT_EQ(e.From(), *vertex_from);
+//       ASSERT_EQ(e.To(), *vertex_to);
 //     }
 //     {
 //       auto ret = vertex_from->OutEdges(View::NEW);
@@ -811,8 +811,8 @@ TEST_P(StorageEdgeTest, EdgeCreateFromSmallerCommit) {
 //       ASSERT_EQ(*vertex_from->OutDegree(View::NEW), 1);
 //       auto e = edges[0];
 //       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.FromVertex(), *vertex_from);
-//       ASSERT_EQ(e.ToVertex(), *vertex_to);
+//       ASSERT_EQ(e.From(), *vertex_from);
+//       ASSERT_EQ(e.To(), *vertex_to);
 //     }
 //     {
 //       auto ret = vertex_to->InEdges(View::OLD);
@@ -822,8 +822,8 @@ TEST_P(StorageEdgeTest, EdgeCreateFromSmallerCommit) {
 //       ASSERT_EQ(*vertex_to->InDegree(View::OLD), 1);
 //       auto e = edges[0];
 //       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.FromVertex(), *vertex_from);
-//       ASSERT_EQ(e.ToVertex(), *vertex_to);
+//       ASSERT_EQ(e.From(), *vertex_from);
+//       ASSERT_EQ(e.To(), *vertex_to);
 //     }
 //     {
 //       auto ret = vertex_to->InEdges(View::NEW);
@@ -833,8 +833,8 @@ TEST_P(StorageEdgeTest, EdgeCreateFromSmallerCommit) {
 //       ASSERT_EQ(*vertex_to->InDegree(View::NEW), 1);
 //       auto e = edges[0];
 //       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.FromVertex(), *vertex_from);
-//       ASSERT_EQ(e.ToVertex(), *vertex_to);
+//       ASSERT_EQ(e.From(), *vertex_from);
+//       ASSERT_EQ(e.To(), *vertex_to);
 //     }
 //     ASSERT_EQ(vertex_to->OutEdges(View::OLD)->size(), 0);
 //     ASSERT_EQ(*vertex_to->OutDegree(View::OLD), 0);
@@ -901,8 +901,8 @@ TEST_P(StorageEdgeTest, EdgeCreateFromLargerAbort) {
     auto edge = res.GetValue();
     ASSERT_EQ(edge.EdgeType(), et);
     ASSERT_EQ(edge.Gid(), edge_id);
-    ASSERT_EQ(edge.FromVertex(), from_id);
-    ASSERT_EQ(edge.ToVertex(), to_id);
+    ASSERT_EQ(edge.From(), from_id);
+    ASSERT_EQ(edge.To(), to_id);
 
     // Check edges without filters
     ASSERT_EQ(vertex_from->InEdges(View::OLD)->size(), 0);
@@ -920,8 +920,8 @@ TEST_P(StorageEdgeTest, EdgeCreateFromLargerAbort) {
       auto e = edges[0];
       ASSERT_EQ(e.EdgeType(), et);
       ASSERT_EQ(e.Gid(), edge_id);
-      ASSERT_EQ(e.FromVertex(), from_id);
-      ASSERT_EQ(e.ToVertex(), to_id);
+      ASSERT_EQ(e.From(), from_id);
+      ASSERT_EQ(e.To(), to_id);
     }
     ASSERT_EQ(vertex_to->InEdges(View::OLD)->size(), 0);
     ASSERT_EQ(*vertex_to->InDegree(View::OLD), 0);
@@ -934,8 +934,8 @@ TEST_P(StorageEdgeTest, EdgeCreateFromLargerAbort) {
       auto e = edges[0];
       ASSERT_EQ(e.EdgeType(), et);
       ASSERT_EQ(e.Gid(), edge_id);
-      ASSERT_EQ(e.FromVertex(), from_id);
-      ASSERT_EQ(e.ToVertex(), to_id);
+      ASSERT_EQ(e.From(), from_id);
+      ASSERT_EQ(e.To(), to_id);
     }
     ASSERT_EQ(vertex_to->OutEdges(View::OLD)->size(), 0);
     ASSERT_EQ(*vertex_to->OutDegree(View::OLD), 0);
@@ -1013,8 +1013,8 @@ TEST_P(StorageEdgeTest, EdgeCreateFromLargerAbort) {
     auto edge = res.GetValue();
     ASSERT_EQ(edge.EdgeType(), et);
     ASSERT_EQ(edge.Gid(), edge_id);
-    ASSERT_EQ(edge.FromVertex(), from_id);
-    ASSERT_EQ(edge.ToVertex(), to_id);
+    ASSERT_EQ(edge.From(), from_id);
+    ASSERT_EQ(edge.To(), to_id);
 
     // Check edges without filters
     ASSERT_EQ(vertex_from->InEdges(View::OLD)->size(), 0);
@@ -1032,8 +1032,8 @@ TEST_P(StorageEdgeTest, EdgeCreateFromLargerAbort) {
       auto e = edges[0];
       ASSERT_EQ(e.EdgeType(), et);
       ASSERT_EQ(e.Gid(), edge_id);
-      ASSERT_EQ(e.FromVertex(), from_id);
-      ASSERT_EQ(e.ToVertex(), to_id);
+      ASSERT_EQ(e.From(), from_id);
+      ASSERT_EQ(e.To(), to_id);
     }
     ASSERT_EQ(vertex_to->InEdges(View::OLD)->size(), 0);
     ASSERT_EQ(*vertex_to->InDegree(View::OLD), 0);
@@ -1046,8 +1046,8 @@ TEST_P(StorageEdgeTest, EdgeCreateFromLargerAbort) {
       auto e = edges[0];
       ASSERT_EQ(e.EdgeType(), et);
       ASSERT_EQ(e.Gid(), edge_id);
-      ASSERT_EQ(e.FromVertex(), from_id);
-      ASSERT_EQ(e.ToVertex(), to_id);
+      ASSERT_EQ(e.From(), from_id);
+      ASSERT_EQ(e.To(), to_id);
     }
     ASSERT_EQ(vertex_to->OutEdges(View::OLD)->size(), 0);
     ASSERT_EQ(*vertex_to->OutDegree(View::OLD), 0);
@@ -1105,8 +1105,8 @@ TEST_P(StorageEdgeTest, EdgeCreateFromLargerAbort) {
       auto e = edges[0];
       ASSERT_EQ(e.EdgeType(), et);
       ASSERT_EQ(e.Gid(), edge_id);
-      ASSERT_EQ(e.FromVertex(), from_id);
-      ASSERT_EQ(e.ToVertex(), to_id);
+      ASSERT_EQ(e.From(), from_id);
+      ASSERT_EQ(e.To(), to_id);
     }
     {
       auto ret = vertex_from->OutEdges(View::NEW);
@@ -1117,8 +1117,8 @@ TEST_P(StorageEdgeTest, EdgeCreateFromLargerAbort) {
       auto e = edges[0];
       ASSERT_EQ(e.EdgeType(), et);
       ASSERT_EQ(e.Gid(), edge_id);
-      ASSERT_EQ(e.FromVertex(), from_id);
-      ASSERT_EQ(e.ToVertex(), to_id);
+      ASSERT_EQ(e.From(), from_id);
+      ASSERT_EQ(e.To(), to_id);
     }
     {
       auto ret = vertex_to->InEdges(View::OLD);
@@ -1129,8 +1129,8 @@ TEST_P(StorageEdgeTest, EdgeCreateFromLargerAbort) {
       auto e = edges[0];
       ASSERT_EQ(e.EdgeType(), et);
       ASSERT_EQ(e.Gid(), edge_id);
-      ASSERT_EQ(e.FromVertex(), from_id);
-      ASSERT_EQ(e.ToVertex(), to_id);
+      ASSERT_EQ(e.From(), from_id);
+      ASSERT_EQ(e.To(), to_id);
     }
     {
       auto ret = vertex_to->InEdges(View::NEW);
@@ -1141,8 +1141,8 @@ TEST_P(StorageEdgeTest, EdgeCreateFromLargerAbort) {
       auto e = edges[0];
       ASSERT_EQ(e.EdgeType(), et);
       ASSERT_EQ(e.Gid(), edge_id);
-      ASSERT_EQ(e.FromVertex(), from_id);
-      ASSERT_EQ(e.ToVertex(), to_id);
+      ASSERT_EQ(e.From(), from_id);
+      ASSERT_EQ(e.To(), to_id);
     }
     ASSERT_EQ(vertex_to->OutEdges(View::OLD)->size(), 0);
     ASSERT_EQ(*vertex_to->OutDegree(View::OLD), 0);
@@ -1199,8 +1199,8 @@ TEST_P(StorageEdgeTest, EdgeCreateFromLargerAbort) {
 //     ASSERT_TRUE(res.HasValue());
 //     auto edge = res.GetValue();
 //     ASSERT_EQ(edge.EdgeType(), et);
-//     ASSERT_EQ(edge.FromVertex(), *vertex);
-//     ASSERT_EQ(edge.ToVertex(), *vertex);
+//     ASSERT_EQ(edge.From(), *vertex);
+//     ASSERT_EQ(edge.To(), *vertex);
 
 //     // Check edges without filters
 //     ASSERT_EQ(vertex->InEdges(View::OLD)->size(), 0);
@@ -1213,8 +1213,8 @@ TEST_P(StorageEdgeTest, EdgeCreateFromLargerAbort) {
 //       ASSERT_EQ(*vertex->InDegree(View::NEW), 1);
 //       auto e = edges[0];
 //       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.FromVertex(), *vertex);
-//       ASSERT_EQ(e.ToVertex(), *vertex);
+//       ASSERT_EQ(e.From(), *vertex);
+//       ASSERT_EQ(e.To(), *vertex);
 //     }
 //     ASSERT_EQ(vertex->OutEdges(View::OLD)->size(), 0);
 //     ASSERT_EQ(*vertex->OutDegree(View::OLD), 0);
@@ -1226,8 +1226,8 @@ TEST_P(StorageEdgeTest, EdgeCreateFromLargerAbort) {
 //       ASSERT_EQ(*vertex->OutDegree(View::NEW), 1);
 //       auto e = edges[0];
 //       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.FromVertex(), *vertex);
-//       ASSERT_EQ(e.ToVertex(), *vertex);
+//       ASSERT_EQ(e.From(), *vertex);
+//       ASSERT_EQ(e.To(), *vertex);
 //     }
 
 //     auto other_et = acc.NameToEdgeType("other");
@@ -1276,8 +1276,8 @@ TEST_P(StorageEdgeTest, EdgeCreateFromLargerAbort) {
 //     ASSERT_TRUE(res.HasValue());
 //     auto edge = res.GetValue();
 //     ASSERT_EQ(edge.EdgeType(), et);
-//     ASSERT_EQ(edge.FromVertex(), *vertex);
-//     ASSERT_EQ(edge.ToVertex(), *vertex);
+//     ASSERT_EQ(edge.From(), *vertex);
+//     ASSERT_EQ(edge.To(), *vertex);
 
 //     // Check edges without filters
 //     ASSERT_EQ(vertex->InEdges(View::OLD)->size(), 0);
@@ -1290,8 +1290,8 @@ TEST_P(StorageEdgeTest, EdgeCreateFromLargerAbort) {
 //       ASSERT_EQ(*vertex->InDegree(View::NEW), 1);
 //       auto e = edges[0];
 //       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.FromVertex(), *vertex);
-//       ASSERT_EQ(e.ToVertex(), *vertex);
+//       ASSERT_EQ(e.From(), *vertex);
+//       ASSERT_EQ(e.To(), *vertex);
 //     }
 //     ASSERT_EQ(vertex->OutEdges(View::OLD)->size(), 0);
 //     ASSERT_EQ(*vertex->OutDegree(View::OLD), 0);
@@ -1303,8 +1303,8 @@ TEST_P(StorageEdgeTest, EdgeCreateFromLargerAbort) {
 //       ASSERT_EQ(*vertex->OutDegree(View::NEW), 1);
 //       auto e = edges[0];
 //       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.FromVertex(), *vertex);
-//       ASSERT_EQ(e.ToVertex(), *vertex);
+//       ASSERT_EQ(e.From(), *vertex);
+//       ASSERT_EQ(e.To(), *vertex);
 //     }
 
 //     auto other_et = acc.NameToEdgeType("other");
@@ -1339,8 +1339,8 @@ TEST_P(StorageEdgeTest, EdgeCreateFromLargerAbort) {
 //       ASSERT_EQ(*vertex->InDegree(View::OLD), 1);
 //       auto e = edges[0];
 //       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.FromVertex(), *vertex);
-//       ASSERT_EQ(e.ToVertex(), *vertex);
+//       ASSERT_EQ(e.From(), *vertex);
+//       ASSERT_EQ(e.To(), *vertex);
 //     }
 //     {
 //       auto ret = vertex->InEdges(View::NEW);
@@ -1350,8 +1350,8 @@ TEST_P(StorageEdgeTest, EdgeCreateFromLargerAbort) {
 //       ASSERT_EQ(*vertex->InDegree(View::NEW), 1);
 //       auto e = edges[0];
 //       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.FromVertex(), *vertex);
-//       ASSERT_EQ(e.ToVertex(), *vertex);
+//       ASSERT_EQ(e.From(), *vertex);
+//       ASSERT_EQ(e.To(), *vertex);
 //     }
 //     {
 //       auto ret = vertex->OutEdges(View::OLD);
@@ -1361,8 +1361,8 @@ TEST_P(StorageEdgeTest, EdgeCreateFromLargerAbort) {
 //       ASSERT_EQ(*vertex->OutDegree(View::OLD), 1);
 //       auto e = edges[0];
 //       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.FromVertex(), *vertex);
-//       ASSERT_EQ(e.ToVertex(), *vertex);
+//       ASSERT_EQ(e.From(), *vertex);
+//       ASSERT_EQ(e.To(), *vertex);
 //     }
 //     {
 //       auto ret = vertex->OutEdges(View::NEW);
@@ -1372,8 +1372,8 @@ TEST_P(StorageEdgeTest, EdgeCreateFromLargerAbort) {
 //       ASSERT_EQ(*vertex->OutDegree(View::NEW), 1);
 //       auto e = edges[0];
 //       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.FromVertex(), *vertex);
-//       ASSERT_EQ(e.ToVertex(), *vertex);
+//       ASSERT_EQ(e.From(), *vertex);
+//       ASSERT_EQ(e.To(), *vertex);
 //     }
 
 //     auto other_et = acc.NameToEdgeType("other");
@@ -1433,8 +1433,8 @@ TEST_P(StorageEdgeTest, EdgeDeleteFromSmallerCommit) {
     auto edge = res.GetValue();
     ASSERT_EQ(edge.EdgeType(), et);
     ASSERT_EQ(edge.Gid(), edge_id);
-    ASSERT_EQ(edge.FromVertex(), from_id);
-    ASSERT_EQ(edge.ToVertex(), to_id);
+    ASSERT_EQ(edge.From(), from_id);
+    ASSERT_EQ(edge.To(), to_id);
 
     // Check edges without filters
     ASSERT_EQ(vertex_from->InEdges(View::OLD)->size(), 0);
@@ -1452,8 +1452,8 @@ TEST_P(StorageEdgeTest, EdgeDeleteFromSmallerCommit) {
       auto e = edges[0];
       ASSERT_EQ(e.EdgeType(), et);
       ASSERT_EQ(e.Gid(), edge_id);
-      ASSERT_EQ(e.FromVertex(), from_id);
-      ASSERT_EQ(e.ToVertex(), to_id);
+      ASSERT_EQ(e.From(), from_id);
+      ASSERT_EQ(e.To(), to_id);
     }
 
     // Check edges with filters
@@ -1491,8 +1491,8 @@ TEST_P(StorageEdgeTest, EdgeDeleteFromSmallerCommit) {
       auto e = edges[0];
       ASSERT_EQ(e.EdgeType(), et);
       ASSERT_EQ(e.Gid(), edge_id);
-      ASSERT_EQ(e.FromVertex(), from_id);
-      ASSERT_EQ(e.ToVertex(), to_id);
+      ASSERT_EQ(e.From(), from_id);
+      ASSERT_EQ(e.To(), to_id);
     }
     {
       auto ret = vertex_from->OutEdges(View::NEW);
@@ -1503,8 +1503,8 @@ TEST_P(StorageEdgeTest, EdgeDeleteFromSmallerCommit) {
       auto e = edges[0];
       ASSERT_EQ(e.EdgeType(), et);
       ASSERT_EQ(e.Gid(), edge_id);
-      ASSERT_EQ(e.FromVertex(), from_id);
-      ASSERT_EQ(e.ToVertex(), to_id);
+      ASSERT_EQ(e.From(), from_id);
+      ASSERT_EQ(e.To(), to_id);
     }
 
     // Check edges with filters
@@ -1531,7 +1531,7 @@ TEST_P(StorageEdgeTest, EdgeDeleteFromSmallerCommit) {
 
     const auto edge = vertex_from->OutEdges(View::NEW).GetValue()[0];
 
-    const auto res = acc.DeleteEdge(edge.FromVertex(), edge.ToVertex(), edge.Gid());
+    const auto res = acc.DeleteEdge(edge.From(), edge.To(), edge.Gid());
     ASSERT_TRUE(res.HasValue());
     ASSERT_TRUE(res.GetValue());
 
@@ -1549,8 +1549,8 @@ TEST_P(StorageEdgeTest, EdgeDeleteFromSmallerCommit) {
       auto e = edges[0];
       ASSERT_EQ(e.EdgeType(), et);
       ASSERT_EQ(e.Gid(), edge_id);
-      ASSERT_EQ(e.FromVertex(), from_id);
-      ASSERT_EQ(e.ToVertex(), to_id);
+      ASSERT_EQ(e.From(), from_id);
+      ASSERT_EQ(e.To(), to_id);
     }
     ASSERT_EQ(vertex_from->OutEdges(View::NEW)->size(), 0);
     ASSERT_EQ(*vertex_from->OutDegree(View::NEW), 0);
@@ -1620,8 +1620,8 @@ TEST_P(StorageEdgeTest, EdgeDeleteFromSmallerCommit) {
 //     ASSERT_TRUE(res.HasValue());
 //     auto edge = res.GetValue();
 //     ASSERT_EQ(edge.EdgeType(), et);
-//     ASSERT_EQ(edge.FromVertex(), *vertex_from);
-//     ASSERT_EQ(edge.ToVertex(), *vertex_to);
+//     ASSERT_EQ(edge.From(), *vertex_from);
+//     ASSERT_EQ(edge.To(), *vertex_to);
 
 //     // Check edges without filters
 //     ASSERT_EQ(vertex_from->InEdges(View::OLD)->size(), 0);
@@ -1638,8 +1638,8 @@ TEST_P(StorageEdgeTest, EdgeDeleteFromSmallerCommit) {
 //       ASSERT_EQ(*vertex_from->OutDegree(View::NEW), 1);
 //       auto e = edges[0];
 //       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.FromVertex(), *vertex_from);
-//       ASSERT_EQ(e.ToVertex(), *vertex_to);
+//       ASSERT_EQ(e.From(), *vertex_from);
+//       ASSERT_EQ(e.To(), *vertex_to);
 //     }
 //     ASSERT_EQ(vertex_to->InEdges(View::OLD)->size(), 0);
 //     ASSERT_EQ(*vertex_to->InDegree(View::OLD), 0);
@@ -1651,8 +1651,8 @@ TEST_P(StorageEdgeTest, EdgeDeleteFromSmallerCommit) {
 //       ASSERT_EQ(*vertex_to->InDegree(View::NEW), 1);
 //       auto e = edges[0];
 //       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.FromVertex(), *vertex_from);
-//       ASSERT_EQ(e.ToVertex(), *vertex_to);
+//       ASSERT_EQ(e.From(), *vertex_from);
+//       ASSERT_EQ(e.To(), *vertex_to);
 //     }
 //     ASSERT_EQ(vertex_to->OutEdges(View::OLD)->size(), 0);
 //     ASSERT_EQ(*vertex_to->OutDegree(View::OLD), 0);
@@ -1697,8 +1697,8 @@ TEST_P(StorageEdgeTest, EdgeDeleteFromSmallerCommit) {
 //       ASSERT_EQ(*vertex_from->OutDegree(View::OLD), 1);
 //       auto e = edges[0];
 //       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.FromVertex(), *vertex_from);
-//       ASSERT_EQ(e.ToVertex(), *vertex_to);
+//       ASSERT_EQ(e.From(), *vertex_from);
+//       ASSERT_EQ(e.To(), *vertex_to);
 //     }
 //     {
 //       auto ret = vertex_from->OutEdges(View::NEW);
@@ -1708,8 +1708,8 @@ TEST_P(StorageEdgeTest, EdgeDeleteFromSmallerCommit) {
 //       ASSERT_EQ(*vertex_from->OutDegree(View::NEW), 1);
 //       auto e = edges[0];
 //       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.FromVertex(), *vertex_from);
-//       ASSERT_EQ(e.ToVertex(), *vertex_to);
+//       ASSERT_EQ(e.From(), *vertex_from);
+//       ASSERT_EQ(e.To(), *vertex_to);
 //     }
 //     {
 //       auto ret = vertex_to->InEdges(View::OLD);
@@ -1719,8 +1719,8 @@ TEST_P(StorageEdgeTest, EdgeDeleteFromSmallerCommit) {
 //       ASSERT_EQ(*vertex_to->InDegree(View::OLD), 1);
 //       auto e = edges[0];
 //       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.FromVertex(), *vertex_from);
-//       ASSERT_EQ(e.ToVertex(), *vertex_to);
+//       ASSERT_EQ(e.From(), *vertex_from);
+//       ASSERT_EQ(e.To(), *vertex_to);
 //     }
 //     {
 //       auto ret = vertex_to->InEdges(View::NEW);
@@ -1730,8 +1730,8 @@ TEST_P(StorageEdgeTest, EdgeDeleteFromSmallerCommit) {
 //       ASSERT_EQ(*vertex_to->InDegree(View::NEW), 1);
 //       auto e = edges[0];
 //       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.FromVertex(), *vertex_from);
-//       ASSERT_EQ(e.ToVertex(), *vertex_to);
+//       ASSERT_EQ(e.From(), *vertex_from);
+//       ASSERT_EQ(e.To(), *vertex_to);
 //     }
 //     ASSERT_EQ(vertex_to->OutEdges(View::OLD)->size(), 0);
 //     ASSERT_EQ(*vertex_to->OutDegree(View::OLD), 0);
@@ -1790,8 +1790,8 @@ TEST_P(StorageEdgeTest, EdgeDeleteFromSmallerCommit) {
 //       ASSERT_EQ(*vertex_from->OutDegree(View::OLD), 1);
 //       auto e = edges[0];
 //       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.FromVertex(), *vertex_from);
-//       ASSERT_EQ(e.ToVertex(), *vertex_to);
+//       ASSERT_EQ(e.From(), *vertex_from);
+//       ASSERT_EQ(e.To(), *vertex_to);
 //     }
 //     ASSERT_EQ(vertex_from->OutEdges(View::NEW)->size(), 0);
 //     ASSERT_EQ(*vertex_from->OutDegree(View::NEW), 0);
@@ -1803,8 +1803,8 @@ TEST_P(StorageEdgeTest, EdgeDeleteFromSmallerCommit) {
 //       ASSERT_EQ(*vertex_to->InDegree(View::OLD), 1);
 //       auto e = edges[0];
 //       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.FromVertex(), *vertex_from);
-//       ASSERT_EQ(e.ToVertex(), *vertex_to);
+//       ASSERT_EQ(e.From(), *vertex_from);
+//       ASSERT_EQ(e.To(), *vertex_to);
 //     }
 //     ASSERT_EQ(vertex_to->InEdges(View::NEW)->size(), 0);
 //     ASSERT_EQ(*vertex_to->InDegree(View::NEW), 0);
@@ -1883,8 +1883,8 @@ TEST_P(StorageEdgeTest, EdgeDeleteFromSmallerCommit) {
 //     ASSERT_TRUE(res.HasValue());
 //     auto edge = res.GetValue();
 //     ASSERT_EQ(edge.EdgeType(), et);
-//     ASSERT_EQ(edge.FromVertex(), *vertex);
-//     ASSERT_EQ(edge.ToVertex(), *vertex);
+//     ASSERT_EQ(edge.From(), *vertex);
+//     ASSERT_EQ(edge.To(), *vertex);
 
 //     // Check edges without filters
 //     ASSERT_EQ(vertex->InEdges(View::OLD)->size(), 0);
@@ -1897,8 +1897,8 @@ TEST_P(StorageEdgeTest, EdgeDeleteFromSmallerCommit) {
 //       ASSERT_EQ(*vertex->InDegree(View::NEW), 1);
 //       auto e = edges[0];
 //       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.FromVertex(), *vertex);
-//       ASSERT_EQ(e.ToVertex(), *vertex);
+//       ASSERT_EQ(e.From(), *vertex);
+//       ASSERT_EQ(e.To(), *vertex);
 //     }
 //     ASSERT_EQ(vertex->OutEdges(View::OLD)->size(), 0);
 //     ASSERT_EQ(*vertex->OutDegree(View::OLD), 0);
@@ -1910,8 +1910,8 @@ TEST_P(StorageEdgeTest, EdgeDeleteFromSmallerCommit) {
 //       ASSERT_EQ(*vertex->OutDegree(View::NEW), 1);
 //       auto e = edges[0];
 //       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.FromVertex(), *vertex);
-//       ASSERT_EQ(e.ToVertex(), *vertex);
+//       ASSERT_EQ(e.From(), *vertex);
+//       ASSERT_EQ(e.To(), *vertex);
 //     }
 
 //     auto other_et = acc.NameToEdgeType("other");
@@ -1946,8 +1946,8 @@ TEST_P(StorageEdgeTest, EdgeDeleteFromSmallerCommit) {
 //       ASSERT_EQ(*vertex->InDegree(View::OLD), 1);
 //       auto e = edges[0];
 //       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.FromVertex(), *vertex);
-//       ASSERT_EQ(e.ToVertex(), *vertex);
+//       ASSERT_EQ(e.From(), *vertex);
+//       ASSERT_EQ(e.To(), *vertex);
 //     }
 //     {
 //       auto ret = vertex->InEdges(View::NEW);
@@ -1957,8 +1957,8 @@ TEST_P(StorageEdgeTest, EdgeDeleteFromSmallerCommit) {
 //       ASSERT_EQ(*vertex->InDegree(View::NEW), 1);
 //       auto e = edges[0];
 //       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.FromVertex(), *vertex);
-//       ASSERT_EQ(e.ToVertex(), *vertex);
+//       ASSERT_EQ(e.From(), *vertex);
+//       ASSERT_EQ(e.To(), *vertex);
 //     }
 //     {
 //       auto ret = vertex->OutEdges(View::OLD);
@@ -1968,8 +1968,8 @@ TEST_P(StorageEdgeTest, EdgeDeleteFromSmallerCommit) {
 //       ASSERT_EQ(*vertex->OutDegree(View::OLD), 1);
 //       auto e = edges[0];
 //       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.FromVertex(), *vertex);
-//       ASSERT_EQ(e.ToVertex(), *vertex);
+//       ASSERT_EQ(e.From(), *vertex);
+//       ASSERT_EQ(e.To(), *vertex);
 //     }
 //     {
 //       auto ret = vertex->OutEdges(View::NEW);
@@ -1979,8 +1979,8 @@ TEST_P(StorageEdgeTest, EdgeDeleteFromSmallerCommit) {
 //       ASSERT_EQ(*vertex->OutDegree(View::NEW), 1);
 //       auto e = edges[0];
 //       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.FromVertex(), *vertex);
-//       ASSERT_EQ(e.ToVertex(), *vertex);
+//       ASSERT_EQ(e.From(), *vertex);
+//       ASSERT_EQ(e.To(), *vertex);
 //     }
 
 //     auto other_et = acc.NameToEdgeType("other");
@@ -2029,8 +2029,8 @@ TEST_P(StorageEdgeTest, EdgeDeleteFromSmallerCommit) {
 //       ASSERT_EQ(*vertex->InDegree(View::OLD), 1);
 //       auto e = edges[0];
 //       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.FromVertex(), *vertex);
-//       ASSERT_EQ(e.ToVertex(), *vertex);
+//       ASSERT_EQ(e.From(), *vertex);
+//       ASSERT_EQ(e.To(), *vertex);
 //     }
 //     ASSERT_EQ(vertex->InEdges(View::NEW)->size(), 0);
 //     ASSERT_EQ(*vertex->InDegree(View::NEW), 0);
@@ -2042,8 +2042,8 @@ TEST_P(StorageEdgeTest, EdgeDeleteFromSmallerCommit) {
 //       ASSERT_EQ(*vertex->OutDegree(View::OLD), 1);
 //       auto e = edges[0];
 //       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.FromVertex(), *vertex);
-//       ASSERT_EQ(e.ToVertex(), *vertex);
+//       ASSERT_EQ(e.From(), *vertex);
+//       ASSERT_EQ(e.To(), *vertex);
 //     }
 //     ASSERT_EQ(vertex->OutEdges(View::NEW)->size(), 0);
 //     ASSERT_EQ(*vertex->OutDegree(View::NEW), 0);
@@ -2113,8 +2113,8 @@ TEST_P(StorageEdgeTest, EdgeDeleteFromSmallerCommit) {
 //     ASSERT_TRUE(res.HasValue());
 //     auto edge = res.GetValue();
 //     ASSERT_EQ(edge.EdgeType(), et);
-//     ASSERT_EQ(edge.FromVertex(), *vertex_from);
-//     ASSERT_EQ(edge.ToVertex(), *vertex_to);
+//     ASSERT_EQ(edge.From(), *vertex_from);
+//     ASSERT_EQ(edge.To(), *vertex_to);
 
 //     // Check edges without filters
 //     ASSERT_EQ(vertex_from->InEdges(View::OLD)->size(), 0);
@@ -2131,8 +2131,8 @@ TEST_P(StorageEdgeTest, EdgeDeleteFromSmallerCommit) {
 //       ASSERT_EQ(*vertex_from->OutDegree(View::NEW), 1);
 //       auto e = edges[0];
 //       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.FromVertex(), *vertex_from);
-//       ASSERT_EQ(e.ToVertex(), *vertex_to);
+//       ASSERT_EQ(e.From(), *vertex_from);
+//       ASSERT_EQ(e.To(), *vertex_to);
 //     }
 //     ASSERT_EQ(vertex_to->InEdges(View::OLD)->size(), 0);
 //     ASSERT_EQ(*vertex_to->InDegree(View::OLD), 0);
@@ -2144,8 +2144,8 @@ TEST_P(StorageEdgeTest, EdgeDeleteFromSmallerCommit) {
 //       ASSERT_EQ(*vertex_to->InDegree(View::NEW), 1);
 //       auto e = edges[0];
 //       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.FromVertex(), *vertex_from);
-//       ASSERT_EQ(e.ToVertex(), *vertex_to);
+//       ASSERT_EQ(e.From(), *vertex_from);
+//       ASSERT_EQ(e.To(), *vertex_to);
 //     }
 //     ASSERT_EQ(vertex_to->OutEdges(View::OLD)->size(), 0);
 //     ASSERT_EQ(*vertex_to->OutDegree(View::OLD), 0);
@@ -2190,8 +2190,8 @@ TEST_P(StorageEdgeTest, EdgeDeleteFromSmallerCommit) {
 //       ASSERT_EQ(*vertex_from->OutDegree(View::OLD), 1);
 //       auto e = edges[0];
 //       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.FromVertex(), *vertex_from);
-//       ASSERT_EQ(e.ToVertex(), *vertex_to);
+//       ASSERT_EQ(e.From(), *vertex_from);
+//       ASSERT_EQ(e.To(), *vertex_to);
 //     }
 //     {
 //       auto ret = vertex_from->OutEdges(View::NEW);
@@ -2201,8 +2201,8 @@ TEST_P(StorageEdgeTest, EdgeDeleteFromSmallerCommit) {
 //       ASSERT_EQ(*vertex_from->OutDegree(View::NEW), 1);
 //       auto e = edges[0];
 //       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.FromVertex(), *vertex_from);
-//       ASSERT_EQ(e.ToVertex(), *vertex_to);
+//       ASSERT_EQ(e.From(), *vertex_from);
+//       ASSERT_EQ(e.To(), *vertex_to);
 //     }
 //     {
 //       auto ret = vertex_to->InEdges(View::OLD);
@@ -2212,8 +2212,8 @@ TEST_P(StorageEdgeTest, EdgeDeleteFromSmallerCommit) {
 //       ASSERT_EQ(*vertex_to->InDegree(View::OLD), 1);
 //       auto e = edges[0];
 //       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.FromVertex(), *vertex_from);
-//       ASSERT_EQ(e.ToVertex(), *vertex_to);
+//       ASSERT_EQ(e.From(), *vertex_from);
+//       ASSERT_EQ(e.To(), *vertex_to);
 //     }
 //     {
 //       auto ret = vertex_to->InEdges(View::NEW);
@@ -2223,8 +2223,8 @@ TEST_P(StorageEdgeTest, EdgeDeleteFromSmallerCommit) {
 //       ASSERT_EQ(*vertex_to->InDegree(View::NEW), 1);
 //       auto e = edges[0];
 //       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.FromVertex(), *vertex_from);
-//       ASSERT_EQ(e.ToVertex(), *vertex_to);
+//       ASSERT_EQ(e.From(), *vertex_from);
+//       ASSERT_EQ(e.To(), *vertex_to);
 //     }
 //     ASSERT_EQ(vertex_to->OutEdges(View::OLD)->size(), 0);
 //     ASSERT_EQ(*vertex_to->OutDegree(View::OLD), 0);
@@ -2283,8 +2283,8 @@ TEST_P(StorageEdgeTest, EdgeDeleteFromSmallerCommit) {
 //       ASSERT_EQ(*vertex_from->OutDegree(View::OLD), 1);
 //       auto e = edges[0];
 //       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.FromVertex(), *vertex_from);
-//       ASSERT_EQ(e.ToVertex(), *vertex_to);
+//       ASSERT_EQ(e.From(), *vertex_from);
+//       ASSERT_EQ(e.To(), *vertex_to);
 //     }
 //     ASSERT_EQ(vertex_from->OutEdges(View::NEW)->size(), 0);
 //     ASSERT_EQ(*vertex_from->OutDegree(View::NEW), 0);
@@ -2296,8 +2296,8 @@ TEST_P(StorageEdgeTest, EdgeDeleteFromSmallerCommit) {
 //       ASSERT_EQ(*vertex_to->InDegree(View::OLD), 1);
 //       auto e = edges[0];
 //       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.FromVertex(), *vertex_from);
-//       ASSERT_EQ(e.ToVertex(), *vertex_to);
+//       ASSERT_EQ(e.From(), *vertex_from);
+//       ASSERT_EQ(e.To(), *vertex_to);
 //     }
 //     ASSERT_EQ(vertex_to->InEdges(View::NEW)->size(), 0);
 //     ASSERT_EQ(*vertex_to->InDegree(View::NEW), 0);
@@ -2344,8 +2344,8 @@ TEST_P(StorageEdgeTest, EdgeDeleteFromSmallerCommit) {
 //       ASSERT_EQ(*vertex_from->OutDegree(View::OLD), 1);
 //       auto e = edges[0];
 //       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.FromVertex(), *vertex_from);
-//       ASSERT_EQ(e.ToVertex(), *vertex_to);
+//       ASSERT_EQ(e.From(), *vertex_from);
+//       ASSERT_EQ(e.To(), *vertex_to);
 //     }
 //     {
 //       auto ret = vertex_from->OutEdges(View::NEW);
@@ -2355,8 +2355,8 @@ TEST_P(StorageEdgeTest, EdgeDeleteFromSmallerCommit) {
 //       ASSERT_EQ(*vertex_from->OutDegree(View::NEW), 1);
 //       auto e = edges[0];
 //       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.FromVertex(), *vertex_from);
-//       ASSERT_EQ(e.ToVertex(), *vertex_to);
+//       ASSERT_EQ(e.From(), *vertex_from);
+//       ASSERT_EQ(e.To(), *vertex_to);
 //     }
 //     {
 //       auto ret = vertex_to->InEdges(View::OLD);
@@ -2366,8 +2366,8 @@ TEST_P(StorageEdgeTest, EdgeDeleteFromSmallerCommit) {
 //       ASSERT_EQ(*vertex_to->InDegree(View::OLD), 1);
 //       auto e = edges[0];
 //       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.FromVertex(), *vertex_from);
-//       ASSERT_EQ(e.ToVertex(), *vertex_to);
+//       ASSERT_EQ(e.From(), *vertex_from);
+//       ASSERT_EQ(e.To(), *vertex_to);
 //     }
 //     {
 //       auto ret = vertex_to->InEdges(View::NEW);
@@ -2377,8 +2377,8 @@ TEST_P(StorageEdgeTest, EdgeDeleteFromSmallerCommit) {
 //       ASSERT_EQ(*vertex_to->InDegree(View::NEW), 1);
 //       auto e = edges[0];
 //       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.FromVertex(), *vertex_from);
-//       ASSERT_EQ(e.ToVertex(), *vertex_to);
+//       ASSERT_EQ(e.From(), *vertex_from);
+//       ASSERT_EQ(e.To(), *vertex_to);
 //     }
 //     ASSERT_EQ(vertex_to->OutEdges(View::OLD)->size(), 0);
 //     ASSERT_EQ(*vertex_to->OutDegree(View::OLD), 0);
@@ -2437,8 +2437,8 @@ TEST_P(StorageEdgeTest, EdgeDeleteFromSmallerCommit) {
 //       ASSERT_EQ(*vertex_from->OutDegree(View::OLD), 1);
 //       auto e = edges[0];
 //       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.FromVertex(), *vertex_from);
-//       ASSERT_EQ(e.ToVertex(), *vertex_to);
+//       ASSERT_EQ(e.From(), *vertex_from);
+//       ASSERT_EQ(e.To(), *vertex_to);
 //     }
 //     ASSERT_EQ(vertex_from->OutEdges(View::NEW)->size(), 0);
 //     ASSERT_EQ(*vertex_from->OutDegree(View::NEW), 0);
@@ -2450,8 +2450,8 @@ TEST_P(StorageEdgeTest, EdgeDeleteFromSmallerCommit) {
 //       ASSERT_EQ(*vertex_to->InDegree(View::OLD), 1);
 //       auto e = edges[0];
 //       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.FromVertex(), *vertex_from);
-//       ASSERT_EQ(e.ToVertex(), *vertex_to);
+//       ASSERT_EQ(e.From(), *vertex_from);
+//       ASSERT_EQ(e.To(), *vertex_to);
 //     }
 //     ASSERT_EQ(vertex_to->InEdges(View::NEW)->size(), 0);
 //     ASSERT_EQ(*vertex_to->InDegree(View::NEW), 0);
@@ -2533,8 +2533,8 @@ TEST_P(StorageEdgeTest, EdgeDeleteFromLargerAbort) {
     auto edge = res.GetValue();
     ASSERT_EQ(edge.EdgeType(), et);
     ASSERT_EQ(edge.Gid(), edge_id);
-    ASSERT_EQ(edge.FromVertex(), from_id);
-    ASSERT_EQ(edge.ToVertex(), to_id);
+    ASSERT_EQ(edge.From(), from_id);
+    ASSERT_EQ(edge.To(), to_id);
 
     // Check edges without filters
     ASSERT_EQ(vertex_to->InEdges(View::OLD)->size(), 0);
@@ -2548,8 +2548,8 @@ TEST_P(StorageEdgeTest, EdgeDeleteFromLargerAbort) {
       auto e = edges[0];
       ASSERT_EQ(e.EdgeType(), et);
       ASSERT_EQ(e.Gid(), edge_id);
-      ASSERT_EQ(e.FromVertex(), from_id);
-      ASSERT_EQ(e.ToVertex(), to_id);
+      ASSERT_EQ(e.From(), from_id);
+      ASSERT_EQ(e.To(), to_id);
     }
     ASSERT_EQ(vertex_to->OutEdges(View::OLD)->size(), 0);
     ASSERT_EQ(*vertex_to->OutDegree(View::OLD), 0);
@@ -2586,8 +2586,8 @@ TEST_P(StorageEdgeTest, EdgeDeleteFromLargerAbort) {
       auto e = edges[0];
       ASSERT_EQ(e.EdgeType(), et);
       ASSERT_EQ(e.Gid(), edge_id);
-      ASSERT_EQ(e.FromVertex(), from_id);
-      ASSERT_EQ(e.ToVertex(), to_id);
+      ASSERT_EQ(e.From(), from_id);
+      ASSERT_EQ(e.To(), to_id);
     }
     {
       auto ret = vertex_to->InEdges(View::NEW);
@@ -2598,8 +2598,8 @@ TEST_P(StorageEdgeTest, EdgeDeleteFromLargerAbort) {
       auto e = edges[0];
       ASSERT_EQ(e.EdgeType(), et);
       ASSERT_EQ(e.Gid(), edge_id);
-      ASSERT_EQ(e.FromVertex(), from_id);
-      ASSERT_EQ(e.ToVertex(), to_id);
+      ASSERT_EQ(e.From(), from_id);
+      ASSERT_EQ(e.To(), to_id);
     }
     ASSERT_EQ(vertex_to->OutEdges(View::OLD)->size(), 0);
     ASSERT_EQ(*vertex_to->OutDegree(View::OLD), 0);
@@ -2639,7 +2639,7 @@ TEST_P(StorageEdgeTest, EdgeDeleteFromLargerAbort) {
 
     const auto edge = vertex_to->InEdges(View::NEW).GetValue()[0];
 
-    auto res = acc.DeleteEdge(edge.FromVertex(), edge.ToVertex(), edge.Gid());
+    auto res = acc.DeleteEdge(edge.From(), edge.To(), edge.Gid());
     ASSERT_TRUE(res.HasValue());
     ASSERT_TRUE(res.GetValue());
 
@@ -2654,8 +2654,8 @@ TEST_P(StorageEdgeTest, EdgeDeleteFromLargerAbort) {
       auto e = edges[0];
       ASSERT_EQ(e.EdgeType(), et);
       ASSERT_EQ(e.Gid(), edge_id);
-      ASSERT_EQ(e.FromVertex(), from_id);
-      ASSERT_EQ(e.ToVertex(), to_id);
+      ASSERT_EQ(e.From(), from_id);
+      ASSERT_EQ(e.To(), to_id);
     }
     ASSERT_EQ(vertex_to->InEdges(View::NEW)->size(), 0);
     ASSERT_EQ(*vertex_to->InDegree(View::NEW), 0);
@@ -2693,8 +2693,8 @@ TEST_P(StorageEdgeTest, EdgeDeleteFromLargerAbort) {
       auto e = edges[0];
       ASSERT_EQ(e.EdgeType(), et);
       ASSERT_EQ(e.Gid(), edge_id);
-      ASSERT_EQ(e.FromVertex(), from_id);
-      ASSERT_EQ(e.ToVertex(), to_id);
+      ASSERT_EQ(e.From(), from_id);
+      ASSERT_EQ(e.To(), to_id);
     }
     {
       auto ret = vertex_to->InEdges(View::NEW);
@@ -2705,8 +2705,8 @@ TEST_P(StorageEdgeTest, EdgeDeleteFromLargerAbort) {
       auto e = edges[0];
       ASSERT_EQ(e.EdgeType(), et);
       ASSERT_EQ(e.Gid(), edge_id);
-      ASSERT_EQ(e.FromVertex(), from_id);
-      ASSERT_EQ(e.ToVertex(), to_id);
+      ASSERT_EQ(e.From(), from_id);
+      ASSERT_EQ(e.To(), to_id);
     }
     ASSERT_EQ(vertex_to->OutEdges(View::OLD)->size(), 0);
     ASSERT_EQ(*vertex_to->OutDegree(View::OLD), 0);
@@ -2746,7 +2746,7 @@ TEST_P(StorageEdgeTest, EdgeDeleteFromLargerAbort) {
 
     const auto edge = vertex_to->InEdges(View::NEW).GetValue()[0];
 
-    auto res = acc.DeleteEdge(edge.FromVertex(), edge.ToVertex(), edge.Gid());
+    auto res = acc.DeleteEdge(edge.From(), edge.To(), edge.Gid());
     ASSERT_TRUE(res.HasValue());
     ASSERT_TRUE(res.GetValue());
 
@@ -2759,8 +2759,8 @@ TEST_P(StorageEdgeTest, EdgeDeleteFromLargerAbort) {
       ASSERT_EQ(*vertex_to->InDegree(View::OLD), 1);
       auto e = edges[0];
       ASSERT_EQ(e.EdgeType(), et);
-      ASSERT_EQ(e.FromVertex(), from_id);
-      ASSERT_EQ(e.ToVertex(), to_id);
+      ASSERT_EQ(e.From(), from_id);
+      ASSERT_EQ(e.To(), to_id);
     }
     ASSERT_EQ(vertex_to->InEdges(View::NEW)->size(), 0);
     ASSERT_EQ(*vertex_to->InDegree(View::NEW), 0);
@@ -2839,8 +2839,8 @@ TEST_P(StorageEdgeTest, EdgeDeleteFromLargerAbort) {
 //     ASSERT_TRUE(res.HasValue());
 //     auto edge = res.GetValue();
 //     ASSERT_EQ(edge.EdgeType(), et);
-//     ASSERT_EQ(edge.FromVertex(), *vertex);
-//     ASSERT_EQ(edge.ToVertex(), *vertex);
+//     ASSERT_EQ(edge.From(), *vertex);
+//     ASSERT_EQ(edge.To(), *vertex);
 
 //     // Check edges without filters
 //     ASSERT_EQ(vertex->InEdges(View::OLD)->size(), 0);
@@ -2853,8 +2853,8 @@ TEST_P(StorageEdgeTest, EdgeDeleteFromLargerAbort) {
 //       ASSERT_EQ(*vertex->InDegree(View::NEW), 1);
 //       auto e = edges[0];
 //       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.FromVertex(), *vertex);
-//       ASSERT_EQ(e.ToVertex(), *vertex);
+//       ASSERT_EQ(e.From(), *vertex);
+//       ASSERT_EQ(e.To(), *vertex);
 //     }
 //     ASSERT_EQ(vertex->OutEdges(View::OLD)->size(), 0);
 //     ASSERT_EQ(*vertex->OutDegree(View::OLD), 0);
@@ -2866,8 +2866,8 @@ TEST_P(StorageEdgeTest, EdgeDeleteFromLargerAbort) {
 //       ASSERT_EQ(*vertex->OutDegree(View::NEW), 1);
 //       auto e = edges[0];
 //       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.FromVertex(), *vertex);
-//       ASSERT_EQ(e.ToVertex(), *vertex);
+//       ASSERT_EQ(e.From(), *vertex);
+//       ASSERT_EQ(e.To(), *vertex);
 //     }
 
 //     auto other_et = acc.NameToEdgeType("other");
@@ -2902,8 +2902,8 @@ TEST_P(StorageEdgeTest, EdgeDeleteFromLargerAbort) {
 //       ASSERT_EQ(*vertex->InDegree(View::OLD), 1);
 //       auto e = edges[0];
 //       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.FromVertex(), *vertex);
-//       ASSERT_EQ(e.ToVertex(), *vertex);
+//       ASSERT_EQ(e.From(), *vertex);
+//       ASSERT_EQ(e.To(), *vertex);
 //     }
 //     {
 //       auto ret = vertex->InEdges(View::NEW);
@@ -2913,8 +2913,8 @@ TEST_P(StorageEdgeTest, EdgeDeleteFromLargerAbort) {
 //       ASSERT_EQ(*vertex->InDegree(View::NEW), 1);
 //       auto e = edges[0];
 //       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.FromVertex(), *vertex);
-//       ASSERT_EQ(e.ToVertex(), *vertex);
+//       ASSERT_EQ(e.From(), *vertex);
+//       ASSERT_EQ(e.To(), *vertex);
 //     }
 //     {
 //       auto ret = vertex->OutEdges(View::OLD);
@@ -2924,8 +2924,8 @@ TEST_P(StorageEdgeTest, EdgeDeleteFromLargerAbort) {
 //       ASSERT_EQ(*vertex->OutDegree(View::OLD), 1);
 //       auto e = edges[0];
 //       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.FromVertex(), *vertex);
-//       ASSERT_EQ(e.ToVertex(), *vertex);
+//       ASSERT_EQ(e.From(), *vertex);
+//       ASSERT_EQ(e.To(), *vertex);
 //     }
 //     {
 //       auto ret = vertex->OutEdges(View::NEW);
@@ -2935,8 +2935,8 @@ TEST_P(StorageEdgeTest, EdgeDeleteFromLargerAbort) {
 //       ASSERT_EQ(*vertex->OutDegree(View::NEW), 1);
 //       auto e = edges[0];
 //       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.FromVertex(), *vertex);
-//       ASSERT_EQ(e.ToVertex(), *vertex);
+//       ASSERT_EQ(e.From(), *vertex);
+//       ASSERT_EQ(e.To(), *vertex);
 //     }
 
 //     auto other_et = acc.NameToEdgeType("other");
@@ -2985,8 +2985,8 @@ TEST_P(StorageEdgeTest, EdgeDeleteFromLargerAbort) {
 //       ASSERT_EQ(*vertex->InDegree(View::OLD), 1);
 //       auto e = edges[0];
 //       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.FromVertex(), *vertex);
-//       ASSERT_EQ(e.ToVertex(), *vertex);
+//       ASSERT_EQ(e.From(), *vertex);
+//       ASSERT_EQ(e.To(), *vertex);
 //     }
 //     ASSERT_EQ(vertex->InEdges(View::NEW)->size(), 0);
 //     ASSERT_EQ(*vertex->InDegree(View::NEW), 0);
@@ -2998,8 +2998,8 @@ TEST_P(StorageEdgeTest, EdgeDeleteFromLargerAbort) {
 //       ASSERT_EQ(*vertex->OutDegree(View::OLD), 1);
 //       auto e = edges[0];
 //       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.FromVertex(), *vertex);
-//       ASSERT_EQ(e.ToVertex(), *vertex);
+//       ASSERT_EQ(e.From(), *vertex);
+//       ASSERT_EQ(e.To(), *vertex);
 //     }
 //     ASSERT_EQ(vertex->OutEdges(View::NEW)->size(), 0);
 //     ASSERT_EQ(*vertex->OutDegree(View::NEW), 0);
@@ -3036,8 +3036,8 @@ TEST_P(StorageEdgeTest, EdgeDeleteFromLargerAbort) {
 //       ASSERT_EQ(*vertex->InDegree(View::OLD), 1);
 //       auto e = edges[0];
 //       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.FromVertex(), *vertex);
-//       ASSERT_EQ(e.ToVertex(), *vertex);
+//       ASSERT_EQ(e.From(), *vertex);
+//       ASSERT_EQ(e.To(), *vertex);
 //     }
 //     {
 //       auto ret = vertex->InEdges(View::NEW);
@@ -3047,8 +3047,8 @@ TEST_P(StorageEdgeTest, EdgeDeleteFromLargerAbort) {
 //       ASSERT_EQ(*vertex->InDegree(View::NEW), 1);
 //       auto e = edges[0];
 //       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.FromVertex(), *vertex);
-//       ASSERT_EQ(e.ToVertex(), *vertex);
+//       ASSERT_EQ(e.From(), *vertex);
+//       ASSERT_EQ(e.To(), *vertex);
 //     }
 //     {
 //       auto ret = vertex->OutEdges(View::OLD);
@@ -3058,8 +3058,8 @@ TEST_P(StorageEdgeTest, EdgeDeleteFromLargerAbort) {
 //       ASSERT_EQ(*vertex->OutDegree(View::OLD), 1);
 //       auto e = edges[0];
 //       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.FromVertex(), *vertex);
-//       ASSERT_EQ(e.ToVertex(), *vertex);
+//       ASSERT_EQ(e.From(), *vertex);
+//       ASSERT_EQ(e.To(), *vertex);
 //     }
 //     {
 //       auto ret = vertex->OutEdges(View::NEW);
@@ -3069,8 +3069,8 @@ TEST_P(StorageEdgeTest, EdgeDeleteFromLargerAbort) {
 //       ASSERT_EQ(*vertex->OutDegree(View::NEW), 1);
 //       auto e = edges[0];
 //       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.FromVertex(), *vertex);
-//       ASSERT_EQ(e.ToVertex(), *vertex);
+//       ASSERT_EQ(e.From(), *vertex);
+//       ASSERT_EQ(e.To(), *vertex);
 //     }
 
 //     auto other_et = acc.NameToEdgeType("other");
@@ -3119,8 +3119,8 @@ TEST_P(StorageEdgeTest, EdgeDeleteFromLargerAbort) {
 //       ASSERT_EQ(*vertex->InDegree(View::OLD), 1);
 //       auto e = edges[0];
 //       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.FromVertex(), *vertex);
-//       ASSERT_EQ(e.ToVertex(), *vertex);
+//       ASSERT_EQ(e.From(), *vertex);
+//       ASSERT_EQ(e.To(), *vertex);
 //     }
 //     ASSERT_EQ(vertex->InEdges(View::NEW)->size(), 0);
 //     ASSERT_EQ(*vertex->InDegree(View::NEW), 0);
@@ -3132,8 +3132,8 @@ TEST_P(StorageEdgeTest, EdgeDeleteFromLargerAbort) {
 //       ASSERT_EQ(*vertex->OutDegree(View::OLD), 1);
 //       auto e = edges[0];
 //       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.FromVertex(), *vertex);
-//       ASSERT_EQ(e.ToVertex(), *vertex);
+//       ASSERT_EQ(e.From(), *vertex);
+//       ASSERT_EQ(e.To(), *vertex);
 //     }
 //     ASSERT_EQ(vertex->OutEdges(View::NEW)->size(), 0);
 //     ASSERT_EQ(*vertex->OutDegree(View::NEW), 0);
@@ -3196,8 +3196,8 @@ TEST_P(StorageEdgeTest, VertexDetachDeleteSingleCommit) {
     auto edge = res.GetValue();
     ASSERT_EQ(edge.EdgeType(), et);
     ASSERT_EQ(edge.Gid(), edge_id);
-    ASSERT_EQ(edge.FromVertex(), from_id);
-    ASSERT_EQ(edge.ToVertex(), to_id);
+    ASSERT_EQ(edge.From(), from_id);
+    ASSERT_EQ(edge.To(), to_id);
 
     // Check edges
     ASSERT_EQ(vertex_from.InEdges(View::NEW)->size(), 0);
@@ -3211,8 +3211,8 @@ TEST_P(StorageEdgeTest, VertexDetachDeleteSingleCommit) {
       auto e = edges[0];
       ASSERT_EQ(e.EdgeType(), et);
       ASSERT_EQ(e.Gid(), edge_id);
-      ASSERT_EQ(e.FromVertex(), from_id);
-      ASSERT_EQ(e.ToVertex(), to_id);
+      ASSERT_EQ(e.From(), from_id);
+      ASSERT_EQ(e.To(), to_id);
     }
     {
       auto ret = vertex_to.InEdges(View::NEW);
@@ -3222,8 +3222,8 @@ TEST_P(StorageEdgeTest, VertexDetachDeleteSingleCommit) {
       ASSERT_EQ(*vertex_to.InDegree(View::NEW), 1);
       auto e = edges[0];
       ASSERT_EQ(e.Gid(), edge_id);
-      ASSERT_EQ(e.FromVertex(), from_id);
-      ASSERT_EQ(e.ToVertex(), to_id);
+      ASSERT_EQ(e.From(), from_id);
+      ASSERT_EQ(e.To(), to_id);
     }
     ASSERT_EQ(vertex_to.OutEdges(View::NEW)->size(), 0);
     ASSERT_EQ(*vertex_to.OutDegree(View::NEW), 0);
@@ -3267,8 +3267,8 @@ TEST_P(StorageEdgeTest, VertexDetachDeleteSingleCommit) {
       auto e = edges[0];
       ASSERT_EQ(e.EdgeType(), et);
       ASSERT_EQ(e.Gid(), edge_id);
-      ASSERT_EQ(e.FromVertex(), from_id);
-      ASSERT_EQ(e.ToVertex(), to_id);
+      ASSERT_EQ(e.From(), from_id);
+      ASSERT_EQ(e.To(), to_id);
     }
     ASSERT_EQ(vertex_from->OutEdges(View::NEW).GetError(), Error::DELETED_OBJECT);
     ASSERT_EQ(vertex_from->OutDegree(View::NEW).GetError(), Error::DELETED_OBJECT);
@@ -3281,8 +3281,8 @@ TEST_P(StorageEdgeTest, VertexDetachDeleteSingleCommit) {
       auto e = edges[0];
       ASSERT_EQ(e.EdgeType(), et);
       ASSERT_EQ(e.Gid(), edge_id);
-      ASSERT_EQ(e.FromVertex(), from_id);
-      ASSERT_EQ(e.ToVertex(), to_id);
+      ASSERT_EQ(e.From(), from_id);
+      ASSERT_EQ(e.To(), to_id);
     }
     ASSERT_EQ(vertex_to->InEdges(View::NEW)->size(), 0);
     ASSERT_EQ(*vertex_to->InDegree(View::NEW), 0);
@@ -3338,29 +3338,29 @@ TEST_P(StorageEdgeTest, VertexDetachDeleteSingleCommit) {
 //     ASSERT_TRUE(res1.HasValue());
 //     auto edge1 = res1.GetValue();
 //     ASSERT_EQ(edge1.EdgeType(), et1);
-//     ASSERT_EQ(edge1.FromVertex(), vertex1);
-//     ASSERT_EQ(edge1.ToVertex(), vertex2);
+//     ASSERT_EQ(edge1.From(), vertex1);
+//     ASSERT_EQ(edge1.To(), vertex2);
 
 //     auto res2 = acc.CreateEdge(&vertex2, &vertex1, et2);
 //     ASSERT_TRUE(res2.HasValue());
 //     auto edge2 = res2.GetValue();
 //     ASSERT_EQ(edge2.EdgeType(), et2);
-//     ASSERT_EQ(edge2.FromVertex(), vertex2);
-//     ASSERT_EQ(edge2.ToVertex(), vertex1);
+//     ASSERT_EQ(edge2.From(), vertex2);
+//     ASSERT_EQ(edge2.To(), vertex1);
 
 //     auto res3 = acc.CreateEdge(&vertex1, &vertex1, et3);
 //     ASSERT_TRUE(res3.HasValue());
 //     auto edge3 = res3.GetValue();
 //     ASSERT_EQ(edge3.EdgeType(), et3);
-//     ASSERT_EQ(edge3.FromVertex(), vertex1);
-//     ASSERT_EQ(edge3.ToVertex(), vertex1);
+//     ASSERT_EQ(edge3.From(), vertex1);
+//     ASSERT_EQ(edge3.To(), vertex1);
 
 //     auto res4 = acc.CreateEdge(&vertex2, &vertex2, et4);
 //     ASSERT_TRUE(res4.HasValue());
 //     auto edge4 = res4.GetValue();
 //     ASSERT_EQ(edge4.EdgeType(), et4);
-//     ASSERT_EQ(edge4.FromVertex(), vertex2);
-//     ASSERT_EQ(edge4.ToVertex(), vertex2);
+//     ASSERT_EQ(edge4.From(), vertex2);
+//     ASSERT_EQ(edge4.To(), vertex2);
 
 //     // Check edges
 //     {
@@ -3372,14 +3372,14 @@ TEST_P(StorageEdgeTest, VertexDetachDeleteSingleCommit) {
 //       {
 //         auto e = edges[0];
 //         ASSERT_EQ(e.EdgeType(), et2);
-//         ASSERT_EQ(e.FromVertex(), vertex2);
-//         ASSERT_EQ(e.ToVertex(), vertex1);
+//         ASSERT_EQ(e.From(), vertex2);
+//         ASSERT_EQ(e.To(), vertex1);
 //       }
 //       {
 //         auto e = edges[1];
 //         ASSERT_EQ(e.EdgeType(), et3);
-//         ASSERT_EQ(e.FromVertex(), vertex1);
-//         ASSERT_EQ(e.ToVertex(), vertex1);
+//         ASSERT_EQ(e.From(), vertex1);
+//         ASSERT_EQ(e.To(), vertex1);
 //       }
 //     }
 //     {
@@ -3391,14 +3391,14 @@ TEST_P(StorageEdgeTest, VertexDetachDeleteSingleCommit) {
 //       {
 //         auto e = edges[0];
 //         ASSERT_EQ(e.EdgeType(), et1);
-//         ASSERT_EQ(e.FromVertex(), vertex1);
-//         ASSERT_EQ(e.ToVertex(), vertex2);
+//         ASSERT_EQ(e.From(), vertex1);
+//         ASSERT_EQ(e.To(), vertex2);
 //       }
 //       {
 //         auto e = edges[1];
 //         ASSERT_EQ(e.EdgeType(), et3);
-//         ASSERT_EQ(e.FromVertex(), vertex1);
-//         ASSERT_EQ(e.ToVertex(), vertex1);
+//         ASSERT_EQ(e.From(), vertex1);
+//         ASSERT_EQ(e.To(), vertex1);
 //       }
 //     }
 //     {
@@ -3410,14 +3410,14 @@ TEST_P(StorageEdgeTest, VertexDetachDeleteSingleCommit) {
 //       {
 //         auto e = edges[0];
 //         ASSERT_EQ(e.EdgeType(), et1);
-//         ASSERT_EQ(e.FromVertex(), vertex1);
-//         ASSERT_EQ(e.ToVertex(), vertex2);
+//         ASSERT_EQ(e.From(), vertex1);
+//         ASSERT_EQ(e.To(), vertex2);
 //       }
 //       {
 //         auto e = edges[1];
 //         ASSERT_EQ(e.EdgeType(), et4);
-//         ASSERT_EQ(e.FromVertex(), vertex2);
-//         ASSERT_EQ(e.ToVertex(), vertex2);
+//         ASSERT_EQ(e.From(), vertex2);
+//         ASSERT_EQ(e.To(), vertex2);
 //       }
 //     }
 //     {
@@ -3429,14 +3429,14 @@ TEST_P(StorageEdgeTest, VertexDetachDeleteSingleCommit) {
 //       {
 //         auto e = edges[0];
 //         ASSERT_EQ(e.EdgeType(), et2);
-//         ASSERT_EQ(e.FromVertex(), vertex2);
-//         ASSERT_EQ(e.ToVertex(), vertex1);
+//         ASSERT_EQ(e.From(), vertex2);
+//         ASSERT_EQ(e.To(), vertex1);
 //       }
 //       {
 //         auto e = edges[1];
 //         ASSERT_EQ(e.EdgeType(), et4);
-//         ASSERT_EQ(e.FromVertex(), vertex2);
-//         ASSERT_EQ(e.ToVertex(), vertex2);
+//         ASSERT_EQ(e.From(), vertex2);
+//         ASSERT_EQ(e.To(), vertex2);
 //       }
 //     }
 
@@ -3480,14 +3480,14 @@ TEST_P(StorageEdgeTest, VertexDetachDeleteSingleCommit) {
 //       {
 //         auto e = edges[0];
 //         ASSERT_EQ(e.EdgeType(), et2);
-//         ASSERT_EQ(e.FromVertex(), *vertex2);
-//         ASSERT_EQ(e.ToVertex(), *vertex1);
+//         ASSERT_EQ(e.From(), *vertex2);
+//         ASSERT_EQ(e.To(), *vertex1);
 //       }
 //       {
 //         auto e = edges[1];
 //         ASSERT_EQ(e.EdgeType(), et3);
-//         ASSERT_EQ(e.FromVertex(), *vertex1);
-//         ASSERT_EQ(e.ToVertex(), *vertex1);
+//         ASSERT_EQ(e.From(), *vertex1);
+//         ASSERT_EQ(e.To(), *vertex1);
 //       }
 //     }
 //     ASSERT_EQ(vertex1->InEdges(View::NEW).GetError(), memgraph::storage::Error::DELETED_OBJECT);
@@ -3501,14 +3501,14 @@ TEST_P(StorageEdgeTest, VertexDetachDeleteSingleCommit) {
 //       {
 //         auto e = edges[0];
 //         ASSERT_EQ(e.EdgeType(), et1);
-//         ASSERT_EQ(e.FromVertex(), *vertex1);
-//         ASSERT_EQ(e.ToVertex(), *vertex2);
+//         ASSERT_EQ(e.From(), *vertex1);
+//         ASSERT_EQ(e.To(), *vertex2);
 //       }
 //       {
 //         auto e = edges[1];
 //         ASSERT_EQ(e.EdgeType(), et3);
-//         ASSERT_EQ(e.FromVertex(), *vertex1);
-//         ASSERT_EQ(e.ToVertex(), *vertex1);
+//         ASSERT_EQ(e.From(), *vertex1);
+//         ASSERT_EQ(e.To(), *vertex1);
 //       }
 //     }
 //     ASSERT_EQ(vertex1->OutEdges(View::NEW).GetError(), memgraph::storage::Error::DELETED_OBJECT);
@@ -3522,14 +3522,14 @@ TEST_P(StorageEdgeTest, VertexDetachDeleteSingleCommit) {
 //       {
 //         auto e = edges[0];
 //         ASSERT_EQ(e.EdgeType(), et1);
-//         ASSERT_EQ(e.FromVertex(), *vertex1);
-//         ASSERT_EQ(e.ToVertex(), *vertex2);
+//         ASSERT_EQ(e.From(), *vertex1);
+//         ASSERT_EQ(e.To(), *vertex2);
 //       }
 //       {
 //         auto e = edges[1];
 //         ASSERT_EQ(e.EdgeType(), et4);
-//         ASSERT_EQ(e.FromVertex(), *vertex2);
-//         ASSERT_EQ(e.ToVertex(), *vertex2);
+//         ASSERT_EQ(e.From(), *vertex2);
+//         ASSERT_EQ(e.To(), *vertex2);
 //       }
 //     }
 //     {
@@ -3540,8 +3540,8 @@ TEST_P(StorageEdgeTest, VertexDetachDeleteSingleCommit) {
 //       ASSERT_EQ(*vertex2->InDegree(View::NEW), 1);
 //       auto e = edges[0];
 //       ASSERT_EQ(e.EdgeType(), et4);
-//       ASSERT_EQ(e.FromVertex(), *vertex2);
-//       ASSERT_EQ(e.ToVertex(), *vertex2);
+//       ASSERT_EQ(e.From(), *vertex2);
+//       ASSERT_EQ(e.To(), *vertex2);
 //     }
 //     {
 //       auto ret = vertex2->OutEdges(View::OLD);
@@ -3552,14 +3552,14 @@ TEST_P(StorageEdgeTest, VertexDetachDeleteSingleCommit) {
 //       {
 //         auto e = edges[0];
 //         ASSERT_EQ(e.EdgeType(), et2);
-//         ASSERT_EQ(e.FromVertex(), *vertex2);
-//         ASSERT_EQ(e.ToVertex(), *vertex1);
+//         ASSERT_EQ(e.From(), *vertex2);
+//         ASSERT_EQ(e.To(), *vertex1);
 //       }
 //       {
 //         auto e = edges[1];
 //         ASSERT_EQ(e.EdgeType(), et4);
-//         ASSERT_EQ(e.FromVertex(), *vertex2);
-//         ASSERT_EQ(e.ToVertex(), *vertex2);
+//         ASSERT_EQ(e.From(), *vertex2);
+//         ASSERT_EQ(e.To(), *vertex2);
 //       }
 //     }
 //     {
@@ -3570,8 +3570,8 @@ TEST_P(StorageEdgeTest, VertexDetachDeleteSingleCommit) {
 //       ASSERT_EQ(*vertex2->OutDegree(View::NEW), 1);
 //       auto e = edges[0];
 //       ASSERT_EQ(e.EdgeType(), et4);
-//       ASSERT_EQ(e.FromVertex(), *vertex2);
-//       ASSERT_EQ(e.ToVertex(), *vertex2);
+//       ASSERT_EQ(e.From(), *vertex2);
+//       ASSERT_EQ(e.To(), *vertex2);
 //     }
 
 //     acc.Commit(GetNextHlc());
@@ -3596,8 +3596,8 @@ TEST_P(StorageEdgeTest, VertexDetachDeleteSingleCommit) {
 //       ASSERT_EQ(*vertex2->InDegree(View::OLD), 1);
 //       auto e = edges[0];
 //       ASSERT_EQ(e.EdgeType(), et4);
-//       ASSERT_EQ(e.FromVertex(), *vertex2);
-//       ASSERT_EQ(e.ToVertex(), *vertex2);
+//       ASSERT_EQ(e.From(), *vertex2);
+//       ASSERT_EQ(e.To(), *vertex2);
 //     }
 //     {
 //       auto ret = vertex2->InEdges(View::NEW);
@@ -3607,8 +3607,8 @@ TEST_P(StorageEdgeTest, VertexDetachDeleteSingleCommit) {
 //       ASSERT_EQ(*vertex2->InDegree(View::NEW), 1);
 //       auto e = edges[0];
 //       ASSERT_EQ(e.EdgeType(), et4);
-//       ASSERT_EQ(e.FromVertex(), *vertex2);
-//       ASSERT_EQ(e.ToVertex(), *vertex2);
+//       ASSERT_EQ(e.From(), *vertex2);
+//       ASSERT_EQ(e.To(), *vertex2);
 //     }
 //     {
 //       auto ret = vertex2->OutEdges(View::OLD);
@@ -3618,8 +3618,8 @@ TEST_P(StorageEdgeTest, VertexDetachDeleteSingleCommit) {
 //       ASSERT_EQ(*vertex2->OutDegree(View::OLD), 1);
 //       auto e = edges[0];
 //       ASSERT_EQ(e.EdgeType(), et4);
-//       ASSERT_EQ(e.FromVertex(), *vertex2);
-//       ASSERT_EQ(e.ToVertex(), *vertex2);
+//       ASSERT_EQ(e.From(), *vertex2);
+//       ASSERT_EQ(e.To(), *vertex2);
 //     }
 //     {
 //       auto ret = vertex2->OutEdges(View::NEW);
@@ -3629,8 +3629,8 @@ TEST_P(StorageEdgeTest, VertexDetachDeleteSingleCommit) {
 //       ASSERT_EQ(*vertex2->OutDegree(View::NEW), 1);
 //       auto e = edges[0];
 //       ASSERT_EQ(e.EdgeType(), et4);
-//       ASSERT_EQ(e.FromVertex(), *vertex2);
-//       ASSERT_EQ(e.ToVertex(), *vertex2);
+//       ASSERT_EQ(e.From(), *vertex2);
+//       ASSERT_EQ(e.To(), *vertex2);
 //     }
 //   }
 // }
@@ -3653,8 +3653,8 @@ TEST_P(StorageEdgeTest, VertexDetachDeleteSingleCommit) {
 //     ASSERT_TRUE(res.HasValue());
 //     auto edge = res.GetValue();
 //     ASSERT_EQ(edge.EdgeType(), et);
-//     ASSERT_EQ(edge.FromVertex(), vertex_from);
-//     ASSERT_EQ(edge.ToVertex(), vertex_to);
+//     ASSERT_EQ(edge.From(), vertex_from);
+//     ASSERT_EQ(edge.To(), vertex_to);
 
 //     gid_from = vertex_from.Gid();
 //     gid_to = vertex_to.Gid();
@@ -3670,8 +3670,8 @@ TEST_P(StorageEdgeTest, VertexDetachDeleteSingleCommit) {
 //       ASSERT_EQ(*vertex_from.OutDegree(View::NEW), 1);
 //       auto e = edges[0];
 //       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.FromVertex(), vertex_from);
-//       ASSERT_EQ(e.ToVertex(), vertex_to);
+//       ASSERT_EQ(e.From(), vertex_from);
+//       ASSERT_EQ(e.To(), vertex_to);
 //     }
 //     {
 //       auto ret = vertex_to.InEdges(View::NEW);
@@ -3681,8 +3681,8 @@ TEST_P(StorageEdgeTest, VertexDetachDeleteSingleCommit) {
 //       ASSERT_EQ(*vertex_to.InDegree(View::NEW), 1);
 //       auto e = edges[0];
 //       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.FromVertex(), vertex_from);
-//       ASSERT_EQ(e.ToVertex(), vertex_to);
+//       ASSERT_EQ(e.From(), vertex_from);
+//       ASSERT_EQ(e.To(), vertex_to);
 //     }
 //     ASSERT_EQ(vertex_to.OutEdges(View::NEW)->size(), 0);
 //     ASSERT_EQ(*vertex_to.OutDegree(View::NEW), 0);
@@ -3727,8 +3727,8 @@ TEST_P(StorageEdgeTest, VertexDetachDeleteSingleCommit) {
 //       ASSERT_EQ(*vertex_from->OutDegree(View::OLD), 1);
 //       auto e = edges[0];
 //       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.FromVertex(), *vertex_from);
-//       ASSERT_EQ(e.ToVertex(), *vertex_to);
+//       ASSERT_EQ(e.From(), *vertex_from);
+//       ASSERT_EQ(e.To(), *vertex_to);
 //     }
 //     ASSERT_EQ(vertex_from->OutEdges(View::NEW).GetError(), memgraph::storage::Error::DELETED_OBJECT);
 //     ASSERT_EQ(vertex_from->OutDegree(View::NEW).GetError(), memgraph::storage::Error::DELETED_OBJECT);
@@ -3740,8 +3740,8 @@ TEST_P(StorageEdgeTest, VertexDetachDeleteSingleCommit) {
 //       ASSERT_EQ(*vertex_to->InDegree(View::OLD), 1);
 //       auto e = edges[0];
 //       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.FromVertex(), *vertex_from);
-//       ASSERT_EQ(e.ToVertex(), *vertex_to);
+//       ASSERT_EQ(e.From(), *vertex_from);
+//       ASSERT_EQ(e.To(), *vertex_to);
 //     }
 //     ASSERT_EQ(vertex_to->InEdges(View::NEW)->size(), 0);
 //     ASSERT_EQ(*vertex_to->InDegree(View::NEW), 0);
@@ -3774,8 +3774,8 @@ TEST_P(StorageEdgeTest, VertexDetachDeleteSingleCommit) {
 //       ASSERT_EQ(*vertex_from->OutDegree(View::NEW), 1);
 //       auto e = edges[0];
 //       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.FromVertex(), *vertex_from);
-//       ASSERT_EQ(e.ToVertex(), *vertex_to);
+//       ASSERT_EQ(e.From(), *vertex_from);
+//       ASSERT_EQ(e.To(), *vertex_to);
 //     }
 //     {
 //       auto ret = vertex_to->InEdges(View::NEW);
@@ -3785,8 +3785,8 @@ TEST_P(StorageEdgeTest, VertexDetachDeleteSingleCommit) {
 //       ASSERT_EQ(*vertex_to->InDegree(View::NEW), 1);
 //       auto e = edges[0];
 //       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.FromVertex(), *vertex_from);
-//       ASSERT_EQ(e.ToVertex(), *vertex_to);
+//       ASSERT_EQ(e.From(), *vertex_from);
+//       ASSERT_EQ(e.To(), *vertex_to);
 //     }
 //     ASSERT_EQ(vertex_to->OutEdges(View::NEW)->size(), 0);
 //     ASSERT_EQ(*vertex_to->OutDegree(View::NEW), 0);
@@ -3831,8 +3831,8 @@ TEST_P(StorageEdgeTest, VertexDetachDeleteSingleCommit) {
 //       ASSERT_EQ(*vertex_from->OutDegree(View::OLD), 1);
 //       auto e = edges[0];
 //       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.FromVertex(), *vertex_from);
-//       ASSERT_EQ(e.ToVertex(), *vertex_to);
+//       ASSERT_EQ(e.From(), *vertex_from);
+//       ASSERT_EQ(e.To(), *vertex_to);
 //     }
 //     ASSERT_EQ(vertex_from->OutEdges(View::NEW).GetError(), memgraph::storage::Error::DELETED_OBJECT);
 //     ASSERT_EQ(vertex_from->OutDegree(View::NEW).GetError(), memgraph::storage::Error::DELETED_OBJECT);
@@ -3844,8 +3844,8 @@ TEST_P(StorageEdgeTest, VertexDetachDeleteSingleCommit) {
 //       ASSERT_EQ(*vertex_to->InDegree(View::OLD), 1);
 //       auto e = edges[0];
 //       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.FromVertex(), *vertex_from);
-//       ASSERT_EQ(e.ToVertex(), *vertex_to);
+//       ASSERT_EQ(e.From(), *vertex_from);
+//       ASSERT_EQ(e.To(), *vertex_to);
 //     }
 //     ASSERT_EQ(vertex_to->InEdges(View::NEW)->size(), 0);
 //     ASSERT_EQ(*vertex_to->InDegree(View::NEW), 0);
@@ -3901,29 +3901,29 @@ TEST_P(StorageEdgeTest, VertexDetachDeleteSingleCommit) {
 //     ASSERT_TRUE(res1.HasValue());
 //     auto edge1 = res1.GetValue();
 //     ASSERT_EQ(edge1.EdgeType(), et1);
-//     ASSERT_EQ(edge1.FromVertex(), vertex1);
-//     ASSERT_EQ(edge1.ToVertex(), vertex2);
+//     ASSERT_EQ(edge1.From(), vertex1);
+//     ASSERT_EQ(edge1.To(), vertex2);
 
 //     auto res2 = acc.CreateEdge(&vertex2, &vertex1, et2);
 //     ASSERT_TRUE(res2.HasValue());
 //     auto edge2 = res2.GetValue();
 //     ASSERT_EQ(edge2.EdgeType(), et2);
-//     ASSERT_EQ(edge2.FromVertex(), vertex2);
-//     ASSERT_EQ(edge2.ToVertex(), vertex1);
+//     ASSERT_EQ(edge2.From(), vertex2);
+//     ASSERT_EQ(edge2.To(), vertex1);
 
 //     auto res3 = acc.CreateEdge(&vertex1, &vertex1, et3);
 //     ASSERT_TRUE(res3.HasValue());
 //     auto edge3 = res3.GetValue();
 //     ASSERT_EQ(edge3.EdgeType(), et3);
-//     ASSERT_EQ(edge3.FromVertex(), vertex1);
-//     ASSERT_EQ(edge3.ToVertex(), vertex1);
+//     ASSERT_EQ(edge3.From(), vertex1);
+//     ASSERT_EQ(edge3.To(), vertex1);
 
 //     auto res4 = acc.CreateEdge(&vertex2, &vertex2, et4);
 //     ASSERT_TRUE(res4.HasValue());
 //     auto edge4 = res4.GetValue();
 //     ASSERT_EQ(edge4.EdgeType(), et4);
-//     ASSERT_EQ(edge4.FromVertex(), vertex2);
-//     ASSERT_EQ(edge4.ToVertex(), vertex2);
+//     ASSERT_EQ(edge4.From(), vertex2);
+//     ASSERT_EQ(edge4.To(), vertex2);
 
 //     // Check edges
 //     {
@@ -3935,14 +3935,14 @@ TEST_P(StorageEdgeTest, VertexDetachDeleteSingleCommit) {
 //       {
 //         auto e = edges[0];
 //         ASSERT_EQ(e.EdgeType(), et2);
-//         ASSERT_EQ(e.FromVertex(), vertex2);
-//         ASSERT_EQ(e.ToVertex(), vertex1);
+//         ASSERT_EQ(e.From(), vertex2);
+//         ASSERT_EQ(e.To(), vertex1);
 //       }
 //       {
 //         auto e = edges[1];
 //         ASSERT_EQ(e.EdgeType(), et3);
-//         ASSERT_EQ(e.FromVertex(), vertex1);
-//         ASSERT_EQ(e.ToVertex(), vertex1);
+//         ASSERT_EQ(e.From(), vertex1);
+//         ASSERT_EQ(e.To(), vertex1);
 //       }
 //     }
 //     {
@@ -3954,14 +3954,14 @@ TEST_P(StorageEdgeTest, VertexDetachDeleteSingleCommit) {
 //       {
 //         auto e = edges[0];
 //         ASSERT_EQ(e.EdgeType(), et1);
-//         ASSERT_EQ(e.FromVertex(), vertex1);
-//         ASSERT_EQ(e.ToVertex(), vertex2);
+//         ASSERT_EQ(e.From(), vertex1);
+//         ASSERT_EQ(e.To(), vertex2);
 //       }
 //       {
 //         auto e = edges[1];
 //         ASSERT_EQ(e.EdgeType(), et3);
-//         ASSERT_EQ(e.FromVertex(), vertex1);
-//         ASSERT_EQ(e.ToVertex(), vertex1);
+//         ASSERT_EQ(e.From(), vertex1);
+//         ASSERT_EQ(e.To(), vertex1);
 //       }
 //     }
 //     {
@@ -3973,14 +3973,14 @@ TEST_P(StorageEdgeTest, VertexDetachDeleteSingleCommit) {
 //       {
 //         auto e = edges[0];
 //         ASSERT_EQ(e.EdgeType(), et1);
-//         ASSERT_EQ(e.FromVertex(), vertex1);
-//         ASSERT_EQ(e.ToVertex(), vertex2);
+//         ASSERT_EQ(e.From(), vertex1);
+//         ASSERT_EQ(e.To(), vertex2);
 //       }
 //       {
 //         auto e = edges[1];
 //         ASSERT_EQ(e.EdgeType(), et4);
-//         ASSERT_EQ(e.FromVertex(), vertex2);
-//         ASSERT_EQ(e.ToVertex(), vertex2);
+//         ASSERT_EQ(e.From(), vertex2);
+//         ASSERT_EQ(e.To(), vertex2);
 //       }
 //     }
 //     {
@@ -3992,14 +3992,14 @@ TEST_P(StorageEdgeTest, VertexDetachDeleteSingleCommit) {
 //       {
 //         auto e = edges[0];
 //         ASSERT_EQ(e.EdgeType(), et2);
-//         ASSERT_EQ(e.FromVertex(), vertex2);
-//         ASSERT_EQ(e.ToVertex(), vertex1);
+//         ASSERT_EQ(e.From(), vertex2);
+//         ASSERT_EQ(e.To(), vertex1);
 //       }
 //       {
 //         auto e = edges[1];
 //         ASSERT_EQ(e.EdgeType(), et4);
-//         ASSERT_EQ(e.FromVertex(), vertex2);
-//         ASSERT_EQ(e.ToVertex(), vertex2);
+//         ASSERT_EQ(e.From(), vertex2);
+//         ASSERT_EQ(e.To(), vertex2);
 //       }
 //     }
 
@@ -4043,14 +4043,14 @@ TEST_P(StorageEdgeTest, VertexDetachDeleteSingleCommit) {
 //       {
 //         auto e = edges[0];
 //         ASSERT_EQ(e.EdgeType(), et2);
-//         ASSERT_EQ(e.FromVertex(), *vertex2);
-//         ASSERT_EQ(e.ToVertex(), *vertex1);
+//         ASSERT_EQ(e.From(), *vertex2);
+//         ASSERT_EQ(e.To(), *vertex1);
 //       }
 //       {
 //         auto e = edges[1];
 //         ASSERT_EQ(e.EdgeType(), et3);
-//         ASSERT_EQ(e.FromVertex(), *vertex1);
-//         ASSERT_EQ(e.ToVertex(), *vertex1);
+//         ASSERT_EQ(e.From(), *vertex1);
+//         ASSERT_EQ(e.To(), *vertex1);
 //       }
 //     }
 //     ASSERT_EQ(vertex1->InEdges(View::NEW).GetError(), memgraph::storage::Error::DELETED_OBJECT);
@@ -4064,14 +4064,14 @@ TEST_P(StorageEdgeTest, VertexDetachDeleteSingleCommit) {
 //       {
 //         auto e = edges[0];
 //         ASSERT_EQ(e.EdgeType(), et1);
-//         ASSERT_EQ(e.FromVertex(), *vertex1);
-//         ASSERT_EQ(e.ToVertex(), *vertex2);
+//         ASSERT_EQ(e.From(), *vertex1);
+//         ASSERT_EQ(e.To(), *vertex2);
 //       }
 //       {
 //         auto e = edges[1];
 //         ASSERT_EQ(e.EdgeType(), et3);
-//         ASSERT_EQ(e.FromVertex(), *vertex1);
-//         ASSERT_EQ(e.ToVertex(), *vertex1);
+//         ASSERT_EQ(e.From(), *vertex1);
+//         ASSERT_EQ(e.To(), *vertex1);
 //       }
 //     }
 //     ASSERT_EQ(vertex1->OutEdges(View::NEW).GetError(), memgraph::storage::Error::DELETED_OBJECT);
@@ -4085,14 +4085,14 @@ TEST_P(StorageEdgeTest, VertexDetachDeleteSingleCommit) {
 //       {
 //         auto e = edges[0];
 //         ASSERT_EQ(e.EdgeType(), et1);
-//         ASSERT_EQ(e.FromVertex(), *vertex1);
-//         ASSERT_EQ(e.ToVertex(), *vertex2);
+//         ASSERT_EQ(e.From(), *vertex1);
+//         ASSERT_EQ(e.To(), *vertex2);
 //       }
 //       {
 //         auto e = edges[1];
 //         ASSERT_EQ(e.EdgeType(), et4);
-//         ASSERT_EQ(e.FromVertex(), *vertex2);
-//         ASSERT_EQ(e.ToVertex(), *vertex2);
+//         ASSERT_EQ(e.From(), *vertex2);
+//         ASSERT_EQ(e.To(), *vertex2);
 //       }
 //     }
 //     {
@@ -4103,8 +4103,8 @@ TEST_P(StorageEdgeTest, VertexDetachDeleteSingleCommit) {
 //       ASSERT_EQ(*vertex2->InDegree(View::NEW), 1);
 //       auto e = edges[0];
 //       ASSERT_EQ(e.EdgeType(), et4);
-//       ASSERT_EQ(e.FromVertex(), *vertex2);
-//       ASSERT_EQ(e.ToVertex(), *vertex2);
+//       ASSERT_EQ(e.From(), *vertex2);
+//       ASSERT_EQ(e.To(), *vertex2);
 //     }
 //     {
 //       auto ret = vertex2->OutEdges(View::OLD);
@@ -4115,14 +4115,14 @@ TEST_P(StorageEdgeTest, VertexDetachDeleteSingleCommit) {
 //       {
 //         auto e = edges[0];
 //         ASSERT_EQ(e.EdgeType(), et2);
-//         ASSERT_EQ(e.FromVertex(), *vertex2);
-//         ASSERT_EQ(e.ToVertex(), *vertex1);
+//         ASSERT_EQ(e.From(), *vertex2);
+//         ASSERT_EQ(e.To(), *vertex1);
 //       }
 //       {
 //         auto e = edges[1];
 //         ASSERT_EQ(e.EdgeType(), et4);
-//         ASSERT_EQ(e.FromVertex(), *vertex2);
-//         ASSERT_EQ(e.ToVertex(), *vertex2);
+//         ASSERT_EQ(e.From(), *vertex2);
+//         ASSERT_EQ(e.To(), *vertex2);
 //       }
 //     }
 //     {
@@ -4133,8 +4133,8 @@ TEST_P(StorageEdgeTest, VertexDetachDeleteSingleCommit) {
 //       ASSERT_EQ(*vertex2->OutDegree(View::NEW), 1);
 //       auto e = edges[0];
 //       ASSERT_EQ(e.EdgeType(), et4);
-//       ASSERT_EQ(e.FromVertex(), *vertex2);
-//       ASSERT_EQ(e.ToVertex(), *vertex2);
+//       ASSERT_EQ(e.From(), *vertex2);
+//       ASSERT_EQ(e.To(), *vertex2);
 //     }
 
 //     acc.Abort();
@@ -4163,14 +4163,14 @@ TEST_P(StorageEdgeTest, VertexDetachDeleteSingleCommit) {
 //       {
 //         auto e = edges[0];
 //         ASSERT_EQ(e.EdgeType(), et2);
-//         ASSERT_EQ(e.FromVertex(), *vertex2);
-//         ASSERT_EQ(e.ToVertex(), *vertex1);
+//         ASSERT_EQ(e.From(), *vertex2);
+//         ASSERT_EQ(e.To(), *vertex1);
 //       }
 //       {
 //         auto e = edges[1];
 //         ASSERT_EQ(e.EdgeType(), et3);
-//         ASSERT_EQ(e.FromVertex(), *vertex1);
-//         ASSERT_EQ(e.ToVertex(), *vertex1);
+//         ASSERT_EQ(e.From(), *vertex1);
+//         ASSERT_EQ(e.To(), *vertex1);
 //       }
 //     }
 //     {
@@ -4182,14 +4182,14 @@ TEST_P(StorageEdgeTest, VertexDetachDeleteSingleCommit) {
 //       {
 //         auto e = edges[0];
 //         ASSERT_EQ(e.EdgeType(), et2);
-//         ASSERT_EQ(e.FromVertex(), *vertex2);
-//         ASSERT_EQ(e.ToVertex(), *vertex1);
+//         ASSERT_EQ(e.From(), *vertex2);
+//         ASSERT_EQ(e.To(), *vertex1);
 //       }
 //       {
 //         auto e = edges[1];
 //         ASSERT_EQ(e.EdgeType(), et3);
-//         ASSERT_EQ(e.FromVertex(), *vertex1);
-//         ASSERT_EQ(e.ToVertex(), *vertex1);
+//         ASSERT_EQ(e.From(), *vertex1);
+//         ASSERT_EQ(e.To(), *vertex1);
 //       }
 //     }
 //     {
@@ -4201,14 +4201,14 @@ TEST_P(StorageEdgeTest, VertexDetachDeleteSingleCommit) {
 //       {
 //         auto e = edges[0];
 //         ASSERT_EQ(e.EdgeType(), et1);
-//         ASSERT_EQ(e.FromVertex(), *vertex1);
-//         ASSERT_EQ(e.ToVertex(), *vertex2);
+//         ASSERT_EQ(e.From(), *vertex1);
+//         ASSERT_EQ(e.To(), *vertex2);
 //       }
 //       {
 //         auto e = edges[1];
 //         ASSERT_EQ(e.EdgeType(), et3);
-//         ASSERT_EQ(e.FromVertex(), *vertex1);
-//         ASSERT_EQ(e.ToVertex(), *vertex1);
+//         ASSERT_EQ(e.From(), *vertex1);
+//         ASSERT_EQ(e.To(), *vertex1);
 //       }
 //     }
 //     {
@@ -4220,14 +4220,14 @@ TEST_P(StorageEdgeTest, VertexDetachDeleteSingleCommit) {
 //       {
 //         auto e = edges[0];
 //         ASSERT_EQ(e.EdgeType(), et1);
-//         ASSERT_EQ(e.FromVertex(), *vertex1);
-//         ASSERT_EQ(e.ToVertex(), *vertex2);
+//         ASSERT_EQ(e.From(), *vertex1);
+//         ASSERT_EQ(e.To(), *vertex2);
 //       }
 //       {
 //         auto e = edges[1];
 //         ASSERT_EQ(e.EdgeType(), et3);
-//         ASSERT_EQ(e.FromVertex(), *vertex1);
-//         ASSERT_EQ(e.ToVertex(), *vertex1);
+//         ASSERT_EQ(e.From(), *vertex1);
+//         ASSERT_EQ(e.To(), *vertex1);
 //       }
 //     }
 //     {
@@ -4239,14 +4239,14 @@ TEST_P(StorageEdgeTest, VertexDetachDeleteSingleCommit) {
 //       {
 //         auto e = edges[0];
 //         ASSERT_EQ(e.EdgeType(), et1);
-//         ASSERT_EQ(e.FromVertex(), *vertex1);
-//         ASSERT_EQ(e.ToVertex(), *vertex2);
+//         ASSERT_EQ(e.From(), *vertex1);
+//         ASSERT_EQ(e.To(), *vertex2);
 //       }
 //       {
 //         auto e = edges[1];
 //         ASSERT_EQ(e.EdgeType(), et4);
-//         ASSERT_EQ(e.FromVertex(), *vertex2);
-//         ASSERT_EQ(e.ToVertex(), *vertex2);
+//         ASSERT_EQ(e.From(), *vertex2);
+//         ASSERT_EQ(e.To(), *vertex2);
 //       }
 //     }
 //     {
@@ -4258,14 +4258,14 @@ TEST_P(StorageEdgeTest, VertexDetachDeleteSingleCommit) {
 //       {
 //         auto e = edges[0];
 //         ASSERT_EQ(e.EdgeType(), et1);
-//         ASSERT_EQ(e.FromVertex(), *vertex1);
-//         ASSERT_EQ(e.ToVertex(), *vertex2);
+//         ASSERT_EQ(e.From(), *vertex1);
+//         ASSERT_EQ(e.To(), *vertex2);
 //       }
 //       {
 //         auto e = edges[1];
 //         ASSERT_EQ(e.EdgeType(), et4);
-//         ASSERT_EQ(e.FromVertex(), *vertex2);
-//         ASSERT_EQ(e.ToVertex(), *vertex2);
+//         ASSERT_EQ(e.From(), *vertex2);
+//         ASSERT_EQ(e.To(), *vertex2);
 //       }
 //     }
 //     {
@@ -4277,14 +4277,14 @@ TEST_P(StorageEdgeTest, VertexDetachDeleteSingleCommit) {
 //       {
 //         auto e = edges[0];
 //         ASSERT_EQ(e.EdgeType(), et2);
-//         ASSERT_EQ(e.FromVertex(), *vertex2);
-//         ASSERT_EQ(e.ToVertex(), *vertex1);
+//         ASSERT_EQ(e.From(), *vertex2);
+//         ASSERT_EQ(e.To(), *vertex1);
 //       }
 //       {
 //         auto e = edges[1];
 //         ASSERT_EQ(e.EdgeType(), et4);
-//         ASSERT_EQ(e.FromVertex(), *vertex2);
-//         ASSERT_EQ(e.ToVertex(), *vertex2);
+//         ASSERT_EQ(e.From(), *vertex2);
+//         ASSERT_EQ(e.To(), *vertex2);
 //       }
 //     }
 //     {
@@ -4296,14 +4296,14 @@ TEST_P(StorageEdgeTest, VertexDetachDeleteSingleCommit) {
 //       {
 //         auto e = edges[0];
 //         ASSERT_EQ(e.EdgeType(), et2);
-//         ASSERT_EQ(e.FromVertex(), *vertex2);
-//         ASSERT_EQ(e.ToVertex(), *vertex1);
+//         ASSERT_EQ(e.From(), *vertex2);
+//         ASSERT_EQ(e.To(), *vertex1);
 //       }
 //       {
 //         auto e = edges[1];
 //         ASSERT_EQ(e.EdgeType(), et4);
-//         ASSERT_EQ(e.FromVertex(), *vertex2);
-//         ASSERT_EQ(e.ToVertex(), *vertex2);
+//         ASSERT_EQ(e.From(), *vertex2);
+//         ASSERT_EQ(e.To(), *vertex2);
 //       }
 //     }
 
@@ -4347,14 +4347,14 @@ TEST_P(StorageEdgeTest, VertexDetachDeleteSingleCommit) {
 //       {
 //         auto e = edges[0];
 //         ASSERT_EQ(e.EdgeType(), et2);
-//         ASSERT_EQ(e.FromVertex(), *vertex2);
-//         ASSERT_EQ(e.ToVertex(), *vertex1);
+//         ASSERT_EQ(e.From(), *vertex2);
+//         ASSERT_EQ(e.To(), *vertex1);
 //       }
 //       {
 //         auto e = edges[1];
 //         ASSERT_EQ(e.EdgeType(), et3);
-//         ASSERT_EQ(e.FromVertex(), *vertex1);
-//         ASSERT_EQ(e.ToVertex(), *vertex1);
+//         ASSERT_EQ(e.From(), *vertex1);
+//         ASSERT_EQ(e.To(), *vertex1);
 //       }
 //     }
 //     ASSERT_EQ(vertex1->InEdges(View::NEW).GetError(), memgraph::storage::Error::DELETED_OBJECT);
@@ -4368,14 +4368,14 @@ TEST_P(StorageEdgeTest, VertexDetachDeleteSingleCommit) {
 //       {
 //         auto e = edges[0];
 //         ASSERT_EQ(e.EdgeType(), et1);
-//         ASSERT_EQ(e.FromVertex(), *vertex1);
-//         ASSERT_EQ(e.ToVertex(), *vertex2);
+//         ASSERT_EQ(e.From(), *vertex1);
+//         ASSERT_EQ(e.To(), *vertex2);
 //       }
 //       {
 //         auto e = edges[1];
 //         ASSERT_EQ(e.EdgeType(), et3);
-//         ASSERT_EQ(e.FromVertex(), *vertex1);
-//         ASSERT_EQ(e.ToVertex(), *vertex1);
+//         ASSERT_EQ(e.From(), *vertex1);
+//         ASSERT_EQ(e.To(), *vertex1);
 //       }
 //     }
 //     ASSERT_EQ(vertex1->OutEdges(View::NEW).GetError(), memgraph::storage::Error::DELETED_OBJECT);
@@ -4389,14 +4389,14 @@ TEST_P(StorageEdgeTest, VertexDetachDeleteSingleCommit) {
 //       {
 //         auto e = edges[0];
 //         ASSERT_EQ(e.EdgeType(), et1);
-//         ASSERT_EQ(e.FromVertex(), *vertex1);
-//         ASSERT_EQ(e.ToVertex(), *vertex2);
+//         ASSERT_EQ(e.From(), *vertex1);
+//         ASSERT_EQ(e.To(), *vertex2);
 //       }
 //       {
 //         auto e = edges[1];
 //         ASSERT_EQ(e.EdgeType(), et4);
-//         ASSERT_EQ(e.FromVertex(), *vertex2);
-//         ASSERT_EQ(e.ToVertex(), *vertex2);
+//         ASSERT_EQ(e.From(), *vertex2);
+//         ASSERT_EQ(e.To(), *vertex2);
 //       }
 //     }
 //     {
@@ -4407,8 +4407,8 @@ TEST_P(StorageEdgeTest, VertexDetachDeleteSingleCommit) {
 //       ASSERT_EQ(*vertex2->InDegree(View::NEW), 1);
 //       auto e = edges[0];
 //       ASSERT_EQ(e.EdgeType(), et4);
-//       ASSERT_EQ(e.FromVertex(), *vertex2);
-//       ASSERT_EQ(e.ToVertex(), *vertex2);
+//       ASSERT_EQ(e.From(), *vertex2);
+//       ASSERT_EQ(e.To(), *vertex2);
 //     }
 //     {
 //       auto ret = vertex2->OutEdges(View::OLD);
@@ -4419,14 +4419,14 @@ TEST_P(StorageEdgeTest, VertexDetachDeleteSingleCommit) {
 //       {
 //         auto e = edges[0];
 //         ASSERT_EQ(e.EdgeType(), et2);
-//         ASSERT_EQ(e.FromVertex(), *vertex2);
-//         ASSERT_EQ(e.ToVertex(), *vertex1);
+//         ASSERT_EQ(e.From(), *vertex2);
+//         ASSERT_EQ(e.To(), *vertex1);
 //       }
 //       {
 //         auto e = edges[1];
 //         ASSERT_EQ(e.EdgeType(), et4);
-//         ASSERT_EQ(e.FromVertex(), *vertex2);
-//         ASSERT_EQ(e.ToVertex(), *vertex2);
+//         ASSERT_EQ(e.From(), *vertex2);
+//         ASSERT_EQ(e.To(), *vertex2);
 //       }
 //     }
 //     {
@@ -4437,8 +4437,8 @@ TEST_P(StorageEdgeTest, VertexDetachDeleteSingleCommit) {
 //       ASSERT_EQ(*vertex2->OutDegree(View::NEW), 1);
 //       auto e = edges[0];
 //       ASSERT_EQ(e.EdgeType(), et4);
-//       ASSERT_EQ(e.FromVertex(), *vertex2);
-//       ASSERT_EQ(e.ToVertex(), *vertex2);
+//       ASSERT_EQ(e.From(), *vertex2);
+//       ASSERT_EQ(e.To(), *vertex2);
 //     }
 
 //     acc.Commit(GetNextHlc());
@@ -4463,8 +4463,8 @@ TEST_P(StorageEdgeTest, VertexDetachDeleteSingleCommit) {
 //       ASSERT_EQ(*vertex2->InDegree(View::OLD), 1);
 //       auto e = edges[0];
 //       ASSERT_EQ(e.EdgeType(), et4);
-//       ASSERT_EQ(e.FromVertex(), *vertex2);
-//       ASSERT_EQ(e.ToVertex(), *vertex2);
+//       ASSERT_EQ(e.From(), *vertex2);
+//       ASSERT_EQ(e.To(), *vertex2);
 //     }
 //     {
 //       auto ret = vertex2->InEdges(View::NEW);
@@ -4474,8 +4474,8 @@ TEST_P(StorageEdgeTest, VertexDetachDeleteSingleCommit) {
 //       ASSERT_EQ(*vertex2->InDegree(View::NEW), 1);
 //       auto e = edges[0];
 //       ASSERT_EQ(e.EdgeType(), et4);
-//       ASSERT_EQ(e.FromVertex(), *vertex2);
-//       ASSERT_EQ(e.ToVertex(), *vertex2);
+//       ASSERT_EQ(e.From(), *vertex2);
+//       ASSERT_EQ(e.To(), *vertex2);
 //     }
 //     {
 //       auto ret = vertex2->OutEdges(View::OLD);
@@ -4485,8 +4485,8 @@ TEST_P(StorageEdgeTest, VertexDetachDeleteSingleCommit) {
 //       ASSERT_EQ(*vertex2->OutDegree(View::OLD), 1);
 //       auto e = edges[0];
 //       ASSERT_EQ(e.EdgeType(), et4);
-//       ASSERT_EQ(e.FromVertex(), *vertex2);
-//       ASSERT_EQ(e.ToVertex(), *vertex2);
+//       ASSERT_EQ(e.From(), *vertex2);
+//       ASSERT_EQ(e.To(), *vertex2);
 //     }
 //     {
 //       auto ret = vertex2->OutEdges(View::NEW);
@@ -4496,8 +4496,8 @@ TEST_P(StorageEdgeTest, VertexDetachDeleteSingleCommit) {
 //       ASSERT_EQ(*vertex2->OutDegree(View::NEW), 1);
 //       auto e = edges[0];
 //       ASSERT_EQ(e.EdgeType(), et4);
-//       ASSERT_EQ(e.FromVertex(), *vertex2);
-//       ASSERT_EQ(e.ToVertex(), *vertex2);
+//       ASSERT_EQ(e.From(), *vertex2);
+//       ASSERT_EQ(e.To(), *vertex2);
 //     }
 //   }
 // }
@@ -4513,8 +4513,8 @@ TEST_P(StorageEdgeTest, VertexDetachDeleteSingleCommit) {
 //     auto et = acc.NameToEdgeType("et5");
 //     auto edge = acc.CreateEdge(&vertex, &vertex, et).GetValue();
 //     ASSERT_EQ(edge.EdgeType(), et);
-//     ASSERT_EQ(edge.FromVertex(), vertex);
-//     ASSERT_EQ(edge.ToVertex(), vertex);
+//     ASSERT_EQ(edge.From(), vertex);
+//     ASSERT_EQ(edge.To(), vertex);
 
 //     auto property = acc.NameToProperty("property5");
 
@@ -4645,8 +4645,8 @@ TEST_P(StorageEdgeTest, VertexDetachDeleteSingleCommit) {
 //     auto et = acc.NameToEdgeType("et5");
 //     auto edge = acc.CreateEdge(&vertex, &vertex, et).GetValue();
 //     ASSERT_EQ(edge.EdgeType(), et);
-//     ASSERT_EQ(edge.FromVertex(), vertex);
-//     ASSERT_EQ(edge.ToVertex(), vertex);
+//     ASSERT_EQ(edge.From(), vertex);
+//     ASSERT_EQ(edge.To(), vertex);
 //     acc.Commit(GetNextHlc());
 //   }
 
@@ -4934,8 +4934,8 @@ TEST_P(StorageEdgeTest, VertexDetachDeleteSingleCommit) {
 //     auto et = acc.NameToEdgeType("et5");
 //     auto edge = acc.CreateEdge(&vertex, &vertex, et).GetValue();
 //     ASSERT_EQ(edge.EdgeType(), et);
-//     ASSERT_EQ(edge.FromVertex(), vertex);
-//     ASSERT_EQ(edge.ToVertex(), vertex);
+//     ASSERT_EQ(edge.From(), vertex);
+//     ASSERT_EQ(edge.To(), vertex);
 //     acc.Commit(GetNextHlc());
 //   }
 
@@ -5045,8 +5045,8 @@ TEST_P(StorageEdgeTest, VertexDetachDeleteSingleCommit) {
 //     auto et = acc.NameToEdgeType("et5");
 //     auto edge = acc.CreateEdge(&vertex, &vertex, et).GetValue();
 //     ASSERT_EQ(edge.EdgeType(), et);
-//     ASSERT_EQ(edge.FromVertex(), vertex);
-//     ASSERT_EQ(edge.ToVertex(), vertex);
+//     ASSERT_EQ(edge.From(), vertex);
+//     ASSERT_EQ(edge.To(), vertex);
 
 //     auto old_value = edge.SetProperty(property1, memgraph::storage::PropertyValue("value"));
 //     ASSERT_TRUE(old_value.HasValue());
@@ -5158,8 +5158,8 @@ TEST_P(StorageEdgeTest, VertexDetachDeleteSingleCommit) {
 //     auto et = acc.NameToEdgeType("et5");
 //     auto edge = acc.CreateEdge(&vertex, &vertex, et).GetValue();
 //     ASSERT_EQ(edge.EdgeType(), et);
-//     ASSERT_EQ(edge.FromVertex(), vertex);
-//     ASSERT_EQ(edge.ToVertex(), vertex);
+//     ASSERT_EQ(edge.From(), vertex);
+//     ASSERT_EQ(edge.To(), vertex);
 //     acc.Commit(GetNextHlc());
 //   }
 //   {
@@ -5226,8 +5226,8 @@ TEST_P(StorageEdgeTest, VertexDetachDeleteSingleCommit) {
 //     auto et = acc.NameToEdgeType("et5");
 //     auto edge = acc.CreateEdge(&vertex, &vertex, et).GetValue();
 //     ASSERT_EQ(edge.EdgeType(), et);
-//     ASSERT_EQ(edge.FromVertex(), vertex);
-//     ASSERT_EQ(edge.ToVertex(), vertex);
+//     ASSERT_EQ(edge.From(), vertex);
+//     ASSERT_EQ(edge.To(), vertex);
 //     acc.Commit(GetNextHlc());
 //   }
 //   {

From 94bc671551281a426e5c3ea94e0c3ca3d22fdba3 Mon Sep 17 00:00:00 2001
From: Kostas Kyrimis <kostaskyrim@gmail.com>
Date: Wed, 9 Nov 2022 18:15:30 +0200
Subject: [PATCH 02/26] Add awesome memgraph functions e2e tests

---
 tests/e2e/distributed_queries/CMakeLists.txt  |  1 +
 .../awesome_memgraph_functions.py             | 90 +++++++++++++++++++
 tests/e2e/distributed_queries/workloads.yaml  |  5 ++
 3 files changed, 96 insertions(+)
 create mode 100644 tests/e2e/distributed_queries/awesome_memgraph_functions.py

diff --git a/tests/e2e/distributed_queries/CMakeLists.txt b/tests/e2e/distributed_queries/CMakeLists.txt
index 455e6ad45..5a7a8d81b 100644
--- a/tests/e2e/distributed_queries/CMakeLists.txt
+++ b/tests/e2e/distributed_queries/CMakeLists.txt
@@ -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(optional_match.py)
 distributed_queries_e2e_python_files(common.py)
+distributed_queries_e2e_python_files(awesome_memgraph_functions.py)
diff --git a/tests/e2e/distributed_queries/awesome_memgraph_functions.py b/tests/e2e/distributed_queries/awesome_memgraph_functions.py
new file mode 100644
index 000000000..469979733
--- /dev/null
+++ b/tests/e2e/distributed_queries/awesome_memgraph_functions.py
@@ -0,0 +1,90 @@
+# 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 time
+import typing
+
+import mgclient
+import pytest
+
+from common import *
+
+
+def test_vertex_creation_and_scanall(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"]))
diff --git a/tests/e2e/distributed_queries/workloads.yaml b/tests/e2e/distributed_queries/workloads.yaml
index 741d6d939..eacc3e713 100644
--- a/tests/e2e/distributed_queries/workloads.yaml
+++ b/tests/e2e/distributed_queries/workloads.yaml
@@ -36,3 +36,8 @@ workloads:
     binary: "tests/e2e/pytest_runner.sh"
     args: ["distributed_queries/optional_match.py"]
     <<: *template_cluster
+
+  - name: "Awesome memgraph functions"
+    binary: "tests/e2e/pytest_runner.sh"
+    args: ["distributed_queries/awesome_memgraph_functions.py"]
+    <<: *template_cluster

From 213583f91649621dc796b54958b50ff6eb08bc62 Mon Sep 17 00:00:00 2001
From: Kostas Kyrimis <kostaskyrim@gmail.com>
Date: Mon, 14 Nov 2022 20:44:32 +0200
Subject: [PATCH 03/26] Add expression evaluator && awesome_memgraph_functions
 unit tests

---
 tests/unit/CMakeLists.txt                    |    4 +
 tests/unit/query_v2_expression_evaluator.cpp | 2192 ++++++++++++++++++
 2 files changed, 2196 insertions(+)
 create mode 100644 tests/unit/query_v2_expression_evaluator.cpp

diff --git a/tests/unit/CMakeLists.txt b/tests/unit/CMakeLists.txt
index 0e5824318..2f16ab8c2 100644
--- a/tests/unit/CMakeLists.txt
+++ b/tests/unit/CMakeLists.txt
@@ -403,3 +403,7 @@ target_link_libraries(${test_prefix}coordinator_shard_map mg-coordinator)
 # Tests for many shards, many creates, scan
 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)
+
+# 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)
diff --git a/tests/unit/query_v2_expression_evaluator.cpp b/tests/unit/query_v2_expression_evaluator.cpp
new file mode 100644
index 000000000..6bc6e1c8b
--- /dev/null
+++ b/tests/unit/query_v2_expression_evaluator.cpp
@@ -0,0 +1,2192 @@
+// 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.
+
+#include <chrono>
+#include <cmath>
+#include <iterator>
+#include <memory>
+#include <unordered_map>
+#include <vector>
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include "coordinator/shard_map.hpp"
+#include "exceptions.hpp"
+#include "functions/awesome_memgraph_functions.hpp"
+#include "parser/opencypher/parser.hpp"
+#include "query/v2/accessors.hpp"
+#include "query/v2/bindings/eval.hpp"
+#include "query/v2/bindings/frame.hpp"
+#include "query/v2/context.hpp"
+#include "query/v2/frontend/ast/ast.hpp"
+#include "query/v2/requests.hpp"
+#include "query/v2/shard_request_manager.hpp"
+#include "storage/v3/storage.hpp"
+#include "utils/exceptions.hpp"
+#include "utils/string.hpp"
+
+#include "query_v2_query_common.hpp"
+//#include "utils/temporal.hpp"
+
+using namespace memgraph::query::v2;
+using memgraph::query::v2::test_common::ToIntList;
+using testing::ElementsAre;
+using testing::UnorderedElementsAre;
+
+using memgraph::io::Time;
+using memgraph::io::TimedOut;
+using memgraph::io::simulator::Simulator;
+using memgraph::io::simulator::SimulatorConfig;
+using memgraph::io::simulator::SimulatorTransport;
+using memgraph::msgs::CreateExpandRequest;
+using memgraph::msgs::CreateExpandResponse;
+using memgraph::msgs::CreateVerticesRequest;
+using memgraph::msgs::CreateVerticesResponse;
+using memgraph::msgs::ExpandOneRequest;
+using memgraph::msgs::ExpandOneResponse;
+using memgraph::msgs::ExpandOneResultRow;
+using memgraph::msgs::NewExpand;
+using memgraph::msgs::NewVertex;
+using memgraph::msgs::ScanVerticesRequest;
+using memgraph::msgs::ScanVerticesResponse;
+using ShardMap = memgraph::coordinator::ShardMap;
+using LabelId = memgraph::storage::v3::LabelId;
+using PropertyId = memgraph::storage::v3::PropertyId;
+using memgraph::coordinator::Shards;
+using CompoundKey = memgraph::coordinator::PrimaryKey;
+using memgraph::expr::ExpressionRuntimeException;
+using memgraph::functions::FunctionRuntimeException;
+
+namespace {
+
+class MockedShardRequestManager : public memgraph::msgs::ShardRequestManagerInterface {
+ public:
+  using VertexAccessor = memgraph::query::v2::accessors::VertexAccessor;
+  explicit MockedShardRequestManager(ShardMap shard_map) : shards_map_(std::move(shard_map)) { SetUpNameIdMappers(); }
+  memgraph::storage::v3::EdgeTypeId NameToEdgeType(const std::string &name) const override {
+    return shards_map_.GetEdgeTypeId(name).value();
+  }
+
+  memgraph::storage::v3::PropertyId NameToProperty(const std::string &name) const override {
+    return shards_map_.GetPropertyId(name).value();
+  }
+
+  memgraph::storage::v3::LabelId NameToLabel(const std::string &name) const override {
+    return shards_map_.GetLabelId(name).value();
+  }
+  void StartTransaction() override {}
+  void Commit() override {}
+  std::vector<VertexAccessor> Request(
+      memgraph::msgs::ExecutionState<memgraph::msgs::ScanVerticesRequest> &state) override {
+    return {};
+  }
+
+  std::vector<CreateVerticesResponse> Request(memgraph::msgs::ExecutionState<CreateVerticesRequest> &state,
+                                              std::vector<memgraph::msgs::NewVertex> new_vertices) override {
+    return {};
+  }
+
+  std::vector<ExpandOneResultRow> Request(memgraph::msgs::ExecutionState<ExpandOneRequest> &state,
+                                          ExpandOneRequest request) override {
+    return {};
+  }
+
+  std::vector<CreateExpandResponse> Request(memgraph::msgs::ExecutionState<CreateExpandRequest> &state,
+                                            std::vector<NewExpand> new_edges) override {
+    return {};
+  }
+
+  const std::string &PropertyToName(memgraph::storage::v3::PropertyId id) const override {
+    return properties_.IdToName(id.AsUint());
+  }
+
+  const std::string &LabelToName(memgraph::storage::v3::LabelId id) const override {
+    return labels_.IdToName(id.AsUint());
+  }
+
+  const std::string &EdgeTypeToName(memgraph::storage::v3::EdgeTypeId id) const override {
+    return edge_types_.IdToName(id.AsUint());
+  }
+
+  bool IsPrimaryLabel(LabelId label) const override { return true; }
+
+  bool IsPrimaryKey(LabelId primary_label, PropertyId property) const override { return true; }
+
+ private:
+  void SetUpNameIdMappers() {
+    std::unordered_map<uint64_t, std::string> id_to_name;
+    for (const auto &[name, id] : shards_map_.labels) {
+      id_to_name.emplace(id.AsUint(), name);
+    }
+    labels_.StoreMapping(std::move(id_to_name));
+    id_to_name.clear();
+    for (const auto &[name, id] : shards_map_.properties) {
+      id_to_name.emplace(id.AsUint(), name);
+    }
+    properties_.StoreMapping(std::move(id_to_name));
+    id_to_name.clear();
+    for (const auto &[name, id] : shards_map_.edge_types) {
+      id_to_name.emplace(id.AsUint(), name);
+    }
+    edge_types_.StoreMapping(std::move(id_to_name));
+  }
+
+  ShardMap shards_map_;
+  memgraph::storage::v3::NameIdMapper properties_;
+  memgraph::storage::v3::NameIdMapper edge_types_;
+  memgraph::storage::v3::NameIdMapper labels_;
+};
+
+ShardMap CreateDummyShardmap() {
+  static const std::string label_name = std::string("label1");
+  ShardMap sm;
+
+  // register new properties
+  const std::vector<std::string> property_names = {"prop", "property_2", "age", "height", "a", "b", "c"};
+  const auto properties = sm.AllocatePropertyIds(property_names);
+  const auto property_id_1 = properties.at("prop");
+  const auto property_id_2 = properties.at("property_2");
+  const auto property_id_3 = properties.at("age");
+  const auto property_id_4 = properties.at("height");
+  const auto property_id_5 = properties.at("a");
+  const auto property_id_6 = properties.at("b");
+  const auto property_id_7 = properties.at("c");
+  const auto type_1 = memgraph::common::SchemaType::INT;
+
+  using SchemaProperty = memgraph::coordinator::SchemaProperty;
+  // register new label space
+  std::vector<SchemaProperty> schema = {
+      SchemaProperty{.property_id = property_id_1, .type = type_1},
+      SchemaProperty{.property_id = property_id_2, .type = type_1},
+      SchemaProperty{.property_id = property_id_3, .type = type_1},
+      SchemaProperty{.property_id = property_id_4, .type = type_1},
+      SchemaProperty{.property_id = property_id_5, .type = type_1},
+      SchemaProperty{.property_id = property_id_6, .type = type_1},
+      SchemaProperty{.property_id = property_id_7, .type = type_1},
+  };
+
+  auto label_success = sm.InitializeNewLabel(label_name, schema, 1, sm.shard_map_version);
+  MG_ASSERT(label_success);
+
+  const LabelId label_id = sm.labels.at(label_name);
+  auto &label_space = sm.label_spaces.at(label_id);
+  Shards &shards_for_label = label_space.shards;
+  shards_for_label.clear();
+
+  auto key1 = memgraph::storage::v3::PropertyValue(0);
+  auto key2 = memgraph::storage::v3::PropertyValue(0);
+  CompoundKey compound_key_1 = {key1, key2};
+  shards_for_label[compound_key_1] = {};
+
+  auto key3 = memgraph::storage::v3::PropertyValue(12);
+  auto key4 = memgraph::storage::v3::PropertyValue(13);
+  CompoundKey compound_key_2 = {key3, key4};
+  shards_for_label[compound_key_2] = {};
+
+  sm.AllocateEdgeTypeIds(std::vector<memgraph::coordinator::EdgeTypeName>{"edge_type"});
+
+  return sm;
+}
+
+class ExpressionEvaluatorTest : public ::testing::Test {
+ public:
+  ExpressionEvaluatorTest() {}
+
+ protected:
+  //  memgraph::storage::Storage db;
+  //  memgraph::storage::Storage::Accessor storage_dba{db.Access()};
+  //  memgraph::query::DbAccessor dba{&storage_dba};
+  //
+  AstStorage storage;
+  memgraph::utils::MonotonicBufferResource mem{1024};
+  EvaluationContext ctx{.memory = &mem, .timestamp = memgraph::query::v2::QueryTimestamp()};
+  SymbolTable symbol_table;
+
+  Frame frame{128};
+  std::unique_ptr<memgraph::msgs::ShardRequestManagerInterface> shard_manager =
+      std::make_unique<MockedShardRequestManager>(CreateDummyShardmap());
+  ExpressionEvaluator eval{&frame, symbol_table, ctx, shard_manager.get(), memgraph::storage::v3::View::OLD};
+
+  Identifier *CreateIdentifierWithValue(std::string name, const TypedValue &value) {
+    auto id = storage.Create<Identifier>(name, true);
+    auto symbol = symbol_table.CreateSymbol(name, true);
+    id->MapTo(symbol);
+    frame[symbol] = value;
+    return id;
+  }
+
+  template <class TExpression>
+  auto Eval(TExpression *expr) {
+    ctx.properties = NamesToProperties(storage.properties_, shard_manager.get());
+    ctx.labels = NamesToLabels(storage.labels_, shard_manager.get());
+    auto value = expr->Accept(eval);
+    EXPECT_EQ(value.GetMemoryResource(), &mem) << "ExpressionEvaluator must use the MemoryResource from "
+                                                  "EvaluationContext for allocations!";
+    return value;
+  }
+};
+
+TEST_F(ExpressionEvaluatorTest, OrOperator) {
+  auto *op =
+      storage.Create<OrOperator>(storage.Create<PrimitiveLiteral>(true), storage.Create<PrimitiveLiteral>(false));
+  auto val1 = Eval(op);
+  ASSERT_EQ(val1.ValueBool(), true);
+  op = storage.Create<OrOperator>(storage.Create<PrimitiveLiteral>(true), storage.Create<PrimitiveLiteral>(true));
+  auto val2 = Eval(op);
+  ASSERT_EQ(val2.ValueBool(), true);
+}
+
+TEST_F(ExpressionEvaluatorTest, XorOperator) {
+  auto *op =
+      storage.Create<XorOperator>(storage.Create<PrimitiveLiteral>(true), storage.Create<PrimitiveLiteral>(false));
+  auto val1 = Eval(op);
+  ASSERT_EQ(val1.ValueBool(), true);
+  op = storage.Create<XorOperator>(storage.Create<PrimitiveLiteral>(true), storage.Create<PrimitiveLiteral>(true));
+  auto val2 = Eval(op);
+  ASSERT_EQ(val2.ValueBool(), false);
+}
+
+TEST_F(ExpressionEvaluatorTest, AndOperator) {
+  auto *op =
+      storage.Create<AndOperator>(storage.Create<PrimitiveLiteral>(true), storage.Create<PrimitiveLiteral>(true));
+  auto val1 = Eval(op);
+  ASSERT_EQ(val1.ValueBool(), true);
+  op = storage.Create<AndOperator>(storage.Create<PrimitiveLiteral>(false), storage.Create<PrimitiveLiteral>(true));
+  auto val2 = Eval(op);
+  ASSERT_EQ(val2.ValueBool(), false);
+}
+
+TEST_F(ExpressionEvaluatorTest, AndOperatorShortCircuit) {
+  {
+    auto *op =
+        storage.Create<AndOperator>(storage.Create<PrimitiveLiteral>(false), storage.Create<PrimitiveLiteral>(5));
+    auto value = Eval(op);
+    EXPECT_EQ(value.ValueBool(), false);
+  }
+  {
+    auto *op =
+        storage.Create<AndOperator>(storage.Create<PrimitiveLiteral>(5), storage.Create<PrimitiveLiteral>(false));
+    // We are evaluating left to right, so we don't short circuit here and
+    // raise due to `5`. This differs from neo4j, where they evaluate both
+    // sides and return `false` without checking for type of the first
+    // expression.
+    EXPECT_THROW(Eval(op), ExpressionRuntimeException);
+  }
+}
+
+TEST_F(ExpressionEvaluatorTest, AndOperatorNull) {
+  {
+    // Null doesn't short circuit
+    auto *op = storage.Create<AndOperator>(storage.Create<PrimitiveLiteral>(TypedValue()),
+                                           storage.Create<PrimitiveLiteral>(5));
+    EXPECT_THROW(Eval(op), ExpressionRuntimeException);
+  }
+  {
+    auto *op = storage.Create<AndOperator>(storage.Create<PrimitiveLiteral>(TypedValue()),
+                                           storage.Create<PrimitiveLiteral>(true));
+    auto value = Eval(op);
+    EXPECT_TRUE(value.IsNull());
+  }
+  {
+    auto *op = storage.Create<AndOperator>(storage.Create<PrimitiveLiteral>(TypedValue()),
+                                           storage.Create<PrimitiveLiteral>(false));
+    auto value = Eval(op);
+    ASSERT_TRUE(value.IsBool());
+    EXPECT_EQ(value.ValueBool(), false);
+  }
+}
+
+TEST_F(ExpressionEvaluatorTest, AdditionOperator) {
+  auto *op = storage.Create<AdditionOperator>(storage.Create<PrimitiveLiteral>(2), storage.Create<PrimitiveLiteral>(3));
+  auto value = Eval(op);
+  ASSERT_EQ(value.ValueInt(), 5);
+}
+
+TEST_F(ExpressionEvaluatorTest, SubtractionOperator) {
+  auto *op =
+      storage.Create<SubtractionOperator>(storage.Create<PrimitiveLiteral>(2), storage.Create<PrimitiveLiteral>(3));
+  auto value = Eval(op);
+  ASSERT_EQ(value.ValueInt(), -1);
+}
+
+TEST_F(ExpressionEvaluatorTest, MultiplicationOperator) {
+  auto *op =
+      storage.Create<MultiplicationOperator>(storage.Create<PrimitiveLiteral>(2), storage.Create<PrimitiveLiteral>(3));
+  auto value = Eval(op);
+  ASSERT_EQ(value.ValueInt(), 6);
+}
+
+TEST_F(ExpressionEvaluatorTest, DivisionOperator) {
+  auto *op =
+      storage.Create<DivisionOperator>(storage.Create<PrimitiveLiteral>(50), storage.Create<PrimitiveLiteral>(10));
+  auto value = Eval(op);
+  ASSERT_EQ(value.ValueInt(), 5);
+}
+
+TEST_F(ExpressionEvaluatorTest, ModOperator) {
+  auto *op = storage.Create<ModOperator>(storage.Create<PrimitiveLiteral>(65), storage.Create<PrimitiveLiteral>(10));
+  auto value = Eval(op);
+  ASSERT_EQ(value.ValueInt(), 5);
+}
+
+TEST_F(ExpressionEvaluatorTest, EqualOperator) {
+  auto *op = storage.Create<EqualOperator>(storage.Create<PrimitiveLiteral>(10), storage.Create<PrimitiveLiteral>(15));
+  auto val1 = Eval(op);
+  ASSERT_EQ(val1.ValueBool(), false);
+  op = storage.Create<EqualOperator>(storage.Create<PrimitiveLiteral>(15), storage.Create<PrimitiveLiteral>(15));
+  auto val2 = Eval(op);
+  ASSERT_EQ(val2.ValueBool(), true);
+  op = storage.Create<EqualOperator>(storage.Create<PrimitiveLiteral>(20), storage.Create<PrimitiveLiteral>(15));
+  auto val3 = Eval(op);
+  ASSERT_EQ(val3.ValueBool(), false);
+}
+
+TEST_F(ExpressionEvaluatorTest, NotEqualOperator) {
+  auto *op =
+      storage.Create<NotEqualOperator>(storage.Create<PrimitiveLiteral>(10), storage.Create<PrimitiveLiteral>(15));
+  auto val1 = Eval(op);
+  ASSERT_EQ(val1.ValueBool(), true);
+  op = storage.Create<NotEqualOperator>(storage.Create<PrimitiveLiteral>(15), storage.Create<PrimitiveLiteral>(15));
+  auto val2 = Eval(op);
+  ASSERT_EQ(val2.ValueBool(), false);
+  op = storage.Create<NotEqualOperator>(storage.Create<PrimitiveLiteral>(20), storage.Create<PrimitiveLiteral>(15));
+  auto val3 = Eval(op);
+  ASSERT_EQ(val3.ValueBool(), true);
+}
+
+TEST_F(ExpressionEvaluatorTest, LessOperator) {
+  auto *op = storage.Create<LessOperator>(storage.Create<PrimitiveLiteral>(10), storage.Create<PrimitiveLiteral>(15));
+  auto val1 = Eval(op);
+  ASSERT_EQ(val1.ValueBool(), true);
+  op = storage.Create<LessOperator>(storage.Create<PrimitiveLiteral>(15), storage.Create<PrimitiveLiteral>(15));
+  auto val2 = Eval(op);
+  ASSERT_EQ(val2.ValueBool(), false);
+  op = storage.Create<LessOperator>(storage.Create<PrimitiveLiteral>(20), storage.Create<PrimitiveLiteral>(15));
+  auto val3 = Eval(op);
+  ASSERT_EQ(val3.ValueBool(), false);
+}
+
+TEST_F(ExpressionEvaluatorTest, GreaterOperator) {
+  auto *op =
+      storage.Create<GreaterOperator>(storage.Create<PrimitiveLiteral>(10), storage.Create<PrimitiveLiteral>(15));
+  auto val1 = Eval(op);
+  ASSERT_EQ(val1.ValueBool(), false);
+  op = storage.Create<GreaterOperator>(storage.Create<PrimitiveLiteral>(15), storage.Create<PrimitiveLiteral>(15));
+  auto val2 = Eval(op);
+  ASSERT_EQ(val2.ValueBool(), false);
+  op = storage.Create<GreaterOperator>(storage.Create<PrimitiveLiteral>(20), storage.Create<PrimitiveLiteral>(15));
+  auto val3 = Eval(op);
+  ASSERT_EQ(val3.ValueBool(), true);
+}
+
+TEST_F(ExpressionEvaluatorTest, LessEqualOperator) {
+  auto *op =
+      storage.Create<LessEqualOperator>(storage.Create<PrimitiveLiteral>(10), storage.Create<PrimitiveLiteral>(15));
+  auto val1 = Eval(op);
+  ASSERT_EQ(val1.ValueBool(), true);
+  op = storage.Create<LessEqualOperator>(storage.Create<PrimitiveLiteral>(15), storage.Create<PrimitiveLiteral>(15));
+  auto val2 = Eval(op);
+  ASSERT_EQ(val2.ValueBool(), true);
+  op = storage.Create<LessEqualOperator>(storage.Create<PrimitiveLiteral>(20), storage.Create<PrimitiveLiteral>(15));
+  auto val3 = Eval(op);
+  ASSERT_EQ(val3.ValueBool(), false);
+}
+
+TEST_F(ExpressionEvaluatorTest, GreaterEqualOperator) {
+  auto *op =
+      storage.Create<GreaterEqualOperator>(storage.Create<PrimitiveLiteral>(10), storage.Create<PrimitiveLiteral>(15));
+  auto val1 = Eval(op);
+  ASSERT_EQ(val1.ValueBool(), false);
+  op = storage.Create<GreaterEqualOperator>(storage.Create<PrimitiveLiteral>(15), storage.Create<PrimitiveLiteral>(15));
+  auto val2 = Eval(op);
+  ASSERT_EQ(val2.ValueBool(), true);
+  op = storage.Create<GreaterEqualOperator>(storage.Create<PrimitiveLiteral>(20), storage.Create<PrimitiveLiteral>(15));
+  auto val3 = Eval(op);
+  ASSERT_EQ(val3.ValueBool(), true);
+}
+
+TEST_F(ExpressionEvaluatorTest, InListOperator) {
+  auto *list_literal = storage.Create<ListLiteral>(std::vector<Expression *>{
+      storage.Create<PrimitiveLiteral>(1), storage.Create<PrimitiveLiteral>(2), storage.Create<PrimitiveLiteral>("a")});
+  {
+    // Element exists in list.
+    auto *op = storage.Create<InListOperator>(storage.Create<PrimitiveLiteral>(2), list_literal);
+    auto value = Eval(op);
+    EXPECT_EQ(value.ValueBool(), true);
+  }
+  {
+    // Element doesn't exist in list.
+    auto *op = storage.Create<InListOperator>(storage.Create<PrimitiveLiteral>("x"), list_literal);
+    auto value = Eval(op);
+    EXPECT_EQ(value.ValueBool(), false);
+  }
+  {
+    auto *list_literal = storage.Create<ListLiteral>(
+        std::vector<Expression *>{storage.Create<PrimitiveLiteral>(TypedValue()), storage.Create<PrimitiveLiteral>(2),
+                                  storage.Create<PrimitiveLiteral>("a")});
+    // Element doesn't exist in list with null element.
+    auto *op = storage.Create<InListOperator>(storage.Create<PrimitiveLiteral>("x"), list_literal);
+    auto value = Eval(op);
+    EXPECT_TRUE(value.IsNull());
+  }
+  {
+    // Null list.
+    auto *op = storage.Create<InListOperator>(storage.Create<PrimitiveLiteral>("x"),
+                                              storage.Create<PrimitiveLiteral>(TypedValue()));
+    auto value = Eval(op);
+    EXPECT_TRUE(value.IsNull());
+  }
+  {
+    // Null literal.
+    auto *op = storage.Create<InListOperator>(storage.Create<PrimitiveLiteral>(TypedValue()), list_literal);
+    auto value = Eval(op);
+    EXPECT_TRUE(value.IsNull());
+  }
+  {
+    // Null literal, empty list.
+    auto *op = storage.Create<InListOperator>(storage.Create<PrimitiveLiteral>(TypedValue()),
+                                              storage.Create<ListLiteral>(std::vector<Expression *>()));
+    auto value = Eval(op);
+    EXPECT_FALSE(value.ValueBool());
+  }
+}
+
+TEST_F(ExpressionEvaluatorTest, ListIndexing) {
+  auto *list_literal = storage.Create<ListLiteral>(
+      std::vector<Expression *>{storage.Create<PrimitiveLiteral>(1), storage.Create<PrimitiveLiteral>(2),
+                                storage.Create<PrimitiveLiteral>(3), storage.Create<PrimitiveLiteral>(4)});
+  {
+    // Legal indexing.
+    auto *op = storage.Create<SubscriptOperator>(list_literal, storage.Create<PrimitiveLiteral>(2));
+    auto value = Eval(op);
+    EXPECT_EQ(value.ValueInt(), 3);
+  }
+  {
+    // Out of bounds indexing.
+    auto *op = storage.Create<SubscriptOperator>(list_literal, storage.Create<PrimitiveLiteral>(4));
+    auto value = Eval(op);
+    EXPECT_TRUE(value.IsNull());
+  }
+  {
+    // Out of bounds indexing with negative bound.
+    auto *op = storage.Create<SubscriptOperator>(list_literal, storage.Create<PrimitiveLiteral>(-100));
+    auto value = Eval(op);
+    EXPECT_TRUE(value.IsNull());
+  }
+  {
+    // Legal indexing with negative index.
+    auto *op = storage.Create<SubscriptOperator>(list_literal, storage.Create<PrimitiveLiteral>(-2));
+    auto value = Eval(op);
+    EXPECT_EQ(value.ValueInt(), 3);
+  }
+  {
+    // Indexing with one operator being null.
+    auto *op = storage.Create<SubscriptOperator>(storage.Create<PrimitiveLiteral>(TypedValue()),
+                                                 storage.Create<PrimitiveLiteral>(-2));
+    auto value = Eval(op);
+    EXPECT_TRUE(value.IsNull());
+  }
+  {
+    // Indexing with incompatible type.
+    auto *op = storage.Create<SubscriptOperator>(list_literal, storage.Create<PrimitiveLiteral>("bla"));
+    EXPECT_THROW(Eval(op), ExpressionRuntimeException);
+  }
+}
+
+TEST_F(ExpressionEvaluatorTest, MapIndexing) {
+  auto *map_literal = storage.Create<MapLiteral>(
+      std::unordered_map<PropertyIx, Expression *>{{storage.GetPropertyIx("a"), storage.Create<PrimitiveLiteral>(1)},
+                                                   {storage.GetPropertyIx("b"), storage.Create<PrimitiveLiteral>(2)},
+                                                   {storage.GetPropertyIx("c"), storage.Create<PrimitiveLiteral>(3)}});
+  {
+    // Legal indexing.
+    auto *op = storage.Create<SubscriptOperator>(map_literal, storage.Create<PrimitiveLiteral>("b"));
+    auto value = Eval(op);
+    EXPECT_EQ(value.ValueInt(), 2);
+  }
+  {
+    // Legal indexing, non-existing key.
+    auto *op = storage.Create<SubscriptOperator>(map_literal, storage.Create<PrimitiveLiteral>("z"));
+    auto value = Eval(op);
+    EXPECT_TRUE(value.IsNull());
+  }
+  {
+    // Wrong key type.
+    auto *op = storage.Create<SubscriptOperator>(map_literal, storage.Create<PrimitiveLiteral>(42));
+    EXPECT_THROW(Eval(op), ExpressionRuntimeException);
+  }
+  {
+    // Indexing with Null.
+    auto *op = storage.Create<SubscriptOperator>(map_literal, storage.Create<PrimitiveLiteral>(TypedValue()));
+    auto value = Eval(op);
+    EXPECT_TRUE(value.IsNull());
+  }
+}
+
+using Vertex = memgraph::msgs::Vertex;
+using Edge = memgraph::msgs::Edge;
+using EdgeType = memgraph::msgs::EdgeType;
+using Value = memgraph::msgs::Value;
+using VertexId = memgraph::msgs::VertexId;
+using Label = memgraph::msgs::Label;
+
+memgraph::query::v2::accessors::VertexAccessor CreateVertex(std::vector<std::pair<PropertyId, Value>> props,
+                                                            const memgraph::msgs::ShardRequestManagerInterface *manager,
+                                                            Label label = {}) {
+  static size_t id = 0;
+  return {Vertex{VertexId{label, id++}, {label}}, std::move(props), manager};
+}
+
+memgraph::query::v2::accessors::EdgeAccessor CreateEdge(std::vector<std::pair<PropertyId, Value>> props,
+                                                        const memgraph::msgs::ShardRequestManagerInterface *manager) {
+  auto edge = Edge{.src = VertexId{{}, 0},
+                   .dst = VertexId{{}, 0},
+                   .properties = std::move(props),
+                   .type = EdgeType{manager->NameToEdgeType("edge_type")}};
+  return memgraph::query::v2::accessors::EdgeAccessor{std::move(edge), manager};
+}
+
+TEST_F(ExpressionEvaluatorTest, VertexAndEdgeIndexing) {
+  auto prop = shard_manager->NameToProperty("prop");
+  auto vertex = CreateVertex({{prop, Value(static_cast<int64_t>(42))}}, shard_manager.get());
+  auto edge = CreateEdge({{prop, Value(static_cast<int64_t>(43))}}, shard_manager.get());
+
+  auto *vertex_id = CreateIdentifierWithValue("v1", TypedValue(vertex));
+  auto *edge_id = CreateIdentifierWithValue("e11", TypedValue(edge));
+  {
+    // Legal indexing.
+    auto *op1 = storage.Create<SubscriptOperator>(vertex_id, storage.Create<PrimitiveLiteral>("prop"));
+    auto value1 = Eval(op1);
+    EXPECT_EQ(value1.ValueInt(), 42);
+
+    auto *op2 = storage.Create<SubscriptOperator>(edge_id, storage.Create<PrimitiveLiteral>("prop"));
+    auto value2 = Eval(op2);
+    EXPECT_EQ(value2.ValueInt(), 43);
+  }
+  // TODO(kostasrim) Investigate
+  //  Shall we return null on missing properties? Or shall we throw bad optional access as we do now?
+
+  //   {
+  //     // Legal indexing, non-existing key.
+  //     auto *op1 = storage.Create<SubscriptOperator>(vertex_id, storage.Create<PrimitiveLiteral>("blah"));
+  //     auto value1 = Eval(op1);
+  //     EXPECT_TRUE(value1.IsNull());
+  //
+  //     auto *op2 = storage.Create<SubscriptOperator>(edge_id, storage.Create<PrimitiveLiteral>("blah"));
+  //     auto value2 = Eval(op2);
+  //     EXPECT_TRUE(value2.IsNull());
+  //   }
+  //   {
+  //     // Wrong key type.
+  //     auto *op1 = storage.Create<SubscriptOperator>(vertex_id, storage.Create<PrimitiveLiteral>(1));
+  //     EXPECT_THROW(Eval(op1), ExpressionRuntimeException);
+  //
+  //     auto *op2 = storage.Create<SubscriptOperator>(edge_id, storage.Create<PrimitiveLiteral>(1));
+  //     EXPECT_THROW(Eval(op2), ExpressionRuntimeException);
+  //   }
+  //   {
+  //     // Indexing with Null.
+  //     auto *op1 = storage.Create<SubscriptOperator>(vertex_id,
+  //                                                   storage.Create<PrimitiveLiteral>(memgraph::storage::PropertyValue()));
+  //     auto value1 = Eval(op1);
+  //     EXPECT_TRUE(value1.IsNull());
+  //
+  //     auto *op2 = storage.Create<SubscriptOperator>(edge_id,
+  //                                                   storage.Create<PrimitiveLiteral>(memgraph::storage::PropertyValue()));
+  //     auto value2 = Eval(op2);
+  //     EXPECT_TRUE(value2.IsNull());
+  //   }
+}
+
+TEST_F(ExpressionEvaluatorTest, ListSlicingOperator) {
+  auto *list_literal = storage.Create<ListLiteral>(
+      std::vector<Expression *>{storage.Create<PrimitiveLiteral>(1), storage.Create<PrimitiveLiteral>(2),
+                                storage.Create<PrimitiveLiteral>(3), storage.Create<PrimitiveLiteral>(4)});
+
+  auto extract_ints = [](TypedValue list) {
+    std::vector<int64_t> int_list;
+    for (auto x : list.ValueList()) {
+      int_list.push_back(x.ValueInt());
+    }
+    return int_list;
+  };
+  {
+    // Legal slicing with both bounds defined.
+    auto *op = storage.Create<ListSlicingOperator>(list_literal, storage.Create<PrimitiveLiteral>(2),
+                                                   storage.Create<PrimitiveLiteral>(4));
+    auto value = Eval(op);
+    EXPECT_THAT(extract_ints(value), ElementsAre(3, 4));
+  }
+  {
+    // Legal slicing with negative bound.
+    auto *op = storage.Create<ListSlicingOperator>(list_literal, storage.Create<PrimitiveLiteral>(2),
+                                                   storage.Create<PrimitiveLiteral>(-1));
+    auto value = Eval(op);
+    EXPECT_THAT(extract_ints(value), ElementsAre(3));
+  }
+  {
+    // Lower bound larger than upper bound.
+    auto *op = storage.Create<ListSlicingOperator>(list_literal, storage.Create<PrimitiveLiteral>(2),
+                                                   storage.Create<PrimitiveLiteral>(-4));
+    auto value = Eval(op);
+    EXPECT_THAT(extract_ints(value), ElementsAre());
+  }
+  {
+    // Bounds ouf or range.
+    auto *op = storage.Create<ListSlicingOperator>(list_literal, storage.Create<PrimitiveLiteral>(-100),
+                                                   storage.Create<PrimitiveLiteral>(10));
+    auto value = Eval(op);
+    EXPECT_THAT(extract_ints(value), ElementsAre(1, 2, 3, 4));
+  }
+  {
+    // Lower bound undefined.
+    auto *op = storage.Create<ListSlicingOperator>(list_literal, nullptr, storage.Create<PrimitiveLiteral>(3));
+    auto value = Eval(op);
+    EXPECT_THAT(extract_ints(value), ElementsAre(1, 2, 3));
+  }
+  {
+    // Upper bound undefined.
+    auto *op = storage.Create<ListSlicingOperator>(list_literal, storage.Create<PrimitiveLiteral>(-2), nullptr);
+    auto value = Eval(op);
+    EXPECT_THAT(extract_ints(value), ElementsAre(3, 4));
+  }
+  {
+    // Bound of illegal type and null value bound.
+    auto *op = storage.Create<ListSlicingOperator>(list_literal, storage.Create<PrimitiveLiteral>(TypedValue()),
+                                                   storage.Create<PrimitiveLiteral>("mirko"));
+    EXPECT_THROW(Eval(op), ExpressionRuntimeException);
+  }
+  {
+    // List of illegal type.
+    auto *op = storage.Create<ListSlicingOperator>(storage.Create<PrimitiveLiteral>("a"),
+                                                   storage.Create<PrimitiveLiteral>(-2), nullptr);
+    EXPECT_THROW(Eval(op), ExpressionRuntimeException);
+  }
+  {
+    // Null value list with undefined upper bound.
+    auto *op = storage.Create<ListSlicingOperator>(storage.Create<PrimitiveLiteral>(TypedValue()),
+                                                   storage.Create<PrimitiveLiteral>(-2), nullptr);
+    auto value = Eval(op);
+    EXPECT_TRUE(value.IsNull());
+    ;
+  }
+  {
+    // Null value index.
+    auto *op = storage.Create<ListSlicingOperator>(list_literal, storage.Create<PrimitiveLiteral>(-2),
+                                                   storage.Create<PrimitiveLiteral>(TypedValue()));
+    auto value = Eval(op);
+    EXPECT_TRUE(value.IsNull());
+    ;
+  }
+}
+
+TEST_F(ExpressionEvaluatorTest, IfOperator) {
+  auto *then_expression = storage.Create<PrimitiveLiteral>(10);
+  auto *else_expression = storage.Create<PrimitiveLiteral>(20);
+  {
+    auto *condition_true =
+        storage.Create<EqualOperator>(storage.Create<PrimitiveLiteral>(2), storage.Create<PrimitiveLiteral>(2));
+    auto *op = storage.Create<IfOperator>(condition_true, then_expression, else_expression);
+    auto value = Eval(op);
+    ASSERT_EQ(value.ValueInt(), 10);
+  }
+  {
+    auto *condition_false =
+        storage.Create<EqualOperator>(storage.Create<PrimitiveLiteral>(2), storage.Create<PrimitiveLiteral>(3));
+    auto *op = storage.Create<IfOperator>(condition_false, then_expression, else_expression);
+    auto value = Eval(op);
+    ASSERT_EQ(value.ValueInt(), 20);
+  }
+  {
+    auto *condition_exception =
+        storage.Create<AdditionOperator>(storage.Create<PrimitiveLiteral>(2), storage.Create<PrimitiveLiteral>(3));
+    auto *op = storage.Create<IfOperator>(condition_exception, then_expression, else_expression);
+    ASSERT_THROW(Eval(op), ExpressionRuntimeException);
+  }
+}
+
+TEST_F(ExpressionEvaluatorTest, NotOperator) {
+  auto *op = storage.Create<NotOperator>(storage.Create<PrimitiveLiteral>(false));
+  auto value = Eval(op);
+  ASSERT_EQ(value.ValueBool(), true);
+}
+
+TEST_F(ExpressionEvaluatorTest, UnaryPlusOperator) {
+  auto *op = storage.Create<UnaryPlusOperator>(storage.Create<PrimitiveLiteral>(5));
+  auto value = Eval(op);
+  ASSERT_EQ(value.ValueInt(), 5);
+}
+
+TEST_F(ExpressionEvaluatorTest, UnaryMinusOperator) {
+  auto *op = storage.Create<UnaryMinusOperator>(storage.Create<PrimitiveLiteral>(5));
+  auto value = Eval(op);
+  ASSERT_EQ(value.ValueInt(), -5);
+}
+
+TEST_F(ExpressionEvaluatorTest, IsNullOperator) {
+  auto *op = storage.Create<IsNullOperator>(storage.Create<PrimitiveLiteral>(1));
+  auto val1 = Eval(op);
+  ASSERT_EQ(val1.ValueBool(), false);
+  op = storage.Create<IsNullOperator>(storage.Create<PrimitiveLiteral>(TypedValue()));
+  auto val2 = Eval(op);
+  ASSERT_EQ(val2.ValueBool(), true);
+}
+
+// TEST_F(ExpressionEvaluatorTest, LabelsTest) {
+//   auto v1 = dba.InsertVertex();
+//   ASSERT_TRUE(v1.AddLabel(dba.NameToLabel("ANIMAL")).HasValue());
+//   ASSERT_TRUE(v1.AddLabel(dba.NameToLabel("DOG")).HasValue());
+//   ASSERT_TRUE(v1.AddLabel(dba.NameToLabel("NICE_DOG")).HasValue());
+//   dba.AdvanceCommand();
+//   auto *identifier = storage.Create<Identifier>("n");
+//   auto node_symbol = symbol_table.CreateSymbol("n", true);
+//   identifier->MapTo(node_symbol);
+//   frame[node_symbol] = TypedValue(v1);
+//   {
+//     auto *op = storage.Create<LabelsTest>(
+//         identifier, std::vector<LabelIx>{storage.GetLabelIx("DOG"), storage.GetLabelIx("ANIMAL")});
+//     auto value = Eval(op);
+//     EXPECT_EQ(value.ValueBool(), true);
+//   }
+//   {
+//     auto *op = storage.Create<LabelsTest>(
+//         identifier,
+//         std::vector<LabelIx>{storage.GetLabelIx("DOG"), storage.GetLabelIx("BAD_DOG"),
+//         storage.GetLabelIx("ANIMAL")});
+//     auto value = Eval(op);
+//     EXPECT_EQ(value.ValueBool(), false);
+//   }
+//   {
+//     frame[node_symbol] = TypedValue();
+//     auto *op = storage.Create<LabelsTest>(
+//         identifier,
+//         std::vector<LabelIx>{storage.GetLabelIx("DOG"), storage.GetLabelIx("BAD_DOG"),
+//         storage.GetLabelIx("ANIMAL")});
+//     auto value = Eval(op);
+//     EXPECT_TRUE(value.IsNull());
+//   }
+// }
+//
+TEST_F(ExpressionEvaluatorTest, Aggregation) {
+  auto aggr = storage.Create<Aggregation>(storage.Create<PrimitiveLiteral>(42), nullptr, Aggregation::Op::COUNT);
+  auto aggr_sym = symbol_table.CreateSymbol("aggr", true);
+  aggr->MapTo(aggr_sym);
+  frame[aggr_sym] = TypedValue(1);
+  auto value = Eval(aggr);
+  EXPECT_EQ(value.ValueInt(), 1);
+}
+
+TEST_F(ExpressionEvaluatorTest, ListLiteral) {
+  auto *list_literal = storage.Create<ListLiteral>(std::vector<Expression *>{storage.Create<PrimitiveLiteral>(1),
+                                                                             storage.Create<PrimitiveLiteral>("bla"),
+                                                                             storage.Create<PrimitiveLiteral>(true)});
+  TypedValue result = Eval(list_literal);
+  ASSERT_TRUE(result.IsList());
+  auto &result_elems = result.ValueList();
+  ASSERT_EQ(3, result_elems.size());
+  EXPECT_TRUE(result_elems[0].IsInt());
+  ;
+  EXPECT_TRUE(result_elems[1].IsString());
+  ;
+  EXPECT_TRUE(result_elems[2].IsBool());
+  ;
+}
+
+TEST_F(ExpressionEvaluatorTest, ParameterLookup) {
+  ctx.parameters.Add(0, memgraph::storage::v3::PropertyValue(42));
+  auto *param_lookup = storage.Create<ParameterLookup>(0);
+  auto value = Eval(param_lookup);
+  ASSERT_TRUE(value.IsInt());
+  EXPECT_EQ(value.ValueInt(), 42);
+}
+
+TEST_F(ExpressionEvaluatorTest, FunctionAll1) {
+  AstStorage storage;
+  auto *ident_x = IDENT("x");
+  auto *all = ALL("x", LIST(LITERAL(1), LITERAL(1)), WHERE(EQ(ident_x, LITERAL(1))));
+  const auto x_sym = symbol_table.CreateSymbol("x", true);
+  all->identifier_->MapTo(x_sym);
+  ident_x->MapTo(x_sym);
+  auto value = Eval(all);
+  ASSERT_TRUE(value.IsBool());
+  EXPECT_TRUE(value.ValueBool());
+}
+
+TEST_F(ExpressionEvaluatorTest, FunctionAll2) {
+  AstStorage storage;
+  auto *ident_x = IDENT("x");
+  auto *all = ALL("x", LIST(LITERAL(1), LITERAL(2)), WHERE(EQ(ident_x, LITERAL(1))));
+  const auto x_sym = symbol_table.CreateSymbol("x", true);
+  all->identifier_->MapTo(x_sym);
+  ident_x->MapTo(x_sym);
+  auto value = Eval(all);
+  ASSERT_TRUE(value.IsBool());
+  EXPECT_FALSE(value.ValueBool());
+}
+
+TEST_F(ExpressionEvaluatorTest, FunctionAllNullList) {
+  AstStorage storage;
+  auto *all = ALL("x", LITERAL(TypedValue()), WHERE(LITERAL(true)));
+  const auto x_sym = symbol_table.CreateSymbol("x", true);
+  all->identifier_->MapTo(x_sym);
+  auto value = Eval(all);
+  EXPECT_TRUE(value.IsNull());
+}
+
+TEST_F(ExpressionEvaluatorTest, FunctionAllNullElementInList1) {
+  AstStorage storage;
+  auto *ident_x = IDENT("x");
+  auto *all = ALL("x", LIST(LITERAL(1), LITERAL(TypedValue())), WHERE(EQ(ident_x, LITERAL(1))));
+  const auto x_sym = symbol_table.CreateSymbol("x", true);
+  all->identifier_->MapTo(x_sym);
+  ident_x->MapTo(x_sym);
+  auto value = Eval(all);
+  ASSERT_TRUE(value.IsBool());
+  EXPECT_FALSE(value.ValueBool());
+}
+
+TEST_F(ExpressionEvaluatorTest, FunctionAllNullElementInList2) {
+  AstStorage storage;
+  auto *ident_x = IDENT("x");
+  auto *all = ALL("x", LIST(LITERAL(2), LITERAL(TypedValue())), WHERE(EQ(ident_x, LITERAL(1))));
+  const auto x_sym = symbol_table.CreateSymbol("x", true);
+  all->identifier_->MapTo(x_sym);
+  ident_x->MapTo(x_sym);
+  auto value = Eval(all);
+  ASSERT_TRUE(value.IsBool());
+  EXPECT_FALSE(value.ValueBool());
+}
+
+TEST_F(ExpressionEvaluatorTest, FunctionAllWhereWrongType) {
+  AstStorage storage;
+  auto *all = ALL("x", LIST(LITERAL(1)), WHERE(LITERAL(2)));
+  const auto x_sym = symbol_table.CreateSymbol("x", true);
+  all->identifier_->MapTo(x_sym);
+  EXPECT_THROW(Eval(all), ExpressionRuntimeException);
+}
+
+TEST_F(ExpressionEvaluatorTest, FunctionSingle1) {
+  AstStorage storage;
+  auto *ident_x = IDENT("x");
+  auto *single = SINGLE("x", LIST(LITERAL(1), LITERAL(2)), WHERE(EQ(ident_x, LITERAL(1))));
+  const auto x_sym = symbol_table.CreateSymbol("x", true);
+  single->identifier_->MapTo(x_sym);
+  ident_x->MapTo(x_sym);
+  auto value = Eval(single);
+  ASSERT_TRUE(value.IsBool());
+  EXPECT_TRUE(value.ValueBool());
+}
+
+TEST_F(ExpressionEvaluatorTest, FunctionSingle2) {
+  AstStorage storage;
+  auto *ident_x = IDENT("x");
+  auto *single = SINGLE("x", LIST(LITERAL(1), LITERAL(2)), WHERE(GREATER(ident_x, LITERAL(0))));
+  const auto x_sym = symbol_table.CreateSymbol("x", true);
+  single->identifier_->MapTo(x_sym);
+  ident_x->MapTo(x_sym);
+  auto value = Eval(single);
+  ASSERT_TRUE(value.IsBool());
+  EXPECT_FALSE(value.ValueBool());
+}
+
+TEST_F(ExpressionEvaluatorTest, FunctionSingleNullList) {
+  AstStorage storage;
+  auto *single = SINGLE("x", LITERAL(TypedValue()), WHERE(LITERAL(true)));
+  const auto x_sym = symbol_table.CreateSymbol("x", true);
+  single->identifier_->MapTo(x_sym);
+  auto value = Eval(single);
+  EXPECT_TRUE(value.IsNull());
+}
+
+TEST_F(ExpressionEvaluatorTest, FunctionSingleNullElementInList1) {
+  AstStorage storage;
+  auto *ident_x = IDENT("x");
+  auto *single = SINGLE("x", LIST(LITERAL(1), LITERAL(TypedValue())), WHERE(EQ(ident_x, LITERAL(1))));
+  const auto x_sym = symbol_table.CreateSymbol("x", true);
+  single->identifier_->MapTo(x_sym);
+  ident_x->MapTo(x_sym);
+  auto value = Eval(single);
+  ASSERT_TRUE(value.IsBool());
+  EXPECT_TRUE(value.ValueBool());
+}
+
+TEST_F(ExpressionEvaluatorTest, FunctionSingleNullElementInList2) {
+  AstStorage storage;
+  auto *ident_x = IDENT("x");
+  auto *single = SINGLE("x", LIST(LITERAL(2), LITERAL(TypedValue())), WHERE(EQ(ident_x, LITERAL(1))));
+  const auto x_sym = symbol_table.CreateSymbol("x", true);
+  single->identifier_->MapTo(x_sym);
+  ident_x->MapTo(x_sym);
+  auto value = Eval(single);
+  ASSERT_TRUE(value.IsBool());
+  EXPECT_FALSE(value.ValueBool());
+}
+
+TEST_F(ExpressionEvaluatorTest, FunctionAny1) {
+  AstStorage storage;
+  auto *ident_x = IDENT("x");
+  auto *any = ANY("x", LIST(LITERAL(1), LITERAL(2)), WHERE(EQ(ident_x, LITERAL(1))));
+  const auto x_sym = symbol_table.CreateSymbol("x", true);
+  any->identifier_->MapTo(x_sym);
+  ident_x->MapTo(x_sym);
+  auto value = Eval(any);
+  ASSERT_TRUE(value.IsBool());
+  EXPECT_TRUE(value.ValueBool());
+}
+
+TEST_F(ExpressionEvaluatorTest, FunctionAny2) {
+  AstStorage storage;
+  auto *ident_x = IDENT("x");
+  auto *any = ANY("x", LIST(LITERAL(1), LITERAL(2)), WHERE(EQ(ident_x, LITERAL(0))));
+  const auto x_sym = symbol_table.CreateSymbol("x", true);
+  any->identifier_->MapTo(x_sym);
+  ident_x->MapTo(x_sym);
+  auto value = Eval(any);
+  ASSERT_TRUE(value.IsBool());
+  EXPECT_FALSE(value.ValueBool());
+}
+
+TEST_F(ExpressionEvaluatorTest, FunctionAnyNullList) {
+  AstStorage storage;
+  auto *any = ANY("x", LITERAL(TypedValue()), WHERE(LITERAL(true)));
+  const auto x_sym = symbol_table.CreateSymbol("x", true);
+  any->identifier_->MapTo(x_sym);
+  auto value = Eval(any);
+  EXPECT_TRUE(value.IsNull());
+}
+
+TEST_F(ExpressionEvaluatorTest, FunctionAnyNullElementInList1) {
+  AstStorage storage;
+  auto *ident_x = IDENT("x");
+  auto *any = ANY("x", LIST(LITERAL(0), LITERAL(TypedValue())), WHERE(EQ(ident_x, LITERAL(0))));
+  const auto x_sym = symbol_table.CreateSymbol("x", true);
+  any->identifier_->MapTo(x_sym);
+  ident_x->MapTo(x_sym);
+  auto value = Eval(any);
+  EXPECT_TRUE(value.ValueBool());
+}
+
+TEST_F(ExpressionEvaluatorTest, FunctionAnyNullElementInList2) {
+  AstStorage storage;
+  auto *ident_x = IDENT("x");
+  auto *any = ANY("x", LIST(LITERAL(1), LITERAL(TypedValue())), WHERE(EQ(ident_x, LITERAL(0))));
+  const auto x_sym = symbol_table.CreateSymbol("x", true);
+  any->identifier_->MapTo(x_sym);
+  ident_x->MapTo(x_sym);
+  auto value = Eval(any);
+  EXPECT_FALSE(value.ValueBool());
+}
+
+TEST_F(ExpressionEvaluatorTest, FunctionAnyWhereWrongType) {
+  AstStorage storage;
+  auto *any = ANY("x", LIST(LITERAL(1)), WHERE(LITERAL(2)));
+  const auto x_sym = symbol_table.CreateSymbol("x", true);
+  any->identifier_->MapTo(x_sym);
+  EXPECT_THROW(Eval(any), ExpressionRuntimeException);
+}
+
+TEST_F(ExpressionEvaluatorTest, FunctionNone1) {
+  AstStorage storage;
+  auto *ident_x = IDENT("x");
+  auto *none = NONE("x", LIST(LITERAL(1), LITERAL(2)), WHERE(EQ(ident_x, LITERAL(0))));
+  const auto x_sym = symbol_table.CreateSymbol("x", true);
+  none->identifier_->MapTo(x_sym);
+  ident_x->MapTo(x_sym);
+  auto value = Eval(none);
+  ASSERT_TRUE(value.IsBool());
+  EXPECT_TRUE(value.ValueBool());
+}
+
+TEST_F(ExpressionEvaluatorTest, FunctionNone2) {
+  AstStorage storage;
+  auto *ident_x = IDENT("x");
+  auto *none = NONE("x", LIST(LITERAL(1), LITERAL(2)), WHERE(EQ(ident_x, LITERAL(1))));
+  const auto x_sym = symbol_table.CreateSymbol("x", true);
+  none->identifier_->MapTo(x_sym);
+  ident_x->MapTo(x_sym);
+  auto value = Eval(none);
+  ASSERT_TRUE(value.IsBool());
+  EXPECT_FALSE(value.ValueBool());
+}
+
+TEST_F(ExpressionEvaluatorTest, FunctionNoneNullList) {
+  AstStorage storage;
+  auto *none = NONE("x", LITERAL(TypedValue()), WHERE(LITERAL(true)));
+  const auto x_sym = symbol_table.CreateSymbol("x", true);
+  none->identifier_->MapTo(x_sym);
+  auto value = Eval(none);
+  EXPECT_TRUE(value.IsNull());
+}
+
+TEST_F(ExpressionEvaluatorTest, FunctionNoneNullElementInList1) {
+  AstStorage storage;
+  auto *ident_x = IDENT("x");
+  auto *any = NONE("x", LIST(LITERAL(1), LITERAL(TypedValue())), WHERE(EQ(ident_x, LITERAL(0))));
+  const auto x_sym = symbol_table.CreateSymbol("x", true);
+  any->identifier_->MapTo(x_sym);
+  ident_x->MapTo(x_sym);
+  auto value = Eval(any);
+  EXPECT_TRUE(value.ValueBool());
+}
+
+TEST_F(ExpressionEvaluatorTest, FunctionNoneNullElementInList2) {
+  AstStorage storage;
+  auto *ident_x = IDENT("x");
+  auto *none = NONE("x", LIST(LITERAL(0), LITERAL(TypedValue())), WHERE(EQ(ident_x, LITERAL(0))));
+  const auto x_sym = symbol_table.CreateSymbol("x", true);
+  none->identifier_->MapTo(x_sym);
+  ident_x->MapTo(x_sym);
+  auto value = Eval(none);
+  EXPECT_FALSE(value.ValueBool());
+}
+
+TEST_F(ExpressionEvaluatorTest, FunctionNoneWhereWrongType) {
+  AstStorage storage;
+  auto *none = NONE("x", LIST(LITERAL(1)), WHERE(LITERAL(2)));
+  const auto x_sym = symbol_table.CreateSymbol("x", true);
+  none->identifier_->MapTo(x_sym);
+  EXPECT_THROW(Eval(none), ExpressionRuntimeException);
+}
+
+TEST_F(ExpressionEvaluatorTest, FunctionReduce) {
+  AstStorage storage;
+  auto *ident_sum = IDENT("sum");
+  auto *ident_x = IDENT("x");
+  auto *reduce = REDUCE("sum", LITERAL(0), "x", LIST(LITERAL(1), LITERAL(2)), ADD(ident_sum, ident_x));
+  const auto sum_sym = symbol_table.CreateSymbol("sum", true);
+  reduce->accumulator_->MapTo(sum_sym);
+  ident_sum->MapTo(sum_sym);
+  const auto x_sym = symbol_table.CreateSymbol("x", true);
+  reduce->identifier_->MapTo(x_sym);
+  ident_x->MapTo(x_sym);
+  auto value = Eval(reduce);
+  ASSERT_TRUE(value.IsInt());
+  EXPECT_EQ(value.ValueInt(), 3);
+}
+
+TEST_F(ExpressionEvaluatorTest, FunctionExtract) {
+  AstStorage storage;
+  auto *ident_x = IDENT("x");
+  auto *extract = EXTRACT("x", LIST(LITERAL(1), LITERAL(2), LITERAL(TypedValue())), ADD(ident_x, LITERAL(1)));
+  const auto x_sym = symbol_table.CreateSymbol("x", true);
+  extract->identifier_->MapTo(x_sym);
+  ident_x->MapTo(x_sym);
+  auto value = Eval(extract);
+  EXPECT_TRUE(value.IsList());
+  ;
+  auto result = value.ValueList();
+  EXPECT_EQ(result[0].ValueInt(), 2);
+  EXPECT_EQ(result[1].ValueInt(), 3);
+  EXPECT_TRUE(result[2].IsNull());
+}
+
+TEST_F(ExpressionEvaluatorTest, FunctionExtractNull) {
+  AstStorage storage;
+  auto *ident_x = IDENT("x");
+  auto *extract = EXTRACT("x", LITERAL(TypedValue()), ADD(ident_x, LITERAL(1)));
+  const auto x_sym = symbol_table.CreateSymbol("x", true);
+  extract->identifier_->MapTo(x_sym);
+  ident_x->MapTo(x_sym);
+  auto value = Eval(extract);
+  EXPECT_TRUE(value.IsNull());
+}
+
+TEST_F(ExpressionEvaluatorTest, FunctionExtractExceptions) {
+  AstStorage storage;
+  auto *ident_x = IDENT("x");
+  auto *extract = EXTRACT("x", LITERAL("bla"), ADD(ident_x, LITERAL(1)));
+  const auto x_sym = symbol_table.CreateSymbol("x", true);
+  extract->identifier_->MapTo(x_sym);
+  ident_x->MapTo(x_sym);
+  EXPECT_THROW(Eval(extract), ExpressionRuntimeException);
+}
+
+TEST_F(ExpressionEvaluatorTest, RegexMatchInvalidArguments) {
+  EXPECT_TRUE(Eval(storage.Create<RegexMatch>(LITERAL(TypedValue()), LITERAL("regex"))).IsNull());
+  EXPECT_TRUE(Eval(storage.Create<RegexMatch>(LITERAL(3), LITERAL("regex"))).IsNull());
+  EXPECT_TRUE(Eval(storage.Create<RegexMatch>(LIST(LITERAL("string")), LITERAL("regex"))).IsNull());
+  EXPECT_TRUE(Eval(storage.Create<RegexMatch>(LITERAL("string"), LITERAL(TypedValue()))).IsNull());
+  EXPECT_THROW(Eval(storage.Create<RegexMatch>(LITERAL("string"), LITERAL(42))), ExpressionRuntimeException);
+  EXPECT_THROW(Eval(storage.Create<RegexMatch>(LITERAL("string"), LIST(LITERAL("regex")))), ExpressionRuntimeException);
+}
+
+TEST_F(ExpressionEvaluatorTest, RegexMatchInvalidRegex) {
+  EXPECT_THROW(Eval(storage.Create<RegexMatch>(LITERAL("text"), LITERAL("*ext"))), ExpressionRuntimeException);
+  EXPECT_THROW(Eval(storage.Create<RegexMatch>(LITERAL("text"), LITERAL("[ext"))), ExpressionRuntimeException);
+}
+
+TEST_F(ExpressionEvaluatorTest, RegexMatch) {
+  EXPECT_FALSE(Eval(storage.Create<RegexMatch>(LITERAL("text"), LITERAL(".*ex"))).ValueBool());
+  EXPECT_TRUE(Eval(storage.Create<RegexMatch>(LITERAL("text"), LITERAL(".*ext"))).ValueBool());
+  EXPECT_FALSE(Eval(storage.Create<RegexMatch>(LITERAL("text"), LITERAL("[ext]"))).ValueBool());
+  EXPECT_TRUE(Eval(storage.Create<RegexMatch>(LITERAL("text"), LITERAL(".+[ext]"))).ValueBool());
+}
+
+class ExpressionEvaluatorPropertyLookup : public ExpressionEvaluatorTest {
+ protected:
+  std::pair<std::string, memgraph::storage::v3::PropertyId> prop_age =
+      std::make_pair("age", shard_manager->NameToProperty("age"));
+  std::pair<std::string, memgraph::storage::v3::PropertyId> prop_height =
+      std::make_pair("height", shard_manager->NameToProperty("height"));
+  Identifier *identifier = storage.Create<Identifier>("element");
+  Symbol symbol = symbol_table.CreateSymbol("element", true);
+
+  void SetUp() { identifier->MapTo(symbol); }
+
+  auto Value(std::pair<std::string, memgraph::storage::v3::PropertyId> property) {
+    auto *op = storage.Create<PropertyLookup>(identifier, storage.GetPropertyIx(property.first));
+    return Eval(op);
+  }
+};
+
+// TEST_F(ExpressionEvaluatorPropertyLookup, Vertex) {
+//   auto v1 = dba.InsertVertex();
+//   ASSERT_TRUE(v1.SetProperty(prop_age.second, memgraph::storage::PropertyValue(10)).HasValue());
+//   dba.AdvanceCommand();
+//   frame[symbol] = TypedValue(v1);
+//   EXPECT_EQ(Value(prop_age).ValueInt(), 10);
+//   EXPECT_TRUE(Value(prop_height).IsNull());
+// }
+//
+// TEST_F(ExpressionEvaluatorPropertyLookup, Duration) {
+//   const memgraph::utils::Duration dur({10, 1, 30, 2, 22, 45});
+//   frame[symbol] = TypedValue(dur);
+//
+//   const std::pair day = std::make_pair("day", dba.NameToProperty("day"));
+//   const auto total_days = Value(day);
+//   EXPECT_TRUE(total_days.IsInt());
+//   EXPECT_EQ(total_days.ValueInt(), 10);
+//
+//   const std::pair hour = std::make_pair("hour", dba.NameToProperty("hour"));
+//   const auto total_hours = Value(hour);
+//   EXPECT_TRUE(total_hours.IsInt());
+//   EXPECT_EQ(total_hours.ValueInt(), 1);
+//
+//   const std::pair minute = std::make_pair("minute", dba.NameToProperty("minute"));
+//   const auto total_mins = Value(minute);
+//   EXPECT_TRUE(total_mins.IsInt());
+//
+//   EXPECT_EQ(total_mins.ValueInt(), 1 * 60 + 30);
+//
+//   const std::pair sec = std::make_pair("second", dba.NameToProperty("second"));
+//   const auto total_secs = Value(sec);
+//   EXPECT_TRUE(total_secs.IsInt());
+//   const auto expected_secs = total_mins.ValueInt() * 60 + 2;
+//   EXPECT_EQ(total_secs.ValueInt(), expected_secs);
+//
+//   const std::pair milli = std::make_pair("millisecond", dba.NameToProperty("millisecond"));
+//   const auto total_milli = Value(milli);
+//   EXPECT_TRUE(total_milli.IsInt());
+//   const auto expected_milli = total_secs.ValueInt() * 1000 + 22;
+//   EXPECT_EQ(total_milli.ValueInt(), expected_milli);
+//
+//   const std::pair micro = std::make_pair("microsecond", dba.NameToProperty("microsecond"));
+//   const auto total_micros = Value(micro);
+//   EXPECT_TRUE(total_micros.IsInt());
+//   const auto expected_micros = expected_milli * 1000 + 45;
+//   EXPECT_EQ(total_micros.ValueInt(), expected_micros);
+//
+//   const std::pair nano = std::make_pair("nanosecond", dba.NameToProperty("nanosecond"));
+//   const auto total_nano = Value(nano);
+//   EXPECT_TRUE(total_nano.IsInt());
+//   const auto expected_nano = expected_micros * 1000;
+//   EXPECT_EQ(total_nano.ValueInt(), expected_nano);
+// }
+//
+// TEST_F(ExpressionEvaluatorPropertyLookup, Date) {
+//   const memgraph::utils::Date date({1996, 11, 22});
+//   frame[symbol] = TypedValue(date);
+//
+//   const std::pair year = std::make_pair("year", dba.NameToProperty("year"));
+//   const auto y = Value(year);
+//   EXPECT_TRUE(y.IsInt());
+//   EXPECT_EQ(y.ValueInt(), 1996);
+//
+//   const std::pair month = std::make_pair("month", dba.NameToProperty("month"));
+//   const auto m = Value(month);
+//   EXPECT_TRUE(m.IsInt());
+//   EXPECT_EQ(m.ValueInt(), 11);
+//
+//   const std::pair day = std::make_pair("day", dba.NameToProperty("day"));
+//   const auto d = Value(day);
+//   EXPECT_TRUE(d.IsInt());
+//   EXPECT_EQ(d.ValueInt(), 22);
+// }
+//
+// TEST_F(ExpressionEvaluatorPropertyLookup, LocalTime) {
+//   const memgraph::utils::LocalTime lt({1, 2, 3, 11, 22});
+//   frame[symbol] = TypedValue(lt);
+//
+//   const std::pair hour = std::make_pair("hour", dba.NameToProperty("hour"));
+//   const auto h = Value(hour);
+//   EXPECT_TRUE(h.IsInt());
+//   EXPECT_EQ(h.ValueInt(), 1);
+//
+//   const std::pair minute = std::make_pair("minute", dba.NameToProperty("minute"));
+//   const auto min = Value(minute);
+//   EXPECT_TRUE(min.IsInt());
+//   EXPECT_EQ(min.ValueInt(), 2);
+//
+//   const std::pair second = std::make_pair("second", dba.NameToProperty("second"));
+//   const auto sec = Value(second);
+//   EXPECT_TRUE(sec.IsInt());
+//   EXPECT_EQ(sec.ValueInt(), 3);
+//
+//   const std::pair millis = std::make_pair("millisecond", dba.NameToProperty("millisecond"));
+//   const auto mil = Value(millis);
+//   EXPECT_TRUE(mil.IsInt());
+//   EXPECT_EQ(mil.ValueInt(), 11);
+//
+//   const std::pair micros = std::make_pair("microsecond", dba.NameToProperty("microsecond"));
+//   const auto mic = Value(micros);
+//   EXPECT_TRUE(mic.IsInt());
+//   EXPECT_EQ(mic.ValueInt(), 22);
+// }
+//
+// TEST_F(ExpressionEvaluatorPropertyLookup, LocalDateTime) {
+//   const memgraph::utils::LocalDateTime ldt({1993, 8, 6}, {2, 3, 4, 55, 40});
+//   frame[symbol] = TypedValue(ldt);
+//
+//   const std::pair year = std::make_pair("year", dba.NameToProperty("year"));
+//   const auto y = Value(year);
+//   EXPECT_TRUE(y.IsInt());
+//   EXPECT_EQ(y.ValueInt(), 1993);
+//
+//   const std::pair month = std::make_pair("month", dba.NameToProperty("month"));
+//   const auto m = Value(month);
+//   EXPECT_TRUE(m.IsInt());
+//   EXPECT_EQ(m.ValueInt(), 8);
+//
+//   const std::pair day = std::make_pair("day", dba.NameToProperty("day"));
+//   const auto d = Value(day);
+//   EXPECT_TRUE(d.IsInt());
+//   EXPECT_EQ(d.ValueInt(), 6);
+//
+//   const std::pair hour = std::make_pair("hour", dba.NameToProperty("hour"));
+//   const auto h = Value(hour);
+//   EXPECT_TRUE(h.IsInt());
+//   EXPECT_EQ(h.ValueInt(), 2);
+//
+//   const std::pair minute = std::make_pair("minute", dba.NameToProperty("minute"));
+//   const auto min = Value(minute);
+//   EXPECT_TRUE(min.IsInt());
+//   EXPECT_EQ(min.ValueInt(), 3);
+//
+//   const std::pair second = std::make_pair("second", dba.NameToProperty("second"));
+//   const auto sec = Value(second);
+//   EXPECT_TRUE(sec.IsInt());
+//   EXPECT_EQ(sec.ValueInt(), 4);
+//
+//   const std::pair millis = std::make_pair("millisecond", dba.NameToProperty("millisecond"));
+//   const auto mil = Value(millis);
+//   EXPECT_TRUE(mil.IsInt());
+//   EXPECT_EQ(mil.ValueInt(), 55);
+//
+//   const std::pair micros = std::make_pair("microsecond", dba.NameToProperty("microsecond"));
+//   const auto mic = Value(micros);
+//   EXPECT_TRUE(mic.IsInt());
+//   EXPECT_EQ(mic.ValueInt(), 40);
+// }
+//
+// TEST_F(ExpressionEvaluatorPropertyLookup, Edge) {
+//   auto v1 = dba.InsertVertex();
+//   auto v2 = dba.InsertVertex();
+//   auto e12 = dba.InsertEdge(&v1, &v2, dba.NameToEdgeType("edge_type"));
+//   ASSERT_TRUE(e12.HasValue());
+//   ASSERT_TRUE(e12->SetProperty(prop_age.second, memgraph::storage::PropertyValue(10)).HasValue());
+//   dba.AdvanceCommand();
+//   frame[symbol] = TypedValue(*e12);
+//   EXPECT_EQ(Value(prop_age).ValueInt(), 10);
+//   EXPECT_TRUE(Value(prop_height).IsNull());
+// }
+//
+TEST_F(ExpressionEvaluatorPropertyLookup, Null) {
+  frame[symbol] = TypedValue();
+  EXPECT_TRUE(Value(prop_age).IsNull());
+}
+
+TEST_F(ExpressionEvaluatorPropertyLookup, MapLiteral) {
+  frame[symbol] = TypedValue(std::map<std::string, TypedValue>{{prop_age.first, TypedValue(10)}});
+  EXPECT_EQ(Value(prop_age).ValueInt(), 10);
+  EXPECT_TRUE(Value(prop_height).IsNull());
+}
+
+class FunctionTest : public ExpressionEvaluatorTest {
+ protected:
+  std::vector<Expression *> ExpressionsFromTypedValues(const std::vector<TypedValue> &tvs) {
+    std::vector<Expression *> expressions;
+    expressions.reserve(tvs.size());
+
+    for (size_t i = 0; i < tvs.size(); ++i) {
+      auto *ident = storage.Create<Identifier>("arg_" + std::to_string(i), true);
+      auto sym = symbol_table.CreateSymbol("arg_" + std::to_string(i), true);
+      ident->MapTo(sym);
+      frame[sym] = tvs[i];
+      expressions.push_back(ident);
+    }
+
+    return expressions;
+  }
+
+  TypedValue EvaluateFunctionWithExprs(const std::string &function_name, const std::vector<Expression *> &expressions) {
+    auto *op = storage.Create<Function>(function_name, expressions);
+    return Eval(op);
+  }
+
+  template <class... TArgs>
+  TypedValue EvaluateFunction(const std::string &function_name, std::tuple<TArgs...> args) {
+    std::vector<TypedValue> tv_args;
+    tv_args.reserve(args.size());
+    for (auto &arg : args) tv_args.emplace_back(std::move(arg));
+    return EvaluateFunctionWithExprs(function_name, ExpressionsFromTypedValues(tv_args));
+  }
+
+  template <class... TArgs>
+  TypedValue EvaluateFunction(const std::string &function_name, TArgs &&...args) {
+    return EvaluateFunctionWithExprs(function_name,
+                                     ExpressionsFromTypedValues(std::vector<TypedValue>{TypedValue(args)...}));
+  }
+};
+
+template <class... TArgs>
+static TypedValue MakeTypedValueList(TArgs &&...args) {
+  return TypedValue(std::vector<TypedValue>{TypedValue(args)...});
+}
+
+TEST_F(FunctionTest, EndNode) {
+  ASSERT_THROW(EvaluateFunction("ENDNODE"), FunctionRuntimeException);
+  ASSERT_TRUE(EvaluateFunction("ENDNODE", TypedValue()).IsNull());
+  auto v1 = CreateVertex({}, shard_manager.get());
+  auto e = CreateEdge({}, shard_manager.get());
+  const auto expected = VertexId{{}, 0};
+  const auto res = EvaluateFunction("ENDNODE", e).ValueVertex().Id();
+  ASSERT_EQ(res, expected);
+  ASSERT_THROW(EvaluateFunction("ENDNODE", 2), FunctionRuntimeException);
+}
+
+TEST_F(FunctionTest, Head) {
+  ASSERT_THROW(EvaluateFunction("HEAD"), FunctionRuntimeException);
+  ASSERT_TRUE(EvaluateFunction("HEAD", TypedValue()).IsNull());
+  auto argument = MakeTypedValueList(3, 4, 5);
+  ASSERT_EQ(EvaluateFunction("HEAD", argument).ValueInt(), 3);
+  argument.ValueList().clear();
+  ASSERT_TRUE(EvaluateFunction("HEAD", argument).IsNull());
+  ASSERT_THROW(EvaluateFunction("HEAD", 2), FunctionRuntimeException);
+}
+
+TEST_F(FunctionTest, Properties) {
+  ASSERT_THROW(EvaluateFunction("PROPERTIES"), FunctionRuntimeException);
+  ASSERT_TRUE(EvaluateFunction("PROPERTIES", TypedValue()).IsNull());
+  const auto height = shard_manager->NameToProperty("height");
+  const auto age = shard_manager->NameToProperty("age");
+  auto v1 = CreateVertex({{height, Value(static_cast<int64_t>(5))}, {age, Value(static_cast<int64_t>(10))}},
+                         shard_manager.get());
+  auto e = CreateEdge({{height, Value(static_cast<int64_t>(3))}, {age, Value(static_cast<int64_t>(15))}},
+                      shard_manager.get());
+
+  auto prop_values_to_int = [](TypedValue t) {
+    std::unordered_map<std::string, int> properties;
+    for (auto property : t.ValueMap()) {
+      properties[std::string(property.first)] = property.second.ValueInt();
+    }
+    return properties;
+  };
+
+  ASSERT_THAT(prop_values_to_int(EvaluateFunction("PROPERTIES", v1)),
+              UnorderedElementsAre(testing::Pair("height", 5), testing::Pair("age", 10)));
+  ASSERT_THAT(prop_values_to_int(EvaluateFunction("PROPERTIES", e)),
+              UnorderedElementsAre(testing::Pair("height", 3), testing::Pair("age", 15)));
+  ASSERT_THROW(EvaluateFunction("PROPERTIES", 2), FunctionRuntimeException);
+}
+
+TEST_F(FunctionTest, Last) {
+  ASSERT_THROW(EvaluateFunction("LAST"), FunctionRuntimeException);
+  ASSERT_TRUE(EvaluateFunction("LAST", TypedValue()).IsNull());
+  auto argument = MakeTypedValueList(3, 4, 5);
+  ASSERT_EQ(EvaluateFunction("LAST", argument).ValueInt(), 5);
+  argument.ValueList().clear();
+  ASSERT_TRUE(EvaluateFunction("LAST", argument).IsNull());
+  ASSERT_THROW(EvaluateFunction("LAST", 5), FunctionRuntimeException);
+}
+
+TEST_F(FunctionTest, Size) {
+  ASSERT_THROW(EvaluateFunction("SIZE"), FunctionRuntimeException);
+  ASSERT_TRUE(EvaluateFunction("SIZE", TypedValue()).IsNull());
+  auto argument = MakeTypedValueList(3, 4, 5);
+  ASSERT_EQ(EvaluateFunction("SIZE", argument).ValueInt(), 3);
+  ASSERT_EQ(EvaluateFunction("SIZE", "john").ValueInt(), 4);
+  ASSERT_EQ(EvaluateFunction("SIZE",
+                             std::map<std::string, TypedValue>{
+                                 {"a", TypedValue(5)}, {"b", TypedValue(true)}, {"c", TypedValue("123")}})
+                .ValueInt(),
+            3);
+  ASSERT_THROW(EvaluateFunction("SIZE", 5), FunctionRuntimeException);
+
+  // TODO(kostasrim) Add this when we enable paths on the accessors
+  //  auto v0 = dba.InsertVertex();
+  //  memgraph::query::Path path(v0);
+  //  EXPECT_EQ(EvaluateFunction("SIZE", path).ValueInt(), 0);
+  //  auto v1 = dba.InsertVertex();
+  //  auto edge = dba.InsertEdge(&v0, &v1, dba.NameToEdgeType("type"));
+  //  ASSERT_TRUE(edge.HasValue());
+  //  path.Expand(*edge);
+  //  path.Expand(v1);
+  //  EXPECT_EQ(EvaluateFunction("SIZE", path).ValueInt(), 1);
+}
+
+TEST_F(FunctionTest, StartNode) {
+  ASSERT_THROW(EvaluateFunction("STARTNODE"), FunctionRuntimeException);
+  ASSERT_TRUE(EvaluateFunction("STARTNODE", TypedValue()).IsNull());
+  auto v1 = CreateVertex({}, shard_manager.get());
+  auto e = CreateEdge({}, shard_manager.get());
+  const auto expected = VertexId{{}, 0};
+  const auto res = EvaluateFunction("STARTNODE", e).ValueVertex().Id();
+  ASSERT_EQ(res, expected);
+  ASSERT_THROW(EvaluateFunction("STARTNODE", 2), FunctionRuntimeException);
+}
+
+// TODO(kostasrim) Enable this test once we add degree to the accessors
+// TEST_F(FunctionTest, Degree) {
+//   ASSERT_THROW(EvaluateFunction("DEGREE"), ExpressionRuntimeException);
+//   ASSERT_TRUE(EvaluateFunction("DEGREE", TypedValue()).IsNull());
+//   auto v1 = dba.InsertVertex();
+//   auto v2 = dba.InsertVertex();
+//   auto v3 = dba.InsertVertex();
+//   auto e12 = dba.InsertEdge(&v1, &v2, dba.NameToEdgeType("t"));
+//   ASSERT_TRUE(e12.HasValue());
+//   ASSERT_TRUE(dba.InsertEdge(&v3, &v2, dba.NameToEdgeType("t")).HasValue());
+//   dba.AdvanceCommand();
+//   ASSERT_EQ(EvaluateFunction("DEGREE", v1).ValueInt(), 1);
+//   ASSERT_EQ(EvaluateFunction("DEGREE", v2).ValueInt(), 2);
+//   ASSERT_EQ(EvaluateFunction("DEGREE", v3).ValueInt(), 1);
+//   ASSERT_THROW(EvaluateFunction("DEGREE", 2), ExpressionRuntimeException);
+//   ASSERT_THROW(EvaluateFunction("DEGREE", *e12), ExpressionRuntimeException);
+// }
+//
+// TODO(kostasrim) Enable this test once we add InDegree to the accessors
+// TEST_F(FunctionTest, InDegree) {
+//   ASSERT_THROW(EvaluateFunction("INDEGREE"), ExpressionRuntimeException);
+//   ASSERT_TRUE(EvaluateFunction("INDEGREE", TypedValue()).IsNull());
+//   auto v1 = dba.InsertVertex();
+//   auto v2 = dba.InsertVertex();
+//   auto v3 = dba.InsertVertex();
+//   auto e12 = dba.InsertEdge(&v1, &v2, dba.NameToEdgeType("t"));
+//   ASSERT_TRUE(e12.HasValue());
+//   ASSERT_TRUE(dba.InsertEdge(&v3, &v2, dba.NameToEdgeType("t")).HasValue());
+//   dba.AdvanceCommand();
+//   ASSERT_EQ(EvaluateFunction("INDEGREE", v1).ValueInt(), 0);
+//   ASSERT_EQ(EvaluateFunction("INDEGREE", v2).ValueInt(), 2);
+//   ASSERT_EQ(EvaluateFunction("INDEGREE", v3).ValueInt(), 0);
+//   ASSERT_THROW(EvaluateFunction("INDEGREE", 2), ExpressionRuntimeException);
+//   ASSERT_THROW(EvaluateFunction("INDEGREE", *e12), ExpressionRuntimeException);
+// }
+//
+// TODO(kostasrim) Enable this test once we add OutDegree to the accessors
+// TEST_F(FunctionTest, OutDegree) {
+//   ASSERT_THROW(EvaluateFunction("OUTDEGREE"), ExpressionRuntimeException);
+//   ASSERT_TRUE(EvaluateFunction("OUTDEGREE", TypedValue()).IsNull());
+//   auto v1 = dba.InsertVertex();
+//   auto v2 = dba.InsertVertex();
+//   auto v3 = dba.InsertVertex();
+//   auto e12 = dba.InsertEdge(&v1, &v2, dba.NameToEdgeType("t"));
+//   ASSERT_TRUE(e12.HasValue());
+//   ASSERT_TRUE(dba.InsertEdge(&v3, &v2, dba.NameToEdgeType("t")).HasValue());
+//   dba.AdvanceCommand();
+//   ASSERT_EQ(EvaluateFunction("OUTDEGREE", v1).ValueInt(), 1);
+//   ASSERT_EQ(EvaluateFunction("OUTDEGREE", v2).ValueInt(), 0);
+//   ASSERT_EQ(EvaluateFunction("OUTDEGREE", v3).ValueInt(), 1);
+//   ASSERT_THROW(EvaluateFunction("OUTDEGREE", 2), ExpressionRuntimeException);
+//   ASSERT_THROW(EvaluateFunction("OUTDEGREE", *e12), ExpressionRuntimeException);
+// }
+//
+TEST_F(FunctionTest, ToBoolean) {
+  ASSERT_THROW(EvaluateFunction("TOBOOLEAN"), FunctionRuntimeException);
+  ASSERT_TRUE(EvaluateFunction("TOBOOLEAN", TypedValue()).IsNull());
+  ASSERT_EQ(EvaluateFunction("TOBOOLEAN", 123).ValueBool(), true);
+  ASSERT_EQ(EvaluateFunction("TOBOOLEAN", -213).ValueBool(), true);
+  ASSERT_EQ(EvaluateFunction("TOBOOLEAN", 0).ValueBool(), false);
+  ASSERT_EQ(EvaluateFunction("TOBOOLEAN", " trUE \n\t").ValueBool(), true);
+  ASSERT_EQ(EvaluateFunction("TOBOOLEAN", "\n\tFalsE").ValueBool(), false);
+  ASSERT_TRUE(EvaluateFunction("TOBOOLEAN", "\n\tFALSEA ").IsNull());
+  ASSERT_EQ(EvaluateFunction("TOBOOLEAN", true).ValueBool(), true);
+  ASSERT_EQ(EvaluateFunction("TOBOOLEAN", false).ValueBool(), false);
+}
+
+TEST_F(FunctionTest, ToFloat) {
+  ASSERT_THROW(EvaluateFunction("TOFLOAT"), FunctionRuntimeException);
+  ASSERT_TRUE(EvaluateFunction("TOFLOAT", TypedValue()).IsNull());
+  ASSERT_EQ(EvaluateFunction("TOFLOAT", " -3.5 \n\t").ValueDouble(), -3.5);
+  ASSERT_EQ(EvaluateFunction("TOFLOAT", "\n\t0.5e-1").ValueDouble(), 0.05);
+  ASSERT_TRUE(EvaluateFunction("TOFLOAT", "\n\t3.4e-3X ").IsNull());
+  ASSERT_EQ(EvaluateFunction("TOFLOAT", -3.5).ValueDouble(), -3.5);
+  ASSERT_EQ(EvaluateFunction("TOFLOAT", -3).ValueDouble(), -3.0);
+  ASSERT_THROW(EvaluateFunction("TOFLOAT", true), FunctionRuntimeException);
+}
+
+TEST_F(FunctionTest, ToInteger) {
+  ASSERT_THROW(EvaluateFunction("TOINTEGER"), FunctionRuntimeException);
+  ASSERT_TRUE(EvaluateFunction("TOINTEGER", TypedValue()).IsNull());
+  ASSERT_EQ(EvaluateFunction("TOINTEGER", false).ValueInt(), 0);
+  ASSERT_EQ(EvaluateFunction("TOINTEGER", true).ValueInt(), 1);
+  ASSERT_EQ(EvaluateFunction("TOINTEGER", "\n\t3").ValueInt(), 3);
+  ASSERT_EQ(EvaluateFunction("TOINTEGER", " -3.5 \n\t").ValueInt(), -3);
+  ASSERT_TRUE(EvaluateFunction("TOINTEGER", "\n\t3X ").IsNull());
+  ASSERT_EQ(EvaluateFunction("TOINTEGER", -3.5).ValueInt(), -3);
+  ASSERT_EQ(EvaluateFunction("TOINTEGER", 3.5).ValueInt(), 3);
+}
+
+TEST_F(FunctionTest, Type) {
+  ASSERT_THROW(EvaluateFunction("TYPE"), FunctionRuntimeException);
+  ASSERT_TRUE(EvaluateFunction("TYPE", TypedValue()).IsNull());
+  auto e = CreateEdge({}, shard_manager.get());
+  ASSERT_EQ(EvaluateFunction("TYPE", e).ValueString(), "edge_type");
+  ASSERT_THROW(EvaluateFunction("TYPE", 2), FunctionRuntimeException);
+}
+
+TEST_F(FunctionTest, ValueType) {
+  ASSERT_THROW(EvaluateFunction("VALUETYPE"), FunctionRuntimeException);
+  ASSERT_THROW(EvaluateFunction("VALUETYPE", TypedValue(), TypedValue()), FunctionRuntimeException);
+  ASSERT_EQ(EvaluateFunction("VALUETYPE", TypedValue()).ValueString(), "NULL");
+  ASSERT_EQ(EvaluateFunction("VALUETYPE", TypedValue(true)).ValueString(), "BOOLEAN");
+  ASSERT_EQ(EvaluateFunction("VALUETYPE", TypedValue(1)).ValueString(), "INTEGER");
+  ASSERT_EQ(EvaluateFunction("VALUETYPE", TypedValue(1.1)).ValueString(), "FLOAT");
+  ASSERT_EQ(EvaluateFunction("VALUETYPE", TypedValue("test")).ValueString(), "STRING");
+  ASSERT_EQ(
+      EvaluateFunction("VALUETYPE", TypedValue(std::vector<TypedValue>{TypedValue(1), TypedValue(2)})).ValueString(),
+      "LIST");
+  ASSERT_EQ(EvaluateFunction("VALUETYPE", TypedValue(std::map<std::string, TypedValue>{{"test", TypedValue(1)}}))
+                .ValueString(),
+            "MAP");
+  auto v1 = CreateVertex({}, shard_manager.get());
+  ASSERT_EQ(EvaluateFunction("VALUETYPE", v1).ValueString(), "NODE");
+  auto e = CreateEdge({}, shard_manager.get());
+  ASSERT_EQ(EvaluateFunction("VALUETYPE", e).ValueString(), "RELATIONSHIP");
+  // TODO(kostasrim) Fix this when we add Path to accessors
+  //  Path p(v1, *e, v2);
+  //  ASSERT_EQ(EvaluateFunction("VALUETYPE", p).ValueString(), "PATH");
+}
+
+TEST_F(FunctionTest, Labels) {
+  ASSERT_THROW(EvaluateFunction("LABELS"), FunctionRuntimeException);
+  ASSERT_TRUE(EvaluateFunction("LABELS", TypedValue()).IsNull());
+  Label label{shard_manager->NameToLabel("label1")};
+  auto v = CreateVertex({}, shard_manager.get(), std::move(label));
+  std::vector<std::string> labels;
+  auto _labels = EvaluateFunction("LABELS", v).ValueList();
+  labels.reserve(_labels.size());
+  for (auto label : _labels) {
+    labels.emplace_back(label.ValueString());
+  }
+  ASSERT_THAT(labels, UnorderedElementsAre("label1"));
+  ASSERT_THROW(EvaluateFunction("LABELS", 2), FunctionRuntimeException);
+}
+
+// TODO(kostasrim) Enable this once we fix accessors Path
+// TEST_F(FunctionTest, NodesRelationships) {
+//   EXPECT_THROW(EvaluateFunction("NODES"), ExpressionRuntimeException);
+//   EXPECT_THROW(EvaluateFunction("RELATIONSHIPS"), ExpressionRuntimeException);
+//   EXPECT_TRUE(EvaluateFunction("NODES", TypedValue()).IsNull());
+//   EXPECT_TRUE(EvaluateFunction("RELATIONSHIPS", TypedValue()).IsNull());
+//
+//   {
+//     auto v1 = dba.InsertVertex();
+//     auto v2 = dba.InsertVertex();
+//     auto v3 = dba.InsertVertex();
+//     auto e1 = dba.InsertEdge(&v1, &v2, dba.NameToEdgeType("Type"));
+//     ASSERT_TRUE(e1.HasValue());
+//     auto e2 = dba.InsertEdge(&v2, &v3, dba.NameToEdgeType("Type"));
+//     ASSERT_TRUE(e2.HasValue());
+//     memgraph::query::Path path{v1, *e1, v2, *e2, v3};
+//     dba.AdvanceCommand();
+//
+//     auto _nodes = EvaluateFunction("NODES", path).ValueList();
+//     std::vector<memgraph::query::VertexAccessor> nodes;
+//     for (const auto &node : _nodes) {
+//       nodes.push_back(node.ValueVertex());
+//     }
+//     EXPECT_THAT(nodes, ElementsAre(v1, v2, v3));
+//
+//     auto _edges = EvaluateFunction("RELATIONSHIPS", path).ValueList();
+//     std::vector<memgraph::query::EdgeAccessor> edges;
+//     for (const auto &edge : _edges) {
+//       edges.push_back(edge.ValueEdge());
+//     }
+//     EXPECT_THAT(edges, ElementsAre(*e1, *e2));
+//   }
+//
+//   EXPECT_THROW(EvaluateFunction("NODES", 2), ExpressionRuntimeException);
+//   EXPECT_THROW(EvaluateFunction("RELATIONSHIPS", 2), ExpressionRuntimeException);
+// }
+//
+TEST_F(FunctionTest, Range) {
+  EXPECT_THROW(EvaluateFunction("RANGE"), FunctionRuntimeException);
+  EXPECT_TRUE(EvaluateFunction("RANGE", 1, 2, TypedValue()).IsNull());
+  EXPECT_THROW(EvaluateFunction("RANGE", 1, TypedValue(), 1.3), FunctionRuntimeException);
+  EXPECT_THROW(EvaluateFunction("RANGE", 1, 2, 0), FunctionRuntimeException);
+  EXPECT_THAT(ToIntList(EvaluateFunction("RANGE", 1, 3)), ElementsAre(1, 2, 3));
+  EXPECT_THAT(ToIntList(EvaluateFunction("RANGE", -1, 5, 2)), ElementsAre(-1, 1, 3, 5));
+  EXPECT_THAT(ToIntList(EvaluateFunction("RANGE", 2, 10, 3)), ElementsAre(2, 5, 8));
+  EXPECT_THAT(ToIntList(EvaluateFunction("RANGE", 2, 2, 2)), ElementsAre(2));
+  EXPECT_THAT(ToIntList(EvaluateFunction("RANGE", 3, 0, 5)), ElementsAre());
+  EXPECT_THAT(ToIntList(EvaluateFunction("RANGE", 5, 1, -2)), ElementsAre(5, 3, 1));
+  EXPECT_THAT(ToIntList(EvaluateFunction("RANGE", 6, 1, -2)), ElementsAre(6, 4, 2));
+  EXPECT_THAT(ToIntList(EvaluateFunction("RANGE", 2, 2, -3)), ElementsAre(2));
+  EXPECT_THAT(ToIntList(EvaluateFunction("RANGE", -2, 4, -1)), ElementsAre());
+}
+
+TEST_F(FunctionTest, Keys) {
+  ASSERT_THROW(EvaluateFunction("KEYS"), FunctionRuntimeException);
+  ASSERT_TRUE(EvaluateFunction("KEYS", TypedValue()).IsNull());
+  const auto height = shard_manager->NameToProperty("height");
+  const auto age = shard_manager->NameToProperty("age");
+  auto v1 = CreateVertex({{height, Value(static_cast<int64_t>(5))}, {age, Value(static_cast<int64_t>(10))}},
+                         shard_manager.get());
+  auto edge = CreateEdge({{height, Value(static_cast<int64_t>(3))}, {age, Value(static_cast<int64_t>(15))}},
+                         shard_manager.get());
+  auto prop_keys_to_string = [](TypedValue t) {
+    std::vector<std::string> keys;
+    for (auto property : t.ValueList()) {
+      keys.emplace_back(property.ValueString());
+    }
+    return keys;
+  };
+  ASSERT_THAT(prop_keys_to_string(EvaluateFunction("KEYS", v1)), UnorderedElementsAre("height", "age"));
+  ASSERT_THAT(prop_keys_to_string(EvaluateFunction("KEYS", edge)), UnorderedElementsAre("height", "age"));
+  ASSERT_THROW(EvaluateFunction("KEYS", 2), FunctionRuntimeException);
+}
+
+TEST_F(FunctionTest, Tail) {
+  ASSERT_THROW(EvaluateFunction("TAIL"), FunctionRuntimeException);
+  ASSERT_TRUE(EvaluateFunction("TAIL", TypedValue()).IsNull());
+  auto argument = MakeTypedValueList();
+  ASSERT_EQ(EvaluateFunction("TAIL", argument).ValueList().size(), 0U);
+  argument = MakeTypedValueList(3, 4, true, "john");
+  auto list = EvaluateFunction("TAIL", argument).ValueList();
+  ASSERT_EQ(list.size(), 3U);
+  ASSERT_EQ(list[0].ValueInt(), 4);
+  ASSERT_EQ(list[1].ValueBool(), true);
+  ASSERT_EQ(list[2].ValueString(), "john");
+  ASSERT_THROW(EvaluateFunction("TAIL", 2), FunctionRuntimeException);
+}
+
+TEST_F(FunctionTest, UniformSample) {
+  ASSERT_THROW(EvaluateFunction("UNIFORMSAMPLE"), FunctionRuntimeException);
+  ASSERT_TRUE(EvaluateFunction("UNIFORMSAMPLE", TypedValue(), TypedValue()).IsNull());
+  ASSERT_TRUE(EvaluateFunction("UNIFORMSAMPLE", TypedValue(), 1).IsNull());
+  ASSERT_TRUE(EvaluateFunction("UNIFORMSAMPLE", MakeTypedValueList(), TypedValue()).IsNull());
+  ASSERT_TRUE(EvaluateFunction("UNIFORMSAMPLE", MakeTypedValueList(), 1).IsNull());
+  ASSERT_THROW(EvaluateFunction("UNIFORMSAMPLE", MakeTypedValueList(1, 2, 3), -1), FunctionRuntimeException);
+  ASSERT_EQ(EvaluateFunction("UNIFORMSAMPLE", MakeTypedValueList(1, 2, 3), 0).ValueList().size(), 0);
+  ASSERT_EQ(EvaluateFunction("UNIFORMSAMPLE", MakeTypedValueList(1, 2, 3), 2).ValueList().size(), 2);
+  ASSERT_EQ(EvaluateFunction("UNIFORMSAMPLE", MakeTypedValueList(1, 2, 3), 3).ValueList().size(), 3);
+  ASSERT_EQ(EvaluateFunction("UNIFORMSAMPLE", MakeTypedValueList(1, 2, 3), 5).ValueList().size(), 5);
+}
+
+TEST_F(FunctionTest, Abs) {
+  ASSERT_THROW(EvaluateFunction("ABS"), FunctionRuntimeException);
+  ASSERT_TRUE(EvaluateFunction("ABS", TypedValue()).IsNull());
+  ASSERT_EQ(EvaluateFunction("ABS", -2).ValueInt(), 2);
+  ASSERT_EQ(EvaluateFunction("ABS", -2.5).ValueDouble(), 2.5);
+  ASSERT_THROW(EvaluateFunction("ABS", true), FunctionRuntimeException);
+}
+
+//// Test if log works. If it does then all functions wrapped with
+//// WRAP_CMATH_FLOAT_FUNCTION macro should work and are not gonna be tested for
+//// correctnes..
+TEST_F(FunctionTest, Log) {
+  ASSERT_THROW(EvaluateFunction("LOG"), FunctionRuntimeException);
+  ASSERT_TRUE(EvaluateFunction("LOG", TypedValue()).IsNull());
+  ASSERT_DOUBLE_EQ(EvaluateFunction("LOG", 2).ValueDouble(), log(2));
+  ASSERT_DOUBLE_EQ(EvaluateFunction("LOG", 1.5).ValueDouble(), log(1.5));
+  // Not portable, but should work on most platforms.
+  ASSERT_TRUE(std::isnan(EvaluateFunction("LOG", -1.5).ValueDouble()));
+  ASSERT_THROW(EvaluateFunction("LOG", true), FunctionRuntimeException);
+}
+
+//// Function Round wraps round from cmath and will work if FunctionTest.Log test
+//// passes. This test is used to show behavior of round since it differs from
+//// neo4j's round.
+TEST_F(FunctionTest, Round) {
+  ASSERT_THROW(EvaluateFunction("ROUND"), FunctionRuntimeException);
+  ASSERT_TRUE(EvaluateFunction("ROUND", TypedValue()).IsNull());
+  ASSERT_EQ(EvaluateFunction("ROUND", -2).ValueDouble(), -2);
+  ASSERT_EQ(EvaluateFunction("ROUND", -2.4).ValueDouble(), -2);
+  ASSERT_EQ(EvaluateFunction("ROUND", -2.5).ValueDouble(), -3);
+  ASSERT_EQ(EvaluateFunction("ROUND", -2.6).ValueDouble(), -3);
+  ASSERT_EQ(EvaluateFunction("ROUND", 2.4).ValueDouble(), 2);
+  ASSERT_EQ(EvaluateFunction("ROUND", 2.5).ValueDouble(), 3);
+  ASSERT_EQ(EvaluateFunction("ROUND", 2.6).ValueDouble(), 3);
+  ASSERT_THROW(EvaluateFunction("ROUND", true), FunctionRuntimeException);
+}
+
+// Check if wrapped functions are callable (check if everything was spelled
+// correctly...). Wrapper correctnes is checked in FunctionTest.Log function
+// test.
+TEST_F(FunctionTest, WrappedMathFunctions) {
+  for (auto function_name :
+       {"FLOOR", "CEIL", "ROUND", "EXP", "LOG", "LOG10", "SQRT", "ACOS", "ASIN", "ATAN", "COS", "SIN", "TAN"}) {
+    EvaluateFunction(function_name, 0.5);
+  }
+}
+
+TEST_F(FunctionTest, Atan2) {
+  ASSERT_THROW(EvaluateFunction("ATAN2"), FunctionRuntimeException);
+  ASSERT_TRUE(EvaluateFunction("ATAN2", TypedValue(), 1).IsNull());
+  ASSERT_TRUE(EvaluateFunction("ATAN2", 1, TypedValue()).IsNull());
+  ASSERT_DOUBLE_EQ(EvaluateFunction("ATAN2", 2, -1.0).ValueDouble(), atan2(2, -1));
+  ASSERT_THROW(EvaluateFunction("ATAN2", 3.0, true), FunctionRuntimeException);
+}
+
+TEST_F(FunctionTest, Sign) {
+  ASSERT_THROW(EvaluateFunction("SIGN"), FunctionRuntimeException);
+  ASSERT_TRUE(EvaluateFunction("SIGN", TypedValue()).IsNull());
+  ASSERT_EQ(EvaluateFunction("SIGN", -2).ValueInt(), -1);
+  ASSERT_EQ(EvaluateFunction("SIGN", -0.2).ValueInt(), -1);
+  ASSERT_EQ(EvaluateFunction("SIGN", 0.0).ValueInt(), 0);
+  ASSERT_EQ(EvaluateFunction("SIGN", 2.5).ValueInt(), 1);
+  ASSERT_THROW(EvaluateFunction("SIGN", true), FunctionRuntimeException);
+}
+
+TEST_F(FunctionTest, E) {
+  ASSERT_THROW(EvaluateFunction("E", 1), FunctionRuntimeException);
+  ASSERT_DOUBLE_EQ(EvaluateFunction("E").ValueDouble(), M_E);
+}
+
+TEST_F(FunctionTest, Pi) {
+  ASSERT_THROW(EvaluateFunction("PI", 1), FunctionRuntimeException);
+  ASSERT_DOUBLE_EQ(EvaluateFunction("PI").ValueDouble(), M_PI);
+}
+
+TEST_F(FunctionTest, Rand) {
+  ASSERT_THROW(EvaluateFunction("RAND", 1), FunctionRuntimeException);
+  ASSERT_GE(EvaluateFunction("RAND").ValueDouble(), 0.0);
+  ASSERT_LT(EvaluateFunction("RAND").ValueDouble(), 1.0);
+}
+
+using memgraph::functions::kStartsWith;
+TEST_F(FunctionTest, StartsWith) {
+  EXPECT_THROW(EvaluateFunction(kStartsWith), FunctionRuntimeException);
+  EXPECT_TRUE(EvaluateFunction(kStartsWith, "a", TypedValue()).IsNull());
+  EXPECT_THROW(EvaluateFunction(kStartsWith, TypedValue(), 1.3), FunctionRuntimeException);
+  EXPECT_TRUE(EvaluateFunction(kStartsWith, "abc", "abc").ValueBool());
+  EXPECT_TRUE(EvaluateFunction(kStartsWith, "abcdef", "abc").ValueBool());
+  EXPECT_FALSE(EvaluateFunction(kStartsWith, "abcdef", "aBc").ValueBool());
+  EXPECT_FALSE(EvaluateFunction(kStartsWith, "abc", "abcd").ValueBool());
+}
+
+using memgraph::functions::kEndsWith;
+TEST_F(FunctionTest, EndsWith) {
+  EXPECT_THROW(EvaluateFunction(kEndsWith), FunctionRuntimeException);
+  EXPECT_TRUE(EvaluateFunction(kEndsWith, "a", TypedValue()).IsNull());
+  EXPECT_THROW(EvaluateFunction(kEndsWith, TypedValue(), 1.3), FunctionRuntimeException);
+  EXPECT_TRUE(EvaluateFunction(kEndsWith, "abc", "abc").ValueBool());
+  EXPECT_TRUE(EvaluateFunction(kEndsWith, "abcdef", "def").ValueBool());
+  EXPECT_FALSE(EvaluateFunction(kEndsWith, "abcdef", "dEf").ValueBool());
+  EXPECT_FALSE(EvaluateFunction(kEndsWith, "bcd", "abcd").ValueBool());
+}
+
+using memgraph::functions::kContains;
+TEST_F(FunctionTest, Contains) {
+  EXPECT_THROW(EvaluateFunction(kContains), FunctionRuntimeException);
+  EXPECT_TRUE(EvaluateFunction(kContains, "a", TypedValue()).IsNull());
+  EXPECT_THROW(EvaluateFunction(kContains, TypedValue(), 1.3), FunctionRuntimeException);
+  EXPECT_TRUE(EvaluateFunction(kContains, "abc", "abc").ValueBool());
+  EXPECT_TRUE(EvaluateFunction(kContains, "abcde", "bcd").ValueBool());
+  EXPECT_FALSE(EvaluateFunction(kContains, "cde", "abcdef").ValueBool());
+  EXPECT_FALSE(EvaluateFunction(kContains, "abcdef", "dEf").ValueBool());
+}
+
+TEST_F(FunctionTest, Assert) {
+  // Invalid calls.
+  ASSERT_THROW(EvaluateFunction("ASSERT"), FunctionRuntimeException);
+  ASSERT_THROW(EvaluateFunction("ASSERT", false, false), FunctionRuntimeException);
+  ASSERT_THROW(EvaluateFunction("ASSERT", "string", false), FunctionRuntimeException);
+  ASSERT_THROW(EvaluateFunction("ASSERT", false, "reason", true), FunctionRuntimeException);
+
+  // Valid calls, assertion fails.
+  ASSERT_THROW(EvaluateFunction("ASSERT", false), FunctionRuntimeException);
+  ASSERT_THROW(EvaluateFunction("ASSERT", false, "message"), FunctionRuntimeException);
+  try {
+    EvaluateFunction("ASSERT", false, "bbgba");
+  } catch (FunctionRuntimeException &e) {
+    ASSERT_TRUE(std::string(e.what()).find("bbgba") != std::string::npos);
+  }
+
+  // Valid calls, assertion passes.
+  ASSERT_TRUE(EvaluateFunction("ASSERT", true).ValueBool());
+  ASSERT_TRUE(EvaluateFunction("ASSERT", true, "message").ValueBool());
+}
+
+TEST_F(FunctionTest, Counter) {
+  EXPECT_THROW(EvaluateFunction("COUNTER"), FunctionRuntimeException);
+  EXPECT_THROW(EvaluateFunction("COUNTER", "a"), FunctionRuntimeException);
+  EXPECT_THROW(EvaluateFunction("COUNTER", "a", "b"), FunctionRuntimeException);
+  EXPECT_THROW(EvaluateFunction("COUNTER", "a", "b", "c"), FunctionRuntimeException);
+
+  EXPECT_EQ(EvaluateFunction("COUNTER", "c1", 0).ValueInt(), 0);
+  EXPECT_EQ(EvaluateFunction("COUNTER", "c1", 0).ValueInt(), 1);
+  EXPECT_EQ(EvaluateFunction("COUNTER", "c2", 0).ValueInt(), 0);
+  EXPECT_EQ(EvaluateFunction("COUNTER", "c1", 0).ValueInt(), 2);
+  EXPECT_EQ(EvaluateFunction("COUNTER", "c2", 0).ValueInt(), 1);
+
+  EXPECT_EQ(EvaluateFunction("COUNTER", "c3", -1).ValueInt(), -1);
+  EXPECT_EQ(EvaluateFunction("COUNTER", "c3", -1).ValueInt(), 0);
+  EXPECT_EQ(EvaluateFunction("COUNTER", "c3", -1).ValueInt(), 1);
+
+  EXPECT_EQ(EvaluateFunction("COUNTER", "c4", 0, 5).ValueInt(), 0);
+  EXPECT_EQ(EvaluateFunction("COUNTER", "c4", 0, 5).ValueInt(), 5);
+  EXPECT_EQ(EvaluateFunction("COUNTER", "c4", 0, 5).ValueInt(), 10);
+
+  EXPECT_EQ(EvaluateFunction("COUNTER", "c5", 0, -5).ValueInt(), 0);
+  EXPECT_EQ(EvaluateFunction("COUNTER", "c5", 0, -5).ValueInt(), -5);
+  EXPECT_EQ(EvaluateFunction("COUNTER", "c5", 0, -5).ValueInt(), -10);
+
+  EXPECT_THROW(EvaluateFunction("COUNTER", "c6", 0, 0), FunctionRuntimeException);
+}
+
+// TODO(kostasrim) Add this once we fix accessors CypherId() functions
+// TEST_F(FunctionTest, Id) {
+//  auto v = CreateVertex({}, shard_manager.get());
+//  auto e = CreateEdge({}, shard_manager.get());
+//  EXPECT_TRUE(EvaluateFunction("ID", TypedValue()).IsNull());
+//  EXPECT_EQ(EvaluateFunction("ID", v).ValueInt(), 0);
+//  EXPECT_EQ(EvaluateFunction("ID", e).ValueInt(), 0);
+//  EXPECT_THROW(EvaluateFunction("ID"), FunctionRuntimeException);
+//  EXPECT_THROW(EvaluateFunction("ID", 0), FunctionRuntimeException);
+//  EXPECT_THROW(EvaluateFunction("ID", v, e), FunctionRuntimeException);
+//}
+
+TEST_F(FunctionTest, ToStringNull) { EXPECT_TRUE(EvaluateFunction("TOSTRING", TypedValue()).IsNull()); }
+
+TEST_F(FunctionTest, ToStringString) {
+  EXPECT_EQ(EvaluateFunction("TOSTRING", "").ValueString(), "");
+  EXPECT_EQ(EvaluateFunction("TOSTRING", "this is a string").ValueString(), "this is a string");
+}
+
+TEST_F(FunctionTest, ToStringInteger) {
+  EXPECT_EQ(EvaluateFunction("TOSTRING", -23321312).ValueString(), "-23321312");
+  EXPECT_EQ(EvaluateFunction("TOSTRING", 0).ValueString(), "0");
+  EXPECT_EQ(EvaluateFunction("TOSTRING", 42).ValueString(), "42");
+}
+
+TEST_F(FunctionTest, ToStringDouble) {
+  EXPECT_EQ(EvaluateFunction("TOSTRING", -42.42).ValueString(), "-42.420000");
+  EXPECT_EQ(EvaluateFunction("TOSTRING", 0.0).ValueString(), "0.000000");
+  EXPECT_EQ(EvaluateFunction("TOSTRING", 238910.2313217).ValueString(), "238910.231322");
+}
+
+TEST_F(FunctionTest, ToStringBool) {
+  EXPECT_EQ(EvaluateFunction("TOSTRING", true).ValueString(), "true");
+  EXPECT_EQ(EvaluateFunction("TOSTRING", false).ValueString(), "false");
+}
+
+// TEST_F(FunctionTest, ToStringDate) {
+//   const auto date = memgraph::utils::Date({1970, 1, 2});
+//   EXPECT_EQ(EvaluateFunction("TOSTRING", date).ValueString(), "1970-01-02");
+// }
+//
+// TEST_F(FunctionTest, ToStringLocalTime) {
+//   const auto lt = memgraph::utils::LocalTime({13, 2, 40, 100, 50});
+//   EXPECT_EQ(EvaluateFunction("TOSTRING", lt).ValueString(), "13:02:40.100050");
+// }
+//
+// TEST_F(FunctionTest, ToStringLocalDateTime) {
+//   const auto ldt = memgraph::utils::LocalDateTime({1970, 1, 2}, {23, 02, 59});
+//   EXPECT_EQ(EvaluateFunction("TOSTRING", ldt).ValueString(), "1970-01-02T23:02:59.000000");
+// }
+//
+// TEST_F(FunctionTest, ToStringDuration) {
+//   memgraph::utils::Duration duration{{.minute = 2, .second = 2, .microsecond = 33}};
+//   EXPECT_EQ(EvaluateFunction("TOSTRING", duration).ValueString(), "P0DT0H2M2.000033S");
+// }
+//
+TEST_F(FunctionTest, ToStringExceptions) {
+  EXPECT_THROW(EvaluateFunction("TOSTRING", 1, 2, 3), FunctionRuntimeException);
+}
+//
+// TEST_F(FunctionTest, TimestampVoid) {
+//   ctx.timestamp = 42;
+//   EXPECT_EQ(EvaluateFunction("TIMESTAMP").ValueInt(), 42);
+// }
+//
+// TEST_F(FunctionTest, TimestampDate) {
+//   ctx.timestamp = 42;
+//   EXPECT_EQ(EvaluateFunction("TIMESTAMP", memgraph::utils::Date({1970, 1, 1})).ValueInt(), 0);
+//   EXPECT_EQ(EvaluateFunction("TIMESTAMP", memgraph::utils::Date({1971, 1, 1})).ValueInt(), 31536000000000);
+// }
+//
+// TEST_F(FunctionTest, TimestampLocalTime) {
+//   ctx.timestamp = 42;
+//   const memgraph::utils::LocalTime time(10000);
+//   EXPECT_EQ(EvaluateFunction("TIMESTAMP", time).ValueInt(), 10000);
+// }
+//
+// TEST_F(FunctionTest, TimestampLocalDateTime) {
+//   ctx.timestamp = 42;
+//   const memgraph::utils::LocalDateTime time(20000);
+//   EXPECT_EQ(EvaluateFunction("TIMESTAMP", time).ValueInt(), 20000);
+// }
+//
+// TEST_F(FunctionTest, TimestampDuration) {
+//   ctx.timestamp = 42;
+//   const memgraph::utils::Duration time(20000);
+//   EXPECT_EQ(EvaluateFunction("TIMESTAMP", time).ValueInt(), 20000);
+// }
+//
+// TEST_F(FunctionTest, TimestampExceptions) {
+//   ctx.timestamp = 42;
+//   EXPECT_THROW(EvaluateFunction("TIMESTAMP", 1).ValueInt(), ExpressionRuntimeException);
+// }
+//
+TEST_F(FunctionTest, Left) {
+  EXPECT_THROW(EvaluateFunction("LEFT"), FunctionRuntimeException);
+
+  EXPECT_TRUE(EvaluateFunction("LEFT", TypedValue(), TypedValue()).IsNull());
+  EXPECT_TRUE(EvaluateFunction("LEFT", TypedValue(), 10).IsNull());
+  EXPECT_THROW(EvaluateFunction("LEFT", TypedValue(), -10), FunctionRuntimeException);
+
+  EXPECT_EQ(EvaluateFunction("LEFT", "memgraph", 0).ValueString(), "");
+  EXPECT_EQ(EvaluateFunction("LEFT", "memgraph", 3).ValueString(), "mem");
+  EXPECT_EQ(EvaluateFunction("LEFT", "memgraph", 1000).ValueString(), "memgraph");
+  EXPECT_THROW(EvaluateFunction("LEFT", "memgraph", -10), FunctionRuntimeException);
+  EXPECT_THROW(EvaluateFunction("LEFT", "memgraph", "graph"), FunctionRuntimeException);
+
+  EXPECT_THROW(EvaluateFunction("LEFT", 132, 10), FunctionRuntimeException);
+}
+
+TEST_F(FunctionTest, Right) {
+  EXPECT_THROW(EvaluateFunction("RIGHT"), FunctionRuntimeException);
+
+  EXPECT_TRUE(EvaluateFunction("RIGHT", TypedValue(), TypedValue()).IsNull());
+  EXPECT_TRUE(EvaluateFunction("RIGHT", TypedValue(), 10).IsNull());
+  EXPECT_THROW(EvaluateFunction("RIGHT", TypedValue(), -10), FunctionRuntimeException);
+
+  EXPECT_EQ(EvaluateFunction("RIGHT", "memgraph", 0).ValueString(), "");
+  EXPECT_EQ(EvaluateFunction("RIGHT", "memgraph", 3).ValueString(), "aph");
+  EXPECT_EQ(EvaluateFunction("RIGHT", "memgraph", 1000).ValueString(), "memgraph");
+  EXPECT_THROW(EvaluateFunction("RIGHT", "memgraph", -10), FunctionRuntimeException);
+  EXPECT_THROW(EvaluateFunction("RIGHT", "memgraph", "graph"), FunctionRuntimeException);
+
+  EXPECT_THROW(EvaluateFunction("RIGHT", 132, 10), FunctionRuntimeException);
+}
+
+TEST_F(FunctionTest, Trimming) {
+  EXPECT_TRUE(EvaluateFunction("LTRIM", TypedValue()).IsNull());
+  EXPECT_TRUE(EvaluateFunction("RTRIM", TypedValue()).IsNull());
+  EXPECT_TRUE(EvaluateFunction("TRIM", TypedValue()).IsNull());
+
+  EXPECT_EQ(EvaluateFunction("LTRIM", "  abc    ").ValueString(), "abc    ");
+  EXPECT_EQ(EvaluateFunction("RTRIM", " abc ").ValueString(), " abc");
+  EXPECT_EQ(EvaluateFunction("TRIM", "abc").ValueString(), "abc");
+
+  EXPECT_THROW(EvaluateFunction("LTRIM", "x", "y"), FunctionRuntimeException);
+  EXPECT_THROW(EvaluateFunction("RTRIM", "x", "y"), FunctionRuntimeException);
+  EXPECT_THROW(EvaluateFunction("TRIM", "x", "y"), FunctionRuntimeException);
+}
+
+TEST_F(FunctionTest, Reverse) {
+  EXPECT_TRUE(EvaluateFunction("REVERSE", TypedValue()).IsNull());
+  EXPECT_EQ(EvaluateFunction("REVERSE", "abc").ValueString(), "cba");
+  EXPECT_THROW(EvaluateFunction("REVERSE", "x", "y"), FunctionRuntimeException);
+}
+
+TEST_F(FunctionTest, Replace) {
+  EXPECT_THROW(EvaluateFunction("REPLACE"), FunctionRuntimeException);
+  EXPECT_TRUE(EvaluateFunction("REPLACE", TypedValue(), "l", "w").IsNull());
+  EXPECT_TRUE(EvaluateFunction("REPLACE", "hello", TypedValue(), "w").IsNull());
+  EXPECT_TRUE(EvaluateFunction("REPLACE", "hello", "l", TypedValue()).IsNull());
+  EXPECT_EQ(EvaluateFunction("REPLACE", "hello", "l", "w").ValueString(), "hewwo");
+
+  EXPECT_THROW(EvaluateFunction("REPLACE", 1, "l", "w"), FunctionRuntimeException);
+  EXPECT_THROW(EvaluateFunction("REPLACE", "hello", 1, "w"), FunctionRuntimeException);
+  EXPECT_THROW(EvaluateFunction("REPLACE", "hello", "l", 1), FunctionRuntimeException);
+}
+
+TEST_F(FunctionTest, Split) {
+  EXPECT_THROW(EvaluateFunction("SPLIT"), FunctionRuntimeException);
+  EXPECT_THROW(EvaluateFunction("SPLIT", "one,two", 1), FunctionRuntimeException);
+  EXPECT_THROW(EvaluateFunction("SPLIT", 1, "one,two"), FunctionRuntimeException);
+
+  EXPECT_TRUE(EvaluateFunction("SPLIT", TypedValue(), TypedValue()).IsNull());
+  EXPECT_TRUE(EvaluateFunction("SPLIT", "one,two", TypedValue()).IsNull());
+  EXPECT_TRUE(EvaluateFunction("SPLIT", TypedValue(), ",").IsNull());
+
+  auto result = EvaluateFunction("SPLIT", "one,two", ",");
+  EXPECT_TRUE(result.IsList());
+  EXPECT_EQ(result.ValueList()[0].ValueString(), "one");
+  EXPECT_EQ(result.ValueList()[1].ValueString(), "two");
+}
+
+TEST_F(FunctionTest, Substring) {
+  EXPECT_THROW(EvaluateFunction("SUBSTRING"), FunctionRuntimeException);
+
+  EXPECT_TRUE(EvaluateFunction("SUBSTRING", TypedValue(), 0, 10).IsNull());
+  EXPECT_THROW(EvaluateFunction("SUBSTRING", TypedValue(), TypedValue()), FunctionRuntimeException);
+  EXPECT_THROW(EvaluateFunction("SUBSTRING", TypedValue(), -10), FunctionRuntimeException);
+  EXPECT_THROW(EvaluateFunction("SUBSTRING", TypedValue(), 0, TypedValue()), FunctionRuntimeException);
+  EXPECT_THROW(EvaluateFunction("SUBSTRING", TypedValue(), 0, -10), FunctionRuntimeException);
+
+  EXPECT_EQ(EvaluateFunction("SUBSTRING", "hello", 2).ValueString(), "llo");
+  EXPECT_EQ(EvaluateFunction("SUBSTRING", "hello", 10).ValueString(), "");
+  EXPECT_EQ(EvaluateFunction("SUBSTRING", "hello", 2, 0).ValueString(), "");
+  EXPECT_EQ(EvaluateFunction("SUBSTRING", "hello", 1, 3).ValueString(), "ell");
+  EXPECT_EQ(EvaluateFunction("SUBSTRING", "hello", 1, 4).ValueString(), "ello");
+  EXPECT_EQ(EvaluateFunction("SUBSTRING", "hello", 1, 10).ValueString(), "ello");
+}
+
+TEST_F(FunctionTest, ToLower) {
+  EXPECT_THROW(EvaluateFunction("TOLOWER"), FunctionRuntimeException);
+  EXPECT_TRUE(EvaluateFunction("TOLOWER", TypedValue()).IsNull());
+  EXPECT_EQ(EvaluateFunction("TOLOWER", "Ab__C").ValueString(), "ab__c");
+}
+
+TEST_F(FunctionTest, ToUpper) {
+  EXPECT_THROW(EvaluateFunction("TOUPPER"), FunctionRuntimeException);
+  EXPECT_TRUE(EvaluateFunction("TOUPPER", TypedValue()).IsNull());
+  EXPECT_EQ(EvaluateFunction("TOUPPER", "Ab__C").ValueString(), "AB__C");
+}
+
+TEST_F(FunctionTest, ToByteString) {
+  EXPECT_THROW(EvaluateFunction("TOBYTESTRING"), FunctionRuntimeException);
+  EXPECT_THROW(EvaluateFunction("TOBYTESTRING", 42), FunctionRuntimeException);
+  EXPECT_THROW(EvaluateFunction("TOBYTESTRING", TypedValue()), FunctionRuntimeException);
+  EXPECT_THROW(EvaluateFunction("TOBYTESTRING", "", 42), FunctionRuntimeException);
+  EXPECT_THROW(EvaluateFunction("TOBYTESTRING", "ff"), FunctionRuntimeException);
+  EXPECT_THROW(EvaluateFunction("TOBYTESTRING", "00"), FunctionRuntimeException);
+  EXPECT_THROW(EvaluateFunction("TOBYTESTRING", "0xG"), FunctionRuntimeException);
+  EXPECT_EQ(EvaluateFunction("TOBYTESTRING", "").ValueString(), "");
+  EXPECT_EQ(EvaluateFunction("TOBYTESTRING", "0x").ValueString(), "");
+  EXPECT_EQ(EvaluateFunction("TOBYTESTRING", "0X").ValueString(), "");
+  EXPECT_EQ(EvaluateFunction("TOBYTESTRING", "0x0123456789aAbBcCdDeEfF").ValueString(),
+            "\x01\x23\x45\x67\x89\xAA\xBB\xCC\xDD\xEE\xFF");
+  EXPECT_EQ(EvaluateFunction("TOBYTESTRING", "0x042").ValueString().size(), 2);
+  EXPECT_EQ(EvaluateFunction("TOBYTESTRING", "0x042").ValueString(),
+            memgraph::utils::pmr::string("\x00\x42", 2, memgraph::utils::NewDeleteResource()));
+}
+
+TEST_F(FunctionTest, FromByteString) {
+  EXPECT_THROW(EvaluateFunction("FROMBYTESTRING"), FunctionRuntimeException);
+  EXPECT_THROW(EvaluateFunction("FROMBYTESTRING", 42), FunctionRuntimeException);
+  EXPECT_THROW(EvaluateFunction("FROMBYTESTRING", TypedValue()), FunctionRuntimeException);
+  EXPECT_EQ(EvaluateFunction("FROMBYTESTRING", "").ValueString(), "");
+  auto bytestring = EvaluateFunction("TOBYTESTRING", "0x123456789aAbBcCdDeEfF");
+  EXPECT_EQ(EvaluateFunction("FROMBYTESTRING", bytestring).ValueString(), "0x0123456789aabbccddeeff");
+  EXPECT_EQ(EvaluateFunction("FROMBYTESTRING", std::string("\x00\x42", 2)).ValueString(), "0x0042");
+}
+
+// TEST_F(FunctionTest, Date) {
+//   const auto unix_epoch = memgraph::utils::Date({1970, 1, 1});
+//   EXPECT_EQ(EvaluateFunction("DATE", "1970-01-01").ValueDate(), unix_epoch);
+//   const auto map_param = TypedValue(
+//       std::map<std::string, TypedValue>{{"year", TypedValue(1970)}, {"month", TypedValue(1)}, {"day",
+//       TypedValue(1)}});
+//   EXPECT_EQ(EvaluateFunction("DATE", map_param).ValueDate(), unix_epoch);
+//   const auto today = memgraph::utils::CurrentDate();
+//   EXPECT_EQ(EvaluateFunction("DATE").ValueDate(), today);
+//
+//   EXPECT_THROW(EvaluateFunction("DATE", "{}"), memgraph::utils::BasicException);
+//   EXPECT_THROW(EvaluateFunction("DATE", std::map<std::string, TypedValue>{{"years", TypedValue(1970)}}),
+//                ExpressionRuntimeException);
+//   EXPECT_THROW(EvaluateFunction("DATE", std::map<std::string, TypedValue>{{"mnths", TypedValue(1970)}}),
+//                ExpressionRuntimeException);
+//   EXPECT_THROW(EvaluateFunction("DATE", std::map<std::string, TypedValue>{{"dayz", TypedValue(1970)}}),
+//                ExpressionRuntimeException);
+// }
+//
+// TEST_F(FunctionTest, LocalTime) {
+//   const auto local_time = memgraph::utils::LocalTime({13, 3, 2, 0, 0});
+//   EXPECT_EQ(EvaluateFunction("LOCALTIME", "130302").ValueLocalTime(), local_time);
+//   const auto one_sec_in_microseconds = 1000000;
+//   const auto map_param = TypedValue(std::map<std::string, TypedValue>{{"hour", TypedValue(1)},
+//                                                                       {"minute", TypedValue(2)},
+//                                                                       {"second", TypedValue(3)},
+//                                                                       {"millisecond", TypedValue(4)},
+//                                                                       {"microsecond", TypedValue(5)}});
+//   EXPECT_EQ(EvaluateFunction("LOCALTIME", map_param).ValueLocalTime(), memgraph::utils::LocalTime({1, 2, 3, 4, 5}));
+//   const auto today = memgraph::utils::CurrentLocalTime();
+//   EXPECT_NEAR(EvaluateFunction("LOCALTIME").ValueLocalTime().MicrosecondsSinceEpoch(),
+//   today.MicrosecondsSinceEpoch(),
+//               one_sec_in_microseconds);
+//
+//   EXPECT_THROW(EvaluateFunction("LOCALTIME", "{}"), memgraph::utils::BasicException);
+//   EXPECT_THROW(EvaluateFunction("LOCALTIME", TypedValue(std::map<std::string, TypedValue>{{"hous",
+//   TypedValue(1970)}})),
+//                ExpressionRuntimeException);
+//   EXPECT_THROW(
+//       EvaluateFunction("LOCALTIME", TypedValue(std::map<std::string, TypedValue>{{"minut", TypedValue(1970)}})),
+//       ExpressionRuntimeException);
+//   EXPECT_THROW(
+//       EvaluateFunction("LOCALTIME", TypedValue(std::map<std::string, TypedValue>{{"seconds", TypedValue(1970)}})),
+//       ExpressionRuntimeException);
+// }
+//
+// TEST_F(FunctionTest, LocalDateTime) {
+//   const auto local_date_time = memgraph::utils::LocalDateTime({1970, 1, 1}, {13, 3, 2, 0, 0});
+//   EXPECT_EQ(EvaluateFunction("LOCALDATETIME", "1970-01-01T13:03:02").ValueLocalDateTime(), local_date_time);
+//   const auto today = memgraph::utils::CurrentLocalDateTime();
+//   const auto one_sec_in_microseconds = 1000000;
+//   const auto map_param = TypedValue(std::map<std::string, TypedValue>{{"year", TypedValue(1972)},
+//                                                                       {"month", TypedValue(2)},
+//                                                                       {"day", TypedValue(3)},
+//                                                                       {"hour", TypedValue(4)},
+//                                                                       {"minute", TypedValue(5)},
+//                                                                       {"second", TypedValue(6)},
+//                                                                       {"millisecond", TypedValue(7)},
+//                                                                       {"microsecond", TypedValue(8)}});
+//
+//   EXPECT_EQ(EvaluateFunction("LOCALDATETIME", map_param).ValueLocalDateTime(),
+//             memgraph::utils::LocalDateTime({1972, 2, 3}, {4, 5, 6, 7, 8}));
+//   EXPECT_NEAR(EvaluateFunction("LOCALDATETIME").ValueLocalDateTime().MicrosecondsSinceEpoch(),
+//               today.MicrosecondsSinceEpoch(), one_sec_in_microseconds);
+//   EXPECT_THROW(EvaluateFunction("LOCALDATETIME", "{}"), memgraph::utils::BasicException);
+//   EXPECT_THROW(
+//       EvaluateFunction("LOCALDATETIME", TypedValue(std::map<std::string, TypedValue>{{"hours", TypedValue(1970)}})),
+//       ExpressionRuntimeException);
+//   EXPECT_THROW(
+//       EvaluateFunction("LOCALDATETIME", TypedValue(std::map<std::string, TypedValue>{{"seconds",
+//       TypedValue(1970)}})), ExpressionRuntimeException);
+// }
+//
+// TEST_F(FunctionTest, Duration) {
+//   const auto map_param = TypedValue(std::map<std::string, TypedValue>{{"day", TypedValue(3)},
+//                                                                       {"hour", TypedValue(4)},
+//                                                                       {"minute", TypedValue(5)},
+//                                                                       {"second", TypedValue(6)},
+//                                                                       {"millisecond", TypedValue(7)},
+//                                                                       {"microsecond", TypedValue(8)}});
+//
+//   EXPECT_EQ(EvaluateFunction("DURATION", map_param).ValueDuration(), memgraph::utils::Duration({3, 4, 5, 6, 7, 8}));
+//   EXPECT_THROW(EvaluateFunction("DURATION", "{}"), memgraph::utils::BasicException);
+//   EXPECT_THROW(EvaluateFunction("DURATION", TypedValue(std::map<std::string, TypedValue>{{"hours",
+//   TypedValue(1970)}})),
+//                ExpressionRuntimeException);
+//   EXPECT_THROW(
+//       EvaluateFunction("DURATION", TypedValue(std::map<std::string, TypedValue>{{"seconds", TypedValue(1970)}})),
+//       ExpressionRuntimeException);
+//
+//   const auto map_param_negative = TypedValue(std::map<std::string, TypedValue>{{"day", TypedValue(-3)},
+//                                                                                {"hour", TypedValue(-4)},
+//                                                                                {"minute", TypedValue(-5)},
+//                                                                                {"second", TypedValue(-6)},
+//                                                                                {"millisecond", TypedValue(-7)},
+//                                                                                {"microsecond", TypedValue(-8)}});
+//   EXPECT_EQ(EvaluateFunction("DURATION", map_param_negative).ValueDuration(),
+//             memgraph::utils::Duration({-3, -4, -5, -6, -7, -8}));
+//
+//   EXPECT_EQ(EvaluateFunction("DURATION", "P4DT4H5M6.2S").ValueDuration(),
+//             memgraph::utils::Duration({4, 4, 5, 6, 0, 200000}));
+//   EXPECT_EQ(EvaluateFunction("DURATION", "P3DT4H5M6.100S").ValueDuration(),
+//             memgraph::utils::Duration({3, 4, 5, 6, 0, 100000}));
+//   EXPECT_EQ(EvaluateFunction("DURATION", "P3DT4H5M6.100110S").ValueDuration(),
+//             memgraph::utils::Duration({3, 4, 5, 6, 100, 110}));
+// }
+}  // namespace

From 9e81fe791cfaf5bfbf7ab321f5f7325518f6b7dd Mon Sep 17 00:00:00 2001
From: Kostas Kyrimis <kostaskyrim@gmail.com>
Date: Mon, 14 Nov 2022 21:22:28 +0200
Subject: [PATCH 04/26] Fix clang-tidy warnings, remove commented out code and
 add HasLabel functions in ShardRequestManager to avoid throwing bad optional
 on expression evaluator

---
 src/expr/interpret/eval.hpp                  |   2 +-
 src/functions/awesome_memgraph_functions.hpp | 152 ++---
 src/query/v2/accessors.cpp                   |   9 +-
 src/query/v2/shard_request_manager.hpp       |   9 +
 tests/unit/query_v2_expression_evaluator.cpp | 550 +++----------------
 5 files changed, 165 insertions(+), 557 deletions(-)

diff --git a/src/expr/interpret/eval.hpp b/src/expr/interpret/eval.hpp
index 139e37514..8b8b5a7c7 100644
--- a/src/expr/interpret/eval.hpp
+++ b/src/expr/interpret/eval.hpp
@@ -417,7 +417,7 @@ class ExpressionEvaluator : public ExpressionVisitor<TypedValue> {
   TReturnType HasLabelImpl(const VertexAccessor &vertex, const LabelIx &label_ix, QueryEngineTag /*tag*/) {
     auto label = typename VertexAccessor::Label{LabelId::FromUint(label_ix.ix)};
     auto has_label = vertex.HasLabel(label);
-    return !has_label;
+    return has_label;
   }
 
   TypedValue Visit(LabelsTest &labels_test) override {
diff --git a/src/functions/awesome_memgraph_functions.hpp b/src/functions/awesome_memgraph_functions.hpp
index ca415c69b..0a2b873c2 100644
--- a/src/functions/awesome_memgraph_functions.hpp
+++ b/src/functions/awesome_memgraph_functions.hpp
@@ -61,12 +61,10 @@ template <typename TypedValueT, typename FunctionContextT, typename Tag, typenam
 std::function<TypedValueT(const TypedValueT *arguments, int64_t num_arguments, const FunctionContextT &context)>
 NameToFunction(const std::string &function_name);
 
-namespace {
-const char kStartsWith[] = "STARTSWITH";
-const char kEndsWith[] = "ENDSWITH";
-const char kContains[] = "CONTAINS";
-const char kId[] = "ID";
-}  // namespace
+inline const char kStartsWith[] = "STARTSWITH";
+inline const char kEndsWith[] = "ENDSWITH";
+inline const char kContains[] = "CONTAINS";
+inline const char kId[] = "ID";
 
 }  // namespace memgraph::functions
 
@@ -484,11 +482,11 @@ TypedValueT Properties(const TypedValueT *args, int64_t nargs, const FunctionCon
   const auto &value = args[0];
   if (value.IsNull()) {
     return TypedValueT(ctx.memory);
-  } else if (value.IsVertex()) {
-    return get_properties(value.ValueVertex());
-  } else {
-    return get_properties(value.ValueEdge());
   }
+  if (value.IsVertex()) {
+    return get_properties(value.ValueVertex());
+  }
+  return get_properties(value.ValueEdge());
 }
 
 template <typename TypedValueT, typename FunctionContextT>
@@ -497,17 +495,19 @@ TypedValueT Size(const TypedValueT *args, int64_t nargs, const FunctionContextT
   const auto &value = args[0];
   if (value.IsNull()) {
     return TypedValueT(ctx.memory);
-  } else if (value.IsList()) {
+  }
+  if (value.IsList()) {
     return TypedValueT(static_cast<int64_t>(value.ValueList().size()), ctx.memory);
-  } else if (value.IsString()) {
+  }
+  if (value.IsString()) {
     return TypedValueT(static_cast<int64_t>(value.ValueString().size()), ctx.memory);
-  } else if (value.IsMap()) {
+  }
+  if (value.IsMap()) {
     // neo4j doesn't implement size for map, but I don't see a good reason not
     // to do it.
     return TypedValueT(static_cast<int64_t>(value.ValueMap().size()), ctx.memory);
-  } else {
-    return TypedValueT(static_cast<int64_t>(value.ValuePath().edges().size()), ctx.memory);
   }
+  return TypedValueT(static_cast<int64_t>(value.ValuePath().edges().size()), ctx.memory);
 }
 
 template <typename TypedValueT, typename FunctionContextT, typename Tag, typename Conv>
@@ -527,9 +527,9 @@ TypedValueT StartNode(const TypedValueT *args, int64_t nargs, const FunctionCont
   }
 }
 
-namespace {
-
-size_t UnwrapDegreeResult(storage::v3::Result<size_t> maybe_degree) {
+// This is needed because clang-tidy fails to identify the use of this function in the if-constexpr branch
+// NOLINTNEXTLINE(clang-diagnostic-unused-function)
+inline size_t UnwrapDegreeResult(storage::v3::Result<size_t> maybe_degree) {
   if (maybe_degree.HasError()) {
     switch (maybe_degree.GetError()) {
       case storage::v3::Error::DELETED_OBJECT:
@@ -546,8 +546,6 @@ size_t UnwrapDegreeResult(storage::v3::Result<size_t> maybe_degree) {
   return *maybe_degree;
 }
 
-}  // namespace
-
 template <typename TypedValueT, typename FunctionContextT, typename Tag>
 TypedValueT Degree(const TypedValueT *args, int64_t nargs, const FunctionContextT &ctx) {
   FType<TypedValueT, Or<Null, Vertex>>("degree", args, nargs);
@@ -599,18 +597,19 @@ TypedValueT ToBoolean(const TypedValueT *args, int64_t nargs, const FunctionCont
   const auto &value = args[0];
   if (value.IsNull()) {
     return TypedValueT(ctx.memory);
-  } else if (value.IsBool()) {
-    return TypedValueT(value.ValueBool(), ctx.memory);
-  } else if (value.IsInt()) {
-    return TypedValueT(value.ValueInt() != 0L, ctx.memory);
-  } else {
-    auto s = utils::ToUpperCase(utils::Trim(value.ValueString()));
-    if (s == "TRUE") return TypedValueT(true, ctx.memory);
-    if (s == "FALSE") return TypedValueT(false, ctx.memory);
-    // I think this is just stupid and that exception should be thrown, but
-    // neo4j does it this way...
-    return TypedValueT(ctx.memory);
   }
+  if (value.IsBool()) {
+    return TypedValueT(value.ValueBool(), ctx.memory);
+  }
+  if (value.IsInt()) {
+    return TypedValueT(value.ValueInt() != 0L, ctx.memory);
+  }
+  auto s = utils::ToUpperCase(utils::Trim(value.ValueString()));
+  if (s == "TRUE") return TypedValueT(true, ctx.memory);
+  if (s == "FALSE") return TypedValueT(false, ctx.memory);
+  // I think this is just stupid and that exception should be thrown, but
+  // neo4j does it this way...
+  return TypedValueT(ctx.memory);
 }
 
 template <typename TypedValueT, typename FunctionContextT>
@@ -619,16 +618,17 @@ TypedValueT ToFloat(const TypedValueT *args, int64_t nargs, const FunctionContex
   const auto &value = args[0];
   if (value.IsNull()) {
     return TypedValueT(ctx.memory);
-  } else if (value.IsInt()) {
+  }
+  if (value.IsInt()) {
     return TypedValueT(static_cast<double>(value.ValueInt()), ctx.memory);
-  } else if (value.IsDouble()) {
+  }
+  if (value.IsDouble()) {
     return TypedValueT(value, ctx.memory);
-  } else {
-    try {
-      return TypedValueT(utils::ParseDouble(utils::Trim(value.ValueString())), ctx.memory);
-    } catch (const utils::BasicException &) {
-      return TypedValueT(ctx.memory);
-    }
+  }
+  try {
+    return TypedValueT(utils::ParseDouble(utils::Trim(value.ValueString())), ctx.memory);
+  } catch (const utils::BasicException &) {
+    return TypedValueT(ctx.memory);
   }
 }
 
@@ -638,20 +638,22 @@ TypedValueT ToInteger(const TypedValueT *args, int64_t nargs, const FunctionCont
   const auto &value = args[0];
   if (value.IsNull()) {
     return TypedValueT(ctx.memory);
-  } else if (value.IsBool()) {
+  }
+  if (value.IsBool()) {
     return TypedValueT(value.ValueBool() ? 1L : 0L, ctx.memory);
-  } else if (value.IsInt()) {
+  }
+  if (value.IsInt()) {
     return TypedValueT(value, ctx.memory);
-  } else if (value.IsDouble()) {
+  }
+  if (value.IsDouble()) {
     return TypedValueT(static_cast<int64_t>(value.ValueDouble()), ctx.memory);
-  } else {
-    try {
-      // Yup, this is correct. String is valid if it has floating point
-      // number, then it is parsed and converted to int.
-      return TypedValueT(static_cast<int64_t>(utils::ParseDouble(utils::Trim(value.ValueString()))), ctx.memory);
-    } catch (const utils::BasicException &) {
-      return TypedValueT(ctx.memory);
-    }
+  }
+  try {
+    // Yup, this is correct. String is valid if it has floating point
+    // number, then it is parsed and converted to int.
+    return TypedValueT(static_cast<int64_t>(utils::ParseDouble(utils::Trim(value.ValueString()))), ctx.memory);
+  } catch (const utils::BasicException &) {
+    return TypedValueT(ctx.memory);
   }
 }
 
@@ -736,11 +738,11 @@ TypedValueT Keys(const TypedValueT *args, int64_t nargs, const FunctionContextT
   const auto &value = args[0];
   if (value.IsNull()) {
     return TypedValueT(ctx.memory);
-  } else if (value.IsVertex()) {
-    return get_keys(value.ValueVertex());
-  } else {
-    return get_keys(value.ValueEdge());
   }
+  if (value.IsVertex()) {
+    return get_keys(value.ValueVertex());
+  }
+  return get_keys(value.ValueEdge());
 }
 
 template <typename TypedValueT, typename FunctionContextT, typename Tag>
@@ -853,13 +855,14 @@ TypedValueT Abs(const TypedValueT *args, int64_t nargs, const FunctionContextT &
   const auto &value = args[0];
   if (value.IsNull()) {
     return TypedValueT(ctx.memory);
-  } else if (value.IsInt()) {
-    return TypedValueT(std::abs(value.ValueInt()), ctx.memory);
-  } else {
-    return TypedValueT(std::abs(value.ValueDouble()), ctx.memory);
   }
+  if (value.IsInt()) {
+    return TypedValueT(std::abs(value.ValueInt()), ctx.memory);
+  }
+  return TypedValueT(std::abs(value.ValueDouble()), ctx.memory);
 }
 
+// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
 #define WRAP_CMATH_FLOAT_FUNCTION(name, lowercased_name)                                  \
   template <typename TypedValueT, typename FunctionContextT>                              \
   TypedValueT name(const TypedValueT *args, int64_t nargs, const FunctionContextT &ctx) { \
@@ -867,11 +870,11 @@ TypedValueT Abs(const TypedValueT *args, int64_t nargs, const FunctionContextT &
     const auto &value = args[0];                                                          \
     if (value.IsNull()) {                                                                 \
       return TypedValueT(ctx.memory);                                                     \
-    } else if (value.IsInt()) {                                                           \
-      return TypedValueT(lowercased_name(value.ValueInt()), ctx.memory);                  \
-    } else {                                                                              \
-      return TypedValueT(lowercased_name(value.ValueDouble()), ctx.memory);               \
     }                                                                                     \
+    if (value.IsInt()) {                                                                  \
+      return TypedValueT(lowercased_name(value.ValueInt()), ctx.memory);                  \
+    }                                                                                     \
+    return TypedValueT(lowercased_name(value.ValueDouble()), ctx.memory);                 \
   }
 
 WRAP_CMATH_FLOAT_FUNCTION(Ceil, ceil)
@@ -899,9 +902,8 @@ TypedValueT Atan2(const TypedValueT *args, int64_t nargs, const FunctionContextT
   auto to_double = [](const TypedValueT &t) -> double {
     if (t.IsInt()) {
       return t.ValueInt();
-    } else {
-      return t.ValueDouble();
     }
+    return t.ValueDouble();
   };
   double y = to_double(args[0]);
   double x = to_double(args[1]);
@@ -915,11 +917,11 @@ TypedValueT Sign(const TypedValueT *args, int64_t nargs, const FunctionContextT
   const auto &value = args[0];
   if (value.IsNull()) {
     return TypedValueT(ctx.memory);
-  } else if (value.IsInt()) {
-    return sign(value.ValueInt());
-  } else {
-    return sign(value.ValueDouble());
   }
+  if (value.IsInt()) {
+    return sign(value.ValueInt());
+  }
+  return sign(value.ValueDouble());
 }
 
 template <typename TypedValueT, typename FunctionContextT>
@@ -962,7 +964,7 @@ struct StartsWithPredicate {
 };
 
 template <typename TypedValueT, typename FunctionContextT>
-inline auto StartsWith = StringMatchOperator<StartsWithPredicate<TypedValueT>, TypedValueT, FunctionContextT>;
+inline const auto StartsWith = StringMatchOperator<StartsWithPredicate<TypedValueT>, TypedValueT, FunctionContextT>;
 
 // Check if s1 ends with s2.
 template <typename TypedValueT>
@@ -975,7 +977,7 @@ struct EndsWithPredicate {
 };
 
 template <typename TypedValueT, typename FunctionContextT>
-inline auto EndsWith = StringMatchOperator<EndsWithPredicate<TypedValueT>, TypedValueT, FunctionContextT>;
+inline const auto EndsWith = StringMatchOperator<EndsWithPredicate<TypedValueT>, TypedValueT, FunctionContextT>;
 
 // Check if s1 contains s2.
 template <typename TypedValueT>
@@ -988,7 +990,7 @@ struct ContainsPredicate {
 };
 
 template <typename TypedValueT, typename FunctionContextT>
-inline auto Contains = StringMatchOperator<ContainsPredicate<TypedValueT>, TypedValueT, FunctionContextT>;
+inline const auto Contains = StringMatchOperator<ContainsPredicate<TypedValueT>, TypedValueT, FunctionContextT>;
 
 template <typename TypedValueT, typename FunctionContextT>
 TypedValueT Assert(const TypedValueT *args, int64_t nargs, const FunctionContextT &ctx) {
@@ -1026,11 +1028,11 @@ TypedValueT Id(const TypedValueT *args, int64_t nargs, const FunctionContextT &c
   const auto &arg = args[0];
   if (arg.IsNull()) {
     return TypedValueT(ctx.memory);
-  } else if (arg.IsVertex()) {
-    return TypedValueT(static_cast<int64_t>(arg.ValueVertex().CypherId()), ctx.memory);
-  } else {
-    return TypedValueT(static_cast<int64_t>(arg.ValueEdge().CypherId()), ctx.memory);
   }
+  if (arg.IsVertex()) {
+    return TypedValueT(static_cast<int64_t>(arg.ValueVertex().CypherId()), ctx.memory);
+  }
+  return TypedValueT(static_cast<int64_t>(arg.ValueEdge().CypherId()), ctx.memory);
 }
 
 template <typename TypedValueT, typename FunctionContextT>
diff --git a/src/query/v2/accessors.cpp b/src/query/v2/accessors.cpp
index cbdce89e0..63915327f 100644
--- a/src/query/v2/accessors.cpp
+++ b/src/query/v2/accessors.cpp
@@ -23,11 +23,11 @@ EdgeTypeId EdgeAccessor::EdgeType() const { return edge.type.id; }
 const std::vector<std::pair<PropertyId, Value>> &EdgeAccessor::Properties() const { return edge.properties; }
 
 Value EdgeAccessor::GetProperty(const std::string &prop_name) const {
-  auto prop_id = manager_->NameToProperty(prop_name);
-  auto it = std::find_if(edge.properties.begin(), edge.properties.end(), [&](auto &pr) { return prop_id == pr.first; });
-  if (it == edge.properties.end()) {
+  if (!manager_->HasProperty(prop_name)) {
     return {};
   }
+  auto prop_id = manager_->NameToProperty(prop_name);
+  auto it = std::find_if(edge.properties.begin(), edge.properties.end(), [&](auto &pr) { return prop_id == pr.first; });
   return it->second;
 }
 
@@ -88,6 +88,9 @@ Value VertexAccessor::GetProperty(PropertyId prop_id) const {
 
 // NOLINTNEXTLINE(readability-convert-member-functions-to-static)
 Value VertexAccessor::GetProperty(const std::string &prop_name) const {
+  if (!manager_->HasProperty(prop_name)) {
+    return {};
+  }
   return GetProperty(manager_->NameToProperty(prop_name));
 }
 
diff --git a/src/query/v2/shard_request_manager.hpp b/src/query/v2/shard_request_manager.hpp
index a73201046..003cafaf8 100644
--- a/src/query/v2/shard_request_manager.hpp
+++ b/src/query/v2/shard_request_manager.hpp
@@ -129,6 +129,9 @@ class ShardRequestManagerInterface {
   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 &EdgeTypeToName(memgraph::storage::v3::EdgeTypeId type) const = 0;
+  virtual bool HasProperty(const std::string &name) const = 0;
+  virtual bool HasEdgeType(const std::string &name) const = 0;
+  virtual bool HasLabel(const std::string &name) const = 0;
   virtual bool IsPrimaryLabel(LabelId label) const = 0;
   virtual bool IsPrimaryKey(LabelId primary_label, PropertyId property) const = 0;
 };
@@ -353,6 +356,12 @@ class ShardRequestManager : public ShardRequestManagerInterface {
     return result_rows;
   }
 
+  bool HasProperty(const std::string &name) const override { return shards_map_.GetPropertyId(name).has_value(); }
+
+  bool HasEdgeType(const std::string &name) const override { return shards_map_.GetEdgeTypeId(name).has_value(); }
+
+  bool HasLabel(const std::string &name) const override { return shards_map_.GetLabelId(name).has_value(); }
+
  private:
   enum class PaginatedResponseState { Pending, PartiallyFinished };
 
diff --git a/tests/unit/query_v2_expression_evaluator.cpp b/tests/unit/query_v2_expression_evaluator.cpp
index 6bc6e1c8b..97122ff0f 100644
--- a/tests/unit/query_v2_expression_evaluator.cpp
+++ b/tests/unit/query_v2_expression_evaluator.cpp
@@ -30,6 +30,7 @@
 #include "query/v2/frontend/ast/ast.hpp"
 #include "query/v2/requests.hpp"
 #include "query/v2/shard_request_manager.hpp"
+#include "storage/v3/property_value.hpp"
 #include "storage/v3/storage.hpp"
 #include "utils/exceptions.hpp"
 #include "utils/string.hpp"
@@ -117,6 +118,12 @@ class MockedShardRequestManager : public memgraph::msgs::ShardRequestManagerInte
     return edge_types_.IdToName(id.AsUint());
   }
 
+  bool HasProperty(const std::string &name) const override { return shards_map_.GetPropertyId(name).has_value(); }
+
+  bool HasEdgeType(const std::string &name) const override { return shards_map_.GetEdgeTypeId(name).has_value(); }
+
+  bool HasLabel(const std::string &name) const override { return shards_map_.GetLabelId(name).has_value(); }
+
   bool IsPrimaryLabel(LabelId label) const override { return true; }
 
   bool IsPrimaryKey(LabelId primary_label, PropertyId property) const override { return true; }
@@ -202,10 +209,6 @@ class ExpressionEvaluatorTest : public ::testing::Test {
   ExpressionEvaluatorTest() {}
 
  protected:
-  //  memgraph::storage::Storage db;
-  //  memgraph::storage::Storage::Accessor storage_dba{db.Access()};
-  //  memgraph::query::DbAccessor dba{&storage_dba};
-  //
   AstStorage storage;
   memgraph::utils::MonotonicBufferResource mem{1024};
   EvaluationContext ctx{.memory = &mem, .timestamp = memgraph::query::v2::QueryTimestamp()};
@@ -575,36 +578,33 @@ TEST_F(ExpressionEvaluatorTest, VertexAndEdgeIndexing) {
   // TODO(kostasrim) Investigate
   //  Shall we return null on missing properties? Or shall we throw bad optional access as we do now?
 
-  //   {
-  //     // Legal indexing, non-existing key.
-  //     auto *op1 = storage.Create<SubscriptOperator>(vertex_id, storage.Create<PrimitiveLiteral>("blah"));
-  //     auto value1 = Eval(op1);
-  //     EXPECT_TRUE(value1.IsNull());
-  //
-  //     auto *op2 = storage.Create<SubscriptOperator>(edge_id, storage.Create<PrimitiveLiteral>("blah"));
-  //     auto value2 = Eval(op2);
-  //     EXPECT_TRUE(value2.IsNull());
-  //   }
-  //   {
-  //     // Wrong key type.
-  //     auto *op1 = storage.Create<SubscriptOperator>(vertex_id, storage.Create<PrimitiveLiteral>(1));
-  //     EXPECT_THROW(Eval(op1), ExpressionRuntimeException);
-  //
-  //     auto *op2 = storage.Create<SubscriptOperator>(edge_id, storage.Create<PrimitiveLiteral>(1));
-  //     EXPECT_THROW(Eval(op2), ExpressionRuntimeException);
-  //   }
-  //   {
-  //     // Indexing with Null.
-  //     auto *op1 = storage.Create<SubscriptOperator>(vertex_id,
-  //                                                   storage.Create<PrimitiveLiteral>(memgraph::storage::PropertyValue()));
-  //     auto value1 = Eval(op1);
-  //     EXPECT_TRUE(value1.IsNull());
-  //
-  //     auto *op2 = storage.Create<SubscriptOperator>(edge_id,
-  //                                                   storage.Create<PrimitiveLiteral>(memgraph::storage::PropertyValue()));
-  //     auto value2 = Eval(op2);
-  //     EXPECT_TRUE(value2.IsNull());
-  //   }
+  {
+    // Legal indexing, non-existing key.
+    auto *op1 = storage.Create<SubscriptOperator>(vertex_id, storage.Create<PrimitiveLiteral>("blah"));
+    auto value1 = Eval(op1);
+    EXPECT_TRUE(value1.IsNull());
+    auto *op2 = storage.Create<SubscriptOperator>(edge_id, storage.Create<PrimitiveLiteral>("blah"));
+    auto value2 = Eval(op2);
+    EXPECT_TRUE(value2.IsNull());
+  }
+  {
+    // Wrong key type.
+    auto *op1 = storage.Create<SubscriptOperator>(vertex_id, storage.Create<PrimitiveLiteral>(1));
+    EXPECT_THROW(Eval(op1), ExpressionRuntimeException);
+
+    auto *op2 = storage.Create<SubscriptOperator>(edge_id, storage.Create<PrimitiveLiteral>(1));
+    EXPECT_THROW(Eval(op2), ExpressionRuntimeException);
+  }
+  {
+    // Indexing with Null.
+    auto *op1 = storage.Create<SubscriptOperator>(vertex_id, storage.Create<PrimitiveLiteral>(TypedValue{}));
+    auto value1 = Eval(op1);
+    EXPECT_TRUE(value1.IsNull());
+
+    auto *op2 = storage.Create<SubscriptOperator>(edge_id, storage.Create<PrimitiveLiteral>(TypedValue{}));
+    auto value2 = Eval(op2);
+    EXPECT_TRUE(value2.IsNull());
+  }
 }
 
 TEST_F(ExpressionEvaluatorTest, ListSlicingOperator) {
@@ -741,41 +741,31 @@ TEST_F(ExpressionEvaluatorTest, IsNullOperator) {
   ASSERT_EQ(val2.ValueBool(), true);
 }
 
-// TEST_F(ExpressionEvaluatorTest, LabelsTest) {
-//   auto v1 = dba.InsertVertex();
-//   ASSERT_TRUE(v1.AddLabel(dba.NameToLabel("ANIMAL")).HasValue());
-//   ASSERT_TRUE(v1.AddLabel(dba.NameToLabel("DOG")).HasValue());
-//   ASSERT_TRUE(v1.AddLabel(dba.NameToLabel("NICE_DOG")).HasValue());
-//   dba.AdvanceCommand();
-//   auto *identifier = storage.Create<Identifier>("n");
-//   auto node_symbol = symbol_table.CreateSymbol("n", true);
-//   identifier->MapTo(node_symbol);
-//   frame[node_symbol] = TypedValue(v1);
-//   {
-//     auto *op = storage.Create<LabelsTest>(
-//         identifier, std::vector<LabelIx>{storage.GetLabelIx("DOG"), storage.GetLabelIx("ANIMAL")});
-//     auto value = Eval(op);
-//     EXPECT_EQ(value.ValueBool(), true);
-//   }
-//   {
-//     auto *op = storage.Create<LabelsTest>(
-//         identifier,
-//         std::vector<LabelIx>{storage.GetLabelIx("DOG"), storage.GetLabelIx("BAD_DOG"),
-//         storage.GetLabelIx("ANIMAL")});
-//     auto value = Eval(op);
-//     EXPECT_EQ(value.ValueBool(), false);
-//   }
-//   {
-//     frame[node_symbol] = TypedValue();
-//     auto *op = storage.Create<LabelsTest>(
-//         identifier,
-//         std::vector<LabelIx>{storage.GetLabelIx("DOG"), storage.GetLabelIx("BAD_DOG"),
-//         storage.GetLabelIx("ANIMAL")});
-//     auto value = Eval(op);
-//     EXPECT_TRUE(value.IsNull());
-//   }
-// }
-//
+TEST_F(ExpressionEvaluatorTest, LabelsTest) {
+  Label label{shard_manager->NameToLabel("label1")};
+  auto v1 = CreateVertex({}, shard_manager.get(), label);
+  auto *identifier = storage.Create<Identifier>("n");
+  auto node_symbol = symbol_table.CreateSymbol("n", true);
+  identifier->MapTo(node_symbol);
+  frame[node_symbol] = TypedValue(v1);
+  {
+    auto *op = storage.Create<LabelsTest>(identifier, std::vector<LabelIx>{LabelIx{"label1", label.id.AsInt()}});
+    auto value = Eval(op);
+    EXPECT_EQ(value.ValueBool(), true);
+  }
+  {
+    auto *op = storage.Create<LabelsTest>(identifier, std::vector<LabelIx>{LabelIx{"label2", 10}});
+    auto value = Eval(op);
+    EXPECT_EQ(value.ValueBool(), false);
+  }
+  {
+    auto *op = storage.Create<LabelsTest>(identifier, std::vector<LabelIx>{LabelIx{"label2", 10}});
+    frame[node_symbol] = TypedValue();
+    auto value = Eval(op);
+    EXPECT_TRUE(value.IsNull());
+  }
+}
+
 TEST_F(ExpressionEvaluatorTest, Aggregation) {
   auto aggr = storage.Create<Aggregation>(storage.Create<PrimitiveLiteral>(42), nullptr, Aggregation::Op::COUNT);
   auto aggr_sym = symbol_table.CreateSymbol("aggr", true);
@@ -794,11 +784,8 @@ TEST_F(ExpressionEvaluatorTest, ListLiteral) {
   auto &result_elems = result.ValueList();
   ASSERT_EQ(3, result_elems.size());
   EXPECT_TRUE(result_elems[0].IsInt());
-  ;
   EXPECT_TRUE(result_elems[1].IsString());
-  ;
   EXPECT_TRUE(result_elems[2].IsBool());
-  ;
 }
 
 TEST_F(ExpressionEvaluatorTest, ParameterLookup) {
@@ -1148,167 +1135,16 @@ class ExpressionEvaluatorPropertyLookup : public ExpressionEvaluatorTest {
   }
 };
 
+// TODO(kostasrim) These will fail because of memory resource not propagating correctly. This should be done as part of
+// polishing the allocators.
 // TEST_F(ExpressionEvaluatorPropertyLookup, Vertex) {
-//   auto v1 = dba.InsertVertex();
-//   ASSERT_TRUE(v1.SetProperty(prop_age.second, memgraph::storage::PropertyValue(10)).HasValue());
-//   dba.AdvanceCommand();
+//   auto v1 = CreateVertex({{prop_age.second, memgraph::msgs::Value(static_cast<int64_t>(32))}}, shard_manager.get());
 //   frame[symbol] = TypedValue(v1);
 //   EXPECT_EQ(Value(prop_age).ValueInt(), 10);
 //   EXPECT_TRUE(Value(prop_height).IsNull());
 // }
-//
-// TEST_F(ExpressionEvaluatorPropertyLookup, Duration) {
-//   const memgraph::utils::Duration dur({10, 1, 30, 2, 22, 45});
-//   frame[symbol] = TypedValue(dur);
-//
-//   const std::pair day = std::make_pair("day", dba.NameToProperty("day"));
-//   const auto total_days = Value(day);
-//   EXPECT_TRUE(total_days.IsInt());
-//   EXPECT_EQ(total_days.ValueInt(), 10);
-//
-//   const std::pair hour = std::make_pair("hour", dba.NameToProperty("hour"));
-//   const auto total_hours = Value(hour);
-//   EXPECT_TRUE(total_hours.IsInt());
-//   EXPECT_EQ(total_hours.ValueInt(), 1);
-//
-//   const std::pair minute = std::make_pair("minute", dba.NameToProperty("minute"));
-//   const auto total_mins = Value(minute);
-//   EXPECT_TRUE(total_mins.IsInt());
-//
-//   EXPECT_EQ(total_mins.ValueInt(), 1 * 60 + 30);
-//
-//   const std::pair sec = std::make_pair("second", dba.NameToProperty("second"));
-//   const auto total_secs = Value(sec);
-//   EXPECT_TRUE(total_secs.IsInt());
-//   const auto expected_secs = total_mins.ValueInt() * 60 + 2;
-//   EXPECT_EQ(total_secs.ValueInt(), expected_secs);
-//
-//   const std::pair milli = std::make_pair("millisecond", dba.NameToProperty("millisecond"));
-//   const auto total_milli = Value(milli);
-//   EXPECT_TRUE(total_milli.IsInt());
-//   const auto expected_milli = total_secs.ValueInt() * 1000 + 22;
-//   EXPECT_EQ(total_milli.ValueInt(), expected_milli);
-//
-//   const std::pair micro = std::make_pair("microsecond", dba.NameToProperty("microsecond"));
-//   const auto total_micros = Value(micro);
-//   EXPECT_TRUE(total_micros.IsInt());
-//   const auto expected_micros = expected_milli * 1000 + 45;
-//   EXPECT_EQ(total_micros.ValueInt(), expected_micros);
-//
-//   const std::pair nano = std::make_pair("nanosecond", dba.NameToProperty("nanosecond"));
-//   const auto total_nano = Value(nano);
-//   EXPECT_TRUE(total_nano.IsInt());
-//   const auto expected_nano = expected_micros * 1000;
-//   EXPECT_EQ(total_nano.ValueInt(), expected_nano);
-// }
-//
-// TEST_F(ExpressionEvaluatorPropertyLookup, Date) {
-//   const memgraph::utils::Date date({1996, 11, 22});
-//   frame[symbol] = TypedValue(date);
-//
-//   const std::pair year = std::make_pair("year", dba.NameToProperty("year"));
-//   const auto y = Value(year);
-//   EXPECT_TRUE(y.IsInt());
-//   EXPECT_EQ(y.ValueInt(), 1996);
-//
-//   const std::pair month = std::make_pair("month", dba.NameToProperty("month"));
-//   const auto m = Value(month);
-//   EXPECT_TRUE(m.IsInt());
-//   EXPECT_EQ(m.ValueInt(), 11);
-//
-//   const std::pair day = std::make_pair("day", dba.NameToProperty("day"));
-//   const auto d = Value(day);
-//   EXPECT_TRUE(d.IsInt());
-//   EXPECT_EQ(d.ValueInt(), 22);
-// }
-//
-// TEST_F(ExpressionEvaluatorPropertyLookup, LocalTime) {
-//   const memgraph::utils::LocalTime lt({1, 2, 3, 11, 22});
-//   frame[symbol] = TypedValue(lt);
-//
-//   const std::pair hour = std::make_pair("hour", dba.NameToProperty("hour"));
-//   const auto h = Value(hour);
-//   EXPECT_TRUE(h.IsInt());
-//   EXPECT_EQ(h.ValueInt(), 1);
-//
-//   const std::pair minute = std::make_pair("minute", dba.NameToProperty("minute"));
-//   const auto min = Value(minute);
-//   EXPECT_TRUE(min.IsInt());
-//   EXPECT_EQ(min.ValueInt(), 2);
-//
-//   const std::pair second = std::make_pair("second", dba.NameToProperty("second"));
-//   const auto sec = Value(second);
-//   EXPECT_TRUE(sec.IsInt());
-//   EXPECT_EQ(sec.ValueInt(), 3);
-//
-//   const std::pair millis = std::make_pair("millisecond", dba.NameToProperty("millisecond"));
-//   const auto mil = Value(millis);
-//   EXPECT_TRUE(mil.IsInt());
-//   EXPECT_EQ(mil.ValueInt(), 11);
-//
-//   const std::pair micros = std::make_pair("microsecond", dba.NameToProperty("microsecond"));
-//   const auto mic = Value(micros);
-//   EXPECT_TRUE(mic.IsInt());
-//   EXPECT_EQ(mic.ValueInt(), 22);
-// }
-//
-// TEST_F(ExpressionEvaluatorPropertyLookup, LocalDateTime) {
-//   const memgraph::utils::LocalDateTime ldt({1993, 8, 6}, {2, 3, 4, 55, 40});
-//   frame[symbol] = TypedValue(ldt);
-//
-//   const std::pair year = std::make_pair("year", dba.NameToProperty("year"));
-//   const auto y = Value(year);
-//   EXPECT_TRUE(y.IsInt());
-//   EXPECT_EQ(y.ValueInt(), 1993);
-//
-//   const std::pair month = std::make_pair("month", dba.NameToProperty("month"));
-//   const auto m = Value(month);
-//   EXPECT_TRUE(m.IsInt());
-//   EXPECT_EQ(m.ValueInt(), 8);
-//
-//   const std::pair day = std::make_pair("day", dba.NameToProperty("day"));
-//   const auto d = Value(day);
-//   EXPECT_TRUE(d.IsInt());
-//   EXPECT_EQ(d.ValueInt(), 6);
-//
-//   const std::pair hour = std::make_pair("hour", dba.NameToProperty("hour"));
-//   const auto h = Value(hour);
-//   EXPECT_TRUE(h.IsInt());
-//   EXPECT_EQ(h.ValueInt(), 2);
-//
-//   const std::pair minute = std::make_pair("minute", dba.NameToProperty("minute"));
-//   const auto min = Value(minute);
-//   EXPECT_TRUE(min.IsInt());
-//   EXPECT_EQ(min.ValueInt(), 3);
-//
-//   const std::pair second = std::make_pair("second", dba.NameToProperty("second"));
-//   const auto sec = Value(second);
-//   EXPECT_TRUE(sec.IsInt());
-//   EXPECT_EQ(sec.ValueInt(), 4);
-//
-//   const std::pair millis = std::make_pair("millisecond", dba.NameToProperty("millisecond"));
-//   const auto mil = Value(millis);
-//   EXPECT_TRUE(mil.IsInt());
-//   EXPECT_EQ(mil.ValueInt(), 55);
-//
-//   const std::pair micros = std::make_pair("microsecond", dba.NameToProperty("microsecond"));
-//   const auto mic = Value(micros);
-//   EXPECT_TRUE(mic.IsInt());
-//   EXPECT_EQ(mic.ValueInt(), 40);
-// }
-//
-// TEST_F(ExpressionEvaluatorPropertyLookup, Edge) {
-//   auto v1 = dba.InsertVertex();
-//   auto v2 = dba.InsertVertex();
-//   auto e12 = dba.InsertEdge(&v1, &v2, dba.NameToEdgeType("edge_type"));
-//   ASSERT_TRUE(e12.HasValue());
-//   ASSERT_TRUE(e12->SetProperty(prop_age.second, memgraph::storage::PropertyValue(10)).HasValue());
-//   dba.AdvanceCommand();
-//   frame[symbol] = TypedValue(*e12);
-//   EXPECT_EQ(Value(prop_age).ValueInt(), 10);
-//   EXPECT_TRUE(Value(prop_height).IsNull());
-// }
-//
+//  TEST_F(ExpressionEvaluatorPropertyLookup, Edge) {}
+
 TEST_F(ExpressionEvaluatorPropertyLookup, Null) {
   frame[symbol] = TypedValue();
   EXPECT_TRUE(Value(prop_age).IsNull());
@@ -1455,59 +1291,10 @@ TEST_F(FunctionTest, StartNode) {
 }
 
 // TODO(kostasrim) Enable this test once we add degree to the accessors
-// TEST_F(FunctionTest, Degree) {
-//   ASSERT_THROW(EvaluateFunction("DEGREE"), ExpressionRuntimeException);
-//   ASSERT_TRUE(EvaluateFunction("DEGREE", TypedValue()).IsNull());
-//   auto v1 = dba.InsertVertex();
-//   auto v2 = dba.InsertVertex();
-//   auto v3 = dba.InsertVertex();
-//   auto e12 = dba.InsertEdge(&v1, &v2, dba.NameToEdgeType("t"));
-//   ASSERT_TRUE(e12.HasValue());
-//   ASSERT_TRUE(dba.InsertEdge(&v3, &v2, dba.NameToEdgeType("t")).HasValue());
-//   dba.AdvanceCommand();
-//   ASSERT_EQ(EvaluateFunction("DEGREE", v1).ValueInt(), 1);
-//   ASSERT_EQ(EvaluateFunction("DEGREE", v2).ValueInt(), 2);
-//   ASSERT_EQ(EvaluateFunction("DEGREE", v3).ValueInt(), 1);
-//   ASSERT_THROW(EvaluateFunction("DEGREE", 2), ExpressionRuntimeException);
-//   ASSERT_THROW(EvaluateFunction("DEGREE", *e12), ExpressionRuntimeException);
-// }
-//
-// TODO(kostasrim) Enable this test once we add InDegree to the accessors
-// TEST_F(FunctionTest, InDegree) {
-//   ASSERT_THROW(EvaluateFunction("INDEGREE"), ExpressionRuntimeException);
-//   ASSERT_TRUE(EvaluateFunction("INDEGREE", TypedValue()).IsNull());
-//   auto v1 = dba.InsertVertex();
-//   auto v2 = dba.InsertVertex();
-//   auto v3 = dba.InsertVertex();
-//   auto e12 = dba.InsertEdge(&v1, &v2, dba.NameToEdgeType("t"));
-//   ASSERT_TRUE(e12.HasValue());
-//   ASSERT_TRUE(dba.InsertEdge(&v3, &v2, dba.NameToEdgeType("t")).HasValue());
-//   dba.AdvanceCommand();
-//   ASSERT_EQ(EvaluateFunction("INDEGREE", v1).ValueInt(), 0);
-//   ASSERT_EQ(EvaluateFunction("INDEGREE", v2).ValueInt(), 2);
-//   ASSERT_EQ(EvaluateFunction("INDEGREE", v3).ValueInt(), 0);
-//   ASSERT_THROW(EvaluateFunction("INDEGREE", 2), ExpressionRuntimeException);
-//   ASSERT_THROW(EvaluateFunction("INDEGREE", *e12), ExpressionRuntimeException);
-// }
-//
-// TODO(kostasrim) Enable this test once we add OutDegree to the accessors
-// TEST_F(FunctionTest, OutDegree) {
-//   ASSERT_THROW(EvaluateFunction("OUTDEGREE"), ExpressionRuntimeException);
-//   ASSERT_TRUE(EvaluateFunction("OUTDEGREE", TypedValue()).IsNull());
-//   auto v1 = dba.InsertVertex();
-//   auto v2 = dba.InsertVertex();
-//   auto v3 = dba.InsertVertex();
-//   auto e12 = dba.InsertEdge(&v1, &v2, dba.NameToEdgeType("t"));
-//   ASSERT_TRUE(e12.HasValue());
-//   ASSERT_TRUE(dba.InsertEdge(&v3, &v2, dba.NameToEdgeType("t")).HasValue());
-//   dba.AdvanceCommand();
-//   ASSERT_EQ(EvaluateFunction("OUTDEGREE", v1).ValueInt(), 1);
-//   ASSERT_EQ(EvaluateFunction("OUTDEGREE", v2).ValueInt(), 0);
-//   ASSERT_EQ(EvaluateFunction("OUTDEGREE", v3).ValueInt(), 1);
-//   ASSERT_THROW(EvaluateFunction("OUTDEGREE", 2), ExpressionRuntimeException);
-//   ASSERT_THROW(EvaluateFunction("OUTDEGREE", *e12), ExpressionRuntimeException);
-// }
-//
+// TEST_F(FunctionTest, Degree) {}
+// TEST_F(FunctionTest, InDegree) {}
+// TEST_F(FunctionTest, OutDegree) {}
+
 TEST_F(FunctionTest, ToBoolean) {
   ASSERT_THROW(EvaluateFunction("TOBOOLEAN"), FunctionRuntimeException);
   ASSERT_TRUE(EvaluateFunction("TOBOOLEAN", TypedValue()).IsNull());
@@ -1591,42 +1378,8 @@ TEST_F(FunctionTest, Labels) {
 }
 
 // TODO(kostasrim) Enable this once we fix accessors Path
-// TEST_F(FunctionTest, NodesRelationships) {
-//   EXPECT_THROW(EvaluateFunction("NODES"), ExpressionRuntimeException);
-//   EXPECT_THROW(EvaluateFunction("RELATIONSHIPS"), ExpressionRuntimeException);
-//   EXPECT_TRUE(EvaluateFunction("NODES", TypedValue()).IsNull());
-//   EXPECT_TRUE(EvaluateFunction("RELATIONSHIPS", TypedValue()).IsNull());
-//
-//   {
-//     auto v1 = dba.InsertVertex();
-//     auto v2 = dba.InsertVertex();
-//     auto v3 = dba.InsertVertex();
-//     auto e1 = dba.InsertEdge(&v1, &v2, dba.NameToEdgeType("Type"));
-//     ASSERT_TRUE(e1.HasValue());
-//     auto e2 = dba.InsertEdge(&v2, &v3, dba.NameToEdgeType("Type"));
-//     ASSERT_TRUE(e2.HasValue());
-//     memgraph::query::Path path{v1, *e1, v2, *e2, v3};
-//     dba.AdvanceCommand();
-//
-//     auto _nodes = EvaluateFunction("NODES", path).ValueList();
-//     std::vector<memgraph::query::VertexAccessor> nodes;
-//     for (const auto &node : _nodes) {
-//       nodes.push_back(node.ValueVertex());
-//     }
-//     EXPECT_THAT(nodes, ElementsAre(v1, v2, v3));
-//
-//     auto _edges = EvaluateFunction("RELATIONSHIPS", path).ValueList();
-//     std::vector<memgraph::query::EdgeAccessor> edges;
-//     for (const auto &edge : _edges) {
-//       edges.push_back(edge.ValueEdge());
-//     }
-//     EXPECT_THAT(edges, ElementsAre(*e1, *e2));
-//   }
-//
-//   EXPECT_THROW(EvaluateFunction("NODES", 2), ExpressionRuntimeException);
-//   EXPECT_THROW(EvaluateFunction("RELATIONSHIPS", 2), ExpressionRuntimeException);
-// }
-//
+// TEST_F(FunctionTest, NodesRelationships) {}
+
 TEST_F(FunctionTest, Range) {
   EXPECT_THROW(EvaluateFunction("RANGE"), FunctionRuntimeException);
   EXPECT_TRUE(EvaluateFunction("RANGE", 1, 2, TypedValue()).IsNull());
@@ -1889,64 +1642,10 @@ TEST_F(FunctionTest, ToStringBool) {
   EXPECT_EQ(EvaluateFunction("TOSTRING", false).ValueString(), "false");
 }
 
-// TEST_F(FunctionTest, ToStringDate) {
-//   const auto date = memgraph::utils::Date({1970, 1, 2});
-//   EXPECT_EQ(EvaluateFunction("TOSTRING", date).ValueString(), "1970-01-02");
-// }
-//
-// TEST_F(FunctionTest, ToStringLocalTime) {
-//   const auto lt = memgraph::utils::LocalTime({13, 2, 40, 100, 50});
-//   EXPECT_EQ(EvaluateFunction("TOSTRING", lt).ValueString(), "13:02:40.100050");
-// }
-//
-// TEST_F(FunctionTest, ToStringLocalDateTime) {
-//   const auto ldt = memgraph::utils::LocalDateTime({1970, 1, 2}, {23, 02, 59});
-//   EXPECT_EQ(EvaluateFunction("TOSTRING", ldt).ValueString(), "1970-01-02T23:02:59.000000");
-// }
-//
-// TEST_F(FunctionTest, ToStringDuration) {
-//   memgraph::utils::Duration duration{{.minute = 2, .second = 2, .microsecond = 33}};
-//   EXPECT_EQ(EvaluateFunction("TOSTRING", duration).ValueString(), "P0DT0H2M2.000033S");
-// }
-//
 TEST_F(FunctionTest, ToStringExceptions) {
   EXPECT_THROW(EvaluateFunction("TOSTRING", 1, 2, 3), FunctionRuntimeException);
 }
-//
-// TEST_F(FunctionTest, TimestampVoid) {
-//   ctx.timestamp = 42;
-//   EXPECT_EQ(EvaluateFunction("TIMESTAMP").ValueInt(), 42);
-// }
-//
-// TEST_F(FunctionTest, TimestampDate) {
-//   ctx.timestamp = 42;
-//   EXPECT_EQ(EvaluateFunction("TIMESTAMP", memgraph::utils::Date({1970, 1, 1})).ValueInt(), 0);
-//   EXPECT_EQ(EvaluateFunction("TIMESTAMP", memgraph::utils::Date({1971, 1, 1})).ValueInt(), 31536000000000);
-// }
-//
-// TEST_F(FunctionTest, TimestampLocalTime) {
-//   ctx.timestamp = 42;
-//   const memgraph::utils::LocalTime time(10000);
-//   EXPECT_EQ(EvaluateFunction("TIMESTAMP", time).ValueInt(), 10000);
-// }
-//
-// TEST_F(FunctionTest, TimestampLocalDateTime) {
-//   ctx.timestamp = 42;
-//   const memgraph::utils::LocalDateTime time(20000);
-//   EXPECT_EQ(EvaluateFunction("TIMESTAMP", time).ValueInt(), 20000);
-// }
-//
-// TEST_F(FunctionTest, TimestampDuration) {
-//   ctx.timestamp = 42;
-//   const memgraph::utils::Duration time(20000);
-//   EXPECT_EQ(EvaluateFunction("TIMESTAMP", time).ValueInt(), 20000);
-// }
-//
-// TEST_F(FunctionTest, TimestampExceptions) {
-//   ctx.timestamp = 42;
-//   EXPECT_THROW(EvaluateFunction("TIMESTAMP", 1).ValueInt(), ExpressionRuntimeException);
-// }
-//
+
 TEST_F(FunctionTest, Left) {
   EXPECT_THROW(EvaluateFunction("LEFT"), FunctionRuntimeException);
 
@@ -2083,110 +1782,5 @@ TEST_F(FunctionTest, FromByteString) {
   EXPECT_EQ(EvaluateFunction("FROMBYTESTRING", std::string("\x00\x42", 2)).ValueString(), "0x0042");
 }
 
-// TEST_F(FunctionTest, Date) {
-//   const auto unix_epoch = memgraph::utils::Date({1970, 1, 1});
-//   EXPECT_EQ(EvaluateFunction("DATE", "1970-01-01").ValueDate(), unix_epoch);
-//   const auto map_param = TypedValue(
-//       std::map<std::string, TypedValue>{{"year", TypedValue(1970)}, {"month", TypedValue(1)}, {"day",
-//       TypedValue(1)}});
-//   EXPECT_EQ(EvaluateFunction("DATE", map_param).ValueDate(), unix_epoch);
-//   const auto today = memgraph::utils::CurrentDate();
-//   EXPECT_EQ(EvaluateFunction("DATE").ValueDate(), today);
-//
-//   EXPECT_THROW(EvaluateFunction("DATE", "{}"), memgraph::utils::BasicException);
-//   EXPECT_THROW(EvaluateFunction("DATE", std::map<std::string, TypedValue>{{"years", TypedValue(1970)}}),
-//                ExpressionRuntimeException);
-//   EXPECT_THROW(EvaluateFunction("DATE", std::map<std::string, TypedValue>{{"mnths", TypedValue(1970)}}),
-//                ExpressionRuntimeException);
-//   EXPECT_THROW(EvaluateFunction("DATE", std::map<std::string, TypedValue>{{"dayz", TypedValue(1970)}}),
-//                ExpressionRuntimeException);
-// }
-//
-// TEST_F(FunctionTest, LocalTime) {
-//   const auto local_time = memgraph::utils::LocalTime({13, 3, 2, 0, 0});
-//   EXPECT_EQ(EvaluateFunction("LOCALTIME", "130302").ValueLocalTime(), local_time);
-//   const auto one_sec_in_microseconds = 1000000;
-//   const auto map_param = TypedValue(std::map<std::string, TypedValue>{{"hour", TypedValue(1)},
-//                                                                       {"minute", TypedValue(2)},
-//                                                                       {"second", TypedValue(3)},
-//                                                                       {"millisecond", TypedValue(4)},
-//                                                                       {"microsecond", TypedValue(5)}});
-//   EXPECT_EQ(EvaluateFunction("LOCALTIME", map_param).ValueLocalTime(), memgraph::utils::LocalTime({1, 2, 3, 4, 5}));
-//   const auto today = memgraph::utils::CurrentLocalTime();
-//   EXPECT_NEAR(EvaluateFunction("LOCALTIME").ValueLocalTime().MicrosecondsSinceEpoch(),
-//   today.MicrosecondsSinceEpoch(),
-//               one_sec_in_microseconds);
-//
-//   EXPECT_THROW(EvaluateFunction("LOCALTIME", "{}"), memgraph::utils::BasicException);
-//   EXPECT_THROW(EvaluateFunction("LOCALTIME", TypedValue(std::map<std::string, TypedValue>{{"hous",
-//   TypedValue(1970)}})),
-//                ExpressionRuntimeException);
-//   EXPECT_THROW(
-//       EvaluateFunction("LOCALTIME", TypedValue(std::map<std::string, TypedValue>{{"minut", TypedValue(1970)}})),
-//       ExpressionRuntimeException);
-//   EXPECT_THROW(
-//       EvaluateFunction("LOCALTIME", TypedValue(std::map<std::string, TypedValue>{{"seconds", TypedValue(1970)}})),
-//       ExpressionRuntimeException);
-// }
-//
-// TEST_F(FunctionTest, LocalDateTime) {
-//   const auto local_date_time = memgraph::utils::LocalDateTime({1970, 1, 1}, {13, 3, 2, 0, 0});
-//   EXPECT_EQ(EvaluateFunction("LOCALDATETIME", "1970-01-01T13:03:02").ValueLocalDateTime(), local_date_time);
-//   const auto today = memgraph::utils::CurrentLocalDateTime();
-//   const auto one_sec_in_microseconds = 1000000;
-//   const auto map_param = TypedValue(std::map<std::string, TypedValue>{{"year", TypedValue(1972)},
-//                                                                       {"month", TypedValue(2)},
-//                                                                       {"day", TypedValue(3)},
-//                                                                       {"hour", TypedValue(4)},
-//                                                                       {"minute", TypedValue(5)},
-//                                                                       {"second", TypedValue(6)},
-//                                                                       {"millisecond", TypedValue(7)},
-//                                                                       {"microsecond", TypedValue(8)}});
-//
-//   EXPECT_EQ(EvaluateFunction("LOCALDATETIME", map_param).ValueLocalDateTime(),
-//             memgraph::utils::LocalDateTime({1972, 2, 3}, {4, 5, 6, 7, 8}));
-//   EXPECT_NEAR(EvaluateFunction("LOCALDATETIME").ValueLocalDateTime().MicrosecondsSinceEpoch(),
-//               today.MicrosecondsSinceEpoch(), one_sec_in_microseconds);
-//   EXPECT_THROW(EvaluateFunction("LOCALDATETIME", "{}"), memgraph::utils::BasicException);
-//   EXPECT_THROW(
-//       EvaluateFunction("LOCALDATETIME", TypedValue(std::map<std::string, TypedValue>{{"hours", TypedValue(1970)}})),
-//       ExpressionRuntimeException);
-//   EXPECT_THROW(
-//       EvaluateFunction("LOCALDATETIME", TypedValue(std::map<std::string, TypedValue>{{"seconds",
-//       TypedValue(1970)}})), ExpressionRuntimeException);
-// }
-//
-// TEST_F(FunctionTest, Duration) {
-//   const auto map_param = TypedValue(std::map<std::string, TypedValue>{{"day", TypedValue(3)},
-//                                                                       {"hour", TypedValue(4)},
-//                                                                       {"minute", TypedValue(5)},
-//                                                                       {"second", TypedValue(6)},
-//                                                                       {"millisecond", TypedValue(7)},
-//                                                                       {"microsecond", TypedValue(8)}});
-//
-//   EXPECT_EQ(EvaluateFunction("DURATION", map_param).ValueDuration(), memgraph::utils::Duration({3, 4, 5, 6, 7, 8}));
-//   EXPECT_THROW(EvaluateFunction("DURATION", "{}"), memgraph::utils::BasicException);
-//   EXPECT_THROW(EvaluateFunction("DURATION", TypedValue(std::map<std::string, TypedValue>{{"hours",
-//   TypedValue(1970)}})),
-//                ExpressionRuntimeException);
-//   EXPECT_THROW(
-//       EvaluateFunction("DURATION", TypedValue(std::map<std::string, TypedValue>{{"seconds", TypedValue(1970)}})),
-//       ExpressionRuntimeException);
-//
-//   const auto map_param_negative = TypedValue(std::map<std::string, TypedValue>{{"day", TypedValue(-3)},
-//                                                                                {"hour", TypedValue(-4)},
-//                                                                                {"minute", TypedValue(-5)},
-//                                                                                {"second", TypedValue(-6)},
-//                                                                                {"millisecond", TypedValue(-7)},
-//                                                                                {"microsecond", TypedValue(-8)}});
-//   EXPECT_EQ(EvaluateFunction("DURATION", map_param_negative).ValueDuration(),
-//             memgraph::utils::Duration({-3, -4, -5, -6, -7, -8}));
-//
-//   EXPECT_EQ(EvaluateFunction("DURATION", "P4DT4H5M6.2S").ValueDuration(),
-//             memgraph::utils::Duration({4, 4, 5, 6, 0, 200000}));
-//   EXPECT_EQ(EvaluateFunction("DURATION", "P3DT4H5M6.100S").ValueDuration(),
-//             memgraph::utils::Duration({3, 4, 5, 6, 0, 100000}));
-//   EXPECT_EQ(EvaluateFunction("DURATION", "P3DT4H5M6.100110S").ValueDuration(),
-//             memgraph::utils::Duration({3, 4, 5, 6, 100, 110}));
-// }
+// TODO(kostasrim) Add temporal type tests.
 }  // namespace

From 631d18465b5fc8b89fa6c872da2e57a87645944e Mon Sep 17 00:00:00 2001
From: Tyler Neely <t@jujit.su>
Date: Tue, 15 Nov 2022 17:52:38 +0000
Subject: [PATCH 05/26] Allow the RsmClient to store multiple in-flight
 requests. Update the ShardRequestManager to use the new request tokens and
 refactor some bug-prone aspects of it

---
 src/io/rsm/rsm_client.hpp              | 131 +++++++++------
 src/query/v2/shard_request_manager.hpp | 211 ++++++++++++-------------
 2 files changed, 188 insertions(+), 154 deletions(-)

diff --git a/src/io/rsm/rsm_client.hpp b/src/io/rsm/rsm_client.hpp
index b60380b08..ce6781956 100644
--- a/src/io/rsm/rsm_client.hpp
+++ b/src/io/rsm/rsm_client.hpp
@@ -14,6 +14,7 @@
 #include <iostream>
 #include <optional>
 #include <type_traits>
+#include <unordered_map>
 #include <vector>
 
 #include "io/address.hpp"
@@ -36,6 +37,21 @@ using memgraph::io::rsm::WriteRequest;
 using memgraph::io::rsm::WriteResponse;
 using memgraph::utils::BasicResult;
 
+class AsyncRequestToken {
+  size_t id_;
+
+ public:
+  AsyncRequestToken(size_t id) : id_(id) {}
+  size_t GetId() const { return id_; }
+};
+
+template <typename RequestT, typename ResponseT>
+struct AsyncRequest {
+  Time start_time;
+  RequestT request;
+  ResponseFuture<ResponseT> future;
+};
+
 template <typename IoImpl, typename WriteRequestT, typename WriteResponseT, typename ReadRequestT,
           typename ReadResponseT>
 class RsmClient {
@@ -47,13 +63,10 @@ class RsmClient {
 
   /// State for single async read/write operations. In the future this could become a map
   /// of async operations that can be accessed via an ID etc...
-  std::optional<Time> async_read_before_;
-  std::optional<ResponseFuture<ReadResponse<ReadResponseT>>> async_read_;
-  ReadRequestT current_read_request_;
+  std::unordered_map<size_t, AsyncRequest<ReadRequestT, ReadResponse<ReadResponseT>>> async_reads_;
+  std::unordered_map<size_t, AsyncRequest<WriteRequestT, WriteResponse<WriteResponseT>>> async_writes_;
 
-  std::optional<Time> async_write_before_;
-  std::optional<ResponseFuture<WriteResponse<WriteResponseT>>> async_write_;
-  WriteRequestT current_write_request_;
+  size_t async_token_generator_ = 0;
 
   void SelectRandomLeader() {
     std::uniform_int_distribution<size_t> addr_distrib(0, (server_addrs_.size() - 1));
@@ -156,42 +169,56 @@ class RsmClient {
   }
 
   /// AsyncRead methods
-  void SendAsyncReadRequest(const ReadRequestT &req) {
-    MG_ASSERT(!async_read_);
+  AsyncRequestToken SendAsyncReadRequest(const ReadRequestT &req) {
+    size_t token = async_token_generator_++;
 
     ReadRequest<ReadRequestT> read_req = {.operation = req};
 
-    if (!async_read_before_) {
-      async_read_before_ = io_.Now();
-    }
-    current_read_request_ = std::move(req);
-    async_read_ = io_.template Request<ReadRequest<ReadRequestT>, ReadResponse<ReadResponseT>>(leader_, read_req);
+    AsyncRequest<ReadRequestT, ReadResponse<ReadResponseT>> async_request{
+        .start_time = io_.Now(),
+        .request = std::move(req),
+        .future = io_.template Request<ReadRequest<ReadRequestT>, ReadResponse<ReadResponseT>>(leader_, read_req),
+    };
+
+    async_reads_.emplace(token, std::move(async_request));
+
+    return AsyncRequestToken(token);
   }
 
-  std::optional<BasicResult<TimedOut, ReadResponseT>> PollAsyncReadRequest() {
-    MG_ASSERT(async_read_);
+  void ResendAsyncReadRequest(AsyncRequestToken &token) {
+    auto &async_request = async_reads_.at(token.GetId());
 
-    if (!async_read_->IsReady()) {
+    ReadRequest<ReadRequestT> read_req = {.operation = async_request.request};
+
+    async_request.future =
+        io_.template Request<ReadRequest<ReadRequestT>, ReadResponse<ReadResponseT>>(leader_, read_req);
+  }
+
+  std::optional<BasicResult<TimedOut, ReadResponseT>> PollAsyncReadRequest(AsyncRequestToken &token) {
+    auto &async_request = async_reads_.at(token.GetId());
+
+    if (!async_request.future.IsReady()) {
       return std::nullopt;
     }
 
     return AwaitAsyncReadRequest();
   }
 
-  std::optional<BasicResult<TimedOut, ReadResponseT>> AwaitAsyncReadRequest() {
-    ResponseResult<ReadResponse<ReadResponseT>> get_response_result = std::move(*async_read_).Wait();
-    async_read_.reset();
+  std::optional<BasicResult<TimedOut, ReadResponseT>> AwaitAsyncReadRequest(AsyncRequestToken &token) {
+    auto &async_request = async_reads_.at(token.GetId());
+    ResponseResult<ReadResponse<ReadResponseT>> get_response_result = std::move(async_request.future).Wait();
 
     const Duration overall_timeout = io_.GetDefaultTimeout();
-    const bool past_time_out = io_.Now() < *async_read_before_ + overall_timeout;
+    const bool past_time_out = io_.Now() > async_request.start_time + overall_timeout;
     const bool result_has_error = get_response_result.HasError();
 
     if (result_has_error && past_time_out) {
       // TODO static assert the exact type of error.
       spdlog::debug("client timed out while trying to communicate with leader server {}", leader_.ToString());
-      async_read_before_ = std::nullopt;
+      async_reads_.erase(token.GetId());
       return TimedOut{};
     }
+
     if (!result_has_error) {
       ResponseEnvelope<ReadResponse<ReadResponseT>> &&get_response_envelope = std::move(get_response_result.GetValue());
       ReadResponse<ReadResponseT> &&read_get_response = std::move(get_response_envelope.message);
@@ -199,54 +226,69 @@ class RsmClient {
       PossiblyRedirectLeader(read_get_response);
 
       if (read_get_response.success) {
-        async_read_before_ = std::nullopt;
+        async_reads_.erase(token.GetId());
         return std::move(read_get_response.read_return);
       }
-      SendAsyncReadRequest(current_read_request_);
-    } else if (result_has_error) {
+    } else {
       SelectRandomLeader();
-      SendAsyncReadRequest(current_read_request_);
     }
+
+    ResendAsyncReadRequest(token);
+
     return std::nullopt;
   }
 
   /// AsyncWrite methods
-  void SendAsyncWriteRequest(const WriteRequestT &req) {
-    MG_ASSERT(!async_write_);
+  AsyncRequestToken SendAsyncWriteRequest(const WriteRequestT &req) {
+    size_t token = async_token_generator_++;
 
     WriteRequest<WriteRequestT> write_req = {.operation = req};
 
-    if (!async_write_before_) {
-      async_write_before_ = io_.Now();
-    }
-    current_write_request_ = std::move(req);
-    async_write_ = io_.template Request<WriteRequest<WriteRequestT>, WriteResponse<WriteResponseT>>(leader_, write_req);
+    AsyncRequest<WriteRequestT, WriteResponse<WriteResponseT>> async_request{
+        .start_time = io_.Now(),
+        .request = std::move(req),
+        .future = io_.template Request<WriteRequest<WriteRequestT>, WriteResponse<WriteResponseT>>(leader_, write_req),
+    };
+
+    async_writes_.emplace(token, std::move(async_request));
+
+    return AsyncRequestToken(token);
   }
 
-  std::optional<BasicResult<TimedOut, WriteResponseT>> PollAsyncWriteRequest() {
-    MG_ASSERT(async_write_);
+  void ResendAsyncWriteRequest(AsyncRequestToken &token) {
+    auto &async_request = async_writes_.at(token.GetId());
 
-    if (!async_write_->IsReady()) {
+    WriteRequest<WriteRequestT> write_req = {.operation = async_request.request};
+
+    async_request.future =
+        io_.template Request<WriteRequest<WriteRequestT>, WriteResponse<WriteResponseT>>(leader_, write_req);
+  }
+
+  std::optional<BasicResult<TimedOut, WriteResponseT>> PollAsyncWriteRequest(AsyncRequestToken &token) {
+    auto &async_request = async_writes_.at(token.GetId());
+
+    if (!async_request.future.IsReady()) {
       return std::nullopt;
     }
 
     return AwaitAsyncWriteRequest();
   }
 
-  std::optional<BasicResult<TimedOut, WriteResponseT>> AwaitAsyncWriteRequest() {
-    ResponseResult<WriteResponse<WriteResponseT>> get_response_result = std::move(*async_write_).Wait();
-    async_write_.reset();
+  std::optional<BasicResult<TimedOut, WriteResponseT>> AwaitAsyncWriteRequest(AsyncRequestToken &token) {
+    auto &async_request = async_writes_.at(token.GetId());
+    ResponseResult<WriteResponse<WriteResponseT>> get_response_result = std::move(async_request.future).Wait();
 
     const Duration overall_timeout = io_.GetDefaultTimeout();
-    const bool past_time_out = io_.Now() < *async_write_before_ + overall_timeout;
+    const bool past_time_out = io_.Now() > async_request.start_time + overall_timeout;
     const bool result_has_error = get_response_result.HasError();
 
     if (result_has_error && past_time_out) {
       // TODO static assert the exact type of error.
       spdlog::debug("client timed out while trying to communicate with leader server {}", leader_.ToString());
-      async_write_before_ = std::nullopt;
+      async_writes_.erase(token.GetId());
       return TimedOut{};
     }
+
     if (!result_has_error) {
       ResponseEnvelope<WriteResponse<WriteResponseT>> &&get_response_envelope =
           std::move(get_response_result.GetValue());
@@ -255,14 +297,15 @@ class RsmClient {
       PossiblyRedirectLeader(write_get_response);
 
       if (write_get_response.success) {
-        async_write_before_ = std::nullopt;
+        async_writes_.erase(token.GetId());
         return std::move(write_get_response.write_return);
       }
-      SendAsyncWriteRequest(current_write_request_);
-    } else if (result_has_error) {
+    } else {
       SelectRandomLeader();
-      SendAsyncWriteRequest(current_write_request_);
     }
+
+    ResendAsyncWriteRequest(token);
+
     return std::nullopt;
   }
 };
diff --git a/src/query/v2/shard_request_manager.hpp b/src/query/v2/shard_request_manager.hpp
index a73201046..386fb0930 100644
--- a/src/query/v2/shard_request_manager.hpp
+++ b/src/query/v2/shard_request_manager.hpp
@@ -72,6 +72,13 @@ class RsmStorageClientManager {
   std::map<Shard, TStorageClient> cli_cache_;
 };
 
+template <typename TRequest>
+struct ShardRequestState {
+  memgraph::coordinator::Shard shard;
+  TRequest request;
+  std::optional<io::rsm::AsyncRequestToken> async_request_token;
+};
+
 template <typename TRequest>
 struct ExecutionState {
   using CompoundKey = memgraph::io::rsm::ShardRsmKey;
@@ -91,14 +98,13 @@ struct ExecutionState {
   // it pulled all the requested data from the given Shard, it will be removed from the Vector. When the Vector becomes
   // empty, it means that all of the requests have completed succefully.
   // TODO(gvolfing)
-  // Maybe make this into a more complex object to be able to keep track of paginated resutls. E.g. instead of a vector
+  // Maybe make this into a more complex object to be able to keep track of paginated results. E.g. instead of a vector
   // of Shards make it into a std::vector<std::pair<Shard, PaginatedResultType>> (probably a struct instead of a pair)
   // where PaginatedResultType is an enum signaling the progress on the given request. This way we can easily check if
   // a partial response on a shard(if there is one) is finished and we can send off the request for the next batch.
-  std::vector<Shard> shard_cache;
   // 1-1 mapping with `shard_cache`.
   // A vector that tracks request metadata for each shard (For example, next_id for a ScanAll on Shard A)
-  std::vector<TRequest> requests;
+  std::vector<ShardRequestState<TRequest>> requests;
   State state = INITIALIZING;
 };
 
@@ -259,8 +265,8 @@ class ShardRequestManager : public ShardRequestManagerInterface {
     };
 
     std::map<Shard, PaginatedResponseState> paginated_response_tracker;
-    for (const auto &shard : state.shard_cache) {
-      paginated_response_tracker.insert(std::make_pair(shard, PaginatedResponseState::Pending));
+    for (const auto &request : state.requests) {
+      paginated_response_tracker.insert(std::make_pair(request.shard, PaginatedResponseState::Pending));
     }
 
     do {
@@ -278,15 +284,14 @@ class ShardRequestManager : public ShardRequestManagerInterface {
     MG_ASSERT(!new_vertices.empty());
     MaybeInitializeExecutionState(state, new_vertices);
     std::vector<CreateVerticesResponse> responses;
-    auto &shard_cache_ref = state.shard_cache;
 
     // 1. Send the requests.
-    SendAllRequests(state, shard_cache_ref);
+    SendAllRequests(state);
 
     // 2. Block untill all the futures are exhausted
     do {
       AwaitOnResponses(state, responses);
-    } while (!state.shard_cache.empty());
+    } while (!state.requests.empty());
 
     MaybeCompleteState(state);
     // TODO(kostasrim) Before returning start prefetching the batch (this shall be done once we get MgFuture as return
@@ -299,11 +304,9 @@ class ShardRequestManager : public ShardRequestManagerInterface {
     MG_ASSERT(!new_edges.empty());
     MaybeInitializeExecutionState(state, new_edges);
     std::vector<CreateExpandResponse> responses;
-    auto &shard_cache_ref = state.shard_cache;
-    size_t id{0};
-    for (auto shard_it = shard_cache_ref.begin(); shard_it != shard_cache_ref.end(); ++id) {
-      auto &storage_client = GetStorageClientForShard(*shard_it);
-      WriteRequests req = state.requests[id];
+    for (auto &request : state.requests) {
+      auto &storage_client = GetStorageClientForShard(request.shard);
+      WriteRequests req = request.request;
       auto write_response_result = storage_client.SendWriteRequest(std::move(req));
       if (write_response_result.HasError()) {
         throw std::runtime_error("CreateVertices request timedout");
@@ -315,9 +318,9 @@ class ShardRequestManager : public ShardRequestManagerInterface {
         throw std::runtime_error("CreateExpand request did not succeed");
       }
       responses.push_back(mapped_response);
-      shard_it = shard_cache_ref.erase(shard_it);
     }
     // We are done with this state
+    state.requests.clear();
     MaybeCompleteState(state);
     return responses;
   }
@@ -330,15 +333,14 @@ class ShardRequestManager : public ShardRequestManagerInterface {
     // must be fetched again with an ExpandOne(Edges.dst)
     MaybeInitializeExecutionState(state, std::move(request));
     std::vector<ExpandOneResponse> responses;
-    auto &shard_cache_ref = state.shard_cache;
 
     // 1. Send the requests.
-    SendAllRequests(state, shard_cache_ref);
+    SendAllRequests(state);
 
     // 2. Block untill all the futures are exhausted
     do {
       AwaitOnResponses(state, responses);
-    } while (!state.shard_cache.empty());
+    } while (!state.requests.empty());
     std::vector<ExpandOneResultRow> result_rows;
     const auto total_row_count = std::accumulate(
         responses.begin(), responses.end(), 0,
@@ -402,13 +404,17 @@ class ShardRequestManager : public ShardRequestManagerInterface {
       if (!per_shard_request_table.contains(shard)) {
         CreateVerticesRequest create_v_rqst{.transaction_id = transaction_id_};
         per_shard_request_table.insert(std::pair(shard, std::move(create_v_rqst)));
-        state.shard_cache.push_back(shard);
       }
       per_shard_request_table[shard].new_vertices.push_back(std::move(new_vertex));
     }
 
-    for (auto &[shard, rqst] : per_shard_request_table) {
-      state.requests.push_back(std::move(rqst));
+    for (auto &[shard, request] : per_shard_request_table) {
+      ShardRequestState<CreateVerticesRequest> shard_request_state{
+          .shard = shard,
+          .request = request,
+          .async_request_token = std::nullopt,
+      };
+      state.requests.emplace_back(std::move(shard_request_state));
     }
     state.state = ExecutionState<CreateVerticesRequest>::EXECUTING;
   }
@@ -445,8 +451,12 @@ class ShardRequestManager : public ShardRequestManagerInterface {
     }
 
     for (auto &[shard, request] : per_shard_request_table) {
-      state.shard_cache.push_back(shard);
-      state.requests.push_back(std::move(request));
+      ShardRequestState<CreateExpandRequest> shard_request_state{
+          .shard = shard,
+          .request = request,
+          .async_request_token = std::nullopt,
+      };
+      state.requests.emplace_back(std::move(shard_request_state));
     }
     state.state = ExecutionState<CreateExpandRequest>::EXECUTING;
   }
@@ -470,11 +480,18 @@ class ShardRequestManager : public ShardRequestManagerInterface {
     for (auto &shards : multi_shards) {
       for (auto &[key, shard] : shards) {
         MG_ASSERT(!shard.empty());
-        state.shard_cache.push_back(std::move(shard));
-        ScanVerticesRequest rqst;
-        rqst.transaction_id = transaction_id_;
-        rqst.start_id.second = storage::conversions::ConvertValueVector(key);
-        state.requests.push_back(std::move(rqst));
+
+        ScanVerticesRequest request;
+        request.transaction_id = transaction_id_;
+        request.start_id.second = storage::conversions::ConvertValueVector(key);
+
+        ShardRequestState<ScanVerticesRequest> shard_request_state{
+            .shard = shard,
+            .request = std::move(request),
+            .async_request_token = std::nullopt,
+        };
+
+        state.requests.emplace_back(std::move(shard_request_state));
       }
     }
     state.state = ExecutionState<ScanVerticesRequest>::EXECUTING;
@@ -497,13 +514,18 @@ class ShardRequestManager : public ShardRequestManagerInterface {
           shards_map_.GetShardForKey(vertex.first.id, storage::conversions::ConvertPropertyVector(vertex.second));
       if (!per_shard_request_table.contains(shard)) {
         per_shard_request_table.insert(std::pair(shard, top_level_rqst_template));
-        state.shard_cache.push_back(shard);
       }
       per_shard_request_table[shard].src_vertices.push_back(vertex);
     }
 
-    for (auto &[shard, rqst] : per_shard_request_table) {
-      state.requests.push_back(std::move(rqst));
+    for (auto &[shard, request] : per_shard_request_table) {
+      ShardRequestState<ExpandOneRequest> shard_request_state{
+          .shard = shard,
+          .request = request,
+          .async_request_token = std::nullopt,
+      };
+
+      state.requests.emplace_back(std::move(shard_request_state));
     }
     state.state = ExecutionState<ExpandOneRequest>::EXECUTING;
   }
@@ -533,65 +555,46 @@ class ShardRequestManager : public ShardRequestManagerInterface {
   }
 
   void SendAllRequests(ExecutionState<ScanVerticesRequest> &state) {
-    int64_t shard_idx = 0;
-    for (const auto &request : state.requests) {
-      const auto &current_shard = state.shard_cache[shard_idx];
+    for (auto &request : state.requests) {
+      const auto &current_shard = request.shard;
 
       auto &storage_client = GetStorageClientForShard(current_shard);
-      ReadRequests req = request;
-      storage_client.SendAsyncReadRequest(request);
+      ReadRequests req = request.request;
 
-      ++shard_idx;
+      request.async_request_token = storage_client.SendAsyncReadRequest(request.request);
     }
   }
 
-  void SendAllRequests(ExecutionState<CreateVerticesRequest> &state,
-                       std::vector<memgraph::coordinator::Shard> &shard_cache_ref) {
-    size_t id = 0;
-    for (auto shard_it = shard_cache_ref.begin(); shard_it != shard_cache_ref.end(); ++shard_it) {
-      // This is fine because all new_vertices of each request end up on the same shard
-      const auto labels = state.requests[id].new_vertices[0].label_ids;
-      auto req_deep_copy = state.requests[id];
+  void SendAllRequests(ExecutionState<CreateVerticesRequest> &state) {
+    for (auto &request : state.requests) {
+      auto req_deep_copy = request.request;
 
       for (auto &new_vertex : req_deep_copy.new_vertices) {
         new_vertex.label_ids.erase(new_vertex.label_ids.begin());
       }
 
-      auto &storage_client = GetStorageClientForShard(*shard_it);
+      auto &storage_client = GetStorageClientForShard(request.shard);
 
       WriteRequests req = req_deep_copy;
-      storage_client.SendAsyncWriteRequest(req);
-      ++id;
+      request.async_request_token = storage_client.SendAsyncWriteRequest(req);
     }
   }
 
-  void SendAllRequests(ExecutionState<ExpandOneRequest> &state,
-                       std::vector<memgraph::coordinator::Shard> &shard_cache_ref) {
-    size_t id = 0;
-    for (auto shard_it = shard_cache_ref.begin(); shard_it != shard_cache_ref.end(); ++shard_it) {
-      auto &storage_client = GetStorageClientForShard(*shard_it);
-      ReadRequests req = state.requests[id];
-      storage_client.SendAsyncReadRequest(req);
-      ++id;
+  void SendAllRequests(ExecutionState<ExpandOneRequest> &state) {
+    for (auto &request : state.requests) {
+      auto &storage_client = GetStorageClientForShard(request.shard);
+      ReadRequests req = request.request;
+      request.async_request_token = storage_client.SendAsyncReadRequest(req);
     }
   }
 
   void AwaitOnResponses(ExecutionState<CreateVerticesRequest> &state, std::vector<CreateVerticesResponse> &responses) {
-    auto &shard_cache_ref = state.shard_cache;
-    int64_t request_idx = 0;
+    for (auto &request : state.requests) {
+      auto &storage_client = GetStorageClientForShard(request.shard);
 
-    for (auto shard_it = shard_cache_ref.begin(); shard_it != shard_cache_ref.end();) {
-      // This is fine because all new_vertices of each request end up on the same shard
-      const auto labels = state.requests[request_idx].new_vertices[0].label_ids;
-
-      auto &storage_client = GetStorageClientForShard(*shard_it);
-
-      auto poll_result = storage_client.AwaitAsyncWriteRequest();
-      if (!poll_result) {
-        ++shard_it;
-        ++request_idx;
-
-        continue;
+      auto poll_result = storage_client.AwaitAsyncWriteRequest(request.async_request_token.value());
+      while (!poll_result) {
+        poll_result = storage_client.AwaitAsyncWriteRequest(request.async_request_token.value());
       }
 
       if (poll_result->HasError()) {
@@ -605,26 +608,17 @@ class ShardRequestManager : public ShardRequestManagerInterface {
         throw std::runtime_error("CreateVertices request did not succeed");
       }
       responses.push_back(response);
-
-      shard_it = shard_cache_ref.erase(shard_it);
-      // Needed to maintain the 1-1 mapping between the ShardCache and the requests.
-      auto it = state.requests.begin() + request_idx;
-      state.requests.erase(it);
     }
+    state.requests.clear();
   }
 
   void AwaitOnResponses(ExecutionState<ExpandOneRequest> &state, std::vector<ExpandOneResponse> &responses) {
-    auto &shard_cache_ref = state.shard_cache;
-    int64_t request_idx = 0;
+    for (auto &request : state.requests) {
+      auto &storage_client = GetStorageClientForShard(request.shard);
 
-    for (auto shard_it = shard_cache_ref.begin(); shard_it != shard_cache_ref.end();) {
-      auto &storage_client = GetStorageClientForShard(*shard_it);
-
-      auto poll_result = storage_client.PollAsyncReadRequest();
-      if (!poll_result) {
-        ++shard_it;
-        ++request_idx;
-        continue;
+      auto poll_result = storage_client.AwaitAsyncReadRequest(request.async_request_token.value());
+      while (!poll_result) {
+        poll_result = storage_client.AwaitAsyncReadRequest(request.async_request_token.value());
       }
 
       if (poll_result->HasError()) {
@@ -642,36 +636,28 @@ class ShardRequestManager : public ShardRequestManagerInterface {
       }
 
       responses.push_back(std::move(response));
-      shard_it = shard_cache_ref.erase(shard_it);
-      // Needed to maintain the 1-1 mapping between the ShardCache and the requests.
-      auto it = state.requests.begin() + request_idx;
-      state.requests.erase(it);
     }
+    state.requests.clear();
   }
 
   void AwaitOnPaginatedRequests(ExecutionState<ScanVerticesRequest> &state,
                                 std::vector<ScanVerticesResponse> &responses,
                                 std::map<Shard, PaginatedResponseState> &paginated_response_tracker) {
-    auto &shard_cache_ref = state.shard_cache;
+    std::vector<int> to_erase{};
 
-    // Find the first request that is not holding a paginated response.
-    int64_t request_idx = 0;
-    for (auto shard_it = shard_cache_ref.begin(); shard_it != shard_cache_ref.end();) {
-      if (paginated_response_tracker.at(*shard_it) != PaginatedResponseState::Pending) {
-        ++shard_it;
-        ++request_idx;
+    for (int i = 0; i < state.requests.size(); i++) {
+      auto &request = state.requests[i];
+      // only operate on paginated requests
+      if (paginated_response_tracker.at(request.shard) != PaginatedResponseState::Pending) {
         continue;
       }
 
-      auto &storage_client = GetStorageClientForShard(*shard_it);
+      auto &storage_client = GetStorageClientForShard(request.shard);
 
-      auto await_result = storage_client.AwaitAsyncReadRequest();
-
-      if (!await_result) {
-        // Redirection has occured.
-        ++shard_it;
-        ++request_idx;
-        continue;
+      // drive it to completion
+      auto await_result = storage_client.AwaitAsyncReadRequest(request.async_request_token.value());
+      while (!await_result) {
+        await_result = storage_client.AwaitAsyncReadRequest(request.async_request_token.value());
       }
 
       if (await_result->HasError()) {
@@ -685,17 +671,22 @@ class ShardRequestManager : public ShardRequestManagerInterface {
       }
 
       if (!response.next_start_id) {
-        paginated_response_tracker.erase((*shard_it));
-        shard_cache_ref.erase(shard_it);
-        // Needed to maintain the 1-1 mapping between the ShardCache and the requests.
-        auto it = state.requests.begin() + request_idx;
-        state.requests.erase(it);
-
+        paginated_response_tracker.erase(request.shard);
+        to_erase.push_back(i);
       } else {
-        state.requests[request_idx].start_id.second = response.next_start_id->second;
-        paginated_response_tracker[*shard_it] = PaginatedResponseState::PartiallyFinished;
+        request.request.start_id.second = response.next_start_id->second;
+        paginated_response_tracker[request.shard] = PaginatedResponseState::PartiallyFinished;
       }
+
       responses.push_back(std::move(response));
+
+      // reverse sort to_erase to remove requests in reverse order for correctness
+      std::sort(to_erase.begin(), to_erase.end(), std::greater<>());
+
+      auto requests_begin = state.requests.begin();
+      for (int i : to_erase) {
+        state.requests.erase(requests_begin + i);
+      }
     }
   }
 

From 6d544e4fc0e92490b657c1523ae5a71022f04bb4 Mon Sep 17 00:00:00 2001
From: Kostas Kyrimis <kostaskyrim@gmail.com>
Date: Wed, 23 Nov 2022 14:51:38 +0200
Subject: [PATCH 06/26] Address GH comments

---
 src/expr/interpret/eval.hpp                   |    3 +-
 src/functions/CMakeLists.txt                  |    1 -
 src/functions/awesome_memgraph_functions.hpp  |  103 +-
 src/query/v2/accessors.cpp                    |   12 +-
 src/query/v2/accessors.hpp                    |   45 +-
 src/query/v2/bindings/eval.hpp                |    3 +-
 src/query/v2/shard_request_manager.hpp        |   18 +-
 .../awesome_memgraph_functions.py             |    2 +-
 tests/unit/query_v2_expression_evaluator.cpp  |  112 +-
 tests/unit/storage_v3_edge.cpp                | 4046 -----------------
 10 files changed, 76 insertions(+), 4269 deletions(-)

diff --git a/src/expr/interpret/eval.hpp b/src/expr/interpret/eval.hpp
index 8b8b5a7c7..4ad17437b 100644
--- a/src/expr/interpret/eval.hpp
+++ b/src/expr/interpret/eval.hpp
@@ -416,8 +416,7 @@ class ExpressionEvaluator : public ExpressionVisitor<TypedValue> {
             typename TReturnType = std::enable_if_t<std::is_same_v<TTag, QueryEngineTag>, bool>>
   TReturnType HasLabelImpl(const VertexAccessor &vertex, const LabelIx &label_ix, QueryEngineTag /*tag*/) {
     auto label = typename VertexAccessor::Label{LabelId::FromUint(label_ix.ix)};
-    auto has_label = vertex.HasLabel(label);
-    return has_label;
+    return vertex.HasLabel(label);
   }
 
   TypedValue Visit(LabelsTest &labels_test) override {
diff --git a/src/functions/CMakeLists.txt b/src/functions/CMakeLists.txt
index 09720c862..3a3d430cd 100644
--- a/src/functions/CMakeLists.txt
+++ b/src/functions/CMakeLists.txt
@@ -1,2 +1 @@
 add_library(mg-functions INTERFACE)
-target_include_directories(mg-functions INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})
diff --git a/src/functions/awesome_memgraph_functions.hpp b/src/functions/awesome_memgraph_functions.hpp
index 0a2b873c2..33cc954f5 100644
--- a/src/functions/awesome_memgraph_functions.hpp
+++ b/src/functions/awesome_memgraph_functions.hpp
@@ -409,21 +409,13 @@ void FType(const char *name, const TypedValueT *args, int64_t nargs, int64_t pos
 // TODO: Implement degrees, haversin, radians
 // TODO: Implement spatial functions
 
-template <typename TypedValueT, typename FunctionContextT, typename Tag>
+template <typename TypedValueT, typename FunctionContextT>
 TypedValueT EndNode(const TypedValueT *args, int64_t nargs, const FunctionContextT &ctx) {
   FType<TypedValueT, Or<Null, Edge>>("endNode", args, nargs);
-  if (args[0].IsNull()) return TypedValueT(ctx.memory);
-  if constexpr (std::is_same_v<Tag, StorageEngineTag>) {
-    const auto to = args[0].ValueEdge().To();
-    auto pk = to.primary_key;
-    auto maybe_vertex_accessor = ctx.db_accessor->FindVertex(pk, ctx.view);
-    if (!maybe_vertex_accessor) {
-      throw functions::FunctionRuntimeException("Trying to get properties from a deleted object.");
-    }
-    return TypedValueT(*maybe_vertex_accessor, ctx.memory);
-  } else {
-    return TypedValueT(args[0].ValueEdge().To(), ctx.memory);
+  if (args[0].IsNull()) {
+    return TypedValueT(ctx.memory);
   }
+  return TypedValueT(args[0].ValueEdge().To(), ctx.memory);
 }
 
 template <typename TypedValueT, typename FunctionContextT>
@@ -450,6 +442,7 @@ TypedValueT Properties(const TypedValueT *args, int64_t nargs, const FunctionCon
   auto *dba = ctx.db_accessor;
   auto get_properties = [&](const auto &record_accessor) {
     typename TypedValueT::TMap properties(ctx.memory);
+    Conv conv;
     if constexpr (std::is_same_v<Tag, StorageEngineTag>) {
       auto maybe_props = record_accessor.Properties(ctx.view);
       if (maybe_props.HasError()) {
@@ -466,11 +459,9 @@ TypedValueT Properties(const TypedValueT *args, int64_t nargs, const FunctionCon
         }
       }
       for (const auto &property : *maybe_props) {
-        Conv conv;
         properties.emplace(dba->PropertyToName(property.first), conv(property.second));
       }
     } else {
-      Conv conv;
       for (const auto &property : record_accessor.Properties()) {
         properties.emplace(utils::pmr::string(dba->PropertyToName(property.first), ctx.memory),
                            conv(property.second, dba));
@@ -510,21 +501,13 @@ TypedValueT Size(const TypedValueT *args, int64_t nargs, const FunctionContextT
   return TypedValueT(static_cast<int64_t>(value.ValuePath().edges().size()), ctx.memory);
 }
 
-template <typename TypedValueT, typename FunctionContextT, typename Tag, typename Conv>
+template <typename TypedValueT, typename FunctionContextT, typename Conv>
 TypedValueT StartNode(const TypedValueT *args, int64_t nargs, const FunctionContextT &ctx) {
   FType<TypedValueT, Or<Null, Edge>>("startNode", args, nargs);
-  if (args[0].IsNull()) return TypedValueT(ctx.memory);
-  if constexpr (std::is_same_v<Tag, StorageEngineTag>) {
-    const auto to = args[0].ValueEdge().From();
-    auto pk = to.primary_key;
-    auto maybe_vertex_accessor = ctx.db_accessor->FindVertex(pk, ctx.view);
-    if (!maybe_vertex_accessor) {
-      throw functions::FunctionRuntimeException("Trying to get properties from a deleted object.");
-    }
-    return TypedValueT(*maybe_vertex_accessor, ctx.memory);
-  } else {
-    return TypedValueT(args[0].ValueEdge().From(), ctx.memory);
+  if (args[0].IsNull()) {
+    return TypedValueT(ctx.memory);
   }
+  return TypedValueT(args[0].ValueEdge().From(), ctx.memory);
 }
 
 // This is needed because clang-tidy fails to identify the use of this function in the if-constexpr branch
@@ -702,49 +685,6 @@ TypedValueT ValueType(const TypedValueT *args, int64_t nargs, const FunctionCont
   }
 }
 
-// TODO: How is Keys different from Properties function?
-template <typename TypedValueT, typename FunctionContextT, typename Tag>
-TypedValueT Keys(const TypedValueT *args, int64_t nargs, const FunctionContextT &ctx) {
-  FType<TypedValueT, Or<Null, Vertex, Edge>>("keys", args, nargs);
-  auto *dba = ctx.db_accessor;
-  auto get_keys = [&](const auto &record_accessor) {
-    typename TypedValueT::TVector keys(ctx.memory);
-    if constexpr (std::same_as<Tag, StorageEngineTag>) {
-      auto maybe_props = record_accessor.Properties(ctx.view);
-      if (maybe_props.HasError()) {
-        switch (maybe_props.GetError()) {
-          case storage::v3::Error::DELETED_OBJECT:
-            throw functions::FunctionRuntimeException("Trying to get keys from a deleted object.");
-          case storage::v3::Error::NONEXISTENT_OBJECT:
-            throw functions::FunctionRuntimeException("Trying to get keys from an object that doesn't exist.");
-          case storage::v3::Error::SERIALIZATION_ERROR:
-          case storage::v3::Error::VERTEX_HAS_EDGES:
-          case storage::v3::Error::PROPERTIES_DISABLED:
-          case storage::v3::Error::VERTEX_ALREADY_INSERTED:
-            throw functions::FunctionRuntimeException("Unexpected error when getting keys.");
-        }
-      }
-      for (const auto &property : *maybe_props) {
-        keys.emplace_back(dba->PropertyToName(property.first));
-      }
-    } else {
-      for (const auto &property : record_accessor.Properties()) {
-        keys.emplace_back(dba->PropertyToName(property.first));
-      }
-    }
-    return TypedValueT(std::move(keys));
-  };
-
-  const auto &value = args[0];
-  if (value.IsNull()) {
-    return TypedValueT(ctx.memory);
-  }
-  if (value.IsVertex()) {
-    return get_keys(value.ValueVertex());
-  }
-  return get_keys(value.ValueEdge());
-}
-
 template <typename TypedValueT, typename FunctionContextT, typename Tag>
 TypedValueT Labels(const TypedValueT *args, int64_t nargs, const FunctionContextT &ctx) {
   FType<TypedValueT, Or<Null, Vertex>>("labels", args, nargs);
@@ -1026,12 +966,9 @@ template <typename TypedValueT, typename FunctionContextT>
 TypedValueT Id(const TypedValueT *args, int64_t nargs, const FunctionContextT &ctx) {
   FType<TypedValueT, Or<Null, Vertex, Edge>>("id", args, nargs);
   const auto &arg = args[0];
-  if (arg.IsNull()) {
+  if (arg.IsNull() || arg.IsVertex()) {
     return TypedValueT(ctx.memory);
   }
-  if (arg.IsVertex()) {
-    return TypedValueT(static_cast<int64_t>(arg.ValueVertex().CypherId()), ctx.memory);
-  }
   return TypedValueT(static_cast<int64_t>(arg.ValueEdge().CypherId()), ctx.memory);
 }
 
@@ -1382,22 +1319,24 @@ NameToFunction(const std::string &function_name) {
   if (function_name == "DEGREE") return functions::impl::Degree<TypedValueT, FunctionContextT, Tag>;
   if (function_name == "INDEGREE") return functions::impl::InDegree<TypedValueT, FunctionContextT, Tag>;
   if (function_name == "OUTDEGREE") return functions::impl::OutDegree<TypedValueT, FunctionContextT, Tag>;
-  if (function_name == "ENDNODE") return functions::impl::EndNode<TypedValueT, FunctionContextT, Tag>;
   if (function_name == "HEAD") return functions::impl::Head<TypedValueT, FunctionContextT>;
   if (function_name == kId) return functions::impl::Id<TypedValueT, FunctionContextT>;
   if (function_name == "LAST") return functions::impl::Last<TypedValueT, FunctionContextT>;
   if (function_name == "PROPERTIES") return functions::impl::Properties<TypedValueT, FunctionContextT, Tag, Conv>;
   if (function_name == "SIZE") return functions::impl::Size<TypedValueT, FunctionContextT>;
-  if (function_name == "STARTNODE") return functions::impl::StartNode<TypedValueT, FunctionContextT, Tag, Conv>;
   if (function_name == "TIMESTAMP") return functions::impl::Timestamp<TypedValueT, FunctionContextT>;
   if (function_name == "TOBOOLEAN") return functions::impl::ToBoolean<TypedValueT, FunctionContextT>;
   if (function_name == "TOFLOAT") return functions::impl::ToFloat<TypedValueT, FunctionContextT>;
   if (function_name == "TOINTEGER") return functions::impl::ToInteger<TypedValueT, FunctionContextT>;
   if (function_name == "TYPE") return functions::impl::Type<TypedValueT, FunctionContextT>;
   if (function_name == "VALUETYPE") return functions::impl::ValueType<TypedValueT, FunctionContextT>;
+  // Only on QE
+  if constexpr (std::is_same_v<Tag, QueryEngineTag>) {
+    if (function_name == "STARTNODE") return functions::impl::StartNode<TypedValueT, FunctionContextT, Conv>;
+    if (function_name == "ENDNODE") return functions::impl::EndNode<TypedValueT, FunctionContextT>;
+  }
 
   // List functions
-  if (function_name == "KEYS") return functions::impl::Keys<TypedValueT, FunctionContextT, Tag>;
   if (function_name == "LABELS") return functions::impl::Labels<TypedValueT, FunctionContextT, Tag>;
   if (function_name == "NODES") return functions::impl::Nodes<TypedValueT, FunctionContextT>;
   if (function_name == "RANGE") return functions::impl::Range<TypedValueT, FunctionContextT>;
@@ -1449,9 +1388,12 @@ NameToFunction(const std::string &function_name) {
 
   // Memgraph specific functions
   if (function_name == "ASSERT") return functions::impl::Assert<TypedValueT, FunctionContextT>;
-  if (function_name == "COUNTER") return functions::impl::Counter<TypedValueT, FunctionContextT>;
   if (function_name == "TOBYTESTRING") return functions::impl::ToByteString<TypedValueT, FunctionContextT>;
   if (function_name == "FROMBYTESTRING") return functions::impl::FromByteString<TypedValueT, FunctionContextT>;
+  // Only on QE
+  if constexpr (std::is_same_v<Tag, QueryEngineTag>) {
+    if (function_name == "COUNTER") return functions::impl::Counter<TypedValueT, FunctionContextT>;
+  }
 
   // Functions for temporal types
   if (function_name == "DATE") return functions::impl::Date<TypedValueT, FunctionContextT>;
@@ -1459,6 +1401,13 @@ NameToFunction(const std::string &function_name) {
   if (function_name == "LOCALDATETIME") return functions::impl::LocalDateTime<TypedValueT, FunctionContextT>;
   if (function_name == "DURATION") return functions::impl::Duration<TypedValueT, FunctionContextT>;
 
+  // Only on QE
+  if constexpr (std::is_same_v<Tag, QueryEngineTag>) {
+    if (function_name == "COUNTER") return functions::impl::Counter<TypedValueT, FunctionContextT>;
+    if (function_name == "STARTNODE") return functions::impl::StartNode<TypedValueT, FunctionContextT, Conv>;
+    if (function_name == "ENDNODE") return functions::impl::EndNode<TypedValueT, FunctionContextT>;
+  }
+
   return nullptr;
 }
 
diff --git a/src/query/v2/accessors.cpp b/src/query/v2/accessors.cpp
index 63915327f..6d8abeb41 100644
--- a/src/query/v2/accessors.cpp
+++ b/src/query/v2/accessors.cpp
@@ -23,10 +23,11 @@ EdgeTypeId EdgeAccessor::EdgeType() const { return edge.type.id; }
 const std::vector<std::pair<PropertyId, Value>> &EdgeAccessor::Properties() const { return edge.properties; }
 
 Value EdgeAccessor::GetProperty(const std::string &prop_name) const {
-  if (!manager_->HasProperty(prop_name)) {
+  auto maybe_prop = manager_->MaybeNameToProperty(prop_name);
+  if (!maybe_prop) {
     return {};
   }
-  auto prop_id = manager_->NameToProperty(prop_name);
+  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;
 }
@@ -35,6 +36,8 @@ const Edge &EdgeAccessor::GetEdge() const { return edge; }
 
 bool EdgeAccessor::IsCycle() const { return edge.src == edge.dst; };
 
+size_t EdgeAccessor::CypherId() const { return edge.id.gid; }
+
 VertexAccessor EdgeAccessor::To() const {
   return VertexAccessor(Vertex{edge.dst}, std::vector<std::pair<PropertyId, msgs::Value>>{}, manager_);
 }
@@ -88,10 +91,11 @@ Value VertexAccessor::GetProperty(PropertyId prop_id) const {
 
 // NOLINTNEXTLINE(readability-convert-member-functions-to-static)
 Value VertexAccessor::GetProperty(const std::string &prop_name) const {
-  if (!manager_->HasProperty(prop_name)) {
+  auto maybe_prop = manager_->MaybeNameToProperty(prop_name);
+  if (!maybe_prop) {
     return {};
   }
-  return GetProperty(manager_->NameToProperty(prop_name));
+  return GetProperty(*maybe_prop);
 }
 
 msgs::Vertex VertexAccessor::GetVertex() const { return vertex; }
diff --git a/src/query/v2/accessors.hpp b/src/query/v2/accessors.hpp
index 73cc24ba2..ba3937bb8 100644
--- a/src/query/v2/accessors.hpp
+++ b/src/query/v2/accessors.hpp
@@ -53,12 +53,7 @@ class EdgeAccessor final {
 
   [[nodiscard]] bool IsCycle() const;
 
-  // Dummy function
-  // 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]] size_t CypherId() const;
 
   [[nodiscard]] VertexAccessor To() const;
   [[nodiscard]] VertexAccessor From() const;
@@ -98,44 +93,6 @@ class VertexAccessor final {
 
   [[nodiscard]] msgs::Vertex GetVertex() const;
 
-  // Dummy function
-  // NOLINTNEXTLINE(readability-convert-member-functions-to-static)
-  [[nodiscard]] size_t CypherId() const { return 10; }
-
-  //  auto InEdges(storage::View view, const std::vector<storage::EdgeTypeId> &edge_types) const
-  //      -> storage::Result<decltype(iter::imap(MakeEdgeAccessor, *impl_.InEdges(view)))> {
-  //    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));
-  //  }
-
   // NOLINTNEXTLINE(readability-convert-member-functions-to-static)
   [[nodiscard]] size_t InDegree() const { return 0; }
 
diff --git a/src/query/v2/bindings/eval.hpp b/src/query/v2/bindings/eval.hpp
index 52455bdb2..380eb879a 100644
--- a/src/query/v2/bindings/eval.hpp
+++ b/src/query/v2/bindings/eval.hpp
@@ -25,11 +25,10 @@
 
 namespace memgraph::msgs {
 class ShardRequestManagerInterface;
-} // namespace memgraph::msgs
+}  // namespace memgraph::msgs
 
 namespace memgraph::query::v2 {
 
-inline const auto lam = [](const auto &val) { return ValueToTypedValue(val); };
 namespace detail {
 class Callable {
  public:
diff --git a/src/query/v2/shard_request_manager.hpp b/src/query/v2/shard_request_manager.hpp
index 003cafaf8..ef2d3dc43 100644
--- a/src/query/v2/shard_request_manager.hpp
+++ b/src/query/v2/shard_request_manager.hpp
@@ -129,9 +129,9 @@ class ShardRequestManagerInterface {
   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 &EdgeTypeToName(memgraph::storage::v3::EdgeTypeId type) const = 0;
-  virtual bool HasProperty(const std::string &name) const = 0;
-  virtual bool HasEdgeType(const std::string &name) const = 0;
-  virtual bool HasLabel(const std::string &name) const = 0;
+  virtual std::optional<storage::v3::PropertyId> MaybeNameToProperty(const std::string &name) const = 0;
+  virtual std::optional<storage::v3::EdgeTypeId> MaybeNameToEdge(const std::string &name) const = 0;
+  virtual std::optional<storage::v3::LabelId> MaybeNameToLabel(const std::string &name) const = 0;
   virtual bool IsPrimaryLabel(LabelId label) const = 0;
   virtual bool IsPrimaryKey(LabelId primary_label, PropertyId property) const = 0;
 };
@@ -356,11 +356,17 @@ class ShardRequestManager : public ShardRequestManagerInterface {
     return result_rows;
   }
 
-  bool HasProperty(const std::string &name) const override { return shards_map_.GetPropertyId(name).has_value(); }
+  std::optional<storage::v3::PropertyId> MaybeNameToProperty(const std::string &name) const override {
+    return shards_map_.GetPropertyId(name);
+  }
 
-  bool HasEdgeType(const std::string &name) const override { return shards_map_.GetEdgeTypeId(name).has_value(); }
+  std::optional<storage::v3::EdgeTypeId> MaybeNameToEdge(const std::string &name) const override {
+    return shards_map_.GetEdgeTypeId(name);
+  }
 
-  bool HasLabel(const std::string &name) const override { return shards_map_.GetLabelId(name).has_value(); }
+  std::optional<storage::v3::LabelId> MaybeNameToLabel(const std::string &name) const override {
+    return shards_map_.GetLabelId(name);
+  }
 
  private:
   enum class PaginatedResponseState { Pending, PartiallyFinished };
diff --git a/tests/e2e/distributed_queries/awesome_memgraph_functions.py b/tests/e2e/distributed_queries/awesome_memgraph_functions.py
index 469979733..1c4bc87a4 100644
--- a/tests/e2e/distributed_queries/awesome_memgraph_functions.py
+++ b/tests/e2e/distributed_queries/awesome_memgraph_functions.py
@@ -19,7 +19,7 @@ import pytest
 from common import *
 
 
-def test_vertex_creation_and_scanall(connection):
+def test_awesome_memgraph_functions(connection):
     wait_for_shard_manager_to_initialize()
     cursor = connection.cursor()
 
diff --git a/tests/unit/query_v2_expression_evaluator.cpp b/tests/unit/query_v2_expression_evaluator.cpp
index 97122ff0f..1c0130571 100644
--- a/tests/unit/query_v2_expression_evaluator.cpp
+++ b/tests/unit/query_v2_expression_evaluator.cpp
@@ -30,15 +30,12 @@
 #include "query/v2/frontend/ast/ast.hpp"
 #include "query/v2/requests.hpp"
 #include "query/v2/shard_request_manager.hpp"
+#include "query_v2_query_common.hpp"
 #include "storage/v3/property_value.hpp"
 #include "storage/v3/storage.hpp"
 #include "utils/exceptions.hpp"
 #include "utils/string.hpp"
 
-#include "query_v2_query_common.hpp"
-//#include "utils/temporal.hpp"
-
-using namespace memgraph::query::v2;
 using memgraph::query::v2::test_common::ToIntList;
 using testing::ElementsAre;
 using testing::UnorderedElementsAre;
@@ -67,11 +64,11 @@ using CompoundKey = memgraph::coordinator::PrimaryKey;
 using memgraph::expr::ExpressionRuntimeException;
 using memgraph::functions::FunctionRuntimeException;
 
-namespace {
+namespace memgraph::query::v2::tests {
 
 class MockedShardRequestManager : public memgraph::msgs::ShardRequestManagerInterface {
  public:
-  using VertexAccessor = memgraph::query::v2::accessors::VertexAccessor;
+  using VertexAccessor = accessors::VertexAccessor;
   explicit MockedShardRequestManager(ShardMap shard_map) : shards_map_(std::move(shard_map)) { SetUpNameIdMappers(); }
   memgraph::storage::v3::EdgeTypeId NameToEdgeType(const std::string &name) const override {
     return shards_map_.GetEdgeTypeId(name).value();
@@ -118,11 +115,17 @@ class MockedShardRequestManager : public memgraph::msgs::ShardRequestManagerInte
     return edge_types_.IdToName(id.AsUint());
   }
 
-  bool HasProperty(const std::string &name) const override { return shards_map_.GetPropertyId(name).has_value(); }
+  std::optional<storage::v3::PropertyId> MaybeNameToProperty(const std::string &name) const override {
+    return shards_map_.GetPropertyId(name);
+  }
 
-  bool HasEdgeType(const std::string &name) const override { return shards_map_.GetEdgeTypeId(name).has_value(); }
+  std::optional<storage::v3::EdgeTypeId> MaybeNameToEdge(const std::string &name) const override {
+    return shards_map_.GetEdgeTypeId(name);
+  }
 
-  bool HasLabel(const std::string &name) const override { return shards_map_.GetLabelId(name).has_value(); }
+  std::optional<storage::v3::LabelId> MaybeNameToLabel(const std::string &name) const override {
+    return shards_map_.GetLabelId(name);
+  }
 
   bool IsPrimaryLabel(LabelId label) const override { return true; }
 
@@ -211,7 +214,7 @@ class ExpressionEvaluatorTest : public ::testing::Test {
  protected:
   AstStorage storage;
   memgraph::utils::MonotonicBufferResource mem{1024};
-  EvaluationContext ctx{.memory = &mem, .timestamp = memgraph::query::v2::QueryTimestamp()};
+  EvaluationContext ctx{.memory = &mem, .timestamp = QueryTimestamp()};
   SymbolTable symbol_table;
 
   Frame frame{128};
@@ -542,20 +545,19 @@ using Value = memgraph::msgs::Value;
 using VertexId = memgraph::msgs::VertexId;
 using Label = memgraph::msgs::Label;
 
-memgraph::query::v2::accessors::VertexAccessor CreateVertex(std::vector<std::pair<PropertyId, Value>> props,
-                                                            const memgraph::msgs::ShardRequestManagerInterface *manager,
-                                                            Label label = {}) {
-  static size_t id = 0;
-  return {Vertex{VertexId{label, id++}, {label}}, std::move(props), manager};
+accessors::VertexAccessor CreateVertex(std::vector<std::pair<PropertyId, Value>> props,
+                                       const memgraph::msgs::ShardRequestManagerInterface *manager, Label label = {}) {
+  static int64_t id = 0;
+  return {Vertex{VertexId{label, {memgraph::msgs::Value(id++)}}, {label}}, std::move(props), manager};
 }
 
-memgraph::query::v2::accessors::EdgeAccessor CreateEdge(std::vector<std::pair<PropertyId, Value>> props,
-                                                        const memgraph::msgs::ShardRequestManagerInterface *manager) {
-  auto edge = Edge{.src = VertexId{{}, 0},
-                   .dst = VertexId{{}, 0},
+accessors::EdgeAccessor CreateEdge(std::vector<std::pair<PropertyId, Value>> props,
+                                   const memgraph::msgs::ShardRequestManagerInterface *manager) {
+  auto edge = Edge{.src = VertexId{{}, {}},
+                   .dst = VertexId{{}, {}},
                    .properties = std::move(props),
                    .type = EdgeType{manager->NameToEdgeType("edge_type")}};
-  return memgraph::query::v2::accessors::EdgeAccessor{std::move(edge), manager};
+  return accessors::EdgeAccessor{std::move(edge), manager};
 }
 
 TEST_F(ExpressionEvaluatorTest, VertexAndEdgeIndexing) {
@@ -575,8 +577,6 @@ TEST_F(ExpressionEvaluatorTest, VertexAndEdgeIndexing) {
     auto value2 = Eval(op2);
     EXPECT_EQ(value2.ValueInt(), 43);
   }
-  // TODO(kostasrim) Investigate
-  //  Shall we return null on missing properties? Or shall we throw bad optional access as we do now?
 
   {
     // Legal indexing, non-existing key.
@@ -1135,16 +1135,6 @@ class ExpressionEvaluatorPropertyLookup : public ExpressionEvaluatorTest {
   }
 };
 
-// TODO(kostasrim) These will fail because of memory resource not propagating correctly. This should be done as part of
-// polishing the allocators.
-// TEST_F(ExpressionEvaluatorPropertyLookup, Vertex) {
-//   auto v1 = CreateVertex({{prop_age.second, memgraph::msgs::Value(static_cast<int64_t>(32))}}, shard_manager.get());
-//   frame[symbol] = TypedValue(v1);
-//   EXPECT_EQ(Value(prop_age).ValueInt(), 10);
-//   EXPECT_TRUE(Value(prop_height).IsNull());
-// }
-//  TEST_F(ExpressionEvaluatorPropertyLookup, Edge) {}
-
 TEST_F(ExpressionEvaluatorPropertyLookup, Null) {
   frame[symbol] = TypedValue();
   EXPECT_TRUE(Value(prop_age).IsNull());
@@ -1266,17 +1256,6 @@ TEST_F(FunctionTest, Size) {
                 .ValueInt(),
             3);
   ASSERT_THROW(EvaluateFunction("SIZE", 5), FunctionRuntimeException);
-
-  // TODO(kostasrim) Add this when we enable paths on the accessors
-  //  auto v0 = dba.InsertVertex();
-  //  memgraph::query::Path path(v0);
-  //  EXPECT_EQ(EvaluateFunction("SIZE", path).ValueInt(), 0);
-  //  auto v1 = dba.InsertVertex();
-  //  auto edge = dba.InsertEdge(&v0, &v1, dba.NameToEdgeType("type"));
-  //  ASSERT_TRUE(edge.HasValue());
-  //  path.Expand(*edge);
-  //  path.Expand(v1);
-  //  EXPECT_EQ(EvaluateFunction("SIZE", path).ValueInt(), 1);
 }
 
 TEST_F(FunctionTest, StartNode) {
@@ -1290,11 +1269,6 @@ TEST_F(FunctionTest, StartNode) {
   ASSERT_THROW(EvaluateFunction("STARTNODE", 2), FunctionRuntimeException);
 }
 
-// TODO(kostasrim) Enable this test once we add degree to the accessors
-// TEST_F(FunctionTest, Degree) {}
-// TEST_F(FunctionTest, InDegree) {}
-// TEST_F(FunctionTest, OutDegree) {}
-
 TEST_F(FunctionTest, ToBoolean) {
   ASSERT_THROW(EvaluateFunction("TOBOOLEAN"), FunctionRuntimeException);
   ASSERT_TRUE(EvaluateFunction("TOBOOLEAN", TypedValue()).IsNull());
@@ -1368,9 +1342,9 @@ TEST_F(FunctionTest, Labels) {
   Label label{shard_manager->NameToLabel("label1")};
   auto v = CreateVertex({}, shard_manager.get(), std::move(label));
   std::vector<std::string> labels;
-  auto _labels = EvaluateFunction("LABELS", v).ValueList();
-  labels.reserve(_labels.size());
-  for (auto label : _labels) {
+  auto evaluated_labels = EvaluateFunction("LABELS", v).ValueList();
+  labels.reserve(evaluated_labels.size());
+  for (auto label : evaluated_labels) {
     labels.emplace_back(label.ValueString());
   }
   ASSERT_THAT(labels, UnorderedElementsAre("label1"));
@@ -1396,27 +1370,6 @@ TEST_F(FunctionTest, Range) {
   EXPECT_THAT(ToIntList(EvaluateFunction("RANGE", -2, 4, -1)), ElementsAre());
 }
 
-TEST_F(FunctionTest, Keys) {
-  ASSERT_THROW(EvaluateFunction("KEYS"), FunctionRuntimeException);
-  ASSERT_TRUE(EvaluateFunction("KEYS", TypedValue()).IsNull());
-  const auto height = shard_manager->NameToProperty("height");
-  const auto age = shard_manager->NameToProperty("age");
-  auto v1 = CreateVertex({{height, Value(static_cast<int64_t>(5))}, {age, Value(static_cast<int64_t>(10))}},
-                         shard_manager.get());
-  auto edge = CreateEdge({{height, Value(static_cast<int64_t>(3))}, {age, Value(static_cast<int64_t>(15))}},
-                         shard_manager.get());
-  auto prop_keys_to_string = [](TypedValue t) {
-    std::vector<std::string> keys;
-    for (auto property : t.ValueList()) {
-      keys.emplace_back(property.ValueString());
-    }
-    return keys;
-  };
-  ASSERT_THAT(prop_keys_to_string(EvaluateFunction("KEYS", v1)), UnorderedElementsAre("height", "age"));
-  ASSERT_THAT(prop_keys_to_string(EvaluateFunction("KEYS", edge)), UnorderedElementsAre("height", "age"));
-  ASSERT_THROW(EvaluateFunction("KEYS", 2), FunctionRuntimeException);
-}
-
 TEST_F(FunctionTest, Tail) {
   ASSERT_THROW(EvaluateFunction("TAIL"), FunctionRuntimeException);
   ASSERT_TRUE(EvaluateFunction("TAIL", TypedValue()).IsNull());
@@ -1606,18 +1559,6 @@ TEST_F(FunctionTest, Counter) {
   EXPECT_THROW(EvaluateFunction("COUNTER", "c6", 0, 0), FunctionRuntimeException);
 }
 
-// TODO(kostasrim) Add this once we fix accessors CypherId() functions
-// TEST_F(FunctionTest, Id) {
-//  auto v = CreateVertex({}, shard_manager.get());
-//  auto e = CreateEdge({}, shard_manager.get());
-//  EXPECT_TRUE(EvaluateFunction("ID", TypedValue()).IsNull());
-//  EXPECT_EQ(EvaluateFunction("ID", v).ValueInt(), 0);
-//  EXPECT_EQ(EvaluateFunction("ID", e).ValueInt(), 0);
-//  EXPECT_THROW(EvaluateFunction("ID"), FunctionRuntimeException);
-//  EXPECT_THROW(EvaluateFunction("ID", 0), FunctionRuntimeException);
-//  EXPECT_THROW(EvaluateFunction("ID", v, e), FunctionRuntimeException);
-//}
-
 TEST_F(FunctionTest, ToStringNull) { EXPECT_TRUE(EvaluateFunction("TOSTRING", TypedValue()).IsNull()); }
 
 TEST_F(FunctionTest, ToStringString) {
@@ -1782,5 +1723,4 @@ TEST_F(FunctionTest, FromByteString) {
   EXPECT_EQ(EvaluateFunction("FROMBYTESTRING", std::string("\x00\x42", 2)).ValueString(), "0x0042");
 }
 
-// TODO(kostasrim) Add temporal type tests.
-}  // namespace
+}  // namespace memgraph::query::v2::tests
diff --git a/tests/unit/storage_v3_edge.cpp b/tests/unit/storage_v3_edge.cpp
index 5c0759e98..99b981b7b 100644
--- a/tests/unit/storage_v3_edge.cpp
+++ b/tests/unit/storage_v3_edge.cpp
@@ -279,592 +279,6 @@ TEST_P(StorageEdgeTest, EdgeCreateFromSmallerCommit) {
   }
 }
 
-// // NOLINTNEXTLINE(hicpp-special-member-functions)
-// TEST_P(StorageEdgeTest, EdgeCreateFromLargerCommit) {
-//   memgraph::storage::Storage store({.items = {.properties_on_edges = GetParam()}});
-//   memgraph::storage::Gid gid_from = memgraph::storage::Gid::FromUint(std::numeric_limits<uint64_t>::max());
-//   memgraph::storage::Gid gid_to = memgraph::storage::Gid::FromUint(std::numeric_limits<uint64_t>::max());
-
-//   // Create vertices
-//   {
-//     auto acc = store.Access(GetNextHlc());
-//     auto vertex_to = acc.CreateVertex();
-//     auto vertex_from = acc.CreateVertex();
-//     gid_to = vertex_to.Gid();
-//     gid_from = vertex_from.Gid();
-//     acc.Commit(GetNextHlc());
-//   }
-
-//   // Create edge
-//   {
-//     auto acc = store.Access(GetNextHlc());
-//     auto vertex_from = acc.FindVertex(gid_from, View::NEW);
-//     auto vertex_to = acc.FindVertex(gid_to, View::NEW);
-//     ASSERT_TRUE(vertex_from);
-//     ASSERT_TRUE(vertex_to);
-
-//     auto et = acc.NameToEdgeType("et5");
-
-//     auto res = acc.CreateEdge(&from_id, &to_id, et);
-//     ASSERT_TRUE(res.HasValue());
-//     auto edge = res.GetValue();
-//     ASSERT_EQ(edge.EdgeType(), et);
-//     ASSERT_EQ(edge.From(), *vertex_from);
-//     ASSERT_EQ(edge.To(), *vertex_to);
-
-//     // Check edges without filters
-//     ASSERT_EQ(vertex_from->InEdges(View::OLD)->size(), 0);
-//     ASSERT_EQ(*vertex_from->InDegree(View::OLD), 0);
-//     ASSERT_EQ(vertex_from->InEdges(View::NEW)->size(), 0);
-//     ASSERT_EQ(*vertex_from->InDegree(View::NEW), 0);
-//     ASSERT_EQ(vertex_from->OutEdges(View::OLD)->size(), 0);
-//     ASSERT_EQ(*vertex_from->OutDegree(View::OLD), 0);
-//     {
-//       auto ret = vertex_from->OutEdges(View::NEW);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       ASSERT_EQ(edges.size(), 1);
-//       ASSERT_EQ(*vertex_from->OutDegree(View::NEW), 1);
-//       auto e = edges[0];
-//       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.From(), *vertex_from);
-//       ASSERT_EQ(e.To(), *vertex_to);
-//     }
-//     ASSERT_EQ(vertex_to->InEdges(View::OLD)->size(), 0);
-//     ASSERT_EQ(*vertex_to->InDegree(View::OLD), 0);
-//     {
-//       auto ret = vertex_to->InEdges(View::NEW);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       ASSERT_EQ(edges.size(), 1);
-//       ASSERT_EQ(*vertex_to->InDegree(View::NEW), 1);
-//       auto e = edges[0];
-//       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.From(), *vertex_from);
-//       ASSERT_EQ(e.To(), *vertex_to);
-//     }
-//     ASSERT_EQ(vertex_to->OutEdges(View::OLD)->size(), 0);
-//     ASSERT_EQ(*vertex_to->OutDegree(View::OLD), 0);
-//     ASSERT_EQ(vertex_to->OutEdges(View::NEW)->size(), 0);
-//     ASSERT_EQ(*vertex_to->OutDegree(View::NEW), 0);
-
-//     auto other_et = acc.NameToEdgeType("other");
-
-//     // Check edges with filters
-//     ASSERT_EQ(vertex_from->OutEdges(View::NEW, {other_et})->size(), 0);
-//     ASSERT_EQ(vertex_from->OutEdges(View::NEW, {et, other_et})->size(), 1);
-//     ASSERT_EQ(vertex_from->OutEdges(View::NEW, {}, &to_id)->size(), 1);
-//     ASSERT_EQ(vertex_from->OutEdges(View::NEW, {}, &from_id)->size(), 0);
-//     ASSERT_EQ(vertex_to->InEdges(View::NEW, {other_et})->size(), 0);
-//     ASSERT_EQ(vertex_to->InEdges(View::NEW, {et, other_et})->size(), 1);
-//     ASSERT_EQ(vertex_to->InEdges(View::NEW, {}, &from_id)->size(), 1);
-//     ASSERT_EQ(vertex_to->InEdges(View::NEW, {}, &to_id)->size(), 0);
-
-//     acc.Commit(GetNextHlc());
-//   }
-
-//   // Check whether the edge exists
-//   {
-//     auto acc = store.Access(GetNextHlc());
-//     auto vertex_from = acc.FindVertex(gid_from, View::NEW);
-//     auto vertex_to = acc.FindVertex(gid_to, View::NEW);
-//     ASSERT_TRUE(vertex_from);
-//     ASSERT_TRUE(vertex_to);
-
-//     auto et = acc.NameToEdgeType("et5");
-
-//     // Check edges without filters
-//     ASSERT_EQ(vertex_from->InEdges(View::OLD)->size(), 0);
-//     ASSERT_EQ(*vertex_from->InDegree(View::OLD), 0);
-//     ASSERT_EQ(vertex_from->InEdges(View::NEW)->size(), 0);
-//     ASSERT_EQ(*vertex_from->InDegree(View::NEW), 0);
-//     {
-//       auto ret = vertex_from->OutEdges(View::OLD);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       ASSERT_EQ(edges.size(), 1);
-//       ASSERT_EQ(*vertex_from->OutDegree(View::OLD), 1);
-//       auto e = edges[0];
-//       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.From(), *vertex_from);
-//       ASSERT_EQ(e.To(), *vertex_to);
-//     }
-//     {
-//       auto ret = vertex_from->OutEdges(View::NEW);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       ASSERT_EQ(edges.size(), 1);
-//       ASSERT_EQ(*vertex_from->OutDegree(View::NEW), 1);
-//       auto e = edges[0];
-//       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.From(), *vertex_from);
-//       ASSERT_EQ(e.To(), *vertex_to);
-//     }
-//     {
-//       auto ret = vertex_to->InEdges(View::OLD);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       ASSERT_EQ(edges.size(), 1);
-//       ASSERT_EQ(*vertex_to->InDegree(View::OLD), 1);
-//       auto e = edges[0];
-//       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.From(), *vertex_from);
-//       ASSERT_EQ(e.To(), *vertex_to);
-//     }
-//     {
-//       auto ret = vertex_to->InEdges(View::NEW);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       ASSERT_EQ(edges.size(), 1);
-//       ASSERT_EQ(*vertex_to->InDegree(View::NEW), 1);
-//       auto e = edges[0];
-//       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.From(), *vertex_from);
-//       ASSERT_EQ(e.To(), *vertex_to);
-//     }
-//     ASSERT_EQ(vertex_to->OutEdges(View::OLD)->size(), 0);
-//     ASSERT_EQ(*vertex_to->OutDegree(View::OLD), 0);
-//     ASSERT_EQ(vertex_to->OutEdges(View::NEW)->size(), 0);
-//     ASSERT_EQ(*vertex_to->OutDegree(View::NEW), 0);
-
-//     auto other_et = acc.NameToEdgeType("other");
-
-//     // Check edges with filters
-//     ASSERT_EQ(vertex_from->OutEdges(View::OLD, {other_et})->size(), 0);
-//     ASSERT_EQ(vertex_from->OutEdges(View::NEW, {other_et})->size(), 0);
-//     ASSERT_EQ(vertex_from->OutEdges(View::OLD, {et, other_et})->size(), 1);
-//     ASSERT_EQ(vertex_from->OutEdges(View::NEW, {et, other_et})->size(), 1);
-//     ASSERT_EQ(vertex_from->OutEdges(View::OLD, {}, &to_id)->size(), 1);
-//     ASSERT_EQ(vertex_from->OutEdges(View::NEW, {}, &to_id)->size(), 1);
-//     ASSERT_EQ(vertex_from->OutEdges(View::OLD, {}, &from_id)->size(), 0);
-//     ASSERT_EQ(vertex_from->OutEdges(View::NEW, {}, &from_id)->size(), 0);
-//     ASSERT_EQ(vertex_to->InEdges(View::OLD, {other_et})->size(), 0);
-//     ASSERT_EQ(vertex_to->InEdges(View::NEW, {other_et})->size(), 0);
-//     ASSERT_EQ(vertex_to->InEdges(View::OLD, {et, other_et})->size(), 1);
-//     ASSERT_EQ(vertex_to->InEdges(View::NEW, {et, other_et})->size(), 1);
-//     ASSERT_EQ(vertex_to->InEdges(View::OLD, {}, &from_id)->size(), 1);
-//     ASSERT_EQ(vertex_to->InEdges(View::NEW, {}, &from_id)->size(), 1);
-//     ASSERT_EQ(vertex_to->InEdges(View::OLD, {}, &to_id)->size(), 0);
-//     ASSERT_EQ(vertex_to->InEdges(View::NEW, {}, &to_id)->size(), 0);
-
-//     acc.Commit(GetNextHlc());
-//   }
-// }
-
-// // NOLINTNEXTLINE(hicpp-special-member-functions)
-// TEST_P(StorageEdgeTest, EdgeCreateFromSameCommit) {
-//   memgraph::storage::Storage store({.items = {.properties_on_edges = GetParam()}});
-//   memgraph::storage::Gid gid_vertex = memgraph::storage::Gid::FromUint(std::numeric_limits<uint64_t>::max());
-
-//   // Create vertex
-//   {
-//     auto acc = store.Access(GetNextHlc());
-//     auto vertex = acc.CreateVertex();
-//     gid_vertex = vertex.Gid();
-//     acc.Commit(GetNextHlc());
-//   }
-
-//   // Create edge
-//   {
-//     auto acc = store.Access(GetNextHlc());
-//     auto vertex = acc.FindVertex(gid_vertex, View::NEW);
-//     ASSERT_TRUE(vertex);
-
-//     auto et = acc.NameToEdgeType("et5");
-
-//     auto res = acc.CreateEdge(&*vertex, &*vertex, et);
-//     ASSERT_TRUE(res.HasValue());
-//     auto edge = res.GetValue();
-//     ASSERT_EQ(edge.EdgeType(), et);
-//     ASSERT_EQ(edge.From(), *vertex);
-//     ASSERT_EQ(edge.To(), *vertex);
-
-//     // Check edges without filters
-//     ASSERT_EQ(vertex->InEdges(View::OLD)->size(), 0);
-//     ASSERT_EQ(*vertex->InDegree(View::OLD), 0);
-//     {
-//       auto ret = vertex->InEdges(View::NEW);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       ASSERT_EQ(edges.size(), 1);
-//       ASSERT_EQ(*vertex->InDegree(View::NEW), 1);
-//       auto e = edges[0];
-//       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.From(), *vertex);
-//       ASSERT_EQ(e.To(), *vertex);
-//     }
-//     ASSERT_EQ(vertex->OutEdges(View::OLD)->size(), 0);
-//     ASSERT_EQ(*vertex->OutDegree(View::OLD), 0);
-//     {
-//       auto ret = vertex->OutEdges(View::NEW);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       ASSERT_EQ(edges.size(), 1);
-//       ASSERT_EQ(*vertex->OutDegree(View::NEW), 1);
-//       auto e = edges[0];
-//       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.From(), *vertex);
-//       ASSERT_EQ(e.To(), *vertex);
-//     }
-
-//     auto other_et = acc.NameToEdgeType("other");
-
-//     // Check edges with filters
-//     ASSERT_EQ(vertex->OutEdges(View::NEW, {other_et})->size(), 0);
-//     ASSERT_EQ(vertex->OutEdges(View::NEW, {et, other_et})->size(), 1);
-//     ASSERT_EQ(vertex->OutEdges(View::NEW, {}, &*vertex)->size(), 1);
-//     ASSERT_EQ(vertex->OutEdges(View::NEW, {other_et}, &*vertex)->size(), 0);
-//     ASSERT_EQ(vertex->InEdges(View::NEW, {other_et})->size(), 0);
-//     ASSERT_EQ(vertex->InEdges(View::NEW, {et, other_et})->size(), 1);
-//     ASSERT_EQ(vertex->InEdges(View::NEW, {}, &*vertex)->size(), 1);
-//     ASSERT_EQ(vertex->InEdges(View::NEW, {other_et}, &*vertex)->size(), 0);
-
-//     acc.Commit(GetNextHlc());
-//   }
-
-//   // Check whether the edge exists
-//   {
-//     auto acc = store.Access(GetNextHlc());
-//     auto vertex = acc.FindVertex(gid_vertex, View::NEW);
-//     ASSERT_TRUE(vertex);
-
-//     auto et = acc.NameToEdgeType("et5");
-
-//     // Check edges without filters
-//     {
-//       auto ret = vertex->InEdges(View::OLD);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       ASSERT_EQ(edges.size(), 1);
-//       ASSERT_EQ(*vertex->InDegree(View::OLD), 1);
-//       auto e = edges[0];
-//       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.From(), *vertex);
-//       ASSERT_EQ(e.To(), *vertex);
-//     }
-//     {
-//       auto ret = vertex->InEdges(View::NEW);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       ASSERT_EQ(edges.size(), 1);
-//       ASSERT_EQ(*vertex->InDegree(View::NEW), 1);
-//       auto e = edges[0];
-//       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.From(), *vertex);
-//       ASSERT_EQ(e.To(), *vertex);
-//     }
-//     {
-//       auto ret = vertex->OutEdges(View::OLD);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       ASSERT_EQ(edges.size(), 1);
-//       ASSERT_EQ(*vertex->OutDegree(View::OLD), 1);
-//       auto e = edges[0];
-//       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.From(), *vertex);
-//       ASSERT_EQ(e.To(), *vertex);
-//     }
-//     {
-//       auto ret = vertex->OutEdges(View::NEW);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       ASSERT_EQ(edges.size(), 1);
-//       ASSERT_EQ(*vertex->OutDegree(View::NEW), 1);
-//       auto e = edges[0];
-//       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.From(), *vertex);
-//       ASSERT_EQ(e.To(), *vertex);
-//     }
-
-//     auto other_et = acc.NameToEdgeType("other");
-
-//     // Check edges with filters
-//     ASSERT_EQ(vertex->InEdges(View::OLD, {other_et})->size(), 0);
-//     ASSERT_EQ(vertex->InEdges(View::NEW, {other_et})->size(), 0);
-//     ASSERT_EQ(vertex->InEdges(View::OLD, {et, other_et})->size(), 1);
-//     ASSERT_EQ(vertex->InEdges(View::NEW, {et, other_et})->size(), 1);
-//     ASSERT_EQ(vertex->InEdges(View::NEW, {}, &*vertex)->size(), 1);
-//     ASSERT_EQ(vertex->InEdges(View::NEW, {other_et}, &*vertex)->size(), 0);
-//     ASSERT_EQ(vertex->OutEdges(View::OLD, {other_et})->size(), 0);
-//     ASSERT_EQ(vertex->OutEdges(View::NEW, {other_et})->size(), 0);
-//     ASSERT_EQ(vertex->OutEdges(View::OLD, {et, other_et})->size(), 1);
-//     ASSERT_EQ(vertex->OutEdges(View::NEW, {et, other_et})->size(), 1);
-//     ASSERT_EQ(vertex->OutEdges(View::NEW, {}, &*vertex)->size(), 1);
-//     ASSERT_EQ(vertex->OutEdges(View::NEW, {other_et}, &*vertex)->size(), 0);
-
-//     acc.Commit(GetNextHlc());
-//   }
-// }
-
-// // NOLINTNEXTLINE(hicpp-special-member-functions)
-// TEST_P(StorageEdgeTest, EdgeCreateFromSmallerAbort) {
-//   memgraph::storage::Storage store({.items = {.properties_on_edges = GetParam()}});
-//   memgraph::storage::Gid gid_from = memgraph::storage::Gid::FromUint(std::numeric_limits<uint64_t>::max());
-//   memgraph::storage::Gid gid_to = memgraph::storage::Gid::FromUint(std::numeric_limits<uint64_t>::max());
-
-//   // Create vertices
-//   {
-//     auto acc = store.Access(GetNextHlc());
-//     auto vertex_from = acc.CreateVertex();
-//     auto vertex_to = acc.CreateVertex();
-//     gid_from = vertex_from.Gid();
-//     gid_to = vertex_to.Gid();
-//     acc.Commit(GetNextHlc());
-//   }
-
-//   // Create edge, but abort the transaction
-//   {
-//     auto acc = store.Access(GetNextHlc());
-//     auto vertex_from = acc.FindVertex(gid_from, View::NEW);
-//     auto vertex_to = acc.FindVertex(gid_to, View::NEW);
-//     ASSERT_TRUE(vertex_from);
-//     ASSERT_TRUE(vertex_to);
-
-//     auto et = acc.NameToEdgeType("et5");
-
-//     auto res = acc.CreateEdge(&from_id, &to_id, et);
-//     ASSERT_TRUE(res.HasValue());
-//     auto edge = res.GetValue();
-//     ASSERT_EQ(edge.EdgeType(), et);
-//     ASSERT_EQ(edge.From(), *vertex_from);
-//     ASSERT_EQ(edge.To(), *vertex_to);
-
-//     // Check edges without filters
-//     ASSERT_EQ(vertex_from->InEdges(View::OLD)->size(), 0);
-//     ASSERT_EQ(*vertex_from->InDegree(View::OLD), 0);
-//     ASSERT_EQ(vertex_from->InEdges(View::NEW)->size(), 0);
-//     ASSERT_EQ(*vertex_from->InDegree(View::NEW), 0);
-//     ASSERT_EQ(vertex_from->OutEdges(View::OLD)->size(), 0);
-//     ASSERT_EQ(*vertex_from->OutDegree(View::OLD), 0);
-//     {
-//       auto ret = vertex_from->OutEdges(View::NEW);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       ASSERT_EQ(edges.size(), 1);
-//       ASSERT_EQ(*vertex_from->OutDegree(View::NEW), 1);
-//       auto e = edges[0];
-//       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.From(), *vertex_from);
-//       ASSERT_EQ(e.To(), *vertex_to);
-//     }
-//     ASSERT_EQ(vertex_to->InEdges(View::OLD)->size(), 0);
-//     ASSERT_EQ(*vertex_to->InDegree(View::OLD), 0);
-//     {
-//       auto ret = vertex_to->InEdges(View::NEW);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       ASSERT_EQ(edges.size(), 1);
-//       ASSERT_EQ(*vertex_to->InDegree(View::NEW), 1);
-//       auto e = edges[0];
-//       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.From(), *vertex_from);
-//       ASSERT_EQ(e.To(), *vertex_to);
-//     }
-//     ASSERT_EQ(vertex_to->OutEdges(View::OLD)->size(), 0);
-//     ASSERT_EQ(*vertex_to->OutDegree(View::OLD), 0);
-//     ASSERT_EQ(vertex_to->OutEdges(View::NEW)->size(), 0);
-//     ASSERT_EQ(*vertex_to->OutDegree(View::NEW), 0);
-
-//     auto other_et = acc.NameToEdgeType("other");
-
-//     // Check edges with filters
-//     ASSERT_EQ(vertex_from->OutEdges(View::NEW, {other_et})->size(), 0);
-//     ASSERT_EQ(vertex_from->OutEdges(View::NEW, {et, other_et})->size(), 1);
-//     ASSERT_EQ(vertex_from->OutEdges(View::NEW, {}, &to_id)->size(), 1);
-//     ASSERT_EQ(vertex_from->OutEdges(View::NEW, {}, &from_id)->size(), 0);
-//     ASSERT_EQ(vertex_to->InEdges(View::NEW, {other_et})->size(), 0);
-//     ASSERT_EQ(vertex_to->InEdges(View::NEW, {et, other_et})->size(), 1);
-//     ASSERT_EQ(vertex_to->InEdges(View::NEW, {}, &from_id)->size(), 1);
-//     ASSERT_EQ(vertex_to->InEdges(View::NEW, {}, &to_id)->size(), 0);
-
-//     acc.Abort();
-//   }
-
-//   // Check whether the edge exists
-//   {
-//     auto acc = store.Access(GetNextHlc());
-//     auto vertex_from = acc.FindVertex(gid_from, View::NEW);
-//     auto vertex_to = acc.FindVertex(gid_to, View::NEW);
-//     ASSERT_TRUE(vertex_from);
-//     ASSERT_TRUE(vertex_to);
-
-//     // Check edges without filters
-//     ASSERT_EQ(vertex_from->InEdges(View::OLD)->size(), 0);
-//     ASSERT_EQ(*vertex_from->InDegree(View::OLD), 0);
-//     ASSERT_EQ(vertex_from->InEdges(View::NEW)->size(), 0);
-//     ASSERT_EQ(*vertex_from->InDegree(View::NEW), 0);
-//     ASSERT_EQ(vertex_from->OutEdges(View::OLD)->size(), 0);
-//     ASSERT_EQ(*vertex_from->OutDegree(View::OLD), 0);
-//     ASSERT_EQ(vertex_from->OutEdges(View::NEW)->size(), 0);
-//     ASSERT_EQ(*vertex_from->OutDegree(View::NEW), 0);
-//     ASSERT_EQ(vertex_to->InEdges(View::OLD)->size(), 0);
-//     ASSERT_EQ(*vertex_to->InDegree(View::OLD), 0);
-//     ASSERT_EQ(vertex_to->InEdges(View::NEW)->size(), 0);
-//     ASSERT_EQ(*vertex_to->InDegree(View::NEW), 0);
-//     ASSERT_EQ(vertex_to->OutEdges(View::OLD)->size(), 0);
-//     ASSERT_EQ(*vertex_to->OutDegree(View::OLD), 0);
-//     ASSERT_EQ(vertex_to->OutEdges(View::NEW)->size(), 0);
-//     ASSERT_EQ(*vertex_to->OutDegree(View::NEW), 0);
-
-//     acc.Commit(GetNextHlc());
-//   }
-
-//   // Create edge
-//   {
-//     auto acc = store.Access(GetNextHlc());
-//     auto vertex_from = acc.FindVertex(gid_from, View::NEW);
-//     auto vertex_to = acc.FindVertex(gid_to, View::NEW);
-//     ASSERT_TRUE(vertex_from);
-//     ASSERT_TRUE(vertex_to);
-
-//     auto et = acc.NameToEdgeType("et5");
-
-//     auto res = acc.CreateEdge(&from_id, &to_id, et);
-//     ASSERT_TRUE(res.HasValue());
-//     auto edge = res.GetValue();
-//     ASSERT_EQ(edge.EdgeType(), et);
-//     ASSERT_EQ(edge.From(), *vertex_from);
-//     ASSERT_EQ(edge.To(), *vertex_to);
-
-//     // Check edges without filters
-//     ASSERT_EQ(vertex_from->InEdges(View::OLD)->size(), 0);
-//     ASSERT_EQ(*vertex_from->InDegree(View::OLD), 0);
-//     ASSERT_EQ(vertex_from->InEdges(View::NEW)->size(), 0);
-//     ASSERT_EQ(*vertex_from->InDegree(View::NEW), 0);
-//     ASSERT_EQ(vertex_from->OutEdges(View::OLD)->size(), 0);
-//     ASSERT_EQ(*vertex_from->OutDegree(View::OLD), 0);
-//     {
-//       auto ret = vertex_from->OutEdges(View::NEW);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       ASSERT_EQ(edges.size(), 1);
-//       ASSERT_EQ(*vertex_from->OutDegree(View::NEW), 1);
-//       auto e = edges[0];
-//       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.From(), *vertex_from);
-//       ASSERT_EQ(e.To(), *vertex_to);
-//     }
-//     ASSERT_EQ(vertex_to->InEdges(View::OLD)->size(), 0);
-//     ASSERT_EQ(*vertex_to->InDegree(View::OLD), 0);
-//     {
-//       auto ret = vertex_to->InEdges(View::NEW);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       ASSERT_EQ(edges.size(), 1);
-//       ASSERT_EQ(*vertex_to->InDegree(View::NEW), 1);
-//       auto e = edges[0];
-//       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.From(), *vertex_from);
-//       ASSERT_EQ(e.To(), *vertex_to);
-//     }
-//     ASSERT_EQ(vertex_to->OutEdges(View::OLD)->size(), 0);
-//     ASSERT_EQ(*vertex_to->OutDegree(View::OLD), 0);
-//     ASSERT_EQ(vertex_to->OutEdges(View::NEW)->size(), 0);
-//     ASSERT_EQ(*vertex_to->OutDegree(View::NEW), 0);
-
-//     auto other_et = acc.NameToEdgeType("other");
-
-//     // Check edges with filters
-//     ASSERT_EQ(vertex_from->OutEdges(View::NEW, {other_et})->size(), 0);
-//     ASSERT_EQ(vertex_from->OutEdges(View::NEW, {et, other_et})->size(), 1);
-//     ASSERT_EQ(vertex_from->OutEdges(View::NEW, {}, &to_id)->size(), 1);
-//     ASSERT_EQ(vertex_from->OutEdges(View::NEW, {}, &from_id)->size(), 0);
-//     ASSERT_EQ(vertex_to->InEdges(View::NEW, {other_et})->size(), 0);
-//     ASSERT_EQ(vertex_to->InEdges(View::NEW, {et, other_et})->size(), 1);
-//     ASSERT_EQ(vertex_to->InEdges(View::NEW, {}, &from_id)->size(), 1);
-//     ASSERT_EQ(vertex_to->InEdges(View::NEW, {}, &to_id)->size(), 0);
-
-//     acc.Commit(GetNextHlc());
-//   }
-
-//   // Check whether the edge exists
-//   {
-//     auto acc = store.Access(GetNextHlc());
-//     auto vertex_from = acc.FindVertex(gid_from, View::NEW);
-//     auto vertex_to = acc.FindVertex(gid_to, View::NEW);
-//     ASSERT_TRUE(vertex_from);
-//     ASSERT_TRUE(vertex_to);
-
-//     auto et = acc.NameToEdgeType("et5");
-
-//     // Check edges without filters
-//     ASSERT_EQ(vertex_from->InEdges(View::OLD)->size(), 0);
-//     ASSERT_EQ(*vertex_from->InDegree(View::OLD), 0);
-//     ASSERT_EQ(vertex_from->InEdges(View::NEW)->size(), 0);
-//     ASSERT_EQ(*vertex_from->InDegree(View::NEW), 0);
-//     {
-//       auto ret = vertex_from->OutEdges(View::OLD);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       ASSERT_EQ(edges.size(), 1);
-//       ASSERT_EQ(*vertex_from->OutDegree(View::OLD), 1);
-//       auto e = edges[0];
-//       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.From(), *vertex_from);
-//       ASSERT_EQ(e.To(), *vertex_to);
-//     }
-//     {
-//       auto ret = vertex_from->OutEdges(View::NEW);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       ASSERT_EQ(edges.size(), 1);
-//       ASSERT_EQ(*vertex_from->OutDegree(View::NEW), 1);
-//       auto e = edges[0];
-//       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.From(), *vertex_from);
-//       ASSERT_EQ(e.To(), *vertex_to);
-//     }
-//     {
-//       auto ret = vertex_to->InEdges(View::OLD);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       ASSERT_EQ(edges.size(), 1);
-//       ASSERT_EQ(*vertex_to->InDegree(View::OLD), 1);
-//       auto e = edges[0];
-//       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.From(), *vertex_from);
-//       ASSERT_EQ(e.To(), *vertex_to);
-//     }
-//     {
-//       auto ret = vertex_to->InEdges(View::NEW);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       ASSERT_EQ(edges.size(), 1);
-//       ASSERT_EQ(*vertex_to->InDegree(View::NEW), 1);
-//       auto e = edges[0];
-//       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.From(), *vertex_from);
-//       ASSERT_EQ(e.To(), *vertex_to);
-//     }
-//     ASSERT_EQ(vertex_to->OutEdges(View::OLD)->size(), 0);
-//     ASSERT_EQ(*vertex_to->OutDegree(View::OLD), 0);
-//     ASSERT_EQ(vertex_to->OutEdges(View::NEW)->size(), 0);
-//     ASSERT_EQ(*vertex_to->OutDegree(View::NEW), 0);
-
-//     auto other_et = acc.NameToEdgeType("other");
-
-//     // Check edges with filters
-//     ASSERT_EQ(vertex_from->OutEdges(View::OLD, {other_et})->size(), 0);
-//     ASSERT_EQ(vertex_from->OutEdges(View::NEW, {other_et})->size(), 0);
-//     ASSERT_EQ(vertex_from->OutEdges(View::OLD, {et, other_et})->size(), 1);
-//     ASSERT_EQ(vertex_from->OutEdges(View::NEW, {et, other_et})->size(), 1);
-//     ASSERT_EQ(vertex_from->OutEdges(View::OLD, {}, &to_id)->size(), 1);
-//     ASSERT_EQ(vertex_from->OutEdges(View::NEW, {}, &to_id)->size(), 1);
-//     ASSERT_EQ(vertex_from->OutEdges(View::OLD, {}, &from_id)->size(), 0);
-//     ASSERT_EQ(vertex_from->OutEdges(View::NEW, {}, &from_id)->size(), 0);
-//     ASSERT_EQ(vertex_to->InEdges(View::OLD, {other_et})->size(), 0);
-//     ASSERT_EQ(vertex_to->InEdges(View::NEW, {other_et})->size(), 0);
-//     ASSERT_EQ(vertex_to->InEdges(View::OLD, {et, other_et})->size(), 1);
-//     ASSERT_EQ(vertex_to->InEdges(View::NEW, {et, other_et})->size(), 1);
-//     ASSERT_EQ(vertex_to->InEdges(View::OLD, {}, &from_id)->size(), 1);
-//     ASSERT_EQ(vertex_to->InEdges(View::NEW, {}, &from_id)->size(), 1);
-//     ASSERT_EQ(vertex_to->InEdges(View::OLD, {}, &to_id)->size(), 0);
-//     ASSERT_EQ(vertex_to->InEdges(View::NEW, {}, &to_id)->size(), 0);
-
-//     acc.Commit(GetNextHlc());
-//   }
-// }
-
 // NOLINTNEXTLINE(hicpp-special-member-functions)
 TEST_P(StorageEdgeTest, EdgeCreateFromLargerAbort) {
   // Create vertices
@@ -1174,232 +588,6 @@ TEST_P(StorageEdgeTest, EdgeCreateFromLargerAbort) {
   }
 }
 
-// // NOLINTNEXTLINE(hicpp-special-member-functions)
-// TEST_P(StorageEdgeTest, EdgeCreateFromSameAbort) {
-//   memgraph::storage::Storage store({.items = {.properties_on_edges = GetParam()}});
-//   memgraph::storage::Gid gid_vertex = memgraph::storage::Gid::FromUint(std::numeric_limits<uint64_t>::max());
-
-//   // Create vertex
-//   {
-//     auto acc = store.Access(GetNextHlc());
-//     auto vertex = acc.CreateVertex();
-//     gid_vertex = vertex.Gid();
-//     acc.Commit(GetNextHlc());
-//   }
-
-//   // Create edge, but abort the transaction
-//   {
-//     auto acc = store.Access(GetNextHlc());
-//     auto vertex = acc.FindVertex(gid_vertex, View::NEW);
-//     ASSERT_TRUE(vertex);
-
-//     auto et = acc.NameToEdgeType("et5");
-
-//     auto res = acc.CreateEdge(&*vertex, &*vertex, et);
-//     ASSERT_TRUE(res.HasValue());
-//     auto edge = res.GetValue();
-//     ASSERT_EQ(edge.EdgeType(), et);
-//     ASSERT_EQ(edge.From(), *vertex);
-//     ASSERT_EQ(edge.To(), *vertex);
-
-//     // Check edges without filters
-//     ASSERT_EQ(vertex->InEdges(View::OLD)->size(), 0);
-//     ASSERT_EQ(*vertex->InDegree(View::OLD), 0);
-//     {
-//       auto ret = vertex->InEdges(View::NEW);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       ASSERT_EQ(edges.size(), 1);
-//       ASSERT_EQ(*vertex->InDegree(View::NEW), 1);
-//       auto e = edges[0];
-//       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.From(), *vertex);
-//       ASSERT_EQ(e.To(), *vertex);
-//     }
-//     ASSERT_EQ(vertex->OutEdges(View::OLD)->size(), 0);
-//     ASSERT_EQ(*vertex->OutDegree(View::OLD), 0);
-//     {
-//       auto ret = vertex->OutEdges(View::NEW);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       ASSERT_EQ(edges.size(), 1);
-//       ASSERT_EQ(*vertex->OutDegree(View::NEW), 1);
-//       auto e = edges[0];
-//       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.From(), *vertex);
-//       ASSERT_EQ(e.To(), *vertex);
-//     }
-
-//     auto other_et = acc.NameToEdgeType("other");
-
-//     // Check edges with filters
-//     ASSERT_EQ(vertex->OutEdges(View::NEW, {other_et})->size(), 0);
-//     ASSERT_EQ(vertex->OutEdges(View::NEW, {et, other_et})->size(), 1);
-//     ASSERT_EQ(vertex->OutEdges(View::NEW, {}, &*vertex)->size(), 1);
-//     ASSERT_EQ(vertex->OutEdges(View::NEW, {other_et}, &*vertex)->size(), 0);
-//     ASSERT_EQ(vertex->InEdges(View::NEW, {other_et})->size(), 0);
-//     ASSERT_EQ(vertex->InEdges(View::NEW, {et, other_et})->size(), 1);
-//     ASSERT_EQ(vertex->InEdges(View::NEW, {}, &*vertex)->size(), 1);
-//     ASSERT_EQ(vertex->InEdges(View::NEW, {other_et}, &*vertex)->size(), 0);
-
-//     acc.Abort();
-//   }
-
-//   // Check whether the edge exists
-//   {
-//     auto acc = store.Access(GetNextHlc());
-//     auto vertex = acc.FindVertex(gid_vertex, View::NEW);
-//     ASSERT_TRUE(vertex);
-
-//     // Check edges without filters
-//     ASSERT_EQ(vertex->InEdges(View::OLD)->size(), 0);
-//     ASSERT_EQ(*vertex->InDegree(View::OLD), 0);
-//     ASSERT_EQ(vertex->InEdges(View::NEW)->size(), 0);
-//     ASSERT_EQ(*vertex->InDegree(View::NEW), 0);
-//     ASSERT_EQ(vertex->OutEdges(View::OLD)->size(), 0);
-//     ASSERT_EQ(*vertex->OutDegree(View::OLD), 0);
-//     ASSERT_EQ(vertex->OutEdges(View::NEW)->size(), 0);
-//     ASSERT_EQ(*vertex->OutDegree(View::NEW), 0);
-
-//     acc.Commit(GetNextHlc());
-//   }
-
-//   // Create edge
-//   {
-//     auto acc = store.Access(GetNextHlc());
-//     auto vertex = acc.FindVertex(gid_vertex, View::NEW);
-//     ASSERT_TRUE(vertex);
-
-//     auto et = acc.NameToEdgeType("et5");
-
-//     auto res = acc.CreateEdge(&*vertex, &*vertex, et);
-//     ASSERT_TRUE(res.HasValue());
-//     auto edge = res.GetValue();
-//     ASSERT_EQ(edge.EdgeType(), et);
-//     ASSERT_EQ(edge.From(), *vertex);
-//     ASSERT_EQ(edge.To(), *vertex);
-
-//     // Check edges without filters
-//     ASSERT_EQ(vertex->InEdges(View::OLD)->size(), 0);
-//     ASSERT_EQ(*vertex->InDegree(View::OLD), 0);
-//     {
-//       auto ret = vertex->InEdges(View::NEW);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       ASSERT_EQ(edges.size(), 1);
-//       ASSERT_EQ(*vertex->InDegree(View::NEW), 1);
-//       auto e = edges[0];
-//       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.From(), *vertex);
-//       ASSERT_EQ(e.To(), *vertex);
-//     }
-//     ASSERT_EQ(vertex->OutEdges(View::OLD)->size(), 0);
-//     ASSERT_EQ(*vertex->OutDegree(View::OLD), 0);
-//     {
-//       auto ret = vertex->OutEdges(View::NEW);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       ASSERT_EQ(edges.size(), 1);
-//       ASSERT_EQ(*vertex->OutDegree(View::NEW), 1);
-//       auto e = edges[0];
-//       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.From(), *vertex);
-//       ASSERT_EQ(e.To(), *vertex);
-//     }
-
-//     auto other_et = acc.NameToEdgeType("other");
-
-//     // Check edges with filters
-//     ASSERT_EQ(vertex->OutEdges(View::NEW, {other_et})->size(), 0);
-//     ASSERT_EQ(vertex->OutEdges(View::NEW, {et, other_et})->size(), 1);
-//     ASSERT_EQ(vertex->OutEdges(View::NEW, {}, &*vertex)->size(), 1);
-//     ASSERT_EQ(vertex->OutEdges(View::NEW, {other_et}, &*vertex)->size(), 0);
-//     ASSERT_EQ(vertex->InEdges(View::NEW, {other_et})->size(), 0);
-//     ASSERT_EQ(vertex->InEdges(View::NEW, {et, other_et})->size(), 1);
-//     ASSERT_EQ(vertex->InEdges(View::NEW, {}, &*vertex)->size(), 1);
-//     ASSERT_EQ(vertex->InEdges(View::NEW, {other_et}, &*vertex)->size(), 0);
-
-//     acc.Commit(GetNextHlc());
-//   }
-
-//   // Check whether the edge exists
-//   {
-//     auto acc = store.Access(GetNextHlc());
-//     auto vertex = acc.FindVertex(gid_vertex, View::NEW);
-//     ASSERT_TRUE(vertex);
-
-//     auto et = acc.NameToEdgeType("et5");
-
-//     // Check edges without filters
-//     {
-//       auto ret = vertex->InEdges(View::OLD);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       ASSERT_EQ(edges.size(), 1);
-//       ASSERT_EQ(*vertex->InDegree(View::OLD), 1);
-//       auto e = edges[0];
-//       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.From(), *vertex);
-//       ASSERT_EQ(e.To(), *vertex);
-//     }
-//     {
-//       auto ret = vertex->InEdges(View::NEW);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       ASSERT_EQ(edges.size(), 1);
-//       ASSERT_EQ(*vertex->InDegree(View::NEW), 1);
-//       auto e = edges[0];
-//       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.From(), *vertex);
-//       ASSERT_EQ(e.To(), *vertex);
-//     }
-//     {
-//       auto ret = vertex->OutEdges(View::OLD);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       ASSERT_EQ(edges.size(), 1);
-//       ASSERT_EQ(*vertex->OutDegree(View::OLD), 1);
-//       auto e = edges[0];
-//       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.From(), *vertex);
-//       ASSERT_EQ(e.To(), *vertex);
-//     }
-//     {
-//       auto ret = vertex->OutEdges(View::NEW);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       ASSERT_EQ(edges.size(), 1);
-//       ASSERT_EQ(*vertex->OutDegree(View::NEW), 1);
-//       auto e = edges[0];
-//       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.From(), *vertex);
-//       ASSERT_EQ(e.To(), *vertex);
-//     }
-
-//     auto other_et = acc.NameToEdgeType("other");
-
-//     // Check edges with filters
-//     ASSERT_EQ(vertex->InEdges(View::OLD, {other_et})->size(), 0);
-//     ASSERT_EQ(vertex->InEdges(View::NEW, {other_et})->size(), 0);
-//     ASSERT_EQ(vertex->InEdges(View::OLD, {et, other_et})->size(), 1);
-//     ASSERT_EQ(vertex->InEdges(View::NEW, {et, other_et})->size(), 1);
-//     ASSERT_EQ(vertex->InEdges(View::OLD, {}, &*vertex)->size(), 1);
-//     ASSERT_EQ(vertex->InEdges(View::NEW, {}, &*vertex)->size(), 1);
-//     ASSERT_EQ(vertex->InEdges(View::OLD, {other_et}, &*vertex)->size(), 0);
-//     ASSERT_EQ(vertex->InEdges(View::NEW, {other_et}, &*vertex)->size(), 0);
-//     ASSERT_EQ(vertex->OutEdges(View::OLD, {other_et})->size(), 0);
-//     ASSERT_EQ(vertex->OutEdges(View::NEW, {other_et})->size(), 0);
-//     ASSERT_EQ(vertex->OutEdges(View::OLD, {et, other_et})->size(), 1);
-//     ASSERT_EQ(vertex->OutEdges(View::NEW, {et, other_et})->size(), 1);
-//     ASSERT_EQ(vertex->OutEdges(View::OLD, {}, &*vertex)->size(), 1);
-//     ASSERT_EQ(vertex->OutEdges(View::NEW, {}, &*vertex)->size(), 1);
-//     ASSERT_EQ(vertex->OutEdges(View::OLD, {other_et}, &*vertex)->size(), 0);
-//     ASSERT_EQ(vertex->OutEdges(View::NEW, {other_et}, &*vertex)->size(), 0);
-
-//     acc.Commit(GetNextHlc());
-//   }
-// }
-
 // NOLINTNEXTLINE(hicpp-special-member-functions)
 TEST_P(StorageEdgeTest, EdgeDeleteFromSmallerCommit) {
   // Create vertex
@@ -1590,921 +778,6 @@ TEST_P(StorageEdgeTest, EdgeDeleteFromSmallerCommit) {
   }
 }
 
-// // NOLINTNEXTLINE(hicpp-special-member-functions)
-// TEST_P(StorageEdgeTest, EdgeDeleteFromLargerCommit) {
-//   memgraph::storage::Storage store({.items = {.properties_on_edges = GetParam()}});
-//   memgraph::storage::Gid gid_from = memgraph::storage::Gid::FromUint(std::numeric_limits<uint64_t>::max());
-//   memgraph::storage::Gid gid_to = memgraph::storage::Gid::FromUint(std::numeric_limits<uint64_t>::max());
-
-//   // Create vertices
-//   {
-//     auto acc = store.Access(GetNextHlc());
-//     auto vertex_to = acc.CreateVertex();
-//     auto vertex_from = acc.CreateVertex();
-//     gid_from = vertex_from.Gid();
-//     gid_to = vertex_to.Gid();
-//     acc.Commit(GetNextHlc());
-//   }
-
-//   // Create edge
-//   {
-//     auto acc = store.Access(GetNextHlc());
-//     auto vertex_from = acc.FindVertex(gid_from, View::NEW);
-//     auto vertex_to = acc.FindVertex(gid_to, View::NEW);
-//     ASSERT_TRUE(vertex_from);
-//     ASSERT_TRUE(vertex_to);
-
-//     auto et = acc.NameToEdgeType("et5");
-
-//     auto res = acc.CreateEdge(&from_id, &to_id, et);
-//     ASSERT_TRUE(res.HasValue());
-//     auto edge = res.GetValue();
-//     ASSERT_EQ(edge.EdgeType(), et);
-//     ASSERT_EQ(edge.From(), *vertex_from);
-//     ASSERT_EQ(edge.To(), *vertex_to);
-
-//     // Check edges without filters
-//     ASSERT_EQ(vertex_from->InEdges(View::OLD)->size(), 0);
-//     ASSERT_EQ(*vertex_from->InDegree(View::OLD), 0);
-//     ASSERT_EQ(vertex_from->InEdges(View::NEW)->size(), 0);
-//     ASSERT_EQ(*vertex_from->InDegree(View::NEW), 0);
-//     ASSERT_EQ(vertex_from->OutEdges(View::OLD)->size(), 0);
-//     ASSERT_EQ(*vertex_from->OutDegree(View::OLD), 0);
-//     {
-//       auto ret = vertex_from->OutEdges(View::NEW);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       ASSERT_EQ(edges.size(), 1);
-//       ASSERT_EQ(*vertex_from->OutDegree(View::NEW), 1);
-//       auto e = edges[0];
-//       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.From(), *vertex_from);
-//       ASSERT_EQ(e.To(), *vertex_to);
-//     }
-//     ASSERT_EQ(vertex_to->InEdges(View::OLD)->size(), 0);
-//     ASSERT_EQ(*vertex_to->InDegree(View::OLD), 0);
-//     {
-//       auto ret = vertex_to->InEdges(View::NEW);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       ASSERT_EQ(edges.size(), 1);
-//       ASSERT_EQ(*vertex_to->InDegree(View::NEW), 1);
-//       auto e = edges[0];
-//       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.From(), *vertex_from);
-//       ASSERT_EQ(e.To(), *vertex_to);
-//     }
-//     ASSERT_EQ(vertex_to->OutEdges(View::OLD)->size(), 0);
-//     ASSERT_EQ(*vertex_to->OutDegree(View::OLD), 0);
-//     ASSERT_EQ(vertex_to->OutEdges(View::NEW)->size(), 0);
-//     ASSERT_EQ(*vertex_to->OutDegree(View::NEW), 0);
-
-//     auto other_et = acc.NameToEdgeType("other");
-
-//     // Check edges with filters
-//     ASSERT_EQ(vertex_from->OutEdges(View::NEW, {other_et})->size(), 0);
-//     ASSERT_EQ(vertex_from->OutEdges(View::NEW, {et, other_et})->size(), 1);
-//     ASSERT_EQ(vertex_from->OutEdges(View::NEW, {}, &to_id)->size(), 1);
-//     ASSERT_EQ(vertex_from->OutEdges(View::NEW, {}, &from_id)->size(), 0);
-//     ASSERT_EQ(vertex_to->InEdges(View::NEW, {other_et})->size(), 0);
-//     ASSERT_EQ(vertex_to->InEdges(View::NEW, {et, other_et})->size(), 1);
-//     ASSERT_EQ(vertex_to->InEdges(View::NEW, {}, &from_id)->size(), 1);
-//     ASSERT_EQ(vertex_to->InEdges(View::NEW, {}, &to_id)->size(), 0);
-
-//     acc.Commit(GetNextHlc());
-//   }
-
-//   // Check whether the edge exists
-//   {
-//     auto acc = store.Access(GetNextHlc());
-//     auto vertex_from = acc.FindVertex(gid_from, View::NEW);
-//     auto vertex_to = acc.FindVertex(gid_to, View::NEW);
-//     ASSERT_TRUE(vertex_from);
-//     ASSERT_TRUE(vertex_to);
-
-//     auto et = acc.NameToEdgeType("et5");
-
-//     // Check edges without filters
-//     ASSERT_EQ(vertex_from->InEdges(View::OLD)->size(), 0);
-//     ASSERT_EQ(*vertex_from->InDegree(View::OLD), 0);
-//     ASSERT_EQ(vertex_from->InEdges(View::NEW)->size(), 0);
-//     ASSERT_EQ(*vertex_from->InDegree(View::NEW), 0);
-//     {
-//       auto ret = vertex_from->OutEdges(View::OLD);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       ASSERT_EQ(edges.size(), 1);
-//       ASSERT_EQ(*vertex_from->OutDegree(View::OLD), 1);
-//       auto e = edges[0];
-//       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.From(), *vertex_from);
-//       ASSERT_EQ(e.To(), *vertex_to);
-//     }
-//     {
-//       auto ret = vertex_from->OutEdges(View::NEW);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       ASSERT_EQ(edges.size(), 1);
-//       ASSERT_EQ(*vertex_from->OutDegree(View::NEW), 1);
-//       auto e = edges[0];
-//       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.From(), *vertex_from);
-//       ASSERT_EQ(e.To(), *vertex_to);
-//     }
-//     {
-//       auto ret = vertex_to->InEdges(View::OLD);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       ASSERT_EQ(edges.size(), 1);
-//       ASSERT_EQ(*vertex_to->InDegree(View::OLD), 1);
-//       auto e = edges[0];
-//       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.From(), *vertex_from);
-//       ASSERT_EQ(e.To(), *vertex_to);
-//     }
-//     {
-//       auto ret = vertex_to->InEdges(View::NEW);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       ASSERT_EQ(edges.size(), 1);
-//       ASSERT_EQ(*vertex_to->InDegree(View::NEW), 1);
-//       auto e = edges[0];
-//       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.From(), *vertex_from);
-//       ASSERT_EQ(e.To(), *vertex_to);
-//     }
-//     ASSERT_EQ(vertex_to->OutEdges(View::OLD)->size(), 0);
-//     ASSERT_EQ(*vertex_to->OutDegree(View::OLD), 0);
-//     ASSERT_EQ(vertex_to->OutEdges(View::NEW)->size(), 0);
-//     ASSERT_EQ(*vertex_to->OutDegree(View::NEW), 0);
-
-//     auto other_et = acc.NameToEdgeType("other");
-
-//     // Check edges with filters
-//     ASSERT_EQ(vertex_from->OutEdges(View::OLD, {other_et})->size(), 0);
-//     ASSERT_EQ(vertex_from->OutEdges(View::NEW, {other_et})->size(), 0);
-//     ASSERT_EQ(vertex_from->OutEdges(View::OLD, {et, other_et})->size(), 1);
-//     ASSERT_EQ(vertex_from->OutEdges(View::NEW, {et, other_et})->size(), 1);
-//     ASSERT_EQ(vertex_from->OutEdges(View::OLD, {}, &to_id)->size(), 1);
-//     ASSERT_EQ(vertex_from->OutEdges(View::NEW, {}, &to_id)->size(), 1);
-//     ASSERT_EQ(vertex_from->OutEdges(View::OLD, {}, &from_id)->size(), 0);
-//     ASSERT_EQ(vertex_from->OutEdges(View::NEW, {}, &from_id)->size(), 0);
-//     ASSERT_EQ(vertex_to->InEdges(View::OLD, {other_et})->size(), 0);
-//     ASSERT_EQ(vertex_to->InEdges(View::NEW, {other_et})->size(), 0);
-//     ASSERT_EQ(vertex_to->InEdges(View::OLD, {et, other_et})->size(), 1);
-//     ASSERT_EQ(vertex_to->InEdges(View::NEW, {et, other_et})->size(), 1);
-//     ASSERT_EQ(vertex_to->InEdges(View::OLD, {}, &from_id)->size(), 1);
-//     ASSERT_EQ(vertex_to->InEdges(View::NEW, {}, &from_id)->size(), 1);
-//     ASSERT_EQ(vertex_to->InEdges(View::OLD, {}, &to_id)->size(), 0);
-//     ASSERT_EQ(vertex_to->InEdges(View::NEW, {}, &to_id)->size(), 0);
-
-//     acc.Commit(GetNextHlc());
-//   }
-
-//   // Delete edge
-//   {
-//     auto acc = store.Access(GetNextHlc());
-//     auto vertex_from = acc.FindVertex(gid_from, View::NEW);
-//     auto vertex_to = acc.FindVertex(gid_to, View::NEW);
-//     ASSERT_TRUE(vertex_from);
-//     ASSERT_TRUE(vertex_to);
-
-//     auto et = acc.NameToEdgeType("et5");
-
-//     auto edge = vertex_from->OutEdges(View::NEW).GetValue()[0];
-
-//     auto res = acc.DeleteEdge(&edge);
-//     ASSERT_TRUE(res.HasValue());
-//     ASSERT_TRUE(res.GetValue());
-
-//     // Check edges without filters
-//     ASSERT_EQ(vertex_from->InEdges(View::OLD)->size(), 0);
-//     ASSERT_EQ(*vertex_from->InDegree(View::OLD), 0);
-//     ASSERT_EQ(vertex_from->InEdges(View::NEW)->size(), 0);
-//     ASSERT_EQ(*vertex_from->InDegree(View::NEW), 0);
-//     {
-//       auto ret = vertex_from->OutEdges(View::OLD);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       ASSERT_EQ(edges.size(), 1);
-//       ASSERT_EQ(*vertex_from->OutDegree(View::OLD), 1);
-//       auto e = edges[0];
-//       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.From(), *vertex_from);
-//       ASSERT_EQ(e.To(), *vertex_to);
-//     }
-//     ASSERT_EQ(vertex_from->OutEdges(View::NEW)->size(), 0);
-//     ASSERT_EQ(*vertex_from->OutDegree(View::NEW), 0);
-//     {
-//       auto ret = vertex_to->InEdges(View::OLD);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       ASSERT_EQ(edges.size(), 1);
-//       ASSERT_EQ(*vertex_to->InDegree(View::OLD), 1);
-//       auto e = edges[0];
-//       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.From(), *vertex_from);
-//       ASSERT_EQ(e.To(), *vertex_to);
-//     }
-//     ASSERT_EQ(vertex_to->InEdges(View::NEW)->size(), 0);
-//     ASSERT_EQ(*vertex_to->InDegree(View::NEW), 0);
-//     ASSERT_EQ(vertex_to->OutEdges(View::OLD)->size(), 0);
-//     ASSERT_EQ(*vertex_to->OutDegree(View::OLD), 0);
-//     ASSERT_EQ(vertex_to->OutEdges(View::NEW)->size(), 0);
-//     ASSERT_EQ(*vertex_to->OutDegree(View::NEW), 0);
-
-//     auto other_et = acc.NameToEdgeType("other");
-
-//     // Check edges with filters
-//     ASSERT_EQ(vertex_from->OutEdges(View::OLD, {other_et})->size(), 0);
-//     ASSERT_EQ(vertex_from->OutEdges(View::OLD, {et, other_et})->size(), 1);
-//     ASSERT_EQ(vertex_from->OutEdges(View::OLD, {}, &to_id)->size(), 1);
-//     ASSERT_EQ(vertex_from->OutEdges(View::OLD, {}, &from_id)->size(), 0);
-//     ASSERT_EQ(vertex_to->InEdges(View::OLD, {other_et})->size(), 0);
-//     ASSERT_EQ(vertex_to->InEdges(View::OLD, {et, other_et})->size(), 1);
-//     ASSERT_EQ(vertex_to->InEdges(View::OLD, {}, &from_id)->size(), 1);
-//     ASSERT_EQ(vertex_to->InEdges(View::OLD, {}, &to_id)->size(), 0);
-
-//     acc.Commit(GetNextHlc());
-//   }
-
-//   // Check whether the edge exists
-//   {
-//     auto acc = store.Access(GetNextHlc());
-//     auto vertex_from = acc.FindVertex(gid_from, View::NEW);
-//     auto vertex_to = acc.FindVertex(gid_to, View::NEW);
-//     ASSERT_TRUE(vertex_from);
-//     ASSERT_TRUE(vertex_to);
-
-//     // Check edges without filters
-//     ASSERT_EQ(vertex_from->InEdges(View::OLD)->size(), 0);
-//     ASSERT_EQ(*vertex_from->InDegree(View::OLD), 0);
-//     ASSERT_EQ(vertex_from->InEdges(View::NEW)->size(), 0);
-//     ASSERT_EQ(*vertex_from->InDegree(View::NEW), 0);
-//     ASSERT_EQ(vertex_from->OutEdges(View::OLD)->size(), 0);
-//     ASSERT_EQ(*vertex_from->OutDegree(View::OLD), 0);
-//     ASSERT_EQ(vertex_from->OutEdges(View::NEW)->size(), 0);
-//     ASSERT_EQ(*vertex_from->OutDegree(View::NEW), 0);
-//     ASSERT_EQ(vertex_to->InEdges(View::OLD)->size(), 0);
-//     ASSERT_EQ(*vertex_to->InDegree(View::OLD), 0);
-//     ASSERT_EQ(vertex_to->InEdges(View::NEW)->size(), 0);
-//     ASSERT_EQ(*vertex_to->InDegree(View::NEW), 0);
-//     ASSERT_EQ(vertex_to->OutEdges(View::OLD)->size(), 0);
-//     ASSERT_EQ(*vertex_to->OutDegree(View::OLD), 0);
-//     ASSERT_EQ(vertex_to->OutEdges(View::NEW)->size(), 0);
-//     ASSERT_EQ(*vertex_to->OutDegree(View::NEW), 0);
-
-//     acc.Commit(GetNextHlc());
-//   }
-// }
-
-// // NOLINTNEXTLINE(hicpp-special-member-functions)
-// TEST_P(StorageEdgeTest, EdgeDeleteFromSameCommit) {
-//   memgraph::storage::Storage store({.items = {.properties_on_edges = GetParam()}});
-//   memgraph::storage::Gid gid_vertex = memgraph::storage::Gid::FromUint(std::numeric_limits<uint64_t>::max());
-
-//   // Create vertex
-//   {
-//     auto acc = store.Access(GetNextHlc());
-//     auto vertex = acc.CreateVertex();
-//     gid_vertex = vertex.Gid();
-//     acc.Commit(GetNextHlc());
-//   }
-
-//   // Create edge
-//   {
-//     auto acc = store.Access(GetNextHlc());
-//     auto vertex = acc.FindVertex(gid_vertex, View::NEW);
-//     ASSERT_TRUE(vertex);
-
-//     auto et = acc.NameToEdgeType("et5");
-
-//     auto res = acc.CreateEdge(&*vertex, &*vertex, et);
-//     ASSERT_TRUE(res.HasValue());
-//     auto edge = res.GetValue();
-//     ASSERT_EQ(edge.EdgeType(), et);
-//     ASSERT_EQ(edge.From(), *vertex);
-//     ASSERT_EQ(edge.To(), *vertex);
-
-//     // Check edges without filters
-//     ASSERT_EQ(vertex->InEdges(View::OLD)->size(), 0);
-//     ASSERT_EQ(*vertex->InDegree(View::OLD), 0);
-//     {
-//       auto ret = vertex->InEdges(View::NEW);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       ASSERT_EQ(edges.size(), 1);
-//       ASSERT_EQ(*vertex->InDegree(View::NEW), 1);
-//       auto e = edges[0];
-//       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.From(), *vertex);
-//       ASSERT_EQ(e.To(), *vertex);
-//     }
-//     ASSERT_EQ(vertex->OutEdges(View::OLD)->size(), 0);
-//     ASSERT_EQ(*vertex->OutDegree(View::OLD), 0);
-//     {
-//       auto ret = vertex->OutEdges(View::NEW);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       ASSERT_EQ(edges.size(), 1);
-//       ASSERT_EQ(*vertex->OutDegree(View::NEW), 1);
-//       auto e = edges[0];
-//       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.From(), *vertex);
-//       ASSERT_EQ(e.To(), *vertex);
-//     }
-
-//     auto other_et = acc.NameToEdgeType("other");
-
-//     // Check edges with filters
-//     ASSERT_EQ(vertex->OutEdges(View::NEW, {other_et})->size(), 0);
-//     ASSERT_EQ(vertex->OutEdges(View::NEW, {et, other_et})->size(), 1);
-//     ASSERT_EQ(vertex->OutEdges(View::NEW, {}, &*vertex)->size(), 1);
-//     ASSERT_EQ(vertex->OutEdges(View::NEW, {other_et}, &*vertex)->size(), 0);
-//     ASSERT_EQ(vertex->InEdges(View::NEW, {other_et})->size(), 0);
-//     ASSERT_EQ(vertex->InEdges(View::NEW, {et, other_et})->size(), 1);
-//     ASSERT_EQ(vertex->InEdges(View::NEW, {}, &*vertex)->size(), 1);
-//     ASSERT_EQ(vertex->InEdges(View::NEW, {other_et}, &*vertex)->size(), 0);
-
-//     acc.Commit(GetNextHlc());
-//   }
-
-//   // Check whether the edge exists
-//   {
-//     auto acc = store.Access(GetNextHlc());
-//     auto vertex = acc.FindVertex(gid_vertex, View::NEW);
-//     ASSERT_TRUE(vertex);
-
-//     auto et = acc.NameToEdgeType("et5");
-
-//     // Check edges without filters
-//     {
-//       auto ret = vertex->InEdges(View::OLD);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       ASSERT_EQ(edges.size(), 1);
-//       ASSERT_EQ(*vertex->InDegree(View::OLD), 1);
-//       auto e = edges[0];
-//       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.From(), *vertex);
-//       ASSERT_EQ(e.To(), *vertex);
-//     }
-//     {
-//       auto ret = vertex->InEdges(View::NEW);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       ASSERT_EQ(edges.size(), 1);
-//       ASSERT_EQ(*vertex->InDegree(View::NEW), 1);
-//       auto e = edges[0];
-//       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.From(), *vertex);
-//       ASSERT_EQ(e.To(), *vertex);
-//     }
-//     {
-//       auto ret = vertex->OutEdges(View::OLD);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       ASSERT_EQ(edges.size(), 1);
-//       ASSERT_EQ(*vertex->OutDegree(View::OLD), 1);
-//       auto e = edges[0];
-//       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.From(), *vertex);
-//       ASSERT_EQ(e.To(), *vertex);
-//     }
-//     {
-//       auto ret = vertex->OutEdges(View::NEW);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       ASSERT_EQ(edges.size(), 1);
-//       ASSERT_EQ(*vertex->OutDegree(View::NEW), 1);
-//       auto e = edges[0];
-//       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.From(), *vertex);
-//       ASSERT_EQ(e.To(), *vertex);
-//     }
-
-//     auto other_et = acc.NameToEdgeType("other");
-
-//     // Check edges with filters
-//     ASSERT_EQ(vertex->InEdges(View::OLD, {other_et})->size(), 0);
-//     ASSERT_EQ(vertex->InEdges(View::NEW, {other_et})->size(), 0);
-//     ASSERT_EQ(vertex->InEdges(View::OLD, {et, other_et})->size(), 1);
-//     ASSERT_EQ(vertex->InEdges(View::NEW, {et, other_et})->size(), 1);
-//     ASSERT_EQ(vertex->InEdges(View::OLD, {}, &*vertex)->size(), 1);
-//     ASSERT_EQ(vertex->InEdges(View::NEW, {}, &*vertex)->size(), 1);
-//     ASSERT_EQ(vertex->InEdges(View::OLD, {other_et}, &*vertex)->size(), 0);
-//     ASSERT_EQ(vertex->InEdges(View::NEW, {other_et}, &*vertex)->size(), 0);
-//     ASSERT_EQ(vertex->OutEdges(View::OLD, {other_et})->size(), 0);
-//     ASSERT_EQ(vertex->OutEdges(View::NEW, {other_et})->size(), 0);
-//     ASSERT_EQ(vertex->OutEdges(View::OLD, {et, other_et})->size(), 1);
-//     ASSERT_EQ(vertex->OutEdges(View::NEW, {et, other_et})->size(), 1);
-//     ASSERT_EQ(vertex->OutEdges(View::OLD, {}, &*vertex)->size(), 1);
-//     ASSERT_EQ(vertex->OutEdges(View::NEW, {}, &*vertex)->size(), 1);
-//     ASSERT_EQ(vertex->OutEdges(View::OLD, {other_et}, &*vertex)->size(), 0);
-//     ASSERT_EQ(vertex->OutEdges(View::NEW, {other_et}, &*vertex)->size(), 0);
-
-//     acc.Commit(GetNextHlc());
-//   }
-
-//   // Delete edge
-//   {
-//     auto acc = store.Access(GetNextHlc());
-//     auto vertex = acc.FindVertex(gid_vertex, View::NEW);
-//     ASSERT_TRUE(vertex);
-
-//     auto et = acc.NameToEdgeType("et5");
-
-//     auto edge = vertex->OutEdges(View::NEW).GetValue()[0];
-
-//     auto res = acc.DeleteEdge(&edge);
-//     ASSERT_TRUE(res.HasValue());
-//     ASSERT_TRUE(res.GetValue());
-
-//     // Check edges without filters
-//     {
-//       auto ret = vertex->InEdges(View::OLD);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       ASSERT_EQ(edges.size(), 1);
-//       ASSERT_EQ(*vertex->InDegree(View::OLD), 1);
-//       auto e = edges[0];
-//       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.From(), *vertex);
-//       ASSERT_EQ(e.To(), *vertex);
-//     }
-//     ASSERT_EQ(vertex->InEdges(View::NEW)->size(), 0);
-//     ASSERT_EQ(*vertex->InDegree(View::NEW), 0);
-//     {
-//       auto ret = vertex->OutEdges(View::OLD);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       ASSERT_EQ(edges.size(), 1);
-//       ASSERT_EQ(*vertex->OutDegree(View::OLD), 1);
-//       auto e = edges[0];
-//       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.From(), *vertex);
-//       ASSERT_EQ(e.To(), *vertex);
-//     }
-//     ASSERT_EQ(vertex->OutEdges(View::NEW)->size(), 0);
-//     ASSERT_EQ(*vertex->OutDegree(View::NEW), 0);
-
-//     auto other_et = acc.NameToEdgeType("other");
-
-//     // Check edges with filters
-//     ASSERT_EQ(vertex->InEdges(View::OLD, {other_et})->size(), 0);
-//     ASSERT_EQ(vertex->InEdges(View::OLD, {et, other_et})->size(), 1);
-//     ASSERT_EQ(vertex->InEdges(View::OLD, {}, &*vertex)->size(), 1);
-//     ASSERT_EQ(vertex->InEdges(View::OLD, {other_et}, &*vertex)->size(), 0);
-//     ASSERT_EQ(vertex->OutEdges(View::OLD, {other_et})->size(), 0);
-//     ASSERT_EQ(vertex->OutEdges(View::OLD, {et, other_et})->size(), 1);
-//     ASSERT_EQ(vertex->OutEdges(View::OLD, {}, &*vertex)->size(), 1);
-//     ASSERT_EQ(vertex->OutEdges(View::OLD, {other_et}, &*vertex)->size(), 0);
-
-//     acc.Commit(GetNextHlc());
-//   }
-
-//   // Check whether the edge exists
-//   {
-//     auto acc = store.Access(GetNextHlc());
-//     auto vertex = acc.FindVertex(gid_vertex, View::NEW);
-//     ASSERT_TRUE(vertex);
-
-//     // Check edges without filters
-//     ASSERT_EQ(vertex->InEdges(View::OLD)->size(), 0);
-//     ASSERT_EQ(*vertex->InDegree(View::OLD), 0);
-//     ASSERT_EQ(vertex->InEdges(View::NEW)->size(), 0);
-//     ASSERT_EQ(*vertex->InDegree(View::NEW), 0);
-//     ASSERT_EQ(vertex->OutEdges(View::OLD)->size(), 0);
-//     ASSERT_EQ(*vertex->OutDegree(View::OLD), 0);
-//     ASSERT_EQ(vertex->OutEdges(View::NEW)->size(), 0);
-//     ASSERT_EQ(*vertex->OutDegree(View::NEW), 0);
-
-//     acc.Commit(GetNextHlc());
-//   }
-// }
-
-// // NOLINTNEXTLINE(hicpp-special-member-functions)
-// TEST_P(StorageEdgeTest, EdgeDeleteFromSmallerAbort) {
-//   memgraph::storage::Storage store({.items = {.properties_on_edges = GetParam()}});
-//   memgraph::storage::Gid gid_from = memgraph::storage::Gid::FromUint(std::numeric_limits<uint64_t>::max());
-//   memgraph::storage::Gid gid_to = memgraph::storage::Gid::FromUint(std::numeric_limits<uint64_t>::max());
-
-//   // Create vertices
-//   {
-//     auto acc = store.Access(GetNextHlc());
-//     auto vertex_from = acc.CreateVertex();
-//     auto vertex_to = acc.CreateVertex();
-//     gid_from = vertex_from.Gid();
-//     gid_to = vertex_to.Gid();
-//     acc.Commit(GetNextHlc());
-//   }
-
-//   // Create edge
-//   {
-//     auto acc = store.Access(GetNextHlc());
-//     auto vertex_from = acc.FindVertex(gid_from, View::NEW);
-//     auto vertex_to = acc.FindVertex(gid_to, View::NEW);
-//     ASSERT_TRUE(vertex_from);
-//     ASSERT_TRUE(vertex_to);
-
-//     auto et = acc.NameToEdgeType("et5");
-
-//     auto res = acc.CreateEdge(&from_id, &to_id, et);
-//     ASSERT_TRUE(res.HasValue());
-//     auto edge = res.GetValue();
-//     ASSERT_EQ(edge.EdgeType(), et);
-//     ASSERT_EQ(edge.From(), *vertex_from);
-//     ASSERT_EQ(edge.To(), *vertex_to);
-
-//     // Check edges without filters
-//     ASSERT_EQ(vertex_from->InEdges(View::OLD)->size(), 0);
-//     ASSERT_EQ(*vertex_from->InDegree(View::OLD), 0);
-//     ASSERT_EQ(vertex_from->InEdges(View::NEW)->size(), 0);
-//     ASSERT_EQ(*vertex_from->InDegree(View::NEW), 0);
-//     ASSERT_EQ(vertex_from->OutEdges(View::OLD)->size(), 0);
-//     ASSERT_EQ(*vertex_from->OutDegree(View::OLD), 0);
-//     {
-//       auto ret = vertex_from->OutEdges(View::NEW);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       ASSERT_EQ(edges.size(), 1);
-//       ASSERT_EQ(*vertex_from->OutDegree(View::NEW), 1);
-//       auto e = edges[0];
-//       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.From(), *vertex_from);
-//       ASSERT_EQ(e.To(), *vertex_to);
-//     }
-//     ASSERT_EQ(vertex_to->InEdges(View::OLD)->size(), 0);
-//     ASSERT_EQ(*vertex_to->InDegree(View::OLD), 0);
-//     {
-//       auto ret = vertex_to->InEdges(View::NEW);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       ASSERT_EQ(edges.size(), 1);
-//       ASSERT_EQ(*vertex_to->InDegree(View::NEW), 1);
-//       auto e = edges[0];
-//       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.From(), *vertex_from);
-//       ASSERT_EQ(e.To(), *vertex_to);
-//     }
-//     ASSERT_EQ(vertex_to->OutEdges(View::OLD)->size(), 0);
-//     ASSERT_EQ(*vertex_to->OutDegree(View::OLD), 0);
-//     ASSERT_EQ(vertex_to->OutEdges(View::NEW)->size(), 0);
-//     ASSERT_EQ(*vertex_to->OutDegree(View::NEW), 0);
-
-//     auto other_et = acc.NameToEdgeType("other");
-
-//     // Check edges with filters
-//     ASSERT_EQ(vertex_from->OutEdges(View::NEW, {other_et})->size(), 0);
-//     ASSERT_EQ(vertex_from->OutEdges(View::NEW, {et, other_et})->size(), 1);
-//     ASSERT_EQ(vertex_from->OutEdges(View::NEW, {}, &to_id)->size(), 1);
-//     ASSERT_EQ(vertex_from->OutEdges(View::NEW, {}, &from_id)->size(), 0);
-//     ASSERT_EQ(vertex_to->InEdges(View::NEW, {other_et})->size(), 0);
-//     ASSERT_EQ(vertex_to->InEdges(View::NEW, {et, other_et})->size(), 1);
-//     ASSERT_EQ(vertex_to->InEdges(View::NEW, {}, &from_id)->size(), 1);
-//     ASSERT_EQ(vertex_to->InEdges(View::NEW, {}, &to_id)->size(), 0);
-
-//     acc.Commit(GetNextHlc());
-//   }
-
-//   // Check whether the edge exists
-//   {
-//     auto acc = store.Access(GetNextHlc());
-//     auto vertex_from = acc.FindVertex(gid_from, View::NEW);
-//     auto vertex_to = acc.FindVertex(gid_to, View::NEW);
-//     ASSERT_TRUE(vertex_from);
-//     ASSERT_TRUE(vertex_to);
-
-//     auto et = acc.NameToEdgeType("et5");
-
-//     // Check edges without filters
-//     ASSERT_EQ(vertex_from->InEdges(View::OLD)->size(), 0);
-//     ASSERT_EQ(*vertex_from->InDegree(View::OLD), 0);
-//     ASSERT_EQ(vertex_from->InEdges(View::NEW)->size(), 0);
-//     ASSERT_EQ(*vertex_from->InDegree(View::NEW), 0);
-//     {
-//       auto ret = vertex_from->OutEdges(View::OLD);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       ASSERT_EQ(edges.size(), 1);
-//       ASSERT_EQ(*vertex_from->OutDegree(View::OLD), 1);
-//       auto e = edges[0];
-//       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.From(), *vertex_from);
-//       ASSERT_EQ(e.To(), *vertex_to);
-//     }
-//     {
-//       auto ret = vertex_from->OutEdges(View::NEW);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       ASSERT_EQ(edges.size(), 1);
-//       ASSERT_EQ(*vertex_from->OutDegree(View::NEW), 1);
-//       auto e = edges[0];
-//       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.From(), *vertex_from);
-//       ASSERT_EQ(e.To(), *vertex_to);
-//     }
-//     {
-//       auto ret = vertex_to->InEdges(View::OLD);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       ASSERT_EQ(edges.size(), 1);
-//       ASSERT_EQ(*vertex_to->InDegree(View::OLD), 1);
-//       auto e = edges[0];
-//       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.From(), *vertex_from);
-//       ASSERT_EQ(e.To(), *vertex_to);
-//     }
-//     {
-//       auto ret = vertex_to->InEdges(View::NEW);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       ASSERT_EQ(edges.size(), 1);
-//       ASSERT_EQ(*vertex_to->InDegree(View::NEW), 1);
-//       auto e = edges[0];
-//       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.From(), *vertex_from);
-//       ASSERT_EQ(e.To(), *vertex_to);
-//     }
-//     ASSERT_EQ(vertex_to->OutEdges(View::OLD)->size(), 0);
-//     ASSERT_EQ(*vertex_to->OutDegree(View::OLD), 0);
-//     ASSERT_EQ(vertex_to->OutEdges(View::NEW)->size(), 0);
-//     ASSERT_EQ(*vertex_to->OutDegree(View::NEW), 0);
-
-//     auto other_et = acc.NameToEdgeType("other");
-
-//     // Check edges with filters
-//     ASSERT_EQ(vertex_from->OutEdges(View::OLD, {other_et})->size(), 0);
-//     ASSERT_EQ(vertex_from->OutEdges(View::NEW, {other_et})->size(), 0);
-//     ASSERT_EQ(vertex_from->OutEdges(View::OLD, {et, other_et})->size(), 1);
-//     ASSERT_EQ(vertex_from->OutEdges(View::NEW, {et, other_et})->size(), 1);
-//     ASSERT_EQ(vertex_from->OutEdges(View::OLD, {}, &to_id)->size(), 1);
-//     ASSERT_EQ(vertex_from->OutEdges(View::NEW, {}, &to_id)->size(), 1);
-//     ASSERT_EQ(vertex_from->OutEdges(View::OLD, {}, &from_id)->size(), 0);
-//     ASSERT_EQ(vertex_from->OutEdges(View::NEW, {}, &from_id)->size(), 0);
-//     ASSERT_EQ(vertex_to->InEdges(View::OLD, {other_et})->size(), 0);
-//     ASSERT_EQ(vertex_to->InEdges(View::NEW, {other_et})->size(), 0);
-//     ASSERT_EQ(vertex_to->InEdges(View::OLD, {et, other_et})->size(), 1);
-//     ASSERT_EQ(vertex_to->InEdges(View::NEW, {et, other_et})->size(), 1);
-//     ASSERT_EQ(vertex_to->InEdges(View::OLD, {}, &from_id)->size(), 1);
-//     ASSERT_EQ(vertex_to->InEdges(View::NEW, {}, &from_id)->size(), 1);
-//     ASSERT_EQ(vertex_to->InEdges(View::OLD, {}, &to_id)->size(), 0);
-//     ASSERT_EQ(vertex_to->InEdges(View::NEW, {}, &to_id)->size(), 0);
-
-//     acc.Commit(GetNextHlc());
-//   }
-
-//   // Delete the edge, but abort the transaction
-//   {
-//     auto acc = store.Access(GetNextHlc());
-//     auto vertex_from = acc.FindVertex(gid_from, View::NEW);
-//     auto vertex_to = acc.FindVertex(gid_to, View::NEW);
-//     ASSERT_TRUE(vertex_from);
-//     ASSERT_TRUE(vertex_to);
-
-//     auto et = acc.NameToEdgeType("et5");
-
-//     auto edge = vertex_from->OutEdges(View::NEW).GetValue()[0];
-
-//     auto res = acc.DeleteEdge(&edge);
-//     ASSERT_TRUE(res.HasValue());
-//     ASSERT_TRUE(res.GetValue());
-
-//     // Check edges without filters
-//     ASSERT_EQ(vertex_from->InEdges(View::OLD)->size(), 0);
-//     ASSERT_EQ(*vertex_from->InDegree(View::OLD), 0);
-//     ASSERT_EQ(vertex_from->InEdges(View::NEW)->size(), 0);
-//     ASSERT_EQ(*vertex_from->InDegree(View::NEW), 0);
-//     {
-//       auto ret = vertex_from->OutEdges(View::OLD);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       ASSERT_EQ(edges.size(), 1);
-//       ASSERT_EQ(*vertex_from->OutDegree(View::OLD), 1);
-//       auto e = edges[0];
-//       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.From(), *vertex_from);
-//       ASSERT_EQ(e.To(), *vertex_to);
-//     }
-//     ASSERT_EQ(vertex_from->OutEdges(View::NEW)->size(), 0);
-//     ASSERT_EQ(*vertex_from->OutDegree(View::NEW), 0);
-//     {
-//       auto ret = vertex_to->InEdges(View::OLD);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       ASSERT_EQ(edges.size(), 1);
-//       ASSERT_EQ(*vertex_to->InDegree(View::OLD), 1);
-//       auto e = edges[0];
-//       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.From(), *vertex_from);
-//       ASSERT_EQ(e.To(), *vertex_to);
-//     }
-//     ASSERT_EQ(vertex_to->InEdges(View::NEW)->size(), 0);
-//     ASSERT_EQ(*vertex_to->InDegree(View::NEW), 0);
-//     ASSERT_EQ(vertex_to->OutEdges(View::OLD)->size(), 0);
-//     ASSERT_EQ(*vertex_to->OutDegree(View::OLD), 0);
-//     ASSERT_EQ(vertex_to->OutEdges(View::NEW)->size(), 0);
-//     ASSERT_EQ(*vertex_to->OutDegree(View::NEW), 0);
-
-//     auto other_et = acc.NameToEdgeType("other");
-
-//     // Check edges with filters
-//     ASSERT_EQ(vertex_from->OutEdges(View::OLD, {other_et})->size(), 0);
-//     ASSERT_EQ(vertex_from->OutEdges(View::OLD, {et, other_et})->size(), 1);
-//     ASSERT_EQ(vertex_from->OutEdges(View::OLD, {}, &to_id)->size(), 1);
-//     ASSERT_EQ(vertex_from->OutEdges(View::OLD, {}, &from_id)->size(), 0);
-//     ASSERT_EQ(vertex_to->InEdges(View::OLD, {other_et})->size(), 0);
-//     ASSERT_EQ(vertex_to->InEdges(View::OLD, {et, other_et})->size(), 1);
-//     ASSERT_EQ(vertex_to->InEdges(View::OLD, {}, &from_id)->size(), 1);
-//     ASSERT_EQ(vertex_to->InEdges(View::OLD, {}, &to_id)->size(), 0);
-
-//     acc.Abort();
-//   }
-
-//   // Check whether the edge exists
-//   {
-//     auto acc = store.Access(GetNextHlc());
-//     auto vertex_from = acc.FindVertex(gid_from, View::NEW);
-//     auto vertex_to = acc.FindVertex(gid_to, View::NEW);
-//     ASSERT_TRUE(vertex_from);
-//     ASSERT_TRUE(vertex_to);
-
-//     auto et = acc.NameToEdgeType("et5");
-
-//     // Check edges without filters
-//     ASSERT_EQ(vertex_from->InEdges(View::OLD)->size(), 0);
-//     ASSERT_EQ(*vertex_from->InDegree(View::OLD), 0);
-//     ASSERT_EQ(vertex_from->InEdges(View::NEW)->size(), 0);
-//     ASSERT_EQ(*vertex_from->InDegree(View::NEW), 0);
-//     {
-//       auto ret = vertex_from->OutEdges(View::OLD);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       ASSERT_EQ(edges.size(), 1);
-//       ASSERT_EQ(*vertex_from->OutDegree(View::OLD), 1);
-//       auto e = edges[0];
-//       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.From(), *vertex_from);
-//       ASSERT_EQ(e.To(), *vertex_to);
-//     }
-//     {
-//       auto ret = vertex_from->OutEdges(View::NEW);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       ASSERT_EQ(edges.size(), 1);
-//       ASSERT_EQ(*vertex_from->OutDegree(View::NEW), 1);
-//       auto e = edges[0];
-//       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.From(), *vertex_from);
-//       ASSERT_EQ(e.To(), *vertex_to);
-//     }
-//     {
-//       auto ret = vertex_to->InEdges(View::OLD);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       ASSERT_EQ(edges.size(), 1);
-//       ASSERT_EQ(*vertex_to->InDegree(View::OLD), 1);
-//       auto e = edges[0];
-//       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.From(), *vertex_from);
-//       ASSERT_EQ(e.To(), *vertex_to);
-//     }
-//     {
-//       auto ret = vertex_to->InEdges(View::NEW);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       ASSERT_EQ(edges.size(), 1);
-//       ASSERT_EQ(*vertex_to->InDegree(View::NEW), 1);
-//       auto e = edges[0];
-//       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.From(), *vertex_from);
-//       ASSERT_EQ(e.To(), *vertex_to);
-//     }
-//     ASSERT_EQ(vertex_to->OutEdges(View::OLD)->size(), 0);
-//     ASSERT_EQ(*vertex_to->OutDegree(View::OLD), 0);
-//     ASSERT_EQ(vertex_to->OutEdges(View::NEW)->size(), 0);
-//     ASSERT_EQ(*vertex_to->OutDegree(View::NEW), 0);
-
-//     auto other_et = acc.NameToEdgeType("other");
-
-//     // Check edges with filters
-//     ASSERT_EQ(vertex_from->OutEdges(View::OLD, {other_et})->size(), 0);
-//     ASSERT_EQ(vertex_from->OutEdges(View::NEW, {other_et})->size(), 0);
-//     ASSERT_EQ(vertex_from->OutEdges(View::OLD, {et, other_et})->size(), 1);
-//     ASSERT_EQ(vertex_from->OutEdges(View::NEW, {et, other_et})->size(), 1);
-//     ASSERT_EQ(vertex_from->OutEdges(View::OLD, {}, &to_id)->size(), 1);
-//     ASSERT_EQ(vertex_from->OutEdges(View::NEW, {}, &to_id)->size(), 1);
-//     ASSERT_EQ(vertex_from->OutEdges(View::OLD, {}, &from_id)->size(), 0);
-//     ASSERT_EQ(vertex_from->OutEdges(View::NEW, {}, &from_id)->size(), 0);
-//     ASSERT_EQ(vertex_to->InEdges(View::OLD, {other_et})->size(), 0);
-//     ASSERT_EQ(vertex_to->InEdges(View::NEW, {other_et})->size(), 0);
-//     ASSERT_EQ(vertex_to->InEdges(View::OLD, {et, other_et})->size(), 1);
-//     ASSERT_EQ(vertex_to->InEdges(View::NEW, {et, other_et})->size(), 1);
-//     ASSERT_EQ(vertex_to->InEdges(View::OLD, {}, &from_id)->size(), 1);
-//     ASSERT_EQ(vertex_to->InEdges(View::NEW, {}, &from_id)->size(), 1);
-//     ASSERT_EQ(vertex_to->InEdges(View::OLD, {}, &to_id)->size(), 0);
-//     ASSERT_EQ(vertex_to->InEdges(View::NEW, {}, &to_id)->size(), 0);
-
-//     acc.Commit(GetNextHlc());
-//   }
-
-//   // Delete the edge
-//   {
-//     auto acc = store.Access(GetNextHlc());
-//     auto vertex_from = acc.FindVertex(gid_from, View::NEW);
-//     auto vertex_to = acc.FindVertex(gid_to, View::NEW);
-//     ASSERT_TRUE(vertex_from);
-//     ASSERT_TRUE(vertex_to);
-
-//     auto et = acc.NameToEdgeType("et5");
-
-//     auto edge = vertex_from->OutEdges(View::NEW).GetValue()[0];
-
-//     auto res = acc.DeleteEdge(&edge);
-//     ASSERT_TRUE(res.HasValue());
-//     ASSERT_TRUE(res.GetValue());
-
-//     // Check edges without filters
-//     ASSERT_EQ(vertex_from->InEdges(View::OLD)->size(), 0);
-//     ASSERT_EQ(*vertex_from->InDegree(View::OLD), 0);
-//     ASSERT_EQ(vertex_from->InEdges(View::NEW)->size(), 0);
-//     ASSERT_EQ(*vertex_from->InDegree(View::NEW), 0);
-//     {
-//       auto ret = vertex_from->OutEdges(View::OLD);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       ASSERT_EQ(edges.size(), 1);
-//       ASSERT_EQ(*vertex_from->OutDegree(View::OLD), 1);
-//       auto e = edges[0];
-//       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.From(), *vertex_from);
-//       ASSERT_EQ(e.To(), *vertex_to);
-//     }
-//     ASSERT_EQ(vertex_from->OutEdges(View::NEW)->size(), 0);
-//     ASSERT_EQ(*vertex_from->OutDegree(View::NEW), 0);
-//     {
-//       auto ret = vertex_to->InEdges(View::OLD);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       ASSERT_EQ(edges.size(), 1);
-//       ASSERT_EQ(*vertex_to->InDegree(View::OLD), 1);
-//       auto e = edges[0];
-//       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.From(), *vertex_from);
-//       ASSERT_EQ(e.To(), *vertex_to);
-//     }
-//     ASSERT_EQ(vertex_to->InEdges(View::NEW)->size(), 0);
-//     ASSERT_EQ(*vertex_to->InDegree(View::NEW), 0);
-//     ASSERT_EQ(vertex_to->OutEdges(View::OLD)->size(), 0);
-//     ASSERT_EQ(*vertex_to->OutDegree(View::OLD), 0);
-//     ASSERT_EQ(vertex_to->OutEdges(View::NEW)->size(), 0);
-//     ASSERT_EQ(*vertex_to->OutDegree(View::NEW), 0);
-
-//     auto other_et = acc.NameToEdgeType("other");
-
-//     // Check edges with filters
-//     ASSERT_EQ(vertex_from->OutEdges(View::OLD, {other_et})->size(), 0);
-//     ASSERT_EQ(vertex_from->OutEdges(View::OLD, {et, other_et})->size(), 1);
-//     ASSERT_EQ(vertex_from->OutEdges(View::OLD, {}, &to_id)->size(), 1);
-//     ASSERT_EQ(vertex_from->OutEdges(View::OLD, {}, &from_id)->size(), 0);
-//     ASSERT_EQ(vertex_to->InEdges(View::OLD, {other_et})->size(), 0);
-//     ASSERT_EQ(vertex_to->InEdges(View::OLD, {et, other_et})->size(), 1);
-//     ASSERT_EQ(vertex_to->InEdges(View::OLD, {}, &from_id)->size(), 1);
-//     ASSERT_EQ(vertex_to->InEdges(View::OLD, {}, &to_id)->size(), 0);
-
-//     acc.Commit(GetNextHlc());
-//   }
-
-//   // Check whether the edge exists
-//   {
-//     auto acc = store.Access(GetNextHlc());
-//     auto vertex_from = acc.FindVertex(gid_from, View::NEW);
-//     auto vertex_to = acc.FindVertex(gid_to, View::NEW);
-//     ASSERT_TRUE(vertex_from);
-//     ASSERT_TRUE(vertex_to);
-
-//     // Check edges without filters
-//     ASSERT_EQ(vertex_from->InEdges(View::OLD)->size(), 0);
-//     ASSERT_EQ(*vertex_from->InDegree(View::OLD), 0);
-//     ASSERT_EQ(vertex_from->InEdges(View::NEW)->size(), 0);
-//     ASSERT_EQ(*vertex_from->InDegree(View::NEW), 0);
-//     ASSERT_EQ(vertex_from->OutEdges(View::OLD)->size(), 0);
-//     ASSERT_EQ(*vertex_from->OutDegree(View::OLD), 0);
-//     ASSERT_EQ(vertex_from->OutEdges(View::NEW)->size(), 0);
-//     ASSERT_EQ(*vertex_from->OutDegree(View::NEW), 0);
-//     ASSERT_EQ(vertex_to->InEdges(View::OLD)->size(), 0);
-//     ASSERT_EQ(*vertex_to->InDegree(View::OLD), 0);
-//     ASSERT_EQ(vertex_to->InEdges(View::NEW)->size(), 0);
-//     ASSERT_EQ(*vertex_to->InDegree(View::NEW), 0);
-//     ASSERT_EQ(vertex_to->OutEdges(View::OLD)->size(), 0);
-//     ASSERT_EQ(*vertex_to->OutDegree(View::OLD), 0);
-//     ASSERT_EQ(vertex_to->OutEdges(View::NEW)->size(), 0);
-//     ASSERT_EQ(*vertex_to->OutDegree(View::NEW), 0);
-
-//     acc.Commit(GetNextHlc());
-//   }
-// }
-
 // NOLINTNEXTLINE(hicpp-special-member-functions)
 TEST_P(StorageEdgeTest, EdgeDeleteFromLargerAbort) {
   // Create vertex
@@ -2814,365 +1087,6 @@ TEST_P(StorageEdgeTest, EdgeDeleteFromLargerAbort) {
   }
 }
 
-// // NOLINTNEXTLINE(hicpp-special-member-functions)
-// TEST_P(StorageEdgeTest, EdgeDeleteFromSameAbort) {
-//   memgraph::storage::Storage store({.items = {.properties_on_edges = GetParam()}});
-//   memgraph::storage::Gid gid_vertex = memgraph::storage::Gid::FromUint(std::numeric_limits<uint64_t>::max());
-
-//   // Create vertex
-//   {
-//     auto acc = store.Access(GetNextHlc());
-//     auto vertex = acc.CreateVertex();
-//     gid_vertex = vertex.Gid();
-//     acc.Commit(GetNextHlc());
-//   }
-
-//   // Create edge
-//   {
-//     auto acc = store.Access(GetNextHlc());
-//     auto vertex = acc.FindVertex(gid_vertex, View::NEW);
-//     ASSERT_TRUE(vertex);
-
-//     auto et = acc.NameToEdgeType("et5");
-
-//     auto res = acc.CreateEdge(&*vertex, &*vertex, et);
-//     ASSERT_TRUE(res.HasValue());
-//     auto edge = res.GetValue();
-//     ASSERT_EQ(edge.EdgeType(), et);
-//     ASSERT_EQ(edge.From(), *vertex);
-//     ASSERT_EQ(edge.To(), *vertex);
-
-//     // Check edges without filters
-//     ASSERT_EQ(vertex->InEdges(View::OLD)->size(), 0);
-//     ASSERT_EQ(*vertex->InDegree(View::OLD), 0);
-//     {
-//       auto ret = vertex->InEdges(View::NEW);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       ASSERT_EQ(edges.size(), 1);
-//       ASSERT_EQ(*vertex->InDegree(View::NEW), 1);
-//       auto e = edges[0];
-//       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.From(), *vertex);
-//       ASSERT_EQ(e.To(), *vertex);
-//     }
-//     ASSERT_EQ(vertex->OutEdges(View::OLD)->size(), 0);
-//     ASSERT_EQ(*vertex->OutDegree(View::OLD), 0);
-//     {
-//       auto ret = vertex->OutEdges(View::NEW);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       ASSERT_EQ(edges.size(), 1);
-//       ASSERT_EQ(*vertex->OutDegree(View::NEW), 1);
-//       auto e = edges[0];
-//       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.From(), *vertex);
-//       ASSERT_EQ(e.To(), *vertex);
-//     }
-
-//     auto other_et = acc.NameToEdgeType("other");
-
-//     // Check edges with filters
-//     ASSERT_EQ(vertex->OutEdges(View::NEW, {other_et})->size(), 0);
-//     ASSERT_EQ(vertex->OutEdges(View::NEW, {et, other_et})->size(), 1);
-//     ASSERT_EQ(vertex->OutEdges(View::NEW, {}, &*vertex)->size(), 1);
-//     ASSERT_EQ(vertex->OutEdges(View::NEW, {other_et}, &*vertex)->size(), 0);
-//     ASSERT_EQ(vertex->InEdges(View::NEW, {other_et})->size(), 0);
-//     ASSERT_EQ(vertex->InEdges(View::NEW, {et, other_et})->size(), 1);
-//     ASSERT_EQ(vertex->InEdges(View::NEW, {}, &*vertex)->size(), 1);
-//     ASSERT_EQ(vertex->InEdges(View::NEW, {other_et}, &*vertex)->size(), 0);
-
-//     acc.Commit(GetNextHlc());
-//   }
-
-//   // Check whether the edge exists
-//   {
-//     auto acc = store.Access(GetNextHlc());
-//     auto vertex = acc.FindVertex(gid_vertex, View::NEW);
-//     ASSERT_TRUE(vertex);
-
-//     auto et = acc.NameToEdgeType("et5");
-
-//     // Check edges without filters
-//     {
-//       auto ret = vertex->InEdges(View::OLD);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       ASSERT_EQ(edges.size(), 1);
-//       ASSERT_EQ(*vertex->InDegree(View::OLD), 1);
-//       auto e = edges[0];
-//       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.From(), *vertex);
-//       ASSERT_EQ(e.To(), *vertex);
-//     }
-//     {
-//       auto ret = vertex->InEdges(View::NEW);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       ASSERT_EQ(edges.size(), 1);
-//       ASSERT_EQ(*vertex->InDegree(View::NEW), 1);
-//       auto e = edges[0];
-//       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.From(), *vertex);
-//       ASSERT_EQ(e.To(), *vertex);
-//     }
-//     {
-//       auto ret = vertex->OutEdges(View::OLD);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       ASSERT_EQ(edges.size(), 1);
-//       ASSERT_EQ(*vertex->OutDegree(View::OLD), 1);
-//       auto e = edges[0];
-//       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.From(), *vertex);
-//       ASSERT_EQ(e.To(), *vertex);
-//     }
-//     {
-//       auto ret = vertex->OutEdges(View::NEW);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       ASSERT_EQ(edges.size(), 1);
-//       ASSERT_EQ(*vertex->OutDegree(View::NEW), 1);
-//       auto e = edges[0];
-//       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.From(), *vertex);
-//       ASSERT_EQ(e.To(), *vertex);
-//     }
-
-//     auto other_et = acc.NameToEdgeType("other");
-
-//     // Check edges with filters
-//     ASSERT_EQ(vertex->InEdges(View::OLD, {other_et})->size(), 0);
-//     ASSERT_EQ(vertex->InEdges(View::NEW, {other_et})->size(), 0);
-//     ASSERT_EQ(vertex->InEdges(View::OLD, {et, other_et})->size(), 1);
-//     ASSERT_EQ(vertex->InEdges(View::NEW, {et, other_et})->size(), 1);
-//     ASSERT_EQ(vertex->InEdges(View::OLD, {}, &*vertex)->size(), 1);
-//     ASSERT_EQ(vertex->InEdges(View::NEW, {}, &*vertex)->size(), 1);
-//     ASSERT_EQ(vertex->InEdges(View::OLD, {other_et}, &*vertex)->size(), 0);
-//     ASSERT_EQ(vertex->InEdges(View::NEW, {other_et}, &*vertex)->size(), 0);
-//     ASSERT_EQ(vertex->OutEdges(View::OLD, {other_et})->size(), 0);
-//     ASSERT_EQ(vertex->OutEdges(View::NEW, {other_et})->size(), 0);
-//     ASSERT_EQ(vertex->OutEdges(View::OLD, {et, other_et})->size(), 1);
-//     ASSERT_EQ(vertex->OutEdges(View::NEW, {et, other_et})->size(), 1);
-//     ASSERT_EQ(vertex->OutEdges(View::OLD, {}, &*vertex)->size(), 1);
-//     ASSERT_EQ(vertex->OutEdges(View::NEW, {}, &*vertex)->size(), 1);
-//     ASSERT_EQ(vertex->OutEdges(View::OLD, {other_et}, &*vertex)->size(), 0);
-//     ASSERT_EQ(vertex->OutEdges(View::NEW, {other_et}, &*vertex)->size(), 0);
-
-//     acc.Commit(GetNextHlc());
-//   }
-
-//   // Delete the edge, but abort the transaction
-//   {
-//     auto acc = store.Access(GetNextHlc());
-//     auto vertex = acc.FindVertex(gid_vertex, View::NEW);
-//     ASSERT_TRUE(vertex);
-
-//     auto et = acc.NameToEdgeType("et5");
-
-//     auto edge = vertex->OutEdges(View::NEW).GetValue()[0];
-
-//     auto res = acc.DeleteEdge(&edge);
-//     ASSERT_TRUE(res.HasValue());
-//     ASSERT_TRUE(res.GetValue());
-
-//     // Check edges without filters
-//     {
-//       auto ret = vertex->InEdges(View::OLD);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       ASSERT_EQ(edges.size(), 1);
-//       ASSERT_EQ(*vertex->InDegree(View::OLD), 1);
-//       auto e = edges[0];
-//       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.From(), *vertex);
-//       ASSERT_EQ(e.To(), *vertex);
-//     }
-//     ASSERT_EQ(vertex->InEdges(View::NEW)->size(), 0);
-//     ASSERT_EQ(*vertex->InDegree(View::NEW), 0);
-//     {
-//       auto ret = vertex->OutEdges(View::OLD);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       ASSERT_EQ(edges.size(), 1);
-//       ASSERT_EQ(*vertex->OutDegree(View::OLD), 1);
-//       auto e = edges[0];
-//       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.From(), *vertex);
-//       ASSERT_EQ(e.To(), *vertex);
-//     }
-//     ASSERT_EQ(vertex->OutEdges(View::NEW)->size(), 0);
-//     ASSERT_EQ(*vertex->OutDegree(View::NEW), 0);
-
-//     auto other_et = acc.NameToEdgeType("other");
-
-//     // Check edges with filters
-//     ASSERT_EQ(vertex->InEdges(View::OLD, {other_et})->size(), 0);
-//     ASSERT_EQ(vertex->InEdges(View::OLD, {et, other_et})->size(), 1);
-//     ASSERT_EQ(vertex->InEdges(View::OLD, {}, &*vertex)->size(), 1);
-//     ASSERT_EQ(vertex->InEdges(View::OLD, {other_et}, &*vertex)->size(), 0);
-//     ASSERT_EQ(vertex->OutEdges(View::OLD, {other_et})->size(), 0);
-//     ASSERT_EQ(vertex->OutEdges(View::OLD, {et, other_et})->size(), 1);
-//     ASSERT_EQ(vertex->OutEdges(View::OLD, {}, &*vertex)->size(), 1);
-//     ASSERT_EQ(vertex->OutEdges(View::OLD, {other_et}, &*vertex)->size(), 0);
-
-//     acc.Abort();
-//   }
-
-//   // Check whether the edge exists
-//   {
-//     auto acc = store.Access(GetNextHlc());
-//     auto vertex = acc.FindVertex(gid_vertex, View::NEW);
-//     ASSERT_TRUE(vertex);
-
-//     auto et = acc.NameToEdgeType("et5");
-
-//     // Check edges without filters
-//     {
-//       auto ret = vertex->InEdges(View::OLD);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       ASSERT_EQ(edges.size(), 1);
-//       ASSERT_EQ(*vertex->InDegree(View::OLD), 1);
-//       auto e = edges[0];
-//       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.From(), *vertex);
-//       ASSERT_EQ(e.To(), *vertex);
-//     }
-//     {
-//       auto ret = vertex->InEdges(View::NEW);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       ASSERT_EQ(edges.size(), 1);
-//       ASSERT_EQ(*vertex->InDegree(View::NEW), 1);
-//       auto e = edges[0];
-//       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.From(), *vertex);
-//       ASSERT_EQ(e.To(), *vertex);
-//     }
-//     {
-//       auto ret = vertex->OutEdges(View::OLD);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       ASSERT_EQ(edges.size(), 1);
-//       ASSERT_EQ(*vertex->OutDegree(View::OLD), 1);
-//       auto e = edges[0];
-//       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.From(), *vertex);
-//       ASSERT_EQ(e.To(), *vertex);
-//     }
-//     {
-//       auto ret = vertex->OutEdges(View::NEW);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       ASSERT_EQ(edges.size(), 1);
-//       ASSERT_EQ(*vertex->OutDegree(View::NEW), 1);
-//       auto e = edges[0];
-//       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.From(), *vertex);
-//       ASSERT_EQ(e.To(), *vertex);
-//     }
-
-//     auto other_et = acc.NameToEdgeType("other");
-
-//     // Check edges with filters
-//     ASSERT_EQ(vertex->InEdges(View::OLD, {other_et})->size(), 0);
-//     ASSERT_EQ(vertex->InEdges(View::NEW, {other_et})->size(), 0);
-//     ASSERT_EQ(vertex->InEdges(View::OLD, {et, other_et})->size(), 1);
-//     ASSERT_EQ(vertex->InEdges(View::NEW, {et, other_et})->size(), 1);
-//     ASSERT_EQ(vertex->InEdges(View::OLD, {}, &*vertex)->size(), 1);
-//     ASSERT_EQ(vertex->InEdges(View::NEW, {}, &*vertex)->size(), 1);
-//     ASSERT_EQ(vertex->InEdges(View::OLD, {other_et}, &*vertex)->size(), 0);
-//     ASSERT_EQ(vertex->InEdges(View::NEW, {other_et}, &*vertex)->size(), 0);
-//     ASSERT_EQ(vertex->OutEdges(View::OLD, {other_et})->size(), 0);
-//     ASSERT_EQ(vertex->OutEdges(View::NEW, {other_et})->size(), 0);
-//     ASSERT_EQ(vertex->OutEdges(View::OLD, {et, other_et})->size(), 1);
-//     ASSERT_EQ(vertex->OutEdges(View::NEW, {et, other_et})->size(), 1);
-//     ASSERT_EQ(vertex->OutEdges(View::OLD, {}, &*vertex)->size(), 1);
-//     ASSERT_EQ(vertex->OutEdges(View::NEW, {}, &*vertex)->size(), 1);
-//     ASSERT_EQ(vertex->OutEdges(View::OLD, {other_et}, &*vertex)->size(), 0);
-//     ASSERT_EQ(vertex->OutEdges(View::NEW, {other_et}, &*vertex)->size(), 0);
-
-//     acc.Commit(GetNextHlc());
-//   }
-
-//   // Delete the edge
-//   {
-//     auto acc = store.Access(GetNextHlc());
-//     auto vertex = acc.FindVertex(gid_vertex, View::NEW);
-//     ASSERT_TRUE(vertex);
-
-//     auto et = acc.NameToEdgeType("et5");
-
-//     auto edge = vertex->OutEdges(View::NEW).GetValue()[0];
-
-//     auto res = acc.DeleteEdge(&edge);
-//     ASSERT_TRUE(res.HasValue());
-//     ASSERT_TRUE(res.GetValue());
-
-//     // Check edges without filters
-//     {
-//       auto ret = vertex->InEdges(View::OLD);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       ASSERT_EQ(edges.size(), 1);
-//       ASSERT_EQ(*vertex->InDegree(View::OLD), 1);
-//       auto e = edges[0];
-//       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.From(), *vertex);
-//       ASSERT_EQ(e.To(), *vertex);
-//     }
-//     ASSERT_EQ(vertex->InEdges(View::NEW)->size(), 0);
-//     ASSERT_EQ(*vertex->InDegree(View::NEW), 0);
-//     {
-//       auto ret = vertex->OutEdges(View::OLD);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       ASSERT_EQ(edges.size(), 1);
-//       ASSERT_EQ(*vertex->OutDegree(View::OLD), 1);
-//       auto e = edges[0];
-//       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.From(), *vertex);
-//       ASSERT_EQ(e.To(), *vertex);
-//     }
-//     ASSERT_EQ(vertex->OutEdges(View::NEW)->size(), 0);
-//     ASSERT_EQ(*vertex->OutDegree(View::NEW), 0);
-
-//     auto other_et = acc.NameToEdgeType("other");
-
-//     // Check edges with filters
-//     ASSERT_EQ(vertex->InEdges(View::OLD, {other_et})->size(), 0);
-//     ASSERT_EQ(vertex->InEdges(View::OLD, {et, other_et})->size(), 1);
-//     ASSERT_EQ(vertex->InEdges(View::OLD, {}, &*vertex)->size(), 1);
-//     ASSERT_EQ(vertex->InEdges(View::OLD, {other_et}, &*vertex)->size(), 0);
-//     ASSERT_EQ(vertex->OutEdges(View::OLD, {other_et})->size(), 0);
-//     ASSERT_EQ(vertex->OutEdges(View::OLD, {et, other_et})->size(), 1);
-//     ASSERT_EQ(vertex->OutEdges(View::OLD, {}, &*vertex)->size(), 1);
-//     ASSERT_EQ(vertex->OutEdges(View::OLD, {other_et}, &*vertex)->size(), 0);
-
-//     acc.Commit(GetNextHlc());
-//   }
-
-//   // Check whether the edge exists
-//   {
-//     auto acc = store.Access(GetNextHlc());
-//     auto vertex = acc.FindVertex(gid_vertex, View::NEW);
-//     ASSERT_TRUE(vertex);
-
-//     // Check edges without filters
-//     ASSERT_EQ(vertex->InEdges(View::OLD)->size(), 0);
-//     ASSERT_EQ(*vertex->InDegree(View::OLD), 0);
-//     ASSERT_EQ(vertex->InEdges(View::NEW)->size(), 0);
-//     ASSERT_EQ(*vertex->InDegree(View::NEW), 0);
-//     ASSERT_EQ(vertex->OutEdges(View::OLD)->size(), 0);
-//     ASSERT_EQ(*vertex->OutDegree(View::OLD), 0);
-//     ASSERT_EQ(vertex->OutEdges(View::NEW)->size(), 0);
-//     ASSERT_EQ(*vertex->OutDegree(View::NEW), 0);
-
-//     acc.Commit(GetNextHlc());
-//   }
-// }
-
 // NOLINTNEXTLINE(hicpp-special-member-functions)
 TEST_P(StorageEdgeTest, VertexDetachDeleteSingleCommit) {
   // Create vertices
@@ -3313,1964 +1227,4 @@ TEST_P(StorageEdgeTest, VertexDetachDeleteSingleCommit) {
     ASSERT_EQ(*vertex_to->OutDegree(View::NEW), 0);
   }
 }
-
-// // NOLINTNEXTLINE(hicpp-special-member-functions)
-// TEST_P(StorageEdgeTest, VertexDetachDeleteMultipleCommit) {
-//   memgraph::storage::Storage store({.items = {.properties_on_edges = GetParam()}});
-//   memgraph::storage::Gid gid_vertex1 = memgraph::storage::Gid::FromUint(std::numeric_limits<uint64_t>::max());
-//   memgraph::storage::Gid gid_vertex2 = memgraph::storage::Gid::FromUint(std::numeric_limits<uint64_t>::max());
-
-//   // Create dataset
-//   {
-//     auto acc = store.Access(GetNextHlc());
-//     auto vertex1 = acc.CreateVertex();
-//     auto vertex2 = acc.CreateVertex();
-
-//     gid_vertex1 = vertex1.Gid();
-//     gid_vertex2 = vertex2.Gid();
-
-//     auto et1 = acc.NameToEdgeType("et1");
-//     auto et2 = acc.NameToEdgeType("et2");
-//     auto et3 = acc.NameToEdgeType("et3");
-//     auto et4 = acc.NameToEdgeType("et4");
-
-//     auto res1 = acc.CreateEdge(&vertex1, &vertex2, et1);
-//     ASSERT_TRUE(res1.HasValue());
-//     auto edge1 = res1.GetValue();
-//     ASSERT_EQ(edge1.EdgeType(), et1);
-//     ASSERT_EQ(edge1.From(), vertex1);
-//     ASSERT_EQ(edge1.To(), vertex2);
-
-//     auto res2 = acc.CreateEdge(&vertex2, &vertex1, et2);
-//     ASSERT_TRUE(res2.HasValue());
-//     auto edge2 = res2.GetValue();
-//     ASSERT_EQ(edge2.EdgeType(), et2);
-//     ASSERT_EQ(edge2.From(), vertex2);
-//     ASSERT_EQ(edge2.To(), vertex1);
-
-//     auto res3 = acc.CreateEdge(&vertex1, &vertex1, et3);
-//     ASSERT_TRUE(res3.HasValue());
-//     auto edge3 = res3.GetValue();
-//     ASSERT_EQ(edge3.EdgeType(), et3);
-//     ASSERT_EQ(edge3.From(), vertex1);
-//     ASSERT_EQ(edge3.To(), vertex1);
-
-//     auto res4 = acc.CreateEdge(&vertex2, &vertex2, et4);
-//     ASSERT_TRUE(res4.HasValue());
-//     auto edge4 = res4.GetValue();
-//     ASSERT_EQ(edge4.EdgeType(), et4);
-//     ASSERT_EQ(edge4.From(), vertex2);
-//     ASSERT_EQ(edge4.To(), vertex2);
-
-//     // Check edges
-//     {
-//       auto ret = vertex1.InEdges(View::NEW);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       std::sort(edges.begin(), edges.end(), [](const auto &a, const auto &b) { return a.EdgeType() < b.EdgeType();
-//       }); ASSERT_EQ(edges.size(), 2); ASSERT_EQ(*vertex1.InDegree(View::NEW), 2);
-//       {
-//         auto e = edges[0];
-//         ASSERT_EQ(e.EdgeType(), et2);
-//         ASSERT_EQ(e.From(), vertex2);
-//         ASSERT_EQ(e.To(), vertex1);
-//       }
-//       {
-//         auto e = edges[1];
-//         ASSERT_EQ(e.EdgeType(), et3);
-//         ASSERT_EQ(e.From(), vertex1);
-//         ASSERT_EQ(e.To(), vertex1);
-//       }
-//     }
-//     {
-//       auto ret = vertex1.OutEdges(View::NEW);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       std::sort(edges.begin(), edges.end(), [](const auto &a, const auto &b) { return a.EdgeType() < b.EdgeType();
-//       }); ASSERT_EQ(edges.size(), 2); ASSERT_EQ(*vertex1.OutDegree(View::NEW), 2);
-//       {
-//         auto e = edges[0];
-//         ASSERT_EQ(e.EdgeType(), et1);
-//         ASSERT_EQ(e.From(), vertex1);
-//         ASSERT_EQ(e.To(), vertex2);
-//       }
-//       {
-//         auto e = edges[1];
-//         ASSERT_EQ(e.EdgeType(), et3);
-//         ASSERT_EQ(e.From(), vertex1);
-//         ASSERT_EQ(e.To(), vertex1);
-//       }
-//     }
-//     {
-//       auto ret = vertex2.InEdges(View::NEW);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       std::sort(edges.begin(), edges.end(), [](const auto &a, const auto &b) { return a.EdgeType() < b.EdgeType();
-//       }); ASSERT_EQ(edges.size(), 2); ASSERT_EQ(*vertex2.InDegree(View::NEW), 2);
-//       {
-//         auto e = edges[0];
-//         ASSERT_EQ(e.EdgeType(), et1);
-//         ASSERT_EQ(e.From(), vertex1);
-//         ASSERT_EQ(e.To(), vertex2);
-//       }
-//       {
-//         auto e = edges[1];
-//         ASSERT_EQ(e.EdgeType(), et4);
-//         ASSERT_EQ(e.From(), vertex2);
-//         ASSERT_EQ(e.To(), vertex2);
-//       }
-//     }
-//     {
-//       auto ret = vertex2.OutEdges(View::NEW);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       std::sort(edges.begin(), edges.end(), [](const auto &a, const auto &b) { return a.EdgeType() < b.EdgeType();
-//       }); ASSERT_EQ(edges.size(), 2); ASSERT_EQ(*vertex2.OutDegree(View::NEW), 2);
-//       {
-//         auto e = edges[0];
-//         ASSERT_EQ(e.EdgeType(), et2);
-//         ASSERT_EQ(e.From(), vertex2);
-//         ASSERT_EQ(e.To(), vertex1);
-//       }
-//       {
-//         auto e = edges[1];
-//         ASSERT_EQ(e.EdgeType(), et4);
-//         ASSERT_EQ(e.From(), vertex2);
-//         ASSERT_EQ(e.To(), vertex2);
-//       }
-//     }
-
-//     acc.Commit(GetNextHlc());
-//   }
-
-//   // Detach delete vertex
-//   {
-//     auto acc = store.Access(GetNextHlc());
-//     auto vertex1 = acc.FindVertex(gid_vertex1, View::NEW);
-//     auto vertex2 = acc.FindVertex(gid_vertex2, View::NEW);
-//     ASSERT_TRUE(vertex1);
-//     ASSERT_TRUE(vertex2);
-
-//     auto et1 = acc.NameToEdgeType("et1");
-//     auto et2 = acc.NameToEdgeType("et2");
-//     auto et3 = acc.NameToEdgeType("et3");
-//     auto et4 = acc.NameToEdgeType("et4");
-
-//     // Delete must fail
-//     {
-//       auto ret = acc.DeleteVertex(&*vertex1);
-//       ASSERT_TRUE(ret.HasError());
-//       ASSERT_EQ(ret.GetError(), memgraph::storage::Error::VERTEX_HAS_EDGES);
-//     }
-
-//     // Detach delete vertex
-//     {
-//       auto ret = acc.DetachDeleteVertex(&*vertex1);
-//       ASSERT_TRUE(ret.HasValue());
-//       ASSERT_TRUE(*ret);
-//     }
-
-//     // Check edges
-//     {
-//       auto ret = vertex1->InEdges(View::OLD);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       std::sort(edges.begin(), edges.end(), [](const auto &a, const auto &b) { return a.EdgeType() < b.EdgeType();
-//       }); ASSERT_EQ(edges.size(), 2); ASSERT_EQ(*vertex1->InDegree(View::OLD), 2);
-//       {
-//         auto e = edges[0];
-//         ASSERT_EQ(e.EdgeType(), et2);
-//         ASSERT_EQ(e.From(), *vertex2);
-//         ASSERT_EQ(e.To(), *vertex1);
-//       }
-//       {
-//         auto e = edges[1];
-//         ASSERT_EQ(e.EdgeType(), et3);
-//         ASSERT_EQ(e.From(), *vertex1);
-//         ASSERT_EQ(e.To(), *vertex1);
-//       }
-//     }
-//     ASSERT_EQ(vertex1->InEdges(View::NEW).GetError(), memgraph::storage::Error::DELETED_OBJECT);
-//     ASSERT_EQ(vertex1->InDegree(View::NEW).GetError(), memgraph::storage::Error::DELETED_OBJECT);
-//     {
-//       auto ret = vertex1->OutEdges(View::OLD);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       std::sort(edges.begin(), edges.end(), [](const auto &a, const auto &b) { return a.EdgeType() < b.EdgeType();
-//       }); ASSERT_EQ(edges.size(), 2); ASSERT_EQ(*vertex1->OutDegree(View::OLD), 2);
-//       {
-//         auto e = edges[0];
-//         ASSERT_EQ(e.EdgeType(), et1);
-//         ASSERT_EQ(e.From(), *vertex1);
-//         ASSERT_EQ(e.To(), *vertex2);
-//       }
-//       {
-//         auto e = edges[1];
-//         ASSERT_EQ(e.EdgeType(), et3);
-//         ASSERT_EQ(e.From(), *vertex1);
-//         ASSERT_EQ(e.To(), *vertex1);
-//       }
-//     }
-//     ASSERT_EQ(vertex1->OutEdges(View::NEW).GetError(), memgraph::storage::Error::DELETED_OBJECT);
-//     ASSERT_EQ(vertex1->OutDegree(View::NEW).GetError(), memgraph::storage::Error::DELETED_OBJECT);
-//     {
-//       auto ret = vertex2->InEdges(View::OLD);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       std::sort(edges.begin(), edges.end(), [](const auto &a, const auto &b) { return a.EdgeType() < b.EdgeType();
-//       }); ASSERT_EQ(edges.size(), 2); ASSERT_EQ(*vertex2->InDegree(View::OLD), 2);
-//       {
-//         auto e = edges[0];
-//         ASSERT_EQ(e.EdgeType(), et1);
-//         ASSERT_EQ(e.From(), *vertex1);
-//         ASSERT_EQ(e.To(), *vertex2);
-//       }
-//       {
-//         auto e = edges[1];
-//         ASSERT_EQ(e.EdgeType(), et4);
-//         ASSERT_EQ(e.From(), *vertex2);
-//         ASSERT_EQ(e.To(), *vertex2);
-//       }
-//     }
-//     {
-//       auto ret = vertex2->InEdges(View::NEW);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       ASSERT_EQ(edges.size(), 1);
-//       ASSERT_EQ(*vertex2->InDegree(View::NEW), 1);
-//       auto e = edges[0];
-//       ASSERT_EQ(e.EdgeType(), et4);
-//       ASSERT_EQ(e.From(), *vertex2);
-//       ASSERT_EQ(e.To(), *vertex2);
-//     }
-//     {
-//       auto ret = vertex2->OutEdges(View::OLD);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       std::sort(edges.begin(), edges.end(), [](const auto &a, const auto &b) { return a.EdgeType() < b.EdgeType();
-//       }); ASSERT_EQ(edges.size(), 2); ASSERT_EQ(*vertex2->OutDegree(View::OLD), 2);
-//       {
-//         auto e = edges[0];
-//         ASSERT_EQ(e.EdgeType(), et2);
-//         ASSERT_EQ(e.From(), *vertex2);
-//         ASSERT_EQ(e.To(), *vertex1);
-//       }
-//       {
-//         auto e = edges[1];
-//         ASSERT_EQ(e.EdgeType(), et4);
-//         ASSERT_EQ(e.From(), *vertex2);
-//         ASSERT_EQ(e.To(), *vertex2);
-//       }
-//     }
-//     {
-//       auto ret = vertex2->OutEdges(View::NEW);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       ASSERT_EQ(edges.size(), 1);
-//       ASSERT_EQ(*vertex2->OutDegree(View::NEW), 1);
-//       auto e = edges[0];
-//       ASSERT_EQ(e.EdgeType(), et4);
-//       ASSERT_EQ(e.From(), *vertex2);
-//       ASSERT_EQ(e.To(), *vertex2);
-//     }
-
-//     acc.Commit(GetNextHlc());
-//   }
-
-//   // Check dataset
-//   {
-//     auto acc = store.Access(GetNextHlc());
-//     auto vertex1 = acc.FindVertex(gid_vertex1, View::NEW);
-//     auto vertex2 = acc.FindVertex(gid_vertex2, View::NEW);
-//     ASSERT_FALSE(vertex1);
-//     ASSERT_TRUE(vertex2);
-
-//     auto et4 = acc.NameToEdgeType("et4");
-
-//     // Check edges
-//     {
-//       auto ret = vertex2->InEdges(View::OLD);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       ASSERT_EQ(edges.size(), 1);
-//       ASSERT_EQ(*vertex2->InDegree(View::OLD), 1);
-//       auto e = edges[0];
-//       ASSERT_EQ(e.EdgeType(), et4);
-//       ASSERT_EQ(e.From(), *vertex2);
-//       ASSERT_EQ(e.To(), *vertex2);
-//     }
-//     {
-//       auto ret = vertex2->InEdges(View::NEW);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       ASSERT_EQ(edges.size(), 1);
-//       ASSERT_EQ(*vertex2->InDegree(View::NEW), 1);
-//       auto e = edges[0];
-//       ASSERT_EQ(e.EdgeType(), et4);
-//       ASSERT_EQ(e.From(), *vertex2);
-//       ASSERT_EQ(e.To(), *vertex2);
-//     }
-//     {
-//       auto ret = vertex2->OutEdges(View::OLD);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       ASSERT_EQ(edges.size(), 1);
-//       ASSERT_EQ(*vertex2->OutDegree(View::OLD), 1);
-//       auto e = edges[0];
-//       ASSERT_EQ(e.EdgeType(), et4);
-//       ASSERT_EQ(e.From(), *vertex2);
-//       ASSERT_EQ(e.To(), *vertex2);
-//     }
-//     {
-//       auto ret = vertex2->OutEdges(View::NEW);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       ASSERT_EQ(edges.size(), 1);
-//       ASSERT_EQ(*vertex2->OutDegree(View::NEW), 1);
-//       auto e = edges[0];
-//       ASSERT_EQ(e.EdgeType(), et4);
-//       ASSERT_EQ(e.From(), *vertex2);
-//       ASSERT_EQ(e.To(), *vertex2);
-//     }
-//   }
-// }
-
-// // NOLINTNEXTLINE(hicpp-special-member-functions)
-// TEST_P(StorageEdgeTest, VertexDetachDeleteSingleAbort) {
-//   memgraph::storage::Storage store({.items = {.properties_on_edges = GetParam()}});
-//   memgraph::storage::Gid gid_from = memgraph::storage::Gid::FromUint(std::numeric_limits<uint64_t>::max());
-//   memgraph::storage::Gid gid_to = memgraph::storage::Gid::FromUint(std::numeric_limits<uint64_t>::max());
-
-//   // Create dataset
-//   {
-//     auto acc = store.Access(GetNextHlc());
-//     auto vertex_from = acc.CreateVertex();
-//     auto vertex_to = acc.CreateVertex();
-
-//     auto et = acc.NameToEdgeType("et5");
-
-//     auto res = acc.CreateEdge(&vertex_from, &vertex_to, et);
-//     ASSERT_TRUE(res.HasValue());
-//     auto edge = res.GetValue();
-//     ASSERT_EQ(edge.EdgeType(), et);
-//     ASSERT_EQ(edge.From(), vertex_from);
-//     ASSERT_EQ(edge.To(), vertex_to);
-
-//     gid_from = vertex_from.Gid();
-//     gid_to = vertex_to.Gid();
-
-//     // Check edges
-//     ASSERT_EQ(vertex_from.InEdges(View::NEW)->size(), 0);
-//     ASSERT_EQ(*vertex_from.InDegree(View::NEW), 0);
-//     {
-//       auto ret = vertex_from.OutEdges(View::NEW);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       ASSERT_EQ(edges.size(), 1);
-//       ASSERT_EQ(*vertex_from.OutDegree(View::NEW), 1);
-//       auto e = edges[0];
-//       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.From(), vertex_from);
-//       ASSERT_EQ(e.To(), vertex_to);
-//     }
-//     {
-//       auto ret = vertex_to.InEdges(View::NEW);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       ASSERT_EQ(edges.size(), 1);
-//       ASSERT_EQ(*vertex_to.InDegree(View::NEW), 1);
-//       auto e = edges[0];
-//       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.From(), vertex_from);
-//       ASSERT_EQ(e.To(), vertex_to);
-//     }
-//     ASSERT_EQ(vertex_to.OutEdges(View::NEW)->size(), 0);
-//     ASSERT_EQ(*vertex_to.OutDegree(View::NEW), 0);
-
-//     acc.Commit(GetNextHlc());
-//   }
-
-//   // Detach delete vertex, but abort the transaction
-//   {
-//     auto acc = store.Access(GetNextHlc());
-//     auto vertex_from = acc.FindVertex(gid_from, View::NEW);
-//     auto vertex_to = acc.FindVertex(gid_to, View::NEW);
-//     ASSERT_TRUE(vertex_from);
-//     ASSERT_TRUE(vertex_to);
-
-//     auto et = acc.NameToEdgeType("et5");
-
-//     // Delete must fail
-//     {
-//       auto ret = acc.DeleteVertex(&from_id);
-//       ASSERT_TRUE(ret.HasError());
-//       ASSERT_EQ(ret.GetError(), memgraph::storage::Error::VERTEX_HAS_EDGES);
-//     }
-
-//     // Detach delete vertex
-//     {
-//       auto ret = acc.DetachDeleteVertex(&from_id);
-//       ASSERT_TRUE(ret.HasValue());
-//       ASSERT_TRUE(*ret);
-//     }
-
-//     // Check edges
-//     ASSERT_EQ(vertex_from->InEdges(View::OLD)->size(), 0);
-//     ASSERT_EQ(*vertex_from->InDegree(View::OLD), 0);
-//     ASSERT_EQ(vertex_from->InEdges(View::NEW).GetError(), memgraph::storage::Error::DELETED_OBJECT);
-//     ASSERT_EQ(vertex_from->InDegree(View::NEW).GetError(), memgraph::storage::Error::DELETED_OBJECT);
-//     {
-//       auto ret = vertex_from->OutEdges(View::OLD);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       ASSERT_EQ(edges.size(), 1);
-//       ASSERT_EQ(*vertex_from->OutDegree(View::OLD), 1);
-//       auto e = edges[0];
-//       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.From(), *vertex_from);
-//       ASSERT_EQ(e.To(), *vertex_to);
-//     }
-//     ASSERT_EQ(vertex_from->OutEdges(View::NEW).GetError(), memgraph::storage::Error::DELETED_OBJECT);
-//     ASSERT_EQ(vertex_from->OutDegree(View::NEW).GetError(), memgraph::storage::Error::DELETED_OBJECT);
-//     {
-//       auto ret = vertex_to->InEdges(View::OLD);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       ASSERT_EQ(edges.size(), 1);
-//       ASSERT_EQ(*vertex_to->InDegree(View::OLD), 1);
-//       auto e = edges[0];
-//       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.From(), *vertex_from);
-//       ASSERT_EQ(e.To(), *vertex_to);
-//     }
-//     ASSERT_EQ(vertex_to->InEdges(View::NEW)->size(), 0);
-//     ASSERT_EQ(*vertex_to->InDegree(View::NEW), 0);
-//     ASSERT_EQ(vertex_to->OutEdges(View::OLD)->size(), 0);
-//     ASSERT_EQ(*vertex_to->OutDegree(View::OLD), 0);
-//     ASSERT_EQ(vertex_to->OutEdges(View::NEW)->size(), 0);
-//     ASSERT_EQ(*vertex_to->OutDegree(View::NEW), 0);
-
-//     acc.Abort();
-//   }
-
-//   // Check dataset
-//   {
-//     auto acc = store.Access(GetNextHlc());
-//     auto vertex_from = acc.FindVertex(gid_from, View::NEW);
-//     auto vertex_to = acc.FindVertex(gid_to, View::NEW);
-//     ASSERT_TRUE(vertex_from);
-//     ASSERT_TRUE(vertex_to);
-
-//     auto et = acc.NameToEdgeType("et5");
-
-//     // Check edges
-//     ASSERT_EQ(vertex_from->InEdges(View::NEW)->size(), 0);
-//     ASSERT_EQ(*vertex_from->InDegree(View::NEW), 0);
-//     {
-//       auto ret = vertex_from->OutEdges(View::NEW);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       ASSERT_EQ(edges.size(), 1);
-//       ASSERT_EQ(*vertex_from->OutDegree(View::NEW), 1);
-//       auto e = edges[0];
-//       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.From(), *vertex_from);
-//       ASSERT_EQ(e.To(), *vertex_to);
-//     }
-//     {
-//       auto ret = vertex_to->InEdges(View::NEW);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       ASSERT_EQ(edges.size(), 1);
-//       ASSERT_EQ(*vertex_to->InDegree(View::NEW), 1);
-//       auto e = edges[0];
-//       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.From(), *vertex_from);
-//       ASSERT_EQ(e.To(), *vertex_to);
-//     }
-//     ASSERT_EQ(vertex_to->OutEdges(View::NEW)->size(), 0);
-//     ASSERT_EQ(*vertex_to->OutDegree(View::NEW), 0);
-
-//     acc.Commit(GetNextHlc());
-//   }
-
-//   // Detach delete vertex
-//   {
-//     auto acc = store.Access(GetNextHlc());
-//     auto vertex_from = acc.FindVertex(gid_from, View::NEW);
-//     auto vertex_to = acc.FindVertex(gid_to, View::NEW);
-//     ASSERT_TRUE(vertex_from);
-//     ASSERT_TRUE(vertex_to);
-
-//     auto et = acc.NameToEdgeType("et5");
-
-//     // Delete must fail
-//     {
-//       auto ret = acc.DeleteVertex(&from_id);
-//       ASSERT_TRUE(ret.HasError());
-//       ASSERT_EQ(ret.GetError(), memgraph::storage::Error::VERTEX_HAS_EDGES);
-//     }
-
-//     // Detach delete vertex
-//     {
-//       auto ret = acc.DetachDeleteVertex(&from_id);
-//       ASSERT_TRUE(ret.HasValue());
-//       ASSERT_TRUE(*ret);
-//     }
-
-//     // Check edges
-//     ASSERT_EQ(vertex_from->InEdges(View::OLD)->size(), 0);
-//     ASSERT_EQ(*vertex_from->InDegree(View::OLD), 0);
-//     ASSERT_EQ(vertex_from->InEdges(View::NEW).GetError(), memgraph::storage::Error::DELETED_OBJECT);
-//     ASSERT_EQ(vertex_from->InDegree(View::NEW).GetError(), memgraph::storage::Error::DELETED_OBJECT);
-//     {
-//       auto ret = vertex_from->OutEdges(View::OLD);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       ASSERT_EQ(edges.size(), 1);
-//       ASSERT_EQ(*vertex_from->OutDegree(View::OLD), 1);
-//       auto e = edges[0];
-//       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.From(), *vertex_from);
-//       ASSERT_EQ(e.To(), *vertex_to);
-//     }
-//     ASSERT_EQ(vertex_from->OutEdges(View::NEW).GetError(), memgraph::storage::Error::DELETED_OBJECT);
-//     ASSERT_EQ(vertex_from->OutDegree(View::NEW).GetError(), memgraph::storage::Error::DELETED_OBJECT);
-//     {
-//       auto ret = vertex_to->InEdges(View::OLD);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       ASSERT_EQ(edges.size(), 1);
-//       ASSERT_EQ(*vertex_to->InDegree(View::OLD), 1);
-//       auto e = edges[0];
-//       ASSERT_EQ(e.EdgeType(), et);
-//       ASSERT_EQ(e.From(), *vertex_from);
-//       ASSERT_EQ(e.To(), *vertex_to);
-//     }
-//     ASSERT_EQ(vertex_to->InEdges(View::NEW)->size(), 0);
-//     ASSERT_EQ(*vertex_to->InDegree(View::NEW), 0);
-//     ASSERT_EQ(vertex_to->OutEdges(View::OLD)->size(), 0);
-//     ASSERT_EQ(*vertex_to->OutDegree(View::OLD), 0);
-//     ASSERT_EQ(vertex_to->OutEdges(View::NEW)->size(), 0);
-//     ASSERT_EQ(*vertex_to->OutDegree(View::NEW), 0);
-
-//     acc.Commit(GetNextHlc());
-//   }
-
-//   // Check dataset
-//   {
-//     auto acc = store.Access(GetNextHlc());
-//     auto vertex_from = acc.FindVertex(gid_from, View::NEW);
-//     auto vertex_to = acc.FindVertex(gid_to, View::NEW);
-//     ASSERT_FALSE(vertex_from);
-//     ASSERT_TRUE(vertex_to);
-
-//     // Check edges
-//     ASSERT_EQ(vertex_to->InEdges(View::OLD)->size(), 0);
-//     ASSERT_EQ(*vertex_to->InDegree(View::OLD), 0);
-//     ASSERT_EQ(vertex_to->InEdges(View::NEW)->size(), 0);
-//     ASSERT_EQ(*vertex_to->InDegree(View::NEW), 0);
-//     ASSERT_EQ(vertex_to->OutEdges(View::OLD)->size(), 0);
-//     ASSERT_EQ(*vertex_to->OutDegree(View::OLD), 0);
-//     ASSERT_EQ(vertex_to->OutEdges(View::NEW)->size(), 0);
-//     ASSERT_EQ(*vertex_to->OutDegree(View::NEW), 0);
-//   }
-// }
-
-// // NOLINTNEXTLINE(hicpp-special-member-functions)
-// TEST_P(StorageEdgeTest, VertexDetachDeleteMultipleAbort) {
-//   memgraph::storage::Storage store({.items = {.properties_on_edges = GetParam()}});
-//   memgraph::storage::Gid gid_vertex1 = memgraph::storage::Gid::FromUint(std::numeric_limits<uint64_t>::max());
-//   memgraph::storage::Gid gid_vertex2 = memgraph::storage::Gid::FromUint(std::numeric_limits<uint64_t>::max());
-
-//   // Create dataset
-//   {
-//     auto acc = store.Access(GetNextHlc());
-//     auto vertex1 = acc.CreateVertex();
-//     auto vertex2 = acc.CreateVertex();
-
-//     gid_vertex1 = vertex1.Gid();
-//     gid_vertex2 = vertex2.Gid();
-
-//     auto et1 = acc.NameToEdgeType("et1");
-//     auto et2 = acc.NameToEdgeType("et2");
-//     auto et3 = acc.NameToEdgeType("et3");
-//     auto et4 = acc.NameToEdgeType("et4");
-
-//     auto res1 = acc.CreateEdge(&vertex1, &vertex2, et1);
-//     ASSERT_TRUE(res1.HasValue());
-//     auto edge1 = res1.GetValue();
-//     ASSERT_EQ(edge1.EdgeType(), et1);
-//     ASSERT_EQ(edge1.From(), vertex1);
-//     ASSERT_EQ(edge1.To(), vertex2);
-
-//     auto res2 = acc.CreateEdge(&vertex2, &vertex1, et2);
-//     ASSERT_TRUE(res2.HasValue());
-//     auto edge2 = res2.GetValue();
-//     ASSERT_EQ(edge2.EdgeType(), et2);
-//     ASSERT_EQ(edge2.From(), vertex2);
-//     ASSERT_EQ(edge2.To(), vertex1);
-
-//     auto res3 = acc.CreateEdge(&vertex1, &vertex1, et3);
-//     ASSERT_TRUE(res3.HasValue());
-//     auto edge3 = res3.GetValue();
-//     ASSERT_EQ(edge3.EdgeType(), et3);
-//     ASSERT_EQ(edge3.From(), vertex1);
-//     ASSERT_EQ(edge3.To(), vertex1);
-
-//     auto res4 = acc.CreateEdge(&vertex2, &vertex2, et4);
-//     ASSERT_TRUE(res4.HasValue());
-//     auto edge4 = res4.GetValue();
-//     ASSERT_EQ(edge4.EdgeType(), et4);
-//     ASSERT_EQ(edge4.From(), vertex2);
-//     ASSERT_EQ(edge4.To(), vertex2);
-
-//     // Check edges
-//     {
-//       auto ret = vertex1.InEdges(View::NEW);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       std::sort(edges.begin(), edges.end(), [](const auto &a, const auto &b) { return a.EdgeType() < b.EdgeType();
-//       }); ASSERT_EQ(edges.size(), 2); ASSERT_EQ(*vertex1.InDegree(View::NEW), 2);
-//       {
-//         auto e = edges[0];
-//         ASSERT_EQ(e.EdgeType(), et2);
-//         ASSERT_EQ(e.From(), vertex2);
-//         ASSERT_EQ(e.To(), vertex1);
-//       }
-//       {
-//         auto e = edges[1];
-//         ASSERT_EQ(e.EdgeType(), et3);
-//         ASSERT_EQ(e.From(), vertex1);
-//         ASSERT_EQ(e.To(), vertex1);
-//       }
-//     }
-//     {
-//       auto ret = vertex1.OutEdges(View::NEW);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       std::sort(edges.begin(), edges.end(), [](const auto &a, const auto &b) { return a.EdgeType() < b.EdgeType();
-//       }); ASSERT_EQ(edges.size(), 2); ASSERT_EQ(*vertex1.OutDegree(View::NEW), 2);
-//       {
-//         auto e = edges[0];
-//         ASSERT_EQ(e.EdgeType(), et1);
-//         ASSERT_EQ(e.From(), vertex1);
-//         ASSERT_EQ(e.To(), vertex2);
-//       }
-//       {
-//         auto e = edges[1];
-//         ASSERT_EQ(e.EdgeType(), et3);
-//         ASSERT_EQ(e.From(), vertex1);
-//         ASSERT_EQ(e.To(), vertex1);
-//       }
-//     }
-//     {
-//       auto ret = vertex2.InEdges(View::NEW);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       std::sort(edges.begin(), edges.end(), [](const auto &a, const auto &b) { return a.EdgeType() < b.EdgeType();
-//       }); ASSERT_EQ(edges.size(), 2); ASSERT_EQ(*vertex2.InDegree(View::NEW), 2);
-//       {
-//         auto e = edges[0];
-//         ASSERT_EQ(e.EdgeType(), et1);
-//         ASSERT_EQ(e.From(), vertex1);
-//         ASSERT_EQ(e.To(), vertex2);
-//       }
-//       {
-//         auto e = edges[1];
-//         ASSERT_EQ(e.EdgeType(), et4);
-//         ASSERT_EQ(e.From(), vertex2);
-//         ASSERT_EQ(e.To(), vertex2);
-//       }
-//     }
-//     {
-//       auto ret = vertex2.OutEdges(View::NEW);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       std::sort(edges.begin(), edges.end(), [](const auto &a, const auto &b) { return a.EdgeType() < b.EdgeType();
-//       }); ASSERT_EQ(edges.size(), 2); ASSERT_EQ(*vertex2.OutDegree(View::NEW), 2);
-//       {
-//         auto e = edges[0];
-//         ASSERT_EQ(e.EdgeType(), et2);
-//         ASSERT_EQ(e.From(), vertex2);
-//         ASSERT_EQ(e.To(), vertex1);
-//       }
-//       {
-//         auto e = edges[1];
-//         ASSERT_EQ(e.EdgeType(), et4);
-//         ASSERT_EQ(e.From(), vertex2);
-//         ASSERT_EQ(e.To(), vertex2);
-//       }
-//     }
-
-//     acc.Commit(GetNextHlc());
-//   }
-
-//   // Detach delete vertex, but abort the transaction
-//   {
-//     auto acc = store.Access(GetNextHlc());
-//     auto vertex1 = acc.FindVertex(gid_vertex1, View::NEW);
-//     auto vertex2 = acc.FindVertex(gid_vertex2, View::NEW);
-//     ASSERT_TRUE(vertex1);
-//     ASSERT_TRUE(vertex2);
-
-//     auto et1 = acc.NameToEdgeType("et1");
-//     auto et2 = acc.NameToEdgeType("et2");
-//     auto et3 = acc.NameToEdgeType("et3");
-//     auto et4 = acc.NameToEdgeType("et4");
-
-//     // Delete must fail
-//     {
-//       auto ret = acc.DeleteVertex(&*vertex1);
-//       ASSERT_TRUE(ret.HasError());
-//       ASSERT_EQ(ret.GetError(), memgraph::storage::Error::VERTEX_HAS_EDGES);
-//     }
-
-//     // Detach delete vertex
-//     {
-//       auto ret = acc.DetachDeleteVertex(&*vertex1);
-//       ASSERT_TRUE(ret.HasValue());
-//       ASSERT_TRUE(*ret);
-//     }
-
-//     // Check edges
-//     {
-//       auto ret = vertex1->InEdges(View::OLD);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       std::sort(edges.begin(), edges.end(), [](const auto &a, const auto &b) { return a.EdgeType() < b.EdgeType();
-//       }); ASSERT_EQ(edges.size(), 2); ASSERT_EQ(*vertex1->InDegree(View::OLD), 2);
-//       {
-//         auto e = edges[0];
-//         ASSERT_EQ(e.EdgeType(), et2);
-//         ASSERT_EQ(e.From(), *vertex2);
-//         ASSERT_EQ(e.To(), *vertex1);
-//       }
-//       {
-//         auto e = edges[1];
-//         ASSERT_EQ(e.EdgeType(), et3);
-//         ASSERT_EQ(e.From(), *vertex1);
-//         ASSERT_EQ(e.To(), *vertex1);
-//       }
-//     }
-//     ASSERT_EQ(vertex1->InEdges(View::NEW).GetError(), memgraph::storage::Error::DELETED_OBJECT);
-//     ASSERT_EQ(vertex1->InDegree(View::NEW).GetError(), memgraph::storage::Error::DELETED_OBJECT);
-//     {
-//       auto ret = vertex1->OutEdges(View::OLD);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       std::sort(edges.begin(), edges.end(), [](const auto &a, const auto &b) { return a.EdgeType() < b.EdgeType();
-//       }); ASSERT_EQ(edges.size(), 2); ASSERT_EQ(*vertex1->OutDegree(View::OLD), 2);
-//       {
-//         auto e = edges[0];
-//         ASSERT_EQ(e.EdgeType(), et1);
-//         ASSERT_EQ(e.From(), *vertex1);
-//         ASSERT_EQ(e.To(), *vertex2);
-//       }
-//       {
-//         auto e = edges[1];
-//         ASSERT_EQ(e.EdgeType(), et3);
-//         ASSERT_EQ(e.From(), *vertex1);
-//         ASSERT_EQ(e.To(), *vertex1);
-//       }
-//     }
-//     ASSERT_EQ(vertex1->OutEdges(View::NEW).GetError(), memgraph::storage::Error::DELETED_OBJECT);
-//     ASSERT_EQ(vertex1->OutDegree(View::NEW).GetError(), memgraph::storage::Error::DELETED_OBJECT);
-//     {
-//       auto ret = vertex2->InEdges(View::OLD);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       std::sort(edges.begin(), edges.end(), [](const auto &a, const auto &b) { return a.EdgeType() < b.EdgeType();
-//       }); ASSERT_EQ(edges.size(), 2); ASSERT_EQ(*vertex2->InDegree(View::OLD), 2);
-//       {
-//         auto e = edges[0];
-//         ASSERT_EQ(e.EdgeType(), et1);
-//         ASSERT_EQ(e.From(), *vertex1);
-//         ASSERT_EQ(e.To(), *vertex2);
-//       }
-//       {
-//         auto e = edges[1];
-//         ASSERT_EQ(e.EdgeType(), et4);
-//         ASSERT_EQ(e.From(), *vertex2);
-//         ASSERT_EQ(e.To(), *vertex2);
-//       }
-//     }
-//     {
-//       auto ret = vertex2->InEdges(View::NEW);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       ASSERT_EQ(edges.size(), 1);
-//       ASSERT_EQ(*vertex2->InDegree(View::NEW), 1);
-//       auto e = edges[0];
-//       ASSERT_EQ(e.EdgeType(), et4);
-//       ASSERT_EQ(e.From(), *vertex2);
-//       ASSERT_EQ(e.To(), *vertex2);
-//     }
-//     {
-//       auto ret = vertex2->OutEdges(View::OLD);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       std::sort(edges.begin(), edges.end(), [](const auto &a, const auto &b) { return a.EdgeType() < b.EdgeType();
-//       }); ASSERT_EQ(edges.size(), 2); ASSERT_EQ(*vertex2->OutDegree(View::OLD), 2);
-//       {
-//         auto e = edges[0];
-//         ASSERT_EQ(e.EdgeType(), et2);
-//         ASSERT_EQ(e.From(), *vertex2);
-//         ASSERT_EQ(e.To(), *vertex1);
-//       }
-//       {
-//         auto e = edges[1];
-//         ASSERT_EQ(e.EdgeType(), et4);
-//         ASSERT_EQ(e.From(), *vertex2);
-//         ASSERT_EQ(e.To(), *vertex2);
-//       }
-//     }
-//     {
-//       auto ret = vertex2->OutEdges(View::NEW);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       ASSERT_EQ(edges.size(), 1);
-//       ASSERT_EQ(*vertex2->OutDegree(View::NEW), 1);
-//       auto e = edges[0];
-//       ASSERT_EQ(e.EdgeType(), et4);
-//       ASSERT_EQ(e.From(), *vertex2);
-//       ASSERT_EQ(e.To(), *vertex2);
-//     }
-
-//     acc.Abort();
-//   }
-
-//   // Check dataset
-//   {
-//     auto acc = store.Access(GetNextHlc());
-//     auto vertex1 = acc.FindVertex(gid_vertex1, View::NEW);
-//     auto vertex2 = acc.FindVertex(gid_vertex2, View::NEW);
-//     ASSERT_TRUE(vertex1);
-//     ASSERT_TRUE(vertex2);
-
-//     auto et1 = acc.NameToEdgeType("et1");
-//     auto et2 = acc.NameToEdgeType("et2");
-//     auto et3 = acc.NameToEdgeType("et3");
-//     auto et4 = acc.NameToEdgeType("et4");
-
-//     // Check edges
-//     {
-//       auto ret = vertex1->InEdges(View::OLD);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       std::sort(edges.begin(), edges.end(), [](const auto &a, const auto &b) { return a.EdgeType() < b.EdgeType();
-//       }); ASSERT_EQ(edges.size(), 2); ASSERT_EQ(*vertex1->InDegree(View::OLD), 2);
-//       {
-//         auto e = edges[0];
-//         ASSERT_EQ(e.EdgeType(), et2);
-//         ASSERT_EQ(e.From(), *vertex2);
-//         ASSERT_EQ(e.To(), *vertex1);
-//       }
-//       {
-//         auto e = edges[1];
-//         ASSERT_EQ(e.EdgeType(), et3);
-//         ASSERT_EQ(e.From(), *vertex1);
-//         ASSERT_EQ(e.To(), *vertex1);
-//       }
-//     }
-//     {
-//       auto ret = vertex1->InEdges(View::NEW);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       std::sort(edges.begin(), edges.end(), [](const auto &a, const auto &b) { return a.EdgeType() < b.EdgeType();
-//       }); ASSERT_EQ(edges.size(), 2); ASSERT_EQ(*vertex1->InDegree(View::NEW), 2);
-//       {
-//         auto e = edges[0];
-//         ASSERT_EQ(e.EdgeType(), et2);
-//         ASSERT_EQ(e.From(), *vertex2);
-//         ASSERT_EQ(e.To(), *vertex1);
-//       }
-//       {
-//         auto e = edges[1];
-//         ASSERT_EQ(e.EdgeType(), et3);
-//         ASSERT_EQ(e.From(), *vertex1);
-//         ASSERT_EQ(e.To(), *vertex1);
-//       }
-//     }
-//     {
-//       auto ret = vertex1->OutEdges(View::OLD);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       std::sort(edges.begin(), edges.end(), [](const auto &a, const auto &b) { return a.EdgeType() < b.EdgeType();
-//       }); ASSERT_EQ(edges.size(), 2); ASSERT_EQ(*vertex1->OutDegree(View::OLD), 2);
-//       {
-//         auto e = edges[0];
-//         ASSERT_EQ(e.EdgeType(), et1);
-//         ASSERT_EQ(e.From(), *vertex1);
-//         ASSERT_EQ(e.To(), *vertex2);
-//       }
-//       {
-//         auto e = edges[1];
-//         ASSERT_EQ(e.EdgeType(), et3);
-//         ASSERT_EQ(e.From(), *vertex1);
-//         ASSERT_EQ(e.To(), *vertex1);
-//       }
-//     }
-//     {
-//       auto ret = vertex1->OutEdges(View::NEW);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       std::sort(edges.begin(), edges.end(), [](const auto &a, const auto &b) { return a.EdgeType() < b.EdgeType();
-//       }); ASSERT_EQ(edges.size(), 2); ASSERT_EQ(*vertex1->OutDegree(View::NEW), 2);
-//       {
-//         auto e = edges[0];
-//         ASSERT_EQ(e.EdgeType(), et1);
-//         ASSERT_EQ(e.From(), *vertex1);
-//         ASSERT_EQ(e.To(), *vertex2);
-//       }
-//       {
-//         auto e = edges[1];
-//         ASSERT_EQ(e.EdgeType(), et3);
-//         ASSERT_EQ(e.From(), *vertex1);
-//         ASSERT_EQ(e.To(), *vertex1);
-//       }
-//     }
-//     {
-//       auto ret = vertex2->InEdges(View::OLD);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       std::sort(edges.begin(), edges.end(), [](const auto &a, const auto &b) { return a.EdgeType() < b.EdgeType();
-//       }); ASSERT_EQ(edges.size(), 2); ASSERT_EQ(*vertex2->InDegree(View::OLD), 2);
-//       {
-//         auto e = edges[0];
-//         ASSERT_EQ(e.EdgeType(), et1);
-//         ASSERT_EQ(e.From(), *vertex1);
-//         ASSERT_EQ(e.To(), *vertex2);
-//       }
-//       {
-//         auto e = edges[1];
-//         ASSERT_EQ(e.EdgeType(), et4);
-//         ASSERT_EQ(e.From(), *vertex2);
-//         ASSERT_EQ(e.To(), *vertex2);
-//       }
-//     }
-//     {
-//       auto ret = vertex2->InEdges(View::NEW);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       std::sort(edges.begin(), edges.end(), [](const auto &a, const auto &b) { return a.EdgeType() < b.EdgeType();
-//       }); ASSERT_EQ(edges.size(), 2); ASSERT_EQ(*vertex2->InDegree(View::NEW), 2);
-//       {
-//         auto e = edges[0];
-//         ASSERT_EQ(e.EdgeType(), et1);
-//         ASSERT_EQ(e.From(), *vertex1);
-//         ASSERT_EQ(e.To(), *vertex2);
-//       }
-//       {
-//         auto e = edges[1];
-//         ASSERT_EQ(e.EdgeType(), et4);
-//         ASSERT_EQ(e.From(), *vertex2);
-//         ASSERT_EQ(e.To(), *vertex2);
-//       }
-//     }
-//     {
-//       auto ret = vertex2->OutEdges(View::OLD);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       std::sort(edges.begin(), edges.end(), [](const auto &a, const auto &b) { return a.EdgeType() < b.EdgeType();
-//       }); ASSERT_EQ(edges.size(), 2); ASSERT_EQ(*vertex2->OutDegree(View::OLD), 2);
-//       {
-//         auto e = edges[0];
-//         ASSERT_EQ(e.EdgeType(), et2);
-//         ASSERT_EQ(e.From(), *vertex2);
-//         ASSERT_EQ(e.To(), *vertex1);
-//       }
-//       {
-//         auto e = edges[1];
-//         ASSERT_EQ(e.EdgeType(), et4);
-//         ASSERT_EQ(e.From(), *vertex2);
-//         ASSERT_EQ(e.To(), *vertex2);
-//       }
-//     }
-//     {
-//       auto ret = vertex2->OutEdges(View::NEW);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       std::sort(edges.begin(), edges.end(), [](const auto &a, const auto &b) { return a.EdgeType() < b.EdgeType();
-//       }); ASSERT_EQ(edges.size(), 2); ASSERT_EQ(*vertex2->OutDegree(View::NEW), 2);
-//       {
-//         auto e = edges[0];
-//         ASSERT_EQ(e.EdgeType(), et2);
-//         ASSERT_EQ(e.From(), *vertex2);
-//         ASSERT_EQ(e.To(), *vertex1);
-//       }
-//       {
-//         auto e = edges[1];
-//         ASSERT_EQ(e.EdgeType(), et4);
-//         ASSERT_EQ(e.From(), *vertex2);
-//         ASSERT_EQ(e.To(), *vertex2);
-//       }
-//     }
-
-//     acc.Commit(GetNextHlc());
-//   }
-
-//   // Detach delete vertex
-//   {
-//     auto acc = store.Access(GetNextHlc());
-//     auto vertex1 = acc.FindVertex(gid_vertex1, View::NEW);
-//     auto vertex2 = acc.FindVertex(gid_vertex2, View::NEW);
-//     ASSERT_TRUE(vertex1);
-//     ASSERT_TRUE(vertex2);
-
-//     auto et1 = acc.NameToEdgeType("et1");
-//     auto et2 = acc.NameToEdgeType("et2");
-//     auto et3 = acc.NameToEdgeType("et3");
-//     auto et4 = acc.NameToEdgeType("et4");
-
-//     // Delete must fail
-//     {
-//       auto ret = acc.DeleteVertex(&*vertex1);
-//       ASSERT_TRUE(ret.HasError());
-//       ASSERT_EQ(ret.GetError(), memgraph::storage::Error::VERTEX_HAS_EDGES);
-//     }
-
-//     // Detach delete vertex
-//     {
-//       auto ret = acc.DetachDeleteVertex(&*vertex1);
-//       ASSERT_TRUE(ret.HasValue());
-//       ASSERT_TRUE(*ret);
-//     }
-
-//     // Check edges
-//     {
-//       auto ret = vertex1->InEdges(View::OLD);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       std::sort(edges.begin(), edges.end(), [](const auto &a, const auto &b) { return a.EdgeType() < b.EdgeType();
-//       }); ASSERT_EQ(edges.size(), 2); ASSERT_EQ(*vertex1->InDegree(View::OLD), 2);
-//       {
-//         auto e = edges[0];
-//         ASSERT_EQ(e.EdgeType(), et2);
-//         ASSERT_EQ(e.From(), *vertex2);
-//         ASSERT_EQ(e.To(), *vertex1);
-//       }
-//       {
-//         auto e = edges[1];
-//         ASSERT_EQ(e.EdgeType(), et3);
-//         ASSERT_EQ(e.From(), *vertex1);
-//         ASSERT_EQ(e.To(), *vertex1);
-//       }
-//     }
-//     ASSERT_EQ(vertex1->InEdges(View::NEW).GetError(), memgraph::storage::Error::DELETED_OBJECT);
-//     ASSERT_EQ(vertex1->InDegree(View::NEW).GetError(), memgraph::storage::Error::DELETED_OBJECT);
-//     {
-//       auto ret = vertex1->OutEdges(View::OLD);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       std::sort(edges.begin(), edges.end(), [](const auto &a, const auto &b) { return a.EdgeType() < b.EdgeType();
-//       }); ASSERT_EQ(edges.size(), 2); ASSERT_EQ(*vertex1->OutDegree(View::OLD), 2);
-//       {
-//         auto e = edges[0];
-//         ASSERT_EQ(e.EdgeType(), et1);
-//         ASSERT_EQ(e.From(), *vertex1);
-//         ASSERT_EQ(e.To(), *vertex2);
-//       }
-//       {
-//         auto e = edges[1];
-//         ASSERT_EQ(e.EdgeType(), et3);
-//         ASSERT_EQ(e.From(), *vertex1);
-//         ASSERT_EQ(e.To(), *vertex1);
-//       }
-//     }
-//     ASSERT_EQ(vertex1->OutEdges(View::NEW).GetError(), memgraph::storage::Error::DELETED_OBJECT);
-//     ASSERT_EQ(vertex1->OutDegree(View::NEW).GetError(), memgraph::storage::Error::DELETED_OBJECT);
-//     {
-//       auto ret = vertex2->InEdges(View::OLD);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       std::sort(edges.begin(), edges.end(), [](const auto &a, const auto &b) { return a.EdgeType() < b.EdgeType();
-//       }); ASSERT_EQ(edges.size(), 2); ASSERT_EQ(*vertex2->InDegree(View::OLD), 2);
-//       {
-//         auto e = edges[0];
-//         ASSERT_EQ(e.EdgeType(), et1);
-//         ASSERT_EQ(e.From(), *vertex1);
-//         ASSERT_EQ(e.To(), *vertex2);
-//       }
-//       {
-//         auto e = edges[1];
-//         ASSERT_EQ(e.EdgeType(), et4);
-//         ASSERT_EQ(e.From(), *vertex2);
-//         ASSERT_EQ(e.To(), *vertex2);
-//       }
-//     }
-//     {
-//       auto ret = vertex2->InEdges(View::NEW);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       ASSERT_EQ(edges.size(), 1);
-//       ASSERT_EQ(*vertex2->InDegree(View::NEW), 1);
-//       auto e = edges[0];
-//       ASSERT_EQ(e.EdgeType(), et4);
-//       ASSERT_EQ(e.From(), *vertex2);
-//       ASSERT_EQ(e.To(), *vertex2);
-//     }
-//     {
-//       auto ret = vertex2->OutEdges(View::OLD);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       std::sort(edges.begin(), edges.end(), [](const auto &a, const auto &b) { return a.EdgeType() < b.EdgeType();
-//       }); ASSERT_EQ(edges.size(), 2); ASSERT_EQ(*vertex2->OutDegree(View::OLD), 2);
-//       {
-//         auto e = edges[0];
-//         ASSERT_EQ(e.EdgeType(), et2);
-//         ASSERT_EQ(e.From(), *vertex2);
-//         ASSERT_EQ(e.To(), *vertex1);
-//       }
-//       {
-//         auto e = edges[1];
-//         ASSERT_EQ(e.EdgeType(), et4);
-//         ASSERT_EQ(e.From(), *vertex2);
-//         ASSERT_EQ(e.To(), *vertex2);
-//       }
-//     }
-//     {
-//       auto ret = vertex2->OutEdges(View::NEW);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       ASSERT_EQ(edges.size(), 1);
-//       ASSERT_EQ(*vertex2->OutDegree(View::NEW), 1);
-//       auto e = edges[0];
-//       ASSERT_EQ(e.EdgeType(), et4);
-//       ASSERT_EQ(e.From(), *vertex2);
-//       ASSERT_EQ(e.To(), *vertex2);
-//     }
-
-//     acc.Commit(GetNextHlc());
-//   }
-
-//   // Check dataset
-//   {
-//     auto acc = store.Access(GetNextHlc());
-//     auto vertex1 = acc.FindVertex(gid_vertex1, View::NEW);
-//     auto vertex2 = acc.FindVertex(gid_vertex2, View::NEW);
-//     ASSERT_FALSE(vertex1);
-//     ASSERT_TRUE(vertex2);
-
-//     auto et4 = acc.NameToEdgeType("et4");
-
-//     // Check edges
-//     {
-//       auto ret = vertex2->InEdges(View::OLD);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       ASSERT_EQ(edges.size(), 1);
-//       ASSERT_EQ(*vertex2->InDegree(View::OLD), 1);
-//       auto e = edges[0];
-//       ASSERT_EQ(e.EdgeType(), et4);
-//       ASSERT_EQ(e.From(), *vertex2);
-//       ASSERT_EQ(e.To(), *vertex2);
-//     }
-//     {
-//       auto ret = vertex2->InEdges(View::NEW);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       ASSERT_EQ(edges.size(), 1);
-//       ASSERT_EQ(*vertex2->InDegree(View::NEW), 1);
-//       auto e = edges[0];
-//       ASSERT_EQ(e.EdgeType(), et4);
-//       ASSERT_EQ(e.From(), *vertex2);
-//       ASSERT_EQ(e.To(), *vertex2);
-//     }
-//     {
-//       auto ret = vertex2->OutEdges(View::OLD);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       ASSERT_EQ(edges.size(), 1);
-//       ASSERT_EQ(*vertex2->OutDegree(View::OLD), 1);
-//       auto e = edges[0];
-//       ASSERT_EQ(e.EdgeType(), et4);
-//       ASSERT_EQ(e.From(), *vertex2);
-//       ASSERT_EQ(e.To(), *vertex2);
-//     }
-//     {
-//       auto ret = vertex2->OutEdges(View::NEW);
-//       ASSERT_TRUE(ret.HasValue());
-//       auto edges = ret.GetValue();
-//       ASSERT_EQ(edges.size(), 1);
-//       ASSERT_EQ(*vertex2->OutDegree(View::NEW), 1);
-//       auto e = edges[0];
-//       ASSERT_EQ(e.EdgeType(), et4);
-//       ASSERT_EQ(e.From(), *vertex2);
-//       ASSERT_EQ(e.To(), *vertex2);
-//     }
-//   }
-// }
-
-// // NOLINTNEXTLINE(hicpp-special-member-functions)
-// TEST(StorageWithProperties, EdgePropertyCommit) {
-//   memgraph::storage::Storage store({.items = {.properties_on_edges = true}});
-//   memgraph::storage::Gid gid = memgraph::storage::Gid::FromUint(std::numeric_limits<uint64_t>::max());
-//   {
-//     auto acc = store.Access(GetNextHlc());
-//     auto vertex = acc.CreateVertex();
-//     gid = vertex.Gid();
-//     auto et = acc.NameToEdgeType("et5");
-//     auto edge = acc.CreateEdge(&vertex, &vertex, et).GetValue();
-//     ASSERT_EQ(edge.EdgeType(), et);
-//     ASSERT_EQ(edge.From(), vertex);
-//     ASSERT_EQ(edge.To(), vertex);
-
-//     auto property = acc.NameToProperty("property5");
-
-//     ASSERT_TRUE(edge.GetProperty(property, View::NEW)->IsNull());
-//     ASSERT_EQ(edge.Properties(View::NEW)->size(), 0);
-
-//     {
-//       auto old_value = edge.SetProperty(property, memgraph::storage::PropertyValue("temporary"));
-//       ASSERT_TRUE(old_value.HasValue());
-//       ASSERT_TRUE(old_value->IsNull());
-//     }
-
-//     ASSERT_EQ(edge.GetProperty(property, View::NEW)->ValueString(), "temporary");
-//     {
-//       auto properties = edge.Properties(View::NEW).GetValue();
-//       ASSERT_EQ(properties.size(), 1);
-//       ASSERT_EQ(properties[property].ValueString(), "temporary");
-//     }
-
-//     {
-//       auto old_value = edge.SetProperty(property, memgraph::storage::PropertyValue("nandare"));
-//       ASSERT_TRUE(old_value.HasValue());
-//       ASSERT_FALSE(old_value->IsNull());
-//     }
-
-//     ASSERT_EQ(edge.GetProperty(property, View::NEW)->ValueString(), "nandare");
-//     {
-//       auto properties = edge.Properties(View::NEW).GetValue();
-//       ASSERT_EQ(properties.size(), 1);
-//       ASSERT_EQ(properties[property].ValueString(), "nandare");
-//     }
-
-//     acc.Commit(GetNextHlc());
-//   }
-//   {
-//     auto acc = store.Access(GetNextHlc());
-//     auto vertex = acc.FindVertex(gid, View::OLD);
-//     ASSERT_TRUE(vertex);
-//     auto edge = vertex->OutEdges(View::NEW).GetValue()[0];
-
-//     auto property = acc.NameToProperty("property5");
-
-//     ASSERT_EQ(edge.GetProperty(property, View::OLD)->ValueString(), "nandare");
-//     {
-//       auto properties = edge.Properties(View::OLD).GetValue();
-//       ASSERT_EQ(properties.size(), 1);
-//       ASSERT_EQ(properties[property].ValueString(), "nandare");
-//     }
-
-//     ASSERT_EQ(edge.GetProperty(property, View::NEW)->ValueString(), "nandare");
-//     {
-//       auto properties = edge.Properties(View::NEW).GetValue();
-//       ASSERT_EQ(properties.size(), 1);
-//       ASSERT_EQ(properties[property].ValueString(), "nandare");
-//     }
-
-//     auto other_property = acc.NameToProperty("other");
-
-//     ASSERT_TRUE(edge.GetProperty(other_property, View::OLD)->IsNull());
-//     ASSERT_TRUE(edge.GetProperty(other_property, View::NEW)->IsNull());
-
-//     acc.Abort();
-//   }
-//   {
-//     auto acc = store.Access(GetNextHlc());
-//     auto vertex = acc.FindVertex(gid, View::OLD);
-//     ASSERT_TRUE(vertex);
-//     auto edge = vertex->OutEdges(View::NEW).GetValue()[0];
-
-//     auto property = acc.NameToProperty("property5");
-
-//     {
-//       auto old_value = edge.SetProperty(property, memgraph::storage::PropertyValue());
-//       ASSERT_TRUE(old_value.HasValue());
-//       ASSERT_FALSE(old_value->IsNull());
-//     }
-
-//     ASSERT_EQ(edge.GetProperty(property, View::OLD)->ValueString(), "nandare");
-//     {
-//       auto properties = edge.Properties(View::OLD).GetValue();
-//       ASSERT_EQ(properties.size(), 1);
-//       ASSERT_EQ(properties[property].ValueString(), "nandare");
-//     }
-
-//     ASSERT_TRUE(edge.GetProperty(property, View::NEW)->IsNull());
-//     ASSERT_EQ(edge.Properties(View::NEW)->size(), 0);
-
-//     {
-//       auto old_value = edge.SetProperty(property, memgraph::storage::PropertyValue());
-//       ASSERT_TRUE(old_value.HasValue());
-//       ASSERT_TRUE(old_value->IsNull());
-//     }
-
-//     acc.Commit(GetNextHlc());
-//   }
-//   {
-//     auto acc = store.Access(GetNextHlc());
-//     auto vertex = acc.FindVertex(gid, View::OLD);
-//     ASSERT_TRUE(vertex);
-//     auto edge = vertex->OutEdges(View::NEW).GetValue()[0];
-
-//     auto property = acc.NameToProperty("property5");
-
-//     ASSERT_TRUE(edge.GetProperty(property, View::OLD)->IsNull());
-//     ASSERT_TRUE(edge.GetProperty(property, View::NEW)->IsNull());
-//     ASSERT_EQ(edge.Properties(View::OLD)->size(), 0);
-//     ASSERT_EQ(edge.Properties(View::NEW)->size(), 0);
-
-//     auto other_property = acc.NameToProperty("other");
-
-//     ASSERT_TRUE(edge.GetProperty(other_property, View::OLD)->IsNull());
-//     ASSERT_TRUE(edge.GetProperty(other_property, View::NEW)->IsNull());
-
-//     acc.Abort();
-//   }
-// }
-
-// // NOLINTNEXTLINE(hicpp-special-member-functions)
-// TEST(StorageWithProperties, EdgePropertyAbort) {
-//   memgraph::storage::Storage store({.items = {.properties_on_edges = true}});
-//   memgraph::storage::Gid gid = memgraph::storage::Gid::FromUint(std::numeric_limits<uint64_t>::max());
-
-//   // Create the vertex.
-//   {
-//     auto acc = store.Access(GetNextHlc());
-//     auto vertex = acc.CreateVertex();
-//     gid = vertex.Gid();
-//     auto et = acc.NameToEdgeType("et5");
-//     auto edge = acc.CreateEdge(&vertex, &vertex, et).GetValue();
-//     ASSERT_EQ(edge.EdgeType(), et);
-//     ASSERT_EQ(edge.From(), vertex);
-//     ASSERT_EQ(edge.To(), vertex);
-//     acc.Commit(GetNextHlc());
-//   }
-
-//   // Set property 5 to "nandare", but abort the transaction.
-//   {
-//     auto acc = store.Access(GetNextHlc());
-//     auto vertex = acc.FindVertex(gid, View::OLD);
-//     ASSERT_TRUE(vertex);
-//     auto edge = vertex->OutEdges(View::NEW).GetValue()[0];
-
-//     auto property = acc.NameToProperty("property5");
-
-//     ASSERT_TRUE(edge.GetProperty(property, View::NEW)->IsNull());
-//     ASSERT_EQ(edge.Properties(View::NEW)->size(), 0);
-
-//     {
-//       auto old_value = edge.SetProperty(property, memgraph::storage::PropertyValue("temporary"));
-//       ASSERT_TRUE(old_value.HasValue());
-//       ASSERT_TRUE(old_value->IsNull());
-//     }
-
-//     ASSERT_EQ(edge.GetProperty(property, View::NEW)->ValueString(), "temporary");
-//     {
-//       auto properties = edge.Properties(View::NEW).GetValue();
-//       ASSERT_EQ(properties.size(), 1);
-//       ASSERT_EQ(properties[property].ValueString(), "temporary");
-//     }
-
-//     {
-//       auto old_value = edge.SetProperty(property, memgraph::storage::PropertyValue("nandare"));
-//       ASSERT_TRUE(old_value.HasValue());
-//       ASSERT_FALSE(old_value->IsNull());
-//     }
-
-//     ASSERT_EQ(edge.GetProperty(property, View::NEW)->ValueString(), "nandare");
-//     {
-//       auto properties = edge.Properties(View::NEW).GetValue();
-//       ASSERT_EQ(properties.size(), 1);
-//       ASSERT_EQ(properties[property].ValueString(), "nandare");
-//     }
-
-//     acc.Abort();
-//   }
-
-//   // Check that property 5 is null.
-//   {
-//     auto acc = store.Access(GetNextHlc());
-//     auto vertex = acc.FindVertex(gid, View::OLD);
-//     ASSERT_TRUE(vertex);
-//     auto edge = vertex->OutEdges(View::NEW).GetValue()[0];
-
-//     auto property = acc.NameToProperty("property5");
-
-//     ASSERT_TRUE(edge.GetProperty(property, View::OLD)->IsNull());
-//     ASSERT_TRUE(edge.GetProperty(property, View::NEW)->IsNull());
-//     ASSERT_EQ(edge.Properties(View::OLD)->size(), 0);
-//     ASSERT_EQ(edge.Properties(View::NEW)->size(), 0);
-
-//     auto other_property = acc.NameToProperty("other");
-
-//     ASSERT_TRUE(edge.GetProperty(other_property, View::OLD)->IsNull());
-//     ASSERT_TRUE(edge.GetProperty(other_property, View::NEW)->IsNull());
-
-//     acc.Abort();
-//   }
-
-//   // Set property 5 to "nandare".
-//   {
-//     auto acc = store.Access(GetNextHlc());
-//     auto vertex = acc.FindVertex(gid, View::OLD);
-//     ASSERT_TRUE(vertex);
-//     auto edge = vertex->OutEdges(View::NEW).GetValue()[0];
-
-//     auto property = acc.NameToProperty("property5");
-
-//     ASSERT_TRUE(edge.GetProperty(property, View::NEW)->IsNull());
-//     ASSERT_EQ(edge.Properties(View::NEW)->size(), 0);
-
-//     {
-//       auto old_value = edge.SetProperty(property, memgraph::storage::PropertyValue("temporary"));
-//       ASSERT_TRUE(old_value.HasValue());
-//       ASSERT_TRUE(old_value->IsNull());
-//     }
-
-//     ASSERT_EQ(edge.GetProperty(property, View::NEW)->ValueString(), "temporary");
-//     {
-//       auto properties = edge.Properties(View::NEW).GetValue();
-//       ASSERT_EQ(properties.size(), 1);
-//       ASSERT_EQ(properties[property].ValueString(), "temporary");
-//     }
-
-//     {
-//       auto old_value = edge.SetProperty(property, memgraph::storage::PropertyValue("nandare"));
-//       ASSERT_TRUE(old_value.HasValue());
-//       ASSERT_FALSE(old_value->IsNull());
-//     }
-
-//     ASSERT_EQ(edge.GetProperty(property, View::NEW)->ValueString(), "nandare");
-//     {
-//       auto properties = edge.Properties(View::NEW).GetValue();
-//       ASSERT_EQ(properties.size(), 1);
-//       ASSERT_EQ(properties[property].ValueString(), "nandare");
-//     }
-
-//     acc.Commit(GetNextHlc());
-//   }
-
-//   // Check that property 5 is "nandare".
-//   {
-//     auto acc = store.Access(GetNextHlc());
-//     auto vertex = acc.FindVertex(gid, View::OLD);
-//     ASSERT_TRUE(vertex);
-//     auto edge = vertex->OutEdges(View::NEW).GetValue()[0];
-
-//     auto property = acc.NameToProperty("property5");
-
-//     ASSERT_EQ(edge.GetProperty(property, View::OLD)->ValueString(), "nandare");
-//     {
-//       auto properties = edge.Properties(View::OLD).GetValue();
-//       ASSERT_EQ(properties.size(), 1);
-//       ASSERT_EQ(properties[property].ValueString(), "nandare");
-//     }
-
-//     ASSERT_EQ(edge.GetProperty(property, View::NEW)->ValueString(), "nandare");
-//     {
-//       auto properties = edge.Properties(View::NEW).GetValue();
-//       ASSERT_EQ(properties.size(), 1);
-//       ASSERT_EQ(properties[property].ValueString(), "nandare");
-//     }
-
-//     auto other_property = acc.NameToProperty("other");
-
-//     ASSERT_TRUE(edge.GetProperty(other_property, View::OLD)->IsNull());
-//     ASSERT_TRUE(edge.GetProperty(other_property, View::NEW)->IsNull());
-
-//     acc.Abort();
-//   }
-
-//   // Set property 5 to null, but abort the transaction.
-//   {
-//     auto acc = store.Access(GetNextHlc());
-//     auto vertex = acc.FindVertex(gid, View::OLD);
-//     ASSERT_TRUE(vertex);
-//     auto edge = vertex->OutEdges(View::NEW).GetValue()[0];
-
-//     auto property = acc.NameToProperty("property5");
-
-//     ASSERT_EQ(edge.GetProperty(property, View::OLD)->ValueString(), "nandare");
-//     {
-//       auto properties = edge.Properties(View::OLD).GetValue();
-//       ASSERT_EQ(properties.size(), 1);
-//       ASSERT_EQ(properties[property].ValueString(), "nandare");
-//     }
-
-//     ASSERT_EQ(edge.GetProperty(property, View::NEW)->ValueString(), "nandare");
-//     {
-//       auto properties = edge.Properties(View::NEW).GetValue();
-//       ASSERT_EQ(properties.size(), 1);
-//       ASSERT_EQ(properties[property].ValueString(), "nandare");
-//     }
-
-//     {
-//       auto old_value = edge.SetProperty(property, memgraph::storage::PropertyValue());
-//       ASSERT_TRUE(old_value.HasValue());
-//       ASSERT_FALSE(old_value->IsNull());
-//     }
-
-//     ASSERT_EQ(edge.GetProperty(property, View::OLD)->ValueString(), "nandare");
-//     {
-//       auto properties = edge.Properties(View::OLD).GetValue();
-//       ASSERT_EQ(properties.size(), 1);
-//       ASSERT_EQ(properties[property].ValueString(), "nandare");
-//     }
-
-//     ASSERT_TRUE(edge.GetProperty(property, View::NEW)->IsNull());
-//     ASSERT_EQ(edge.Properties(View::NEW)->size(), 0);
-
-//     acc.Abort();
-//   }
-
-//   // Check that property 5 is "nandare".
-//   {
-//     auto acc = store.Access(GetNextHlc());
-//     auto vertex = acc.FindVertex(gid, View::OLD);
-//     ASSERT_TRUE(vertex);
-//     auto edge = vertex->OutEdges(View::NEW).GetValue()[0];
-
-//     auto property = acc.NameToProperty("property5");
-
-//     ASSERT_EQ(edge.GetProperty(property, View::OLD)->ValueString(), "nandare");
-//     {
-//       auto properties = edge.Properties(View::OLD).GetValue();
-//       ASSERT_EQ(properties.size(), 1);
-//       ASSERT_EQ(properties[property].ValueString(), "nandare");
-//     }
-
-//     ASSERT_EQ(edge.GetProperty(property, View::NEW)->ValueString(), "nandare");
-//     {
-//       auto properties = edge.Properties(View::NEW).GetValue();
-//       ASSERT_EQ(properties.size(), 1);
-//       ASSERT_EQ(properties[property].ValueString(), "nandare");
-//     }
-
-//     auto other_property = acc.NameToProperty("other");
-
-//     ASSERT_TRUE(edge.GetProperty(other_property, View::OLD)->IsNull());
-//     ASSERT_TRUE(edge.GetProperty(other_property, View::NEW)->IsNull());
-
-//     acc.Abort();
-//   }
-
-//   // Set property 5 to null.
-//   {
-//     auto acc = store.Access(GetNextHlc());
-//     auto vertex = acc.FindVertex(gid, View::OLD);
-//     ASSERT_TRUE(vertex);
-//     auto edge = vertex->OutEdges(View::NEW).GetValue()[0];
-
-//     auto property = acc.NameToProperty("property5");
-
-//     ASSERT_EQ(edge.GetProperty(property, View::OLD)->ValueString(), "nandare");
-//     {
-//       auto properties = edge.Properties(View::OLD).GetValue();
-//       ASSERT_EQ(properties.size(), 1);
-//       ASSERT_EQ(properties[property].ValueString(), "nandare");
-//     }
-
-//     ASSERT_EQ(edge.GetProperty(property, View::NEW)->ValueString(), "nandare");
-//     {
-//       auto properties = edge.Properties(View::NEW).GetValue();
-//       ASSERT_EQ(properties.size(), 1);
-//       ASSERT_EQ(properties[property].ValueString(), "nandare");
-//     }
-
-//     {
-//       auto old_value = edge.SetProperty(property, memgraph::storage::PropertyValue());
-//       ASSERT_TRUE(old_value.HasValue());
-//       ASSERT_FALSE(old_value->IsNull());
-//     }
-
-//     ASSERT_EQ(edge.GetProperty(property, View::OLD)->ValueString(), "nandare");
-//     {
-//       auto properties = edge.Properties(View::OLD).GetValue();
-//       ASSERT_EQ(properties.size(), 1);
-//       ASSERT_EQ(properties[property].ValueString(), "nandare");
-//     }
-
-//     ASSERT_TRUE(edge.GetProperty(property, View::NEW)->IsNull());
-//     ASSERT_EQ(edge.Properties(View::NEW)->size(), 0);
-
-//     acc.Commit(GetNextHlc());
-//   }
-
-//   // Check that property 5 is null.
-//   {
-//     auto acc = store.Access(GetNextHlc());
-//     auto vertex = acc.FindVertex(gid, View::OLD);
-//     ASSERT_TRUE(vertex);
-//     auto edge = vertex->OutEdges(View::NEW).GetValue()[0];
-
-//     auto property = acc.NameToProperty("property5");
-
-//     ASSERT_TRUE(edge.GetProperty(property, View::OLD)->IsNull());
-//     ASSERT_TRUE(edge.GetProperty(property, View::NEW)->IsNull());
-//     ASSERT_EQ(edge.Properties(View::OLD)->size(), 0);
-//     ASSERT_EQ(edge.Properties(View::NEW)->size(), 0);
-
-//     auto other_property = acc.NameToProperty("other");
-
-//     ASSERT_TRUE(edge.GetProperty(other_property, View::OLD)->IsNull());
-//     ASSERT_TRUE(edge.GetProperty(other_property, View::NEW)->IsNull());
-
-//     acc.Abort();
-//   }
-// }
-
-// // NOLINTNEXTLINE(hicpp-special-member-functions)
-// TEST(StorageWithProperties, EdgePropertySerializationError) {
-//   memgraph::storage::Storage store({.items = {.properties_on_edges = true}});
-//   memgraph::storage::Gid gid = memgraph::storage::Gid::FromUint(std::numeric_limits<uint64_t>::max());
-//   {
-//     auto acc = store.Access(GetNextHlc());
-//     auto vertex = acc.CreateVertex();
-//     gid = vertex.Gid();
-//     auto et = acc.NameToEdgeType("et5");
-//     auto edge = acc.CreateEdge(&vertex, &vertex, et).GetValue();
-//     ASSERT_EQ(edge.EdgeType(), et);
-//     ASSERT_EQ(edge.From(), vertex);
-//     ASSERT_EQ(edge.To(), vertex);
-//     acc.Commit(GetNextHlc());
-//   }
-
-//   auto acc1 = store.Access(GetNextHlc());
-//   auto acc2 = store.Access(GetNextHlc());
-
-//   // Set property 1 to 123 in accessor 1.
-//   {
-//     auto vertex = acc1.FindVertex(gid, View::OLD);
-//     ASSERT_TRUE(vertex);
-//     auto edge = vertex->OutEdges(View::NEW).GetValue()[0];
-
-//     auto property1 = acc1.NameToProperty("property1");
-//     auto property2 = acc1.NameToProperty("property2");
-
-//     ASSERT_TRUE(edge.GetProperty(property1, View::OLD)->IsNull());
-//     ASSERT_TRUE(edge.GetProperty(property1, View::NEW)->IsNull());
-//     ASSERT_TRUE(edge.GetProperty(property2, View::OLD)->IsNull());
-//     ASSERT_TRUE(edge.GetProperty(property2, View::NEW)->IsNull());
-//     ASSERT_EQ(edge.Properties(View::OLD)->size(), 0);
-//     ASSERT_EQ(edge.Properties(View::NEW)->size(), 0);
-
-//     {
-//       auto old_value = edge.SetProperty(property1, memgraph::storage::PropertyValue(123));
-//       ASSERT_TRUE(old_value.HasValue());
-//       ASSERT_TRUE(old_value->IsNull());
-//     }
-
-//     ASSERT_TRUE(edge.GetProperty(property1, View::OLD)->IsNull());
-//     ASSERT_EQ(edge.GetProperty(property1, View::NEW)->ValueInt(), 123);
-//     ASSERT_TRUE(edge.GetProperty(property2, View::OLD)->IsNull());
-//     ASSERT_TRUE(edge.GetProperty(property2, View::NEW)->IsNull());
-//     ASSERT_EQ(edge.Properties(View::OLD)->size(), 0);
-//     {
-//       auto properties = edge.Properties(View::NEW).GetValue();
-//       ASSERT_EQ(properties.size(), 1);
-//       ASSERT_EQ(properties[property1].ValueInt(), 123);
-//     }
-//   }
-
-//   // Set property 2 to "nandare" in accessor 2.
-//   {
-//     auto vertex = acc2.FindVertex(gid, View::OLD);
-//     ASSERT_TRUE(vertex);
-//     auto edge = vertex->OutEdges(View::NEW).GetValue()[0];
-
-//     auto property1 = acc2.NameToProperty("property1");
-//     auto property2 = acc2.NameToProperty("property2");
-
-//     ASSERT_TRUE(edge.GetProperty(property1, View::OLD)->IsNull());
-//     ASSERT_TRUE(edge.GetProperty(property1, View::NEW)->IsNull());
-//     ASSERT_TRUE(edge.GetProperty(property2, View::OLD)->IsNull());
-//     ASSERT_TRUE(edge.GetProperty(property2, View::NEW)->IsNull());
-//     ASSERT_EQ(edge.Properties(View::OLD)->size(), 0);
-//     ASSERT_EQ(edge.Properties(View::NEW)->size(), 0);
-
-//     {
-//       auto res = edge.SetProperty(property2, memgraph::storage::PropertyValue("nandare"));
-//       ASSERT_TRUE(res.HasError());
-//       ASSERT_EQ(res.GetError(), memgraph::storage::Error::SERIALIZATION_ERROR);
-//     }
-//   }
-
-//   // Finalize both accessors.
-//   ASSERT_FALSE(acc1.Commit(GetNextHlc());
-//   acc2.Abort();
-
-//   // Check which properties exist.
-//   {
-//     auto acc = store.Access(GetNextHlc());
-//     auto vertex = acc.FindVertex(gid, View::OLD);
-//     ASSERT_TRUE(vertex);
-//     auto edge = vertex->OutEdges(View::NEW).GetValue()[0];
-
-//     auto property1 = acc.NameToProperty("property1");
-//     auto property2 = acc.NameToProperty("property2");
-
-//     ASSERT_EQ(edge.GetProperty(property1, View::OLD)->ValueInt(), 123);
-//     ASSERT_TRUE(edge.GetProperty(property2, View::OLD)->IsNull());
-//     {
-//       auto properties = edge.Properties(View::OLD).GetValue();
-//       ASSERT_EQ(properties.size(), 1);
-//       ASSERT_EQ(properties[property1].ValueInt(), 123);
-//     }
-
-//     ASSERT_EQ(edge.GetProperty(property1, View::NEW)->ValueInt(), 123);
-//     ASSERT_TRUE(edge.GetProperty(property2, View::NEW)->IsNull());
-//     {
-//       auto properties = edge.Properties(View::NEW).GetValue();
-//       ASSERT_EQ(properties.size(), 1);
-//       ASSERT_EQ(properties[property1].ValueInt(), 123);
-//     }
-
-//     acc.Abort();
-//   }
-// }
-
-// TEST(StorageWithProperties, EdgePropertyClear) {
-//   memgraph::storage::Storage store({.items = {.properties_on_edges = true}});
-//   memgraph::storage::Gid gid;
-//   auto property1 = store.NameToProperty("property1");
-//   auto property2 = store.NameToProperty("property2");
-//   {
-//     auto acc = store.Access(GetNextHlc());
-//     auto vertex = acc.CreateVertex();
-//     gid = vertex.Gid();
-//     auto et = acc.NameToEdgeType("et5");
-//     auto edge = acc.CreateEdge(&vertex, &vertex, et).GetValue();
-//     ASSERT_EQ(edge.EdgeType(), et);
-//     ASSERT_EQ(edge.From(), vertex);
-//     ASSERT_EQ(edge.To(), vertex);
-
-//     auto old_value = edge.SetProperty(property1, memgraph::storage::PropertyValue("value"));
-//     ASSERT_TRUE(old_value.HasValue());
-//     ASSERT_TRUE(old_value->IsNull());
-
-//     acc.Commit(GetNextHlc());
-//   }
-//   {
-//     auto acc = store.Access(GetNextHlc());
-//     auto vertex = acc.FindVertex(gid, View::OLD);
-//     ASSERT_TRUE(vertex);
-//     auto edge = vertex->OutEdges(View::NEW).GetValue()[0];
-
-//     ASSERT_EQ(edge.GetProperty(property1, View::OLD)->ValueString(), "value");
-//     ASSERT_TRUE(edge.GetProperty(property2, View::OLD)->IsNull());
-//     ASSERT_THAT(edge.Properties(View::OLD).GetValue(),
-//                 UnorderedElementsAre(std::pair(property1, memgraph::storage::PropertyValue("value"))));
-
-//     {
-//       auto old_values = edge.ClearProperties();
-//       ASSERT_TRUE(old_values.HasValue());
-//       ASSERT_FALSE(old_values->empty());
-//     }
-
-//     ASSERT_TRUE(edge.GetProperty(property1, View::NEW)->IsNull());
-//     ASSERT_TRUE(edge.GetProperty(property2, View::NEW)->IsNull());
-//     ASSERT_EQ(edge.Properties(View::NEW).GetValue().size(), 0);
-
-//     {
-//       auto old_values = edge.ClearProperties();
-//       ASSERT_TRUE(old_values.HasValue());
-//       ASSERT_TRUE(old_values->empty());
-//     }
-
-//     ASSERT_TRUE(edge.GetProperty(property1, View::NEW)->IsNull());
-//     ASSERT_TRUE(edge.GetProperty(property2, View::NEW)->IsNull());
-//     ASSERT_EQ(edge.Properties(View::NEW).GetValue().size(), 0);
-
-//     acc.Abort();
-//   }
-//   {
-//     auto acc = store.Access(GetNextHlc());
-//     auto vertex = acc.FindVertex(gid, View::OLD);
-//     ASSERT_TRUE(vertex);
-//     auto edge = vertex->OutEdges(View::NEW).GetValue()[0];
-
-//     auto old_value = edge.SetProperty(property2, memgraph::storage::PropertyValue(42));
-//     ASSERT_TRUE(old_value.HasValue());
-//     ASSERT_TRUE(old_value->IsNull());
-
-//     acc.Commit(GetNextHlc());
-//   }
-//   {
-//     auto acc = store.Access(GetNextHlc());
-//     auto vertex = acc.FindVertex(gid, View::OLD);
-//     ASSERT_TRUE(vertex);
-//     auto edge = vertex->OutEdges(View::NEW).GetValue()[0];
-
-//     ASSERT_EQ(edge.GetProperty(property1, View::OLD)->ValueString(), "value");
-//     ASSERT_EQ(edge.GetProperty(property2, View::OLD)->ValueInt(), 42);
-//     ASSERT_THAT(edge.Properties(View::OLD).GetValue(),
-//                 UnorderedElementsAre(std::pair(property1, memgraph::storage::PropertyValue("value")),
-//                                      std::pair(property2, memgraph::storage::PropertyValue(42))));
-
-//     {
-//       auto old_values = edge.ClearProperties();
-//       ASSERT_TRUE(old_values.HasValue());
-//       ASSERT_FALSE(old_values->empty());
-//     }
-
-//     ASSERT_TRUE(edge.GetProperty(property1, View::NEW)->IsNull());
-//     ASSERT_TRUE(edge.GetProperty(property2, View::NEW)->IsNull());
-//     ASSERT_EQ(edge.Properties(View::NEW).GetValue().size(), 0);
-
-//     {
-//       auto old_values = edge.ClearProperties();
-//       ASSERT_TRUE(old_values.HasValue());
-//       ASSERT_TRUE(old_values->empty());
-//     }
-
-//     ASSERT_TRUE(edge.GetProperty(property1, View::NEW)->IsNull());
-//     ASSERT_TRUE(edge.GetProperty(property2, View::NEW)->IsNull());
-//     ASSERT_EQ(edge.Properties(View::NEW).GetValue().size(), 0);
-
-//     acc.Commit(GetNextHlc());
-//   }
-//   {
-//     auto acc = store.Access(GetNextHlc());
-//     auto vertex = acc.FindVertex(gid, View::OLD);
-//     ASSERT_TRUE(vertex);
-//     auto edge = vertex->OutEdges(View::NEW).GetValue()[0];
-
-//     ASSERT_TRUE(edge.GetProperty(property1, View::NEW)->IsNull());
-//     ASSERT_TRUE(edge.GetProperty(property2, View::NEW)->IsNull());
-//     ASSERT_EQ(edge.Properties(View::NEW).GetValue().size(), 0);
-
-//     acc.Abort();
-//   }
-// }
-
-// // NOLINTNEXTLINE(hicpp-special-member-functions)
-// TEST(StorageWithoutProperties, EdgePropertyAbort) {
-//   memgraph::storage::Storage store({.items = {.properties_on_edges = false}});
-//   memgraph::storage::Gid gid = memgraph::storage::Gid::FromUint(std::numeric_limits<uint64_t>::max());
-//   {
-//     auto acc = store.Access(GetNextHlc());
-//     auto vertex = acc.CreateVertex();
-//     gid = vertex.Gid();
-//     auto et = acc.NameToEdgeType("et5");
-//     auto edge = acc.CreateEdge(&vertex, &vertex, et).GetValue();
-//     ASSERT_EQ(edge.EdgeType(), et);
-//     ASSERT_EQ(edge.From(), vertex);
-//     ASSERT_EQ(edge.To(), vertex);
-//     acc.Commit(GetNextHlc());
-//   }
-//   {
-//     auto acc = store.Access(GetNextHlc());
-//     auto vertex = acc.FindVertex(gid, View::OLD);
-//     ASSERT_TRUE(vertex);
-//     auto edge = vertex->OutEdges(View::NEW).GetValue()[0];
-
-//     auto property = acc.NameToProperty("property5");
-
-//     ASSERT_TRUE(edge.GetProperty(property, View::NEW)->IsNull());
-//     ASSERT_EQ(edge.Properties(View::NEW)->size(), 0);
-
-//     {
-//       auto res = edge.SetProperty(property, memgraph::storage::PropertyValue("temporary"));
-//       ASSERT_TRUE(res.HasError());
-//       ASSERT_EQ(res.GetError(), memgraph::storage::Error::PROPERTIES_DISABLED);
-//     }
-
-//     ASSERT_TRUE(edge.GetProperty(property, View::NEW)->IsNull());
-//     ASSERT_EQ(edge.Properties(View::NEW)->size(), 0);
-
-//     {
-//       auto res = edge.SetProperty(property, memgraph::storage::PropertyValue("nandare"));
-//       ASSERT_TRUE(res.HasError());
-//       ASSERT_EQ(res.GetError(), memgraph::storage::Error::PROPERTIES_DISABLED);
-//     }
-
-//     ASSERT_TRUE(edge.GetProperty(property, View::NEW)->IsNull());
-//     ASSERT_EQ(edge.Properties(View::NEW)->size(), 0);
-
-//     acc.Abort();
-//   }
-//   {
-//     auto acc = store.Access(GetNextHlc());
-//     auto vertex = acc.FindVertex(gid, View::OLD);
-//     ASSERT_TRUE(vertex);
-//     auto edge = vertex->OutEdges(View::NEW).GetValue()[0];
-
-//     auto property = acc.NameToProperty("property5");
-
-//     ASSERT_TRUE(edge.GetProperty(property, View::OLD)->IsNull());
-//     ASSERT_EQ(edge.Properties(View::OLD)->size(), 0);
-
-//     ASSERT_TRUE(edge.GetProperty(property, View::NEW)->IsNull());
-//     ASSERT_EQ(edge.Properties(View::NEW)->size(), 0);
-
-//     auto other_property = acc.NameToProperty("other");
-
-//     ASSERT_TRUE(edge.GetProperty(other_property, View::OLD)->IsNull());
-//     ASSERT_TRUE(edge.GetProperty(other_property, View::NEW)->IsNull());
-
-//     acc.Abort();
-//   }
-// }
-
-// TEST(StorageWithoutProperties, EdgePropertyClear) {
-//   memgraph::storage::Storage store({.items = {.properties_on_edges = false}});
-//   memgraph::storage::Gid gid;
-//   {
-//     auto acc = store.Access(GetNextHlc());
-//     auto vertex = acc.CreateVertex();
-//     gid = vertex.Gid();
-//     auto et = acc.NameToEdgeType("et5");
-//     auto edge = acc.CreateEdge(&vertex, &vertex, et).GetValue();
-//     ASSERT_EQ(edge.EdgeType(), et);
-//     ASSERT_EQ(edge.From(), vertex);
-//     ASSERT_EQ(edge.To(), vertex);
-//     acc.Commit(GetNextHlc());
-//   }
-//   {
-//     auto acc = store.Access(GetNextHlc());
-//     auto vertex = acc.FindVertex(gid, View::OLD);
-//     ASSERT_TRUE(vertex);
-//     auto edge = vertex->OutEdges(View::NEW).GetValue()[0];
-
-//     ASSERT_EQ(edge.ClearProperties().GetError(), memgraph::storage::Error::PROPERTIES_DISABLED);
-
-//     acc.Abort();
-//   }
-// }
-
-// TEST(StorageWithProperties, EdgeNonexistentPropertyAPI) {
-//   memgraph::storage::Storage store({.items = {.properties_on_edges = true}});
-
-//   auto property = store.NameToProperty("property");
-
-//   auto acc = store.Access(GetNextHlc());
-//   auto vertex = acc.CreateVertex();
-//   auto edge = acc.CreateEdge(&vertex, &vertex, acc.NameToEdgeType("edge"));
-//   ASSERT_TRUE(edge.HasValue());
-
-//   // Check state before (OLD view).
-//   ASSERT_EQ(edge->Properties(View::OLD).GetError(), memgraph::storage::Error::NONEXISTENT_OBJECT);
-//   ASSERT_EQ(edge->GetProperty(property, View::OLD).GetError(), memgraph::storage::Error::NONEXISTENT_OBJECT);
-
-//   // Check state before (NEW view).
-//   ASSERT_EQ(edge->Properties(View::NEW)->size(), 0);
-//   ASSERT_EQ(*edge->GetProperty(property, View::NEW), memgraph::storage::PropertyValue());
-
-//   // Modify edge.
-//   ASSERT_TRUE(edge->SetProperty(property, memgraph::storage::PropertyValue("value"))->IsNull());
-
-//   // Check state after (OLD view).
-//   ASSERT_EQ(edge->Properties(View::OLD).GetError(), memgraph::storage::Error::NONEXISTENT_OBJECT);
-//   ASSERT_EQ(edge->GetProperty(property, View::OLD).GetError(), memgraph::storage::Error::NONEXISTENT_OBJECT);
-
-//   // Check state after (NEW view).
-//   ASSERT_EQ(edge->Properties(View::NEW)->size(), 1);
-//   ASSERT_EQ(*edge->GetProperty(property, View::NEW), memgraph::storage::PropertyValue("value"));
-
-//   acc.Commit(GetNextHlc());
-// }
 }  // namespace memgraph::storage::v3::tests

From 2ff81ebf047eba12ff4a3d254e1c0e2ddcee7e6b Mon Sep 17 00:00:00 2001
From: Kostas Kyrimis <kostaskyrim@gmail.com>
Date: Wed, 23 Nov 2022 15:16:14 +0200
Subject: [PATCH 07/26] Address missed GH comments && fix broken merge

---
 src/functions/awesome_memgraph_functions.hpp | 8 +-------
 src/storage/v3/edge_accessor.cpp             | 2 +-
 src/storage/v3/vertex_accessor.cpp           | 3 ---
 src/storage/v3/vertex_accessor.hpp           | 3 ---
 tests/unit/query_v2_expression_evaluator.cpp | 2 +-
 5 files changed, 3 insertions(+), 15 deletions(-)

diff --git a/src/functions/awesome_memgraph_functions.hpp b/src/functions/awesome_memgraph_functions.hpp
index 33cc954f5..475380217 100644
--- a/src/functions/awesome_memgraph_functions.hpp
+++ b/src/functions/awesome_memgraph_functions.hpp
@@ -45,19 +45,13 @@ struct FunctionContext {
 struct StorageEngineTag {};
 struct QueryEngineTag {};
 
-namespace impl {
-struct SinkCallable {
-  void operator()() {}
-};
-}  // namespace impl
-
 /// Return the function implementation with the given name.
 ///
 /// Note, returned function signature uses C-style access to an array to allow
 /// having an array stored anywhere the caller likes, as long as it is
 /// contiguous in memory. Since most functions don't take many arguments, it's
 /// convenient to have them stored in the calling stack frame.
-template <typename TypedValueT, typename FunctionContextT, typename Tag, typename Conv = impl::SinkCallable>
+template <typename TypedValueT, typename FunctionContextT, typename Tag, typename Conv>
 std::function<TypedValueT(const TypedValueT *arguments, int64_t num_arguments, const FunctionContextT &context)>
 NameToFunction(const std::string &function_name);
 
diff --git a/src/storage/v3/edge_accessor.cpp b/src/storage/v3/edge_accessor.cpp
index d60cdeebc..312a9c2d7 100644
--- a/src/storage/v3/edge_accessor.cpp
+++ b/src/storage/v3/edge_accessor.cpp
@@ -180,6 +180,6 @@ Result<std::map<PropertyId, PropertyValue>> EdgeAccessor::Properties(View view)
 }
 
 // NOLINTNEXTLINE(readability-convert-member-functions-to-static)
-size_t EdgeAccessor::CypherId() const { return 10; }
+size_t EdgeAccessor::CypherId() const { return Gid().AsUint(); }
 
 }  // namespace memgraph::storage::v3
diff --git a/src/storage/v3/vertex_accessor.cpp b/src/storage/v3/vertex_accessor.cpp
index 10c39dba6..543caa88a 100644
--- a/src/storage/v3/vertex_accessor.cpp
+++ b/src/storage/v3/vertex_accessor.cpp
@@ -733,7 +733,4 @@ Result<size_t> VertexAccessor::OutDegree(View view) const {
   return degree;
 }
 
-// NOLINTNEXTLINE(readability-convert-member-functions-to-static)
-size_t VertexAccessor::CypherId() const { return 10; }
-
 }  // namespace memgraph::storage::v3
diff --git a/src/storage/v3/vertex_accessor.hpp b/src/storage/v3/vertex_accessor.hpp
index d708f723e..682a04e39 100644
--- a/src/storage/v3/vertex_accessor.hpp
+++ b/src/storage/v3/vertex_accessor.hpp
@@ -118,9 +118,6 @@ class VertexAccessor final {
   }
   bool operator!=(const VertexAccessor &other) const noexcept { return !(*this == other); }
 
-  // Dummy function
-  size_t CypherId() const;
-
  private:
   /// Add a label and return `true` if insertion took place.
   /// `false` is returned if the label already existed.
diff --git a/tests/unit/query_v2_expression_evaluator.cpp b/tests/unit/query_v2_expression_evaluator.cpp
index 1c0130571..396d03eb6 100644
--- a/tests/unit/query_v2_expression_evaluator.cpp
+++ b/tests/unit/query_v2_expression_evaluator.cpp
@@ -32,7 +32,7 @@
 #include "query/v2/shard_request_manager.hpp"
 #include "query_v2_query_common.hpp"
 #include "storage/v3/property_value.hpp"
-#include "storage/v3/storage.hpp"
+#include "storage/v3/shard.hpp"
 #include "utils/exceptions.hpp"
 #include "utils/string.hpp"
 

From c4327cfb001bfd6674083d38bad07d365a095142 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=A1nos=20Benjamin=20Antal?= <benjamin.antal@memgraph.io>
Date: Thu, 24 Nov 2022 11:13:55 +0100
Subject: [PATCH 08/26] Make implicit-fallthrough a compilation error

---
 CMakeLists.txt                                 | 3 ++-
 src/communication/bolt/v1/states/executing.hpp | 2 +-
 src/storage/v2/constraints.cpp                 | 4 ++--
 src/storage/v3/request_helper.cpp              | 3 +++
 4 files changed, 8 insertions(+), 4 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 916389424..36e648e8b 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -182,7 +182,8 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)
 # c99-designator is disabled because of required mixture of designated and
 # non-designated initializers in Python Query Module code (`py_module.cpp`).
 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 \
     -Wno-c99-designator \
     -DBOOST_ASIO_USE_TS_EXECUTOR_AS_DEFAULT")
diff --git a/src/communication/bolt/v1/states/executing.hpp b/src/communication/bolt/v1/states/executing.hpp
index 54504985b..de4b2a00e 100644
--- a/src/communication/bolt/v1/states/executing.hpp
+++ b/src/communication/bolt/v1/states/executing.hpp
@@ -74,7 +74,7 @@ State RunHandlerV4(Signature signature, TSession &session, State state, Marker m
     }
     case Signature::Route: {
       if constexpr (bolt_minor >= 3) {
-        if (signature == Signature::Route) return HandleRoute<TSession>(session);
+        return HandleRoute<TSession>(session);
       } else {
         spdlog::trace("Supported only in bolt v4.3");
         return State::Close;
diff --git a/src/storage/v2/constraints.cpp b/src/storage/v2/constraints.cpp
index fab6ee4c4..2a71ee2b0 100644
--- a/src/storage/v2/constraints.cpp
+++ b/src/storage/v2/constraints.cpp
@@ -97,15 +97,15 @@ bool LastCommittedVersionHasLabelProperty(const Vertex &vertex, LabelId label, c
         if (delta->label == label) {
           MG_ASSERT(!has_label, "Invalid database state!");
           has_label = true;
-          break;
         }
+        break;
       }
       case Delta::Action::REMOVE_LABEL: {
         if (delta->label == label) {
           MG_ASSERT(has_label, "Invalid database state!");
           has_label = false;
-          break;
         }
+        break;
       }
       case Delta::Action::ADD_IN_EDGE:
       case Delta::Action::ADD_OUT_EDGE:
diff --git a/src/storage/v3/request_helper.cpp b/src/storage/v3/request_helper.cpp
index 8288a6154..0f6132a1a 100644
--- a/src/storage/v3/request_helper.cpp
+++ b/src/storage/v3/request_helper.cpp
@@ -471,12 +471,14 @@ std::array<std::vector<EdgeAccessor>, 2> GetEdgesFromVertex(const VertexAccessor
       if (edges.HasValue()) {
         in_edges = edges.GetValue();
       }
+      break;
     }
     case memgraph::msgs::EdgeDirection::OUT: {
       auto edges = vertex_accessor.OutEdges(View::OLD);
       if (edges.HasValue()) {
         out_edges = edges.GetValue();
       }
+      break;
     }
     case memgraph::msgs::EdgeDirection::BOTH: {
       auto maybe_in_edges = vertex_accessor.InEdges(View::OLD);
@@ -488,6 +490,7 @@ std::array<std::vector<EdgeAccessor>, 2> GetEdgesFromVertex(const VertexAccessor
       if (maybe_out_edges.HasValue()) {
         out_edges = maybe_out_edges.GetValue();
       }
+      break;
     }
   }
 

From 6f4996de0e5b34fcaced77be2fbbdd9235b7ad37 Mon Sep 17 00:00:00 2001
From: Kostas Kyrimis <kostaskyrim@gmail.com>
Date: Fri, 25 Nov 2022 16:20:38 +0200
Subject: [PATCH 09/26] Fix broken merge and address GH comments

---
 src/functions/awesome_memgraph_functions.hpp | 77 ++++++++++++--------
 src/query/v2/accessors.hpp                   |  5 +-
 src/query/v2/shard_request_manager.hpp       |  4 +-
 src/storage/v3/bindings/db_accessor.hpp      |  2 +-
 src/storage/v3/request_helper.cpp            | 10 +--
 tests/unit/query_v2_expression_evaluator.cpp |  2 +-
 6 files changed, 57 insertions(+), 43 deletions(-)

diff --git a/src/functions/awesome_memgraph_functions.hpp b/src/functions/awesome_memgraph_functions.hpp
index 475380217..7acfa6943 100644
--- a/src/functions/awesome_memgraph_functions.hpp
+++ b/src/functions/awesome_memgraph_functions.hpp
@@ -17,6 +17,7 @@
 #include <unordered_map>
 
 #include "storage/v3/result.hpp"
+#include "storage/v3/shard.hpp"
 #include "storage/v3/view.hpp"
 #include "utils/algorithm.hpp"
 #include "utils/cast.hpp"
@@ -440,15 +441,22 @@ TypedValueT Properties(const TypedValueT *args, int64_t nargs, const FunctionCon
     if constexpr (std::is_same_v<Tag, StorageEngineTag>) {
       auto maybe_props = record_accessor.Properties(ctx.view);
       if (maybe_props.HasError()) {
-        switch (maybe_props.GetError()) {
-          case storage::v3::Error::DELETED_OBJECT:
+        switch (maybe_props.GetError().code) {
+          case common::ErrorCode::DELETED_OBJECT:
             throw functions::FunctionRuntimeException("Trying to get properties from a deleted object.");
-          case storage::v3::Error::NONEXISTENT_OBJECT:
+          case common::ErrorCode::NONEXISTENT_OBJECT:
             throw functions::FunctionRuntimeException("Trying to get properties from an object that doesn't exist.");
-          case storage::v3::Error::SERIALIZATION_ERROR:
-          case storage::v3::Error::VERTEX_HAS_EDGES:
-          case storage::v3::Error::PROPERTIES_DISABLED:
-          case storage::v3::Error::VERTEX_ALREADY_INSERTED:
+          case common::ErrorCode::SERIALIZATION_ERROR:
+          case common::ErrorCode::VERTEX_HAS_EDGES:
+          case common::ErrorCode::PROPERTIES_DISABLED:
+          case common::ErrorCode::VERTEX_ALREADY_INSERTED:
+          case common::ErrorCode::SCHEMA_NO_SCHEMA_DEFINED_FOR_LABEL:
+          case common::ErrorCode::SCHEMA_VERTEX_PROPERTY_WRONG_TYPE:
+          case common::ErrorCode::SCHEMA_VERTEX_UPDATE_PRIMARY_KEY:
+          case common::ErrorCode::SCHEMA_VERTEX_UPDATE_PRIMARY_LABEL:
+          case common::ErrorCode::SCHEMA_VERTEX_SECONDARY_LABEL_IS_PRIMARY:
+          case common::ErrorCode::SCHEMA_VERTEX_PRIMARY_PROPERTIES_UNDEFINED:
+          case common::ErrorCode::OBJECT_NOT_FOUND:
             throw functions::FunctionRuntimeException("Unexpected error when getting properties.");
         }
       }
@@ -506,17 +514,24 @@ TypedValueT StartNode(const TypedValueT *args, int64_t nargs, const FunctionCont
 
 // This is needed because clang-tidy fails to identify the use of this function in the if-constexpr branch
 // NOLINTNEXTLINE(clang-diagnostic-unused-function)
-inline size_t UnwrapDegreeResult(storage::v3::Result<size_t> maybe_degree) {
+inline size_t UnwrapDegreeResult(storage::v3::ShardResult<size_t> maybe_degree) {
   if (maybe_degree.HasError()) {
-    switch (maybe_degree.GetError()) {
-      case storage::v3::Error::DELETED_OBJECT:
+    switch (maybe_degree.GetError().code) {
+      case common::ErrorCode::DELETED_OBJECT:
         throw functions::FunctionRuntimeException("Trying to get degree of a deleted node.");
-      case storage::v3::Error::NONEXISTENT_OBJECT:
+      case common::ErrorCode::NONEXISTENT_OBJECT:
         throw functions::FunctionRuntimeException("Trying to get degree of a node that doesn't exist.");
-      case storage::v3::Error::SERIALIZATION_ERROR:
-      case storage::v3::Error::VERTEX_HAS_EDGES:
-      case storage::v3::Error::PROPERTIES_DISABLED:
-      case storage::v3::Error::VERTEX_ALREADY_INSERTED:
+      case common::ErrorCode::SERIALIZATION_ERROR:
+      case common::ErrorCode::VERTEX_HAS_EDGES:
+      case common::ErrorCode::PROPERTIES_DISABLED:
+      case common::ErrorCode::VERTEX_ALREADY_INSERTED:
+      case common::ErrorCode::SCHEMA_NO_SCHEMA_DEFINED_FOR_LABEL:
+      case common::ErrorCode::SCHEMA_VERTEX_PROPERTY_WRONG_TYPE:
+      case common::ErrorCode::SCHEMA_VERTEX_UPDATE_PRIMARY_KEY:
+      case common::ErrorCode::SCHEMA_VERTEX_UPDATE_PRIMARY_LABEL:
+      case common::ErrorCode::SCHEMA_VERTEX_SECONDARY_LABEL_IS_PRIMARY:
+      case common::ErrorCode::SCHEMA_VERTEX_PRIMARY_PROPERTIES_UNDEFINED:
+      case common::ErrorCode::OBJECT_NOT_FOUND:
         throw functions::FunctionRuntimeException("Unexpected error when getting node degree.");
     }
   }
@@ -688,15 +703,22 @@ TypedValueT Labels(const TypedValueT *args, int64_t nargs, const FunctionContext
   if constexpr (std::is_same_v<Tag, StorageEngineTag>) {
     auto maybe_labels = args[0].ValueVertex().Labels(ctx.view);
     if (maybe_labels.HasError()) {
-      switch (maybe_labels.GetError()) {
-        case storage::v3::Error::DELETED_OBJECT:
+      switch (maybe_labels.GetError().code) {
+        case common::ErrorCode::DELETED_OBJECT:
           throw functions::FunctionRuntimeException("Trying to get labels from a deleted node.");
-        case storage::v3::Error::NONEXISTENT_OBJECT:
+        case common::ErrorCode::NONEXISTENT_OBJECT:
           throw functions::FunctionRuntimeException("Trying to get labels from a node that doesn't exist.");
-        case storage::v3::Error::SERIALIZATION_ERROR:
-        case storage::v3::Error::VERTEX_HAS_EDGES:
-        case storage::v3::Error::PROPERTIES_DISABLED:
-        case storage::v3::Error::VERTEX_ALREADY_INSERTED:
+        case common::ErrorCode::SERIALIZATION_ERROR:
+        case common::ErrorCode::VERTEX_HAS_EDGES:
+        case common::ErrorCode::PROPERTIES_DISABLED:
+        case common::ErrorCode::VERTEX_ALREADY_INSERTED:
+        case common::ErrorCode::SCHEMA_NO_SCHEMA_DEFINED_FOR_LABEL:
+        case common::ErrorCode::SCHEMA_VERTEX_PROPERTY_WRONG_TYPE:
+        case common::ErrorCode::SCHEMA_VERTEX_UPDATE_PRIMARY_KEY:
+        case common::ErrorCode::SCHEMA_VERTEX_UPDATE_PRIMARY_LABEL:
+        case common::ErrorCode::SCHEMA_VERTEX_SECONDARY_LABEL_IS_PRIMARY:
+        case common::ErrorCode::SCHEMA_VERTEX_PRIMARY_PROPERTIES_UNDEFINED:
+        case common::ErrorCode::OBJECT_NOT_FOUND:
           throw functions::FunctionRuntimeException("Unexpected error when getting labels.");
       }
     }
@@ -958,9 +980,9 @@ TypedValueT Counter(const TypedValueT *args, int64_t nargs, const FunctionContex
 
 template <typename TypedValueT, typename FunctionContextT>
 TypedValueT Id(const TypedValueT *args, int64_t nargs, const FunctionContextT &ctx) {
-  FType<TypedValueT, Or<Null, Vertex, Edge>>("id", args, nargs);
+  FType<TypedValueT, Or<Null, Edge>>("id", args, nargs);
   const auto &arg = args[0];
-  if (arg.IsNull() || arg.IsVertex()) {
+  if (arg.IsNull()) {
     return TypedValueT(ctx.memory);
   }
   return TypedValueT(static_cast<int64_t>(arg.ValueEdge().CypherId()), ctx.memory);
@@ -1395,13 +1417,6 @@ NameToFunction(const std::string &function_name) {
   if (function_name == "LOCALDATETIME") return functions::impl::LocalDateTime<TypedValueT, FunctionContextT>;
   if (function_name == "DURATION") return functions::impl::Duration<TypedValueT, FunctionContextT>;
 
-  // Only on QE
-  if constexpr (std::is_same_v<Tag, QueryEngineTag>) {
-    if (function_name == "COUNTER") return functions::impl::Counter<TypedValueT, FunctionContextT>;
-    if (function_name == "STARTNODE") return functions::impl::StartNode<TypedValueT, FunctionContextT, Conv>;
-    if (function_name == "ENDNODE") return functions::impl::EndNode<TypedValueT, FunctionContextT>;
-  }
-
   return nullptr;
 }
 
diff --git a/src/query/v2/accessors.hpp b/src/query/v2/accessors.hpp
index ba3937bb8..bb40fcef8 100644
--- a/src/query/v2/accessors.hpp
+++ b/src/query/v2/accessors.hpp
@@ -94,11 +94,10 @@ class VertexAccessor final {
   [[nodiscard]] msgs::Vertex GetVertex() const;
 
   // NOLINTNEXTLINE(readability-convert-member-functions-to-static)
-  [[nodiscard]] size_t InDegree() const { return 0; }
+  [[nodiscard]] size_t InDegree() const { throw utils::NotYetImplemented("InDegree() not yet implemented"); }
 
   // NOLINTNEXTLINE(readability-convert-member-functions-to-static)
-  [[nodiscard]] size_t OutDegree() const { return 0; }
-  //
+  [[nodiscard]] size_t OutDegree() const { throw utils::NotYetImplemented("OutDegree() not yet implemented"); }
 
   friend bool operator==(const VertexAccessor &lhs, const VertexAccessor &rhs) {
     return lhs.vertex == rhs.vertex && lhs.properties == rhs.properties;
diff --git a/src/query/v2/shard_request_manager.hpp b/src/query/v2/shard_request_manager.hpp
index 9c9c1d89e..dbf3a6bd8 100644
--- a/src/query/v2/shard_request_manager.hpp
+++ b/src/query/v2/shard_request_manager.hpp
@@ -130,7 +130,7 @@ class ShardRequestManagerInterface {
   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 std::optional<storage::v3::PropertyId> MaybeNameToProperty(const std::string &name) const = 0;
-  virtual std::optional<storage::v3::EdgeTypeId> MaybeNameToEdge(const std::string &name) 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(LabelId label) const = 0;
   virtual bool IsPrimaryKey(LabelId primary_label, PropertyId property) const = 0;
@@ -360,7 +360,7 @@ class ShardRequestManager : public ShardRequestManagerInterface {
     return shards_map_.GetPropertyId(name);
   }
 
-  std::optional<storage::v3::EdgeTypeId> MaybeNameToEdge(const std::string &name) const override {
+  std::optional<storage::v3::EdgeTypeId> MaybeNameToEdgeType(const std::string &name) const override {
     return shards_map_.GetEdgeTypeId(name);
   }
 
diff --git a/src/storage/v3/bindings/db_accessor.hpp b/src/storage/v3/bindings/db_accessor.hpp
index 1a5e846fa..6392ed18f 100644
--- a/src/storage/v3/bindings/db_accessor.hpp
+++ b/src/storage/v3/bindings/db_accessor.hpp
@@ -88,7 +88,7 @@ class DbAccessor final {
   }
 
   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()) {
       return res.GetError();
     }
diff --git a/src/storage/v3/request_helper.cpp b/src/storage/v3/request_helper.cpp
index 481741f60..3b0c18326 100644
--- a/src/storage/v3/request_helper.cpp
+++ b/src/storage/v3/request_helper.cpp
@@ -257,7 +257,7 @@ EdgeUniquenessFunction InitializeEdgeUniquenessFunction(bool only_unique_neighbo
         case msgs::EdgeDirection::OUT: {
           is_edge_unique = [](std::set<const storage::v3::VertexId *, VertexIdCmpr> &other_vertex_set,
                               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;
           };
           break;
@@ -265,7 +265,7 @@ EdgeUniquenessFunction InitializeEdgeUniquenessFunction(bool only_unique_neighbo
         case msgs::EdgeDirection::IN: {
           is_edge_unique = [](std::set<const storage::v3::VertexId *, VertexIdCmpr> &other_vertex_set,
                               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;
           };
           break;
@@ -311,8 +311,8 @@ EdgeFiller InitializeEdgeFillerFunction(const msgs::ExpandOneRequest &req) {
         value_properties.insert(std::make_pair(prop_key, FromPropertyValueToValue(std::move(prop_val))));
       }
       using EdgeWithAllProperties = msgs::ExpandOneResultRow::EdgeWithAllProperties;
-      EdgeWithAllProperties edges{ToMsgsVertexId(edge.FromVertex()), msgs::EdgeType{edge.EdgeType()},
-                                  edge.Gid().AsUint(), std::move(value_properties)};
+      EdgeWithAllProperties edges{ToMsgsVertexId(edge.From()), msgs::EdgeType{edge.EdgeType()}, edge.Gid().AsUint(),
+                                  std::move(value_properties)};
       if (is_in_edge) {
         result_row.in_edges_with_all_properties.push_back(std::move(edges));
       } else {
@@ -336,7 +336,7 @@ EdgeFiller InitializeEdgeFillerFunction(const msgs::ExpandOneRequest &req) {
         value_properties.emplace_back(FromPropertyValueToValue(std::move(property_result.GetValue())));
       }
       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)};
       if (is_in_edge) {
         result_row.in_edges_with_specific_properties.push_back(std::move(edges));
diff --git a/tests/unit/query_v2_expression_evaluator.cpp b/tests/unit/query_v2_expression_evaluator.cpp
index 396d03eb6..de324ea2b 100644
--- a/tests/unit/query_v2_expression_evaluator.cpp
+++ b/tests/unit/query_v2_expression_evaluator.cpp
@@ -119,7 +119,7 @@ class MockedShardRequestManager : public memgraph::msgs::ShardRequestManagerInte
     return shards_map_.GetPropertyId(name);
   }
 
-  std::optional<storage::v3::EdgeTypeId> MaybeNameToEdge(const std::string &name) const override {
+  std::optional<storage::v3::EdgeTypeId> MaybeNameToEdgeType(const std::string &name) const override {
     return shards_map_.GetEdgeTypeId(name);
   }
 

From a8dc6fd41e6480e546f0efca30df8bc7926b72f5 Mon Sep 17 00:00:00 2001
From: Tyler Neely <t@jujit.su>
Date: Mon, 28 Nov 2022 09:43:56 +0000
Subject: [PATCH 10/26] Change the namespace of ShardRequestManager to
 query::v2 instead of msgs

---
 src/glue/v2/communication.cpp                 |  10 +-
 src/glue/v2/communication.hpp                 |  18 +-
 src/memgraph.cpp                              |   5 +-
 src/query/v2/accessors.cpp                    |   8 +-
 src/query/v2/accessors.hpp                    |  28 +--
 src/query/v2/bindings/eval.hpp                |  19 +-
 src/query/v2/context.hpp                      |   8 +-
 src/query/v2/conversions.hpp                  |   2 +-
 src/query/v2/cypher_query_interpreter.cpp     |   4 +-
 src/query/v2/cypher_query_interpreter.hpp     |   4 +-
 .../interpret/awesome_memgraph_functions.hpp  |   8 +-
 src/query/v2/interpreter.cpp                  |  24 +--
 src/query/v2/interpreter.hpp                  |   4 +-
 src/query/v2/plan/operator.cpp                |  18 +-
 src/query/v2/plan/pretty_print.cpp            |  18 +-
 src/query/v2/plan/pretty_print.hpp            |  27 ++-
 src/query/v2/plan/vertex_count_cache.hpp      |   2 +-
 src/query/v2/shard_request_manager.hpp        | 192 +++++++++---------
 tests/simulation/shard_request_manager.cpp    |  10 +-
 tests/simulation/test_cluster.hpp             |  11 +-
 tests/unit/high_density_shard_create_scan.cpp |  11 +-
 tests/unit/machine_manager.cpp                |  17 +-
 22 files changed, 225 insertions(+), 223 deletions(-)

diff --git a/src/glue/v2/communication.cpp b/src/glue/v2/communication.cpp
index eedf699bb..3406105b0 100644
--- a/src/glue/v2/communication.cpp
+++ b/src/glue/v2/communication.cpp
@@ -72,7 +72,7 @@ query::v2::TypedValue ToTypedValue(const Value &value) {
 }
 
 communication::bolt::Vertex ToBoltVertex(const query::v2::accessors::VertexAccessor &vertex,
-                                         const msgs::ShardRequestManagerInterface *shard_request_manager,
+                                         const query::v2::ShardRequestManagerInterface *shard_request_manager,
                                          storage::v3::View /*view*/) {
   auto id = communication::bolt::Id::FromUint(0);
 
@@ -92,7 +92,7 @@ communication::bolt::Vertex ToBoltVertex(const query::v2::accessors::VertexAcces
 }
 
 communication::bolt::Edge ToBoltEdge(const query::v2::accessors::EdgeAccessor &edge,
-                                     const msgs::ShardRequestManagerInterface *shard_request_manager,
+                                     const query::v2::ShardRequestManagerInterface *shard_request_manager,
                                      storage::v3::View /*view*/) {
   // TODO(jbajic) Fix bolt communication
   auto id = communication::bolt::Id::FromUint(0);
@@ -109,15 +109,15 @@ communication::bolt::Edge ToBoltEdge(const query::v2::accessors::EdgeAccessor &e
 }
 
 communication::bolt::Path ToBoltPath(const query::v2::accessors::Path & /*edge*/,
-                                     const msgs::ShardRequestManagerInterface * /*shard_request_manager*/,
+                                     const query::v2::ShardRequestManagerInterface * /*shard_request_manager*/,
                                      storage::v3::View /*view*/) {
   // TODO(jbajic) Fix bolt communication
   MG_ASSERT(false, "Path is unimplemented!");
   return {};
 }
 
-Value ToBoltValue(const query::v2::TypedValue &value, const msgs::ShardRequestManagerInterface *shard_request_manager,
-                  storage::v3::View view) {
+Value ToBoltValue(const query::v2::TypedValue &value,
+                  const query::v2::ShardRequestManagerInterface *shard_request_manager, storage::v3::View view) {
   switch (value.type()) {
     case query::v2::TypedValue::Type::Null:
       return {};
diff --git a/src/glue/v2/communication.hpp b/src/glue/v2/communication.hpp
index a20162176..817ff02bd 100644
--- a/src/glue/v2/communication.hpp
+++ b/src/glue/v2/communication.hpp
@@ -32,39 +32,39 @@ namespace memgraph::glue::v2 {
 
 /// @param storage::v3::VertexAccessor for converting to
 ///        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.
 ///
 /// @throw std::bad_alloc
 communication::bolt::Vertex ToBoltVertex(const storage::v3::VertexAccessor &vertex,
-                                         const msgs::ShardRequestManagerInterface *shard_request_manager,
+                                         const query::v2::ShardRequestManagerInterface *shard_request_manager,
                                          storage::v3::View view);
 
 /// @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.
 ///
 /// @throw std::bad_alloc
 communication::bolt::Edge ToBoltEdge(const storage::v3::EdgeAccessor &edge,
-                                     const msgs::ShardRequestManagerInterface *shard_request_manager,
+                                     const query::v2::ShardRequestManagerInterface *shard_request_manager,
                                      storage::v3::View view);
 
 /// @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.
 ///
 /// @throw std::bad_alloc
 communication::bolt::Path ToBoltPath(const query::v2::accessors::Path &path,
-                                     const msgs::ShardRequestManagerInterface *shard_request_manager,
+                                     const query::v2::ShardRequestManagerInterface *shard_request_manager,
                                      storage::v3::View view);
 
 /// @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.
 ///
 /// @throw std::bad_alloc
 communication::bolt::Value ToBoltValue(const query::v2::TypedValue &value,
-                                       const msgs::ShardRequestManagerInterface *shard_request_manager,
+                                       const query::v2::ShardRequestManagerInterface *shard_request_manager,
                                        storage::v3::View view);
 
 query::v2::TypedValue ToTypedValue(const communication::bolt::Value &value);
@@ -76,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,
-                                       const msgs::ShardRequestManagerInterface *shard_request_manager,
+                                       const query::v2::ShardRequestManagerInterface *shard_request_manager,
                                        storage::v3::View view);
 
 }  // namespace memgraph::glue::v2
diff --git a/src/memgraph.cpp b/src/memgraph.cpp
index 5903e65ad..565f9940c 100644
--- a/src/memgraph.cpp
+++ b/src/memgraph.cpp
@@ -497,7 +497,8 @@ class BoltSession final : public memgraph::communication::bolt::Session<memgraph
   /// before forwarding the calls to original TEncoder.
   class TypedValueResultStream {
    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) {}
 
     void Result(const std::vector<memgraph::query::v2::TypedValue> &values) {
@@ -512,7 +513,7 @@ class BoltSession final : public memgraph::communication::bolt::Session<memgraph
 
    private:
     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::communication::v2::ServerEndpoint endpoint_;
diff --git a/src/query/v2/accessors.cpp b/src/query/v2/accessors.cpp
index cbdce89e0..4f6e0d0d7 100644
--- a/src/query/v2/accessors.cpp
+++ b/src/query/v2/accessors.cpp
@@ -15,7 +15,7 @@
 #include "storage/v3/id_types.hpp"
 
 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) {}
 
 EdgeTypeId EdgeAccessor::EdgeType() const { return edge.type.id; }
@@ -44,11 +44,11 @@ VertexAccessor EdgeAccessor::From() const {
 }
 
 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) {}
 
 VertexAccessor::VertexAccessor(Vertex v, std::map<PropertyId, Value> &&props,
-                               const msgs::ShardRequestManagerInterface *manager)
+                               const ShardRequestManagerInterface *manager)
     : vertex(std::move(v)), manager_(manager) {
   properties.reserve(props.size());
   for (auto &[id, value] : props) {
@@ -57,7 +57,7 @@ VertexAccessor::VertexAccessor(Vertex v, 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) {
   properties.reserve(props.size());
   for (const auto &[id, value] : props) {
diff --git a/src/query/v2/accessors.hpp b/src/query/v2/accessors.hpp
index 8e10c865d..df4180818 100644
--- a/src/query/v2/accessors.hpp
+++ b/src/query/v2/accessors.hpp
@@ -24,24 +24,24 @@
 #include "utils/memory.hpp"
 #include "utils/memory_tracker.hpp"
 
-namespace memgraph::msgs {
+namespace memgraph::query::v2 {
 class ShardRequestManagerInterface;
-}  // namespace memgraph::msgs
+}
 
 namespace memgraph::query::v2::accessors {
 
-using Value = memgraph::msgs::Value;
-using Edge = memgraph::msgs::Edge;
-using Vertex = memgraph::msgs::Vertex;
-using Label = memgraph::msgs::Label;
-using PropertyId = memgraph::msgs::PropertyId;
-using EdgeTypeId = memgraph::msgs::EdgeTypeId;
+using Value = msgs::Value;
+using Edge = msgs::Edge;
+using Vertex = msgs::Vertex;
+using Label = msgs::Label;
+using PropertyId = msgs::PropertyId;
+using EdgeTypeId = msgs::EdgeTypeId;
 
 class VertexAccessor;
 
 class EdgeAccessor final {
  public:
-  explicit EdgeAccessor(Edge edge, const msgs::ShardRequestManagerInterface *manager);
+  explicit EdgeAccessor(Edge edge, const ShardRequestManagerInterface *manager);
 
   [[nodiscard]] EdgeTypeId EdgeType() const;
 
@@ -69,7 +69,7 @@ class EdgeAccessor final {
 
  private:
   Edge edge;
-  const msgs::ShardRequestManagerInterface *manager_;
+  const ShardRequestManagerInterface *manager_;
 };
 
 class VertexAccessor final {
@@ -78,10 +78,10 @@ class VertexAccessor final {
   using Label = msgs::Label;
   using VertexId = msgs::VertexId;
   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, const 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 ShardRequestManagerInterface *manager);
 
   [[nodiscard]] Label PrimaryLabel() const;
 
@@ -150,7 +150,7 @@ class VertexAccessor final {
  private:
   Vertex vertex;
   std::vector<std::pair<PropertyId, Value>> properties;
-  const msgs::ShardRequestManagerInterface *manager_;
+  const ShardRequestManagerInterface *manager_;
 };
 
 // inline VertexAccessor EdgeAccessor::To() const { return VertexAccessor(impl_.ToVertex()); }
diff --git a/src/query/v2/bindings/eval.hpp b/src/query/v2/bindings/eval.hpp
index 8f1b19384..584e88922 100644
--- a/src/query/v2/bindings/eval.hpp
+++ b/src/query/v2/bindings/eval.hpp
@@ -24,27 +24,26 @@
 #include "storage/v3/result.hpp"
 #include "storage/v3/view.hpp"
 
-namespace memgraph::msgs {
-class ShardRequestManagerInterface;
-}  // namespace memgraph::msgs
-
 namespace memgraph::query::v2 {
 
+class ShardRequestManagerInterface;
+
 inline const auto lam = [](const auto &val) { return ValueToTypedValue(val); };
 namespace detail {
 class Callable {
  public:
-  auto operator()(const memgraph::storage::v3::PropertyValue &val) const {
-    return memgraph::storage::v3::PropertyToTypedValue<TypedValue>(val);
+  auto operator()(const storage::v3::PropertyValue &val) const {
+    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);
   };
 };
 
 }  // namespace detail
-using ExpressionEvaluator = memgraph::expr::ExpressionEvaluator<
-    TypedValue, memgraph::query::v2::EvaluationContext, memgraph::msgs::ShardRequestManagerInterface, storage::v3::View,
-    storage::v3::LabelId, msgs::Value, detail::Callable, common::ErrorCode, memgraph::expr::QueryEngineTag>;
+using ExpressionEvaluator =
+    expr::ExpressionEvaluator<TypedValue, query::v2::EvaluationContext, ShardRequestManagerInterface, storage::v3::View,
+                              storage::v3::LabelId, msgs::Value, detail::Callable, common::ErrorCode,
+                              expr::QueryEngineTag>;
 
 }  // namespace memgraph::query::v2
diff --git a/src/query/v2/context.hpp b/src/query/v2/context.hpp
index 338546f4d..388342349 100644
--- a/src/query/v2/context.hpp
+++ b/src/query/v2/context.hpp
@@ -60,8 +60,8 @@ struct EvaluationContext {
   mutable std::unordered_map<std::string, int64_t> counters;
 };
 
-inline std::vector<storage::v3::PropertyId> NamesToProperties(
-    const std::vector<std::string> &property_names, msgs::ShardRequestManagerInterface *shard_request_manager) {
+inline std::vector<storage::v3::PropertyId> NamesToProperties(const std::vector<std::string> &property_names,
+                                                              ShardRequestManagerInterface *shard_request_manager) {
   std::vector<storage::v3::PropertyId> properties;
   // TODO Fix by using reference
   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,
-                                                       msgs::ShardRequestManagerInterface *shard_request_manager) {
+                                                       ShardRequestManagerInterface *shard_request_manager) {
   std::vector<storage::v3::LabelId> labels;
   labels.reserve(label_names.size());
   // TODO Fix by using reference
@@ -97,7 +97,7 @@ struct ExecutionContext {
   plan::ProfilingStats *stats_root{nullptr};
   ExecutionStats execution_stats;
   utils::AsyncTimer timer;
-  msgs::ShardRequestManagerInterface *shard_request_manager{nullptr};
+  ShardRequestManagerInterface *shard_request_manager{nullptr};
   IdAllocator *edge_ids_alloc;
 };
 
diff --git a/src/query/v2/conversions.hpp b/src/query/v2/conversions.hpp
index 10299c919..c18ba8cc0 100644
--- a/src/query/v2/conversions.hpp
+++ b/src/query/v2/conversions.hpp
@@ -17,7 +17,7 @@
 
 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;
   switch (value.type) {
     case Value::Type::Null:
diff --git a/src/query/v2/cypher_query_interpreter.cpp b/src/query/v2/cypher_query_interpreter.cpp
index d365a53fb..908ee36cb 100644
--- a/src/query/v2/cypher_query_interpreter.cpp
+++ b/src/query/v2/cypher_query_interpreter.cpp
@@ -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,
-                                             msgs::ShardRequestManagerInterface *shard_manager,
+                                             ShardRequestManagerInterface *shard_manager,
                                              const std::vector<Identifier *> &predefined_identifiers) {
   auto vertex_counts = plan::MakeVertexCountCache(shard_manager);
   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,
                                               const Parameters &parameters, utils::SkipList<PlanCacheEntry> *plan_cache,
-                                              msgs::ShardRequestManagerInterface *shard_manager,
+                                              ShardRequestManagerInterface *shard_manager,
                                               const std::vector<Identifier *> &predefined_identifiers) {
   std::optional<utils::SkipList<PlanCacheEntry>::Accessor> plan_cache_access;
   if (plan_cache) {
diff --git a/src/query/v2/cypher_query_interpreter.hpp b/src/query/v2/cypher_query_interpreter.hpp
index 74dbe85d5..b7f63ab8f 100644
--- a/src/query/v2/cypher_query_interpreter.hpp
+++ b/src/query/v2/cypher_query_interpreter.hpp
@@ -132,7 +132,7 @@ class SingleNodeLogicalPlan final : public LogicalPlan {
 };
 
 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);
 
 /**
@@ -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,
                                               const Parameters &parameters, utils::SkipList<PlanCacheEntry> *plan_cache,
-                                              msgs::ShardRequestManagerInterface *shard_manager,
+                                              ShardRequestManagerInterface *shard_manager,
                                               const std::vector<Identifier *> &predefined_identifiers = {});
 
 }  // namespace memgraph::query::v2
diff --git a/src/query/v2/interpret/awesome_memgraph_functions.hpp b/src/query/v2/interpret/awesome_memgraph_functions.hpp
index 134f05d7d..1fd351cd8 100644
--- a/src/query/v2/interpret/awesome_memgraph_functions.hpp
+++ b/src/query/v2/interpret/awesome_memgraph_functions.hpp
@@ -20,12 +20,10 @@
 #include "storage/v3/view.hpp"
 #include "utils/memory.hpp"
 
-namespace memgraph::msgs {
-class ShardRequestManagerInterface;
-} // namespace memgraph::msgs
-
 namespace memgraph::query::v2 {
 
+class ShardRequestManagerInterface;
+
 namespace {
 const char kStartsWith[] = "STARTSWITH";
 const char kEndsWith[] = "ENDSWITH";
@@ -36,7 +34,7 @@ const char kId[] = "ID";
 struct FunctionContext {
   // TODO(kostasrim) consider optional here. ShardRequestManager does not exist on the storage.
   // DbAccessor *db_accessor;
-  msgs::ShardRequestManagerInterface *manager;
+  ShardRequestManagerInterface *manager;
   utils::MemoryResource *memory;
   int64_t timestamp;
   std::unordered_map<std::string, int64_t> *counters;
diff --git a/src/query/v2/interpreter.cpp b/src/query/v2/interpreter.cpp
index 045d94709..f9dc37184 100644
--- a/src/query/v2/interpreter.cpp
+++ b/src/query/v2/interpreter.cpp
@@ -143,7 +143,7 @@ class ReplQueryHandler final : public query::v2::ReplicationQueryHandler {
 /// @throw QueryRuntimeException if an error ocurred.
 
 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
   // password should be either null or string literal and it's evaluation
   // should not depend on frame.
@@ -312,7 +312,7 @@ Callback HandleAuthQuery(AuthQuery *auth_query, AuthQueryHandler *auth, const Pa
 }
 
 Callback HandleReplicationQuery(ReplicationQuery *repl_query, const Parameters &parameters,
-                                InterpreterContext *interpreter_context, msgs::ShardRequestManagerInterface *manager,
+                                InterpreterContext *interpreter_context, ShardRequestManagerInterface *manager,
                                 std::vector<Notification> *notifications) {
   expr::Frame<TypedValue> frame(0);
   SymbolTable symbol_table;
@@ -448,7 +448,7 @@ Callback HandleReplicationQuery(ReplicationQuery *repl_query, const Parameters &
 }
 
 Callback HandleSettingQuery(SettingQuery *setting_query, const Parameters &parameters,
-                            msgs::ShardRequestManagerInterface *manager) {
+                            ShardRequestManagerInterface *manager) {
   expr::Frame<TypedValue> frame(0);
   SymbolTable symbol_table;
   EvaluationContext evaluation_context;
@@ -649,7 +649,7 @@ struct PullPlanVector {
 struct PullPlan {
   explicit PullPlan(std::shared_ptr<CachedPlan> plan, const Parameters &parameters, bool is_profile_query,
                     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,
                     std::optional<size_t> memory_limit = {});
   std::optional<plan::ProfilingStatsWithTotalTime> Pull(AnyStream *stream, std::optional<int> n,
@@ -679,7 +679,7 @@ struct PullPlan {
 
 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,
-                   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),
       cursor_(plan->plan().MakeCursor(execution_memory)),
       frame_(plan->symbol_table().max_position(), execution_memory),
@@ -804,7 +804,7 @@ Interpreter::Interpreter(InterpreterContext *interpreter_context) : interpreter_
   auto random_uuid = boost::uuids::uuid{boost::uuids::random_generator()()};
   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>(
           query_io, interpreter_context_->coordinator_address, std::vector{interpreter_context_->coordinator_address}),
       std::move(query_io));
@@ -881,7 +881,7 @@ PreparedQuery Interpreter::PrepareTransactionQuery(std::string_view query_upper)
 PreparedQuery PrepareCypherQuery(ParsedQuery parsed_query, std::map<std::string, TypedValue> *summary,
                                  InterpreterContext *interpreter_context, DbAccessor *dba,
                                  utils::MemoryResource *execution_memory, std::vector<Notification> *notifications,
-                                 msgs::ShardRequestManagerInterface *shard_request_manager) {
+                                 ShardRequestManagerInterface *shard_request_manager) {
   //                                 TriggerContextCollector *trigger_context_collector = nullptr) {
   auto *cypher_query = utils::Downcast<CypherQuery>(parsed_query.query);
 
@@ -942,7 +942,7 @@ PreparedQuery PrepareCypherQuery(ParsedQuery parsed_query, std::map<std::string,
 
 PreparedQuery PrepareExplainQuery(ParsedQuery parsed_query, std::map<std::string, TypedValue> *summary,
                                   InterpreterContext *interpreter_context,
-                                  msgs::ShardRequestManagerInterface *shard_request_manager,
+                                  ShardRequestManagerInterface *shard_request_manager,
                                   utils::MemoryResource *execution_memory) {
   const std::string kExplainQueryStart = "explain ";
   MG_ASSERT(utils::StartsWith(utils::ToLowerCase(parsed_query.stripped_query.query()), kExplainQueryStart),
@@ -991,7 +991,7 @@ PreparedQuery PrepareExplainQuery(ParsedQuery parsed_query, std::map<std::string
 PreparedQuery PrepareProfileQuery(ParsedQuery parsed_query, bool in_explicit_transaction,
                                   std::map<std::string, TypedValue> *summary, InterpreterContext *interpreter_context,
                                   DbAccessor *dba, utils::MemoryResource *execution_memory,
-                                  msgs::ShardRequestManagerInterface *shard_request_manager = nullptr) {
+                                  ShardRequestManagerInterface *shard_request_manager = nullptr) {
   const std::string kProfileQueryStart = "profile ";
 
   MG_ASSERT(utils::StartsWith(utils::ToLowerCase(parsed_query.stripped_query.query()), kProfileQueryStart),
@@ -1185,7 +1185,7 @@ PreparedQuery PrepareIndexQuery(ParsedQuery parsed_query, bool in_explicit_trans
 PreparedQuery PrepareAuthQuery(ParsedQuery parsed_query, bool in_explicit_transaction,
                                std::map<std::string, TypedValue> *summary, InterpreterContext *interpreter_context,
                                DbAccessor *dba, utils::MemoryResource *execution_memory,
-                               msgs::ShardRequestManagerInterface *manager) {
+                               ShardRequestManagerInterface *manager) {
   if (in_explicit_transaction) {
     throw UserModificationInMulticommandTxException();
   }
@@ -1221,7 +1221,7 @@ PreparedQuery PrepareAuthQuery(ParsedQuery parsed_query, bool in_explicit_transa
 
 PreparedQuery PrepareReplicationQuery(ParsedQuery parsed_query, const bool in_explicit_transaction,
                                       std::vector<Notification> *notifications, InterpreterContext *interpreter_context,
-                                      msgs::ShardRequestManagerInterface *manager) {
+                                      ShardRequestManagerInterface *manager) {
   if (in_explicit_transaction) {
     throw ReplicationModificationInMulticommandTxException();
   }
@@ -1317,7 +1317,7 @@ PreparedQuery PrepareCreateSnapshotQuery(ParsedQuery parsed_query, bool in_expli
 }
 
 PreparedQuery PrepareSettingQuery(ParsedQuery parsed_query, const bool in_explicit_transaction,
-                                  msgs::ShardRequestManagerInterface *manager) {
+                                  ShardRequestManagerInterface *manager) {
   if (in_explicit_transaction) {
     throw SettingConfigInMulticommandTxException{};
   }
diff --git a/src/query/v2/interpreter.hpp b/src/query/v2/interpreter.hpp
index dc413ef44..afc298a0c 100644
--- a/src/query/v2/interpreter.hpp
+++ b/src/query/v2/interpreter.hpp
@@ -296,7 +296,7 @@ class Interpreter final {
    */
   void Abort();
 
-  const msgs::ShardRequestManagerInterface *GetShardRequestManager() const { return shard_request_manager_.get(); }
+  const ShardRequestManagerInterface *GetShardRequestManager() const { return shard_request_manager_.get(); }
 
  private:
   struct QueryExecution {
@@ -342,7 +342,7 @@ class Interpreter final {
   // move this unique_ptr into a shared_ptr.
   std::unique_ptr<storage::v3::Shard::Accessor> 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 expect_rollback_{false};
 
diff --git a/src/query/v2/plan/operator.cpp b/src/query/v2/plan/operator.cpp
index d82d83034..30db1012e 100644
--- a/src/query/v2/plan/operator.cpp
+++ b/src/query/v2/plan/operator.cpp
@@ -252,7 +252,7 @@ class DistributedCreateNodeCursor : public Cursor {
   std::vector<const NodeCreationInfo *> nodes_info_;
   std::vector<std::vector<std::pair<storage::v3::PropertyId, msgs::Value>>> src_vertex_props_;
   std::vector<msgs::PrimaryKey> primary_keys_;
-  msgs::ExecutionState<msgs::CreateVerticesRequest> state_;
+  ExecutionState<msgs::CreateVerticesRequest> state_;
 };
 
 bool Once::OnceCursor::Pull(Frame &, ExecutionContext &context) {
@@ -365,7 +365,7 @@ class ScanAllCursor : public Cursor {
   std::optional<decltype(vertices_.value().begin())> vertices_it_;
   const char *op_name_;
   std::vector<msgs::ScanVerticesResponse> current_batch;
-  msgs::ExecutionState<msgs::ScanVerticesRequest> request_state;
+  ExecutionState<msgs::ScanVerticesRequest> request_state;
 };
 
 class DistributedScanAllAndFilterCursor : public Cursor {
@@ -386,7 +386,7 @@ class DistributedScanAllAndFilterCursor : public Cursor {
 
   using VertexAccessor = accessors::VertexAccessor;
 
-  bool MakeRequest(msgs::ShardRequestManagerInterface &shard_manager, ExecutionContext &context) {
+  bool MakeRequest(ShardRequestManagerInterface &shard_manager, ExecutionContext &context) {
     {
       SCOPED_REQUEST_WAIT_PROFILE;
       current_batch = shard_manager.Request(request_state_);
@@ -403,7 +403,7 @@ class DistributedScanAllAndFilterCursor : public Cursor {
       if (MustAbort(context)) {
         throw HintedAbortError();
       }
-      using State = msgs::ExecutionState<msgs::ScanVerticesRequest>;
+      using State = ExecutionState<msgs::ScanVerticesRequest>;
 
       if (request_state_.state == State::INITIALIZING) {
         if (!input_cursor_->Pull(frame, context)) {
@@ -430,7 +430,7 @@ class DistributedScanAllAndFilterCursor : public Cursor {
   void ResetExecutionState() {
     current_batch.clear();
     current_vertex_it = current_batch.end();
-    request_state_ = msgs::ExecutionState<msgs::ScanVerticesRequest>{};
+    request_state_ = ExecutionState<msgs::ScanVerticesRequest>{};
   }
 
   void Reset() override {
@@ -444,7 +444,7 @@ class DistributedScanAllAndFilterCursor : public Cursor {
   const char *op_name_;
   std::vector<VertexAccessor> current_batch;
   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<std::pair<storage::v3::PropertyId, Expression *>> property_expression_pair_;
   std::optional<std::vector<Expression *>> filter_expressions_;
@@ -2426,7 +2426,7 @@ class DistributedCreateExpandCursor : public Cursor {
 
   const UniqueCursorPtr input_cursor_;
   const CreateExpand &self_;
-  msgs::ExecutionState<msgs::CreateExpandRequest> state_;
+  ExecutionState<msgs::CreateExpandRequest> state_;
 };
 
 class DistributedExpandCursor : public Cursor {
@@ -2473,7 +2473,7 @@ class DistributedExpandCursor : public Cursor {
     request.edge_properties.emplace();
     request.src_vertices.push_back(get_dst_vertex(edge, direction));
     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));
     MG_ASSERT(result_rows.size() == 1);
     auto &result_row = result_rows.front();
@@ -2499,7 +2499,7 @@ class DistributedExpandCursor : public Cursor {
       // to not fetch any properties of the edges
       request.edge_properties.emplace();
       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 {
         SCOPED_REQUEST_WAIT_PROFILE;
         return context.shard_request_manager->Request(request_state, std::move(request));
diff --git a/src/query/v2/plan/pretty_print.cpp b/src/query/v2/plan/pretty_print.cpp
index b756a6299..b7ab6da6e 100644
--- a/src/query/v2/plan/pretty_print.cpp
+++ b/src/query/v2/plan/pretty_print.cpp
@@ -19,7 +19,7 @@
 
 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) {}
 
 #define PRE_VISIT(TOp)                                   \
@@ -263,14 +263,14 @@ void PlanPrinter::Branch(query::v2::plan::LogicalOperator &op, const std::string
   --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) {
   PlanPrinter printer(&request_manager, out);
   // FIXME(mtomic): We should make visitors that take const arguments.
   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);
   // FIXME(mtomic): We should make visitors that take const arguments.
   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(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);
 }
 
-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);
 }
 
-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);
 }
 
@@ -369,7 +369,7 @@ json ToJson(NamedExpression *nexpr) {
 }
 
 json ToJson(const std::vector<std::pair<storage::v3::PropertyId, Expression *>> &properties,
-            const msgs::ShardRequestManagerInterface &request_manager) {
+            const ShardRequestManagerInterface &request_manager) {
   json json;
   for (const auto &prop_pair : properties) {
     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;
 }
 
-json ToJson(const NodeCreationInfo &node_info, const msgs::ShardRequestManagerInterface &request_manager) {
+json ToJson(const NodeCreationInfo &node_info, const ShardRequestManagerInterface &request_manager) {
   json self;
   self["symbol"] = ToJson(node_info.symbol);
   self["labels"] = ToJson(node_info.labels, request_manager);
@@ -386,7 +386,7 @@ json ToJson(const NodeCreationInfo &node_info, const msgs::ShardRequestManagerIn
   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;
   self["symbol"] = ToJson(edge_info.symbol);
   const auto *props = std::get_if<PropertiesMapList>(&edge_info.properties);
diff --git a/src/query/v2/plan/pretty_print.hpp b/src/query/v2/plan/pretty_print.hpp
index c7442b196..8485723a3 100644
--- a/src/query/v2/plan/pretty_print.hpp
+++ b/src/query/v2/plan/pretty_print.hpp
@@ -30,17 +30,17 @@ class LogicalOperator;
 /// 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
 /// 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);
 
 /// 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);
 }
 
 /// Convert a `LogicalOperator` plan to a JSON representation.
 /// 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 {
  public:
@@ -48,7 +48,7 @@ class PlanPrinter : public virtual HierarchicalLogicalOperatorVisitor {
   using HierarchicalLogicalOperatorVisitor::PreVisit;
   using HierarchicalLogicalOperatorVisitor::Visit;
 
-  PlanPrinter(const msgs::ShardRequestManagerInterface *request_manager, std::ostream *out);
+  PlanPrinter(const ShardRequestManagerInterface *request_manager, std::ostream *out);
 
   bool DefaultPreVisit() override;
 
@@ -115,7 +115,7 @@ class PlanPrinter : public virtual HierarchicalLogicalOperatorVisitor {
   void Branch(LogicalOperator &op, const std::string &branch_name = "");
 
   int64_t depth_{0};
-  const msgs::ShardRequestManagerInterface *request_manager_{nullptr};
+  const ShardRequestManagerInterface *request_manager_{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(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(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);
 
@@ -161,8 +161,7 @@ nlohmann::json ToJson(const std::vector<T> &items, Args &&...args) {
 
 class PlanToJsonVisitor : public virtual HierarchicalLogicalOperatorVisitor {
  public:
-  explicit PlanToJsonVisitor(const msgs::ShardRequestManagerInterface *request_manager)
-      : request_manager_(request_manager) {}
+  explicit PlanToJsonVisitor(const ShardRequestManagerInterface *request_manager) : request_manager_(request_manager) {}
 
   using HierarchicalLogicalOperatorVisitor::PostVisit;
   using HierarchicalLogicalOperatorVisitor::PreVisit;
@@ -218,7 +217,7 @@ class PlanToJsonVisitor : public virtual HierarchicalLogicalOperatorVisitor {
 
  protected:
   nlohmann::json output_;
-  const msgs::ShardRequestManagerInterface *request_manager_;
+  const ShardRequestManagerInterface *request_manager_;
 
   nlohmann::json PopOutput() {
     nlohmann::json tmp;
diff --git a/src/query/v2/plan/vertex_count_cache.hpp b/src/query/v2/plan/vertex_count_cache.hpp
index a7bfbdf85..47a10ba3e 100644
--- a/src/query/v2/plan/vertex_count_cache.hpp
+++ b/src/query/v2/plan/vertex_count_cache.hpp
@@ -57,7 +57,7 @@ class VertexCountCache {
 
   bool LabelPropertyIndexExists(storage::v3::LabelId /*label*/, storage::v3::PropertyId /*property*/) { return false; }
 
-  msgs::ShardRequestManagerInterface *shard_request_manager_;
+  ShardRequestManagerInterface *shard_request_manager_;
 };
 
 template <class TDbAccessor>
diff --git a/src/query/v2/shard_request_manager.hpp b/src/query/v2/shard_request_manager.hpp
index 20bae7b97..68a10f384 100644
--- a/src/query/v2/shard_request_manager.hpp
+++ b/src/query/v2/shard_request_manager.hpp
@@ -42,13 +42,12 @@
 #include "storage/v3/value_conversions.hpp"
 #include "utils/result.hpp"
 
-namespace memgraph::msgs {
+namespace memgraph::query::v2 {
 template <typename TStorageClient>
 class RsmStorageClientManager {
  public:
-  using CompoundKey = memgraph::io::rsm::ShardRsmKey;
-  using Shard = memgraph::coordinator::Shard;
-  using LabelId = memgraph::storage::v3::LabelId;
+  using CompoundKey = io::rsm::ShardRsmKey;
+  using Shard = coordinator::Shard;
   RsmStorageClientManager() = default;
   RsmStorageClientManager(const RsmStorageClientManager &) = delete;
   RsmStorageClientManager(RsmStorageClientManager &&) = delete;
@@ -74,8 +73,8 @@ class RsmStorageClientManager {
 
 template <typename TRequest>
 struct ExecutionState {
-  using CompoundKey = memgraph::io::rsm::ShardRsmKey;
-  using Shard = memgraph::coordinator::Shard;
+  using CompoundKey = io::rsm::ShardRsmKey;
+  using Shard = coordinator::Shard;
 
   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
@@ -85,7 +84,7 @@ struct ExecutionState {
   // of a shard. One example is ScanAll, where we only require the field label.
   std::optional<CompoundKey> key;
   // 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
   // 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
@@ -104,7 +103,7 @@ struct ExecutionState {
 
 class ShardRequestManagerInterface {
  public:
-  using VertexAccessor = memgraph::query::v2::accessors::VertexAccessor;
+  using VertexAccessor = query::v2::accessors::VertexAccessor;
   ShardRequestManagerInterface() = default;
   ShardRequestManagerInterface(const ShardRequestManagerInterface &) = delete;
   ShardRequestManagerInterface(ShardRequestManagerInterface &&) = delete;
@@ -115,38 +114,38 @@ class ShardRequestManagerInterface {
 
   virtual void StartTransaction() = 0;
   virtual void Commit() = 0;
-  virtual std::vector<VertexAccessor> Request(ExecutionState<ScanVerticesRequest> &state) = 0;
-  virtual std::vector<CreateVerticesResponse> Request(ExecutionState<CreateVerticesRequest> &state,
-                                                      std::vector<NewVertex> new_vertices) = 0;
-  virtual std::vector<ExpandOneResultRow> Request(ExecutionState<ExpandOneRequest> &state,
-                                                  ExpandOneRequest request) = 0;
-  virtual std::vector<CreateExpandResponse> Request(ExecutionState<CreateExpandRequest> &state,
-                                                    std::vector<NewExpand> new_edges) = 0;
+  virtual std::vector<VertexAccessor> Request(ExecutionState<msgs::ScanVerticesRequest> &state) = 0;
+  virtual std::vector<msgs::CreateVerticesResponse> Request(ExecutionState<msgs::CreateVerticesRequest> &state,
+                                                            std::vector<msgs::NewVertex> new_vertices) = 0;
+  virtual std::vector<msgs::ExpandOneResultRow> Request(ExecutionState<msgs::ExpandOneRequest> &state,
+                                                        msgs::ExpandOneRequest request) = 0;
+  virtual std::vector<msgs::CreateExpandResponse> Request(ExecutionState<msgs::CreateExpandRequest> &state,
+                                                          std::vector<msgs::NewExpand> new_edges) = 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::LabelId NameToLabel(const std::string &name) 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 &EdgeTypeToName(memgraph::storage::v3::EdgeTypeId type) const = 0;
-  virtual bool IsPrimaryLabel(LabelId label) const = 0;
-  virtual bool IsPrimaryKey(LabelId primary_label, PropertyId property) const = 0;
+  virtual const std::string &PropertyToName(storage::v3::PropertyId prop) const = 0;
+  virtual const std::string &LabelToName(storage::v3::LabelId label) const = 0;
+  virtual const std::string &EdgeTypeToName(storage::v3::EdgeTypeId type) 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
 template <typename TTransport>
 class ShardRequestManager : public ShardRequestManagerInterface {
  public:
-  using StorageClient =
-      memgraph::coordinator::RsmClient<TTransport, WriteRequests, WriteResponses, ReadRequests, ReadResponses>;
-  using CoordinatorWriteRequests = memgraph::coordinator::CoordinatorWriteRequests;
-  using CoordinatorClient = memgraph::coordinator::CoordinatorClient<TTransport>;
-  using Address = memgraph::io::Address;
-  using Shard = memgraph::coordinator::Shard;
-  using ShardMap = memgraph::coordinator::ShardMap;
-  using CompoundKey = memgraph::coordinator::PrimaryKey;
-  using VertexAccessor = memgraph::query::v2::accessors::VertexAccessor;
-  ShardRequestManager(CoordinatorClient coord, memgraph::io::Io<TTransport> &&io)
+  using StorageClient = coordinator::RsmClient<TTransport, msgs::WriteRequests, msgs::WriteResponses,
+                                               msgs::ReadRequests, msgs::ReadResponses>;
+  using CoordinatorWriteRequests = coordinator::CoordinatorWriteRequests;
+  using CoordinatorClient = coordinator::CoordinatorClient<TTransport>;
+  using Address = io::Address;
+  using Shard = coordinator::Shard;
+  using ShardMap = coordinator::ShardMap;
+  using CompoundKey = coordinator::PrimaryKey;
+  using VertexAccessor = query::v2::accessors::VertexAccessor;
+  ShardRequestManager(CoordinatorClient coord, io::Io<TTransport> &&io)
       : coord_cli_(std::move(coord)), io_(std::move(io)) {}
 
   ShardRequestManager(const ShardRequestManager &) = delete;
@@ -157,14 +156,14 @@ class ShardRequestManager : public ShardRequestManagerInterface {
   ~ShardRequestManager() 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;
     auto write_res = coord_cli_.SendWriteRequest(write_req);
     if (write_res.HasError()) {
       throw std::runtime_error("HLC request failed");
     }
     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_ = hlc_response.new_hlc;
@@ -176,14 +175,14 @@ class ShardRequestManager : public ShardRequestManagerInterface {
   }
 
   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;
     auto write_res = coord_cli_.SendWriteRequest(write_req);
     if (write_res.HasError()) {
       throw std::runtime_error("HLC request for commit failed");
     }
     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) {
       shards_map_ = hlc_response.fresher_shard_map.value();
@@ -204,8 +203,8 @@ class ShardRequestManager : public ShardRequestManagerInterface {
         if (commit_response.HasError()) {
           throw std::runtime_error("Commit request timed out");
         }
-        WriteResponses write_response_variant = commit_response.GetValue();
-        auto &response = std::get<CommitResponse>(write_response_variant);
+        msgs::WriteResponses write_response_variant = commit_response.GetValue();
+        auto &response = std::get<msgs::CommitResponse>(write_response_variant);
         if (response.error) {
           throw std::runtime_error("Commit request did not succeed");
         }
@@ -225,17 +224,15 @@ class ShardRequestManager : public ShardRequestManagerInterface {
     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());
   }
-  const std::string &LabelToName(memgraph::storage::v3::LabelId id) const override {
-    return labels_.IdToName(id.AsUint());
-  }
-  const std::string &EdgeTypeToName(memgraph::storage::v3::EdgeTypeId id) const override {
+  const std::string &LabelToName(storage::v3::LabelId id) const override { return labels_.IdToName(id.AsUint()); }
+  const std::string &EdgeTypeToName(storage::v3::EdgeTypeId id) const override {
     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);
     MG_ASSERT(schema_it != shards_map_.schemas.end(), "Invalid primary label id: {}", primary_label.AsUint());
 
@@ -244,12 +241,12 @@ class ShardRequestManager : public ShardRequestManagerInterface {
            }) != 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
-  std::vector<VertexAccessor> Request(ExecutionState<ScanVerticesRequest> &state) override {
+  std::vector<VertexAccessor> Request(ExecutionState<msgs::ScanVerticesRequest> &state) override {
     MaybeInitializeExecutionState(state);
-    std::vector<ScanVerticesResponse> responses;
+    std::vector<msgs::ScanVerticesResponse> responses;
 
     SendAllRequests(state);
     auto all_requests_gathered = [](auto &paginated_rsp_tracker) {
@@ -273,11 +270,11 @@ class ShardRequestManager : public ShardRequestManagerInterface {
     return PostProcess(std::move(responses));
   }
 
-  std::vector<CreateVerticesResponse> Request(ExecutionState<CreateVerticesRequest> &state,
-                                              std::vector<NewVertex> new_vertices) override {
+  std::vector<msgs::CreateVerticesResponse> Request(ExecutionState<msgs::CreateVerticesRequest> &state,
+                                                    std::vector<msgs::NewVertex> new_vertices) override {
     MG_ASSERT(!new_vertices.empty());
     MaybeInitializeExecutionState(state, new_vertices);
-    std::vector<CreateVerticesResponse> responses;
+    std::vector<msgs::CreateVerticesResponse> responses;
     auto &shard_cache_ref = state.shard_cache;
 
     // 1. Send the requests.
@@ -294,22 +291,22 @@ class ShardRequestManager : public ShardRequestManagerInterface {
     return responses;
   }
 
-  std::vector<CreateExpandResponse> Request(ExecutionState<CreateExpandRequest> &state,
-                                            std::vector<NewExpand> new_edges) override {
+  std::vector<msgs::CreateExpandResponse> Request(ExecutionState<msgs::CreateExpandRequest> &state,
+                                                  std::vector<msgs::NewExpand> new_edges) override {
     MG_ASSERT(!new_edges.empty());
     MaybeInitializeExecutionState(state, new_edges);
-    std::vector<CreateExpandResponse> responses;
+    std::vector<msgs::CreateExpandResponse> responses;
     auto &shard_cache_ref = state.shard_cache;
     size_t id{0};
     for (auto shard_it = shard_cache_ref.begin(); shard_it != shard_cache_ref.end(); ++id) {
       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));
       if (write_response_result.HasError()) {
         throw std::runtime_error("CreateVertices request timedout");
       }
-      WriteResponses response_variant = write_response_result.GetValue();
-      CreateExpandResponse mapped_response = std::get<CreateExpandResponse>(response_variant);
+      msgs::WriteResponses response_variant = write_response_result.GetValue();
+      msgs::CreateExpandResponse mapped_response = std::get<msgs::CreateExpandResponse>(response_variant);
 
       if (mapped_response.error) {
         throw std::runtime_error("CreateExpand request did not succeed");
@@ -322,14 +319,15 @@ class ShardRequestManager : public ShardRequestManagerInterface {
     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
     // Expansions of the destination must be handled by the caller. For example
     // 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
     // must be fetched again with an ExpandOne(Edges.dst)
     MaybeInitializeExecutionState(state, std::move(request));
-    std::vector<ExpandOneResponse> responses;
+    std::vector<msgs::ExpandOneResponse> responses;
     auto &shard_cache_ref = state.shard_cache;
 
     // 1. Send the requests.
@@ -339,10 +337,11 @@ class ShardRequestManager : public ShardRequestManagerInterface {
     do {
       AwaitOnResponses(state, responses);
     } while (!state.shard_cache.empty());
-    std::vector<ExpandOneResultRow> result_rows;
-    const auto total_row_count = std::accumulate(
-        responses.begin(), responses.end(), 0,
-        [](const int64_t partial_count, const ExpandOneResponse &resp) { return partial_count + resp.result.size(); });
+    std::vector<msgs::ExpandOneResultRow> result_rows;
+    const auto total_row_count = std::accumulate(responses.begin(), responses.end(), 0,
+                                                 [](const int64_t partial_count, const msgs::ExpandOneResponse &resp) {
+                                                   return partial_count + resp.result.size();
+                                                 });
     result_rows.reserve(total_row_count);
 
     for (auto &response : responses) {
@@ -356,7 +355,7 @@ class ShardRequestManager : public ShardRequestManagerInterface {
  private:
   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;
     for (auto &response : responses) {
       for (auto &result_row : response.results) {
@@ -385,22 +384,22 @@ class ShardRequestManager : public ShardRequestManagerInterface {
     return state.state != ExecutionState::INITIALIZING;
   }
 
-  void MaybeInitializeExecutionState(ExecutionState<CreateVerticesRequest> &state,
-                                     std::vector<NewVertex> new_vertices) {
+  void MaybeInitializeExecutionState(ExecutionState<msgs::CreateVerticesRequest> &state,
+                                     std::vector<msgs::NewVertex> new_vertices) {
     ThrowIfStateCompleted(state);
     if (ShallNotInitializeState(state)) {
       return;
     }
     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) {
       MG_ASSERT(!new_vertex.label_ids.empty(), "This is error!");
       auto shard = shards_map_.GetShardForKey(new_vertex.label_ids[0].id,
                                               storage::conversions::ConvertPropertyVector(new_vertex.primary_key));
       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)));
         state.shard_cache.push_back(shard);
       }
@@ -410,21 +409,22 @@ class ShardRequestManager : public ShardRequestManagerInterface {
     for (auto &[shard, rqst] : per_shard_request_table) {
       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);
     if (ShallNotInitializeState(state)) {
       return;
     }
     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,
                                          transaction_id = transaction_id_](const Shard &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)});
       }
     };
@@ -448,10 +448,10 @@ class ShardRequestManager : public ShardRequestManagerInterface {
       state.shard_cache.push_back(shard);
       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);
     if (ShallNotInitializeState(state)) {
       return;
@@ -471,23 +471,23 @@ class ShardRequestManager : public ShardRequestManagerInterface {
       for (auto &[key, shard] : shards) {
         MG_ASSERT(!shard.empty());
         state.shard_cache.push_back(std::move(shard));
-        ScanVerticesRequest rqst;
+        msgs::ScanVerticesRequest rqst;
         rqst.transaction_id = transaction_id_;
         rqst.start_id.second = storage::conversions::ConvertValueVector(key);
         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);
     if (ShallNotInitializeState(state)) {
       return;
     }
     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;
     top_level_rqst_template.transaction_id = transaction_id_;
     top_level_rqst_template.src_vertices.clear();
@@ -505,7 +505,7 @@ class ShardRequestManager : public ShardRequestManagerInterface {
     for (auto &[shard, rqst] : per_shard_request_table) {
       state.requests.push_back(std::move(rqst));
     }
-    state.state = ExecutionState<ExpandOneRequest>::EXECUTING;
+    state.state = ExecutionState<msgs::ExpandOneRequest>::EXECUTING;
   }
 
   StorageClient &GetStorageClientForShard(Shard shard) {
@@ -532,20 +532,20 @@ class ShardRequestManager : public ShardRequestManagerInterface {
     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;
     for (const auto &request : state.requests) {
       const auto &current_shard = state.shard_cache[shard_idx];
 
       auto &storage_client = GetStorageClientForShard(current_shard);
-      ReadRequests req = request;
+      msgs::ReadRequests req = request;
       storage_client.SendAsyncReadRequest(request);
 
       ++shard_idx;
     }
   }
 
-  void SendAllRequests(ExecutionState<CreateVerticesRequest> &state,
+  void SendAllRequests(ExecutionState<msgs::CreateVerticesRequest> &state,
                        std::vector<memgraph::coordinator::Shard> &shard_cache_ref) {
     size_t id = 0;
     for (auto shard_it = shard_cache_ref.begin(); shard_it != shard_cache_ref.end(); ++shard_it) {
@@ -559,24 +559,25 @@ class ShardRequestManager : public ShardRequestManagerInterface {
 
       auto &storage_client = GetStorageClientForShard(*shard_it);
 
-      WriteRequests req = req_deep_copy;
+      msgs::WriteRequests req = req_deep_copy;
       storage_client.SendAsyncWriteRequest(req);
       ++id;
     }
   }
 
-  void SendAllRequests(ExecutionState<ExpandOneRequest> &state,
+  void SendAllRequests(ExecutionState<msgs::ExpandOneRequest> &state,
                        std::vector<memgraph::coordinator::Shard> &shard_cache_ref) {
     size_t id = 0;
     for (auto shard_it = shard_cache_ref.begin(); shard_it != shard_cache_ref.end(); ++shard_it) {
       auto &storage_client = GetStorageClientForShard(*shard_it);
-      ReadRequests req = state.requests[id];
+      msgs::ReadRequests req = state.requests[id];
       storage_client.SendAsyncReadRequest(req);
       ++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;
     int64_t request_idx = 0;
 
@@ -598,8 +599,8 @@ class ShardRequestManager : public ShardRequestManagerInterface {
         throw std::runtime_error("CreateVertices request timed out");
       }
 
-      WriteResponses response_variant = poll_result->GetValue();
-      auto response = std::get<CreateVerticesResponse>(response_variant);
+      msgs::WriteResponses response_variant = poll_result->GetValue();
+      auto response = std::get<msgs::CreateVerticesResponse>(response_variant);
 
       if (response.error) {
         throw std::runtime_error("CreateVertices request did not succeed");
@@ -613,7 +614,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;
     int64_t request_idx = 0;
 
@@ -631,8 +633,8 @@ class ShardRequestManager : public ShardRequestManagerInterface {
         throw std::runtime_error("ExpandOne request timed out");
       }
 
-      ReadResponses response_variant = poll_result->GetValue();
-      auto response = std::get<ExpandOneResponse>(response_variant);
+      msgs::ReadResponses response_variant = poll_result->GetValue();
+      auto response = std::get<msgs::ExpandOneResponse>(response_variant);
       // -NOTE-
       // Currently a boolean flag for signaling the overall success of the
       // ExpandOne request does not exist. But it should, so here we assume
@@ -649,8 +651,8 @@ class ShardRequestManager : public ShardRequestManagerInterface {
     }
   }
 
-  void AwaitOnPaginatedRequests(ExecutionState<ScanVerticesRequest> &state,
-                                std::vector<ScanVerticesResponse> &responses,
+  void AwaitOnPaginatedRequests(ExecutionState<msgs::ScanVerticesRequest> &state,
+                                std::vector<msgs::ScanVerticesResponse> &responses,
                                 std::map<Shard, PaginatedResponseState> &paginated_response_tracker) {
     auto &shard_cache_ref = state.shard_cache;
 
@@ -678,8 +680,8 @@ class ShardRequestManager : public ShardRequestManagerInterface {
         throw std::runtime_error("ScanAll request timed out");
       }
 
-      ReadResponses read_response_variant = await_result->GetValue();
-      auto response = std::get<ScanVerticesResponse>(read_response_variant);
+      msgs::ReadResponses read_response_variant = await_result->GetValue();
+      auto response = std::get<msgs::ScanVerticesResponse>(read_response_variant);
       if (response.error) {
         throw std::runtime_error("ScanAll request did not succeed");
       }
@@ -723,8 +725,8 @@ class ShardRequestManager : public ShardRequestManagerInterface {
   storage::v3::NameIdMapper labels_;
   CoordinatorClient coord_cli_;
   RsmStorageClientManager<StorageClient> storage_cli_manager_;
-  memgraph::io::Io<TTransport> io_;
-  memgraph::coordinator::Hlc transaction_id_;
+  io::Io<TTransport> io_;
+  coordinator::Hlc transaction_id_;
   // TODO(kostasrim) Add batch prefetching
 };
-}  // namespace memgraph::msgs
+}  // namespace memgraph::query::v2
diff --git a/tests/simulation/shard_request_manager.cpp b/tests/simulation/shard_request_manager.cpp
index 746ab385f..9db18659e 100644
--- a/tests/simulation/shard_request_manager.cpp
+++ b/tests/simulation/shard_request_manager.cpp
@@ -151,7 +151,7 @@ void RunStorageRaft(Raft<IoImpl, MockedShardRsm, WriteRequests, WriteResponses,
   server.Run();
 }
 
-void TestScanVertices(msgs::ShardRequestManagerInterface &io) {
+void TestScanVertices(query::v2::ShardRequestManagerInterface &io) {
   msgs::ExecutionState<ScanVerticesRequest> state{.label = "test_label"};
 
   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;
   msgs::ExecutionState<CreateVerticesRequest> state;
   std::vector<msgs::NewVertex> new_vertices;
@@ -187,7 +187,7 @@ void TestCreateVertices(msgs::ShardRequestManagerInterface &io) {
   MG_ASSERT(result.size() == 2);
 }
 
-void TestCreateExpand(msgs::ShardRequestManagerInterface &io) {
+void TestCreateExpand(query::v2::ShardRequestManagerInterface &io) {
   using PropVal = msgs::Value;
   msgs::ExecutionState<msgs::CreateExpandRequest> state;
   std::vector<msgs::NewExpand> new_expands;
@@ -209,7 +209,7 @@ void TestCreateExpand(msgs::ShardRequestManagerInterface &io) {
   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::ExpandOneRequest request;
   const auto edge_type_id = shard_request_manager.NameToEdgeType("edge_type");
@@ -337,7 +337,7 @@ void DoTest() {
   // also get the current shard map
   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();
   TestScanVertices(io);
diff --git a/tests/simulation/test_cluster.hpp b/tests/simulation/test_cluster.hpp
index 096009b7a..fd62b99f9 100644
--- a/tests/simulation/test_cluster.hpp
+++ b/tests/simulation/test_cluster.hpp
@@ -151,7 +151,7 @@ ShardMap TestShardMap(int n_splits, int replication_factor) {
   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) {
   const auto key1 = memgraph::storage::v3::PropertyValue(create_vertex.first);
   const auto key2 = memgraph::storage::v3::PropertyValue(create_vertex.second);
@@ -164,7 +164,7 @@ void ExecuteOp(msgs::ShardRequestManager<SimulatorTransport> &shard_request_mana
     return;
   }
 
-  msgs::ExecutionState<msgs::CreateVerticesRequest> state;
+  query::v2::ExecutionState<msgs::CreateVerticesRequest> state;
 
   auto label_id = shard_request_manager.NameToLabel("test_label");
 
@@ -182,9 +182,9 @@ void ExecuteOp(msgs::ShardRequestManager<SimulatorTransport> &shard_request_mana
   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) {
-  msgs::ExecutionState<msgs::ScanVerticesRequest> request{.label = "test_label"};
+  query::v2::ExecutionState<msgs::ScanVerticesRequest> request{.label = "test_label"};
 
   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});
   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();
 
diff --git a/tests/unit/high_density_shard_create_scan.cpp b/tests/unit/high_density_shard_create_scan.cpp
index a0c0a0c28..e586a3556 100644
--- a/tests/unit/high_density_shard_create_scan.cpp
+++ b/tests/unit/high_density_shard_create_scan.cpp
@@ -161,7 +161,7 @@ ShardMap TestShardMap(int shards, int replication_factor, int gap_between_shards
   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) {
   const auto key1 = memgraph::storage::v3::PropertyValue(create_vertex.first);
   const auto key2 = memgraph::storage::v3::PropertyValue(create_vertex.second);
@@ -174,7 +174,7 @@ void ExecuteOp(msgs::ShardRequestManager<LocalTransport> &shard_request_manager,
     return;
   }
 
-  msgs::ExecutionState<msgs::CreateVerticesRequest> state;
+  query::v2::ExecutionState<msgs::CreateVerticesRequest> state;
 
   auto label_id = shard_request_manager.NameToLabel("test_label");
 
@@ -192,9 +192,9 @@ void ExecuteOp(msgs::ShardRequestManager<LocalTransport> &shard_request_manager,
   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) {
-  msgs::ExecutionState<msgs::ScanVerticesRequest> request{.label = "test_label"};
+  query::v2::ExecutionState<msgs::ScanVerticesRequest> request{.label = "test_label"};
 
   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);
   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();
 
diff --git a/tests/unit/machine_manager.cpp b/tests/unit/machine_manager.cpp
index 110220eda..834523fee 100644
--- a/tests/unit/machine_manager.cpp
+++ b/tests/unit/machine_manager.cpp
@@ -111,15 +111,15 @@ ShardMap TestShardMap() {
 
 template <typename ShardRequestManager>
 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);
   EXPECT_EQ(result.size(), 2);
 }
 
-void TestCreateVertices(msgs::ShardRequestManagerInterface &shard_request_manager) {
+void TestCreateVertices(query::v2::ShardRequestManagerInterface &shard_request_manager) {
   using PropVal = msgs::Value;
-  msgs::ExecutionState<msgs::CreateVerticesRequest> state;
+  query::v2::ExecutionState<msgs::CreateVerticesRequest> state;
   std::vector<msgs::NewVertex> new_vertices;
   auto label_id = shard_request_manager.NameToLabel(kLabelName);
   msgs::NewVertex a1{.primary_key = {PropVal(int64_t(0)), PropVal(int64_t(0))}};
@@ -134,9 +134,9 @@ void TestCreateVertices(msgs::ShardRequestManagerInterface &shard_request_manage
   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;
-  msgs::ExecutionState<msgs::CreateExpandRequest> state;
+  query::v2::ExecutionState<msgs::CreateExpandRequest> state;
   std::vector<msgs::NewExpand> new_expands;
 
   const auto edge_type_id = shard_request_manager.NameToEdgeType("edge_type");
@@ -155,8 +155,8 @@ void TestCreateExpand(msgs::ShardRequestManagerInterface &shard_request_manager)
   MG_ASSERT(!responses[0].error.has_value());
 }
 
-void TestExpandOne(msgs::ShardRequestManagerInterface &shard_request_manager) {
-  msgs::ExecutionState<msgs::ExpandOneRequest> state{};
+void TestExpandOne(query::v2::ShardRequestManagerInterface &shard_request_manager) {
+  query::v2::ExecutionState<msgs::ExpandOneRequest> state{};
   msgs::ExpandOneRequest request;
   const auto edge_type_id = shard_request_manager.NameToEdgeType("edge_type");
   const auto label = msgs::Label{shard_request_manager.NameToLabel("test_label")};
@@ -226,7 +226,8 @@ TEST(MachineManager, BasicFunctionality) {
 
   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();
   TestCreateVertices(shard_request_manager);

From 6d3c04bd61400e6765d1fb948744b150e9fa2efa Mon Sep 17 00:00:00 2001
From: Tyler Neely <t@jujit.su>
Date: Mon, 28 Nov 2022 10:09:59 +0000
Subject: [PATCH 11/26] Address clang-tidy feedback

---
 src/query/v2/accessors.hpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/query/v2/accessors.hpp b/src/query/v2/accessors.hpp
index df4180818..ca7ec999d 100644
--- a/src/query/v2/accessors.hpp
+++ b/src/query/v2/accessors.hpp
@@ -26,7 +26,7 @@
 
 namespace memgraph::query::v2 {
 class ShardRequestManagerInterface;
-}
+}  // namespace memgraph::query::v2
 
 namespace memgraph::query::v2::accessors {
 

From ed0b67dfdb6d0a6449f48089042b5c0fb565af3d Mon Sep 17 00:00:00 2001
From: Kostas Kyrimis <kostaskyrim@gmail.com>
Date: Mon, 28 Nov 2022 13:38:12 +0200
Subject: [PATCH 12/26] Fix compilation issues of the merge

---
 src/query/v2/conversions.hpp                 |  2 +-
 src/query/v2/frontend/ast/ast.lcp            |  6 +++---
 src/query/v2/shard_request_manager.hpp       |  4 ++--
 tests/unit/query_v2_expression_evaluator.cpp | 18 ++++++++----------
 4 files changed, 14 insertions(+), 16 deletions(-)

diff --git a/src/query/v2/conversions.hpp b/src/query/v2/conversions.hpp
index baeaf90d5..a1db5ed17 100644
--- a/src/query/v2/conversions.hpp
+++ b/src/query/v2/conversions.hpp
@@ -56,7 +56,7 @@ inline TypedValue ValueToTypedValue(const msgs::Value &value, ShardRequestManage
   throw std::runtime_error("Incorrect type in conversion");
 }
 
-inline const auto ValueToTypedValueFunctor = [](const msgs::Value &value, msgs::ShardRequestManagerInterface *manager) {
+inline const auto ValueToTypedValueFunctor = [](const msgs::Value &value, ShardRequestManagerInterface *manager) {
   return ValueToTypedValue(value, manager);
 };
 
diff --git a/src/query/v2/frontend/ast/ast.lcp b/src/query/v2/frontend/ast/ast.lcp
index 209bdfd50..dadcc9fa7 100644
--- a/src/query/v2/frontend/ast/ast.lcp
+++ b/src/query/v2/frontend/ast/ast.lcp
@@ -838,14 +838,14 @@ cpp<#
               :slk-load (slk-load-ast-vector "Expression"))
    (function-name "std::string" :scope :public)
    (function "std::function<TypedValue(const TypedValue *, int64_t,
-                                       const functions::FunctionContext<msgs::ShardRequestManagerInterface> &)>"
+                                       const functions::FunctionContext<ShardRequestManagerInterface> &)>"
              :scope :public
              :dont-save t
              :clone :copy
              :slk-load (lambda (member)
                         #>cpp
                         self->${member} = functions::NameToFunction<TypedValue,
-                                            functions::FunctionContext<msgs::ShardRequestManagerInterface>,
+                                            functions::FunctionContext<ShardRequestManagerInterface>,
                                             functions::QueryEngineTag, decltype(ValueToTypedValueFunctor)>(self->function_name_);
                         cpp<#)))
   (:public
@@ -869,7 +869,7 @@ cpp<#
              const std::vector<Expression *> &arguments)
         : arguments_(arguments),
           function_name_(function_name),
-          function_(functions::NameToFunction<TypedValue, functions::FunctionContext<msgs::ShardRequestManagerInterface>,
+          function_(functions::NameToFunction<TypedValue, functions::FunctionContext<ShardRequestManagerInterface>,
                                               functions::QueryEngineTag, decltype(ValueToTypedValueFunctor)>(function_name_)) {
       if (!function_) {
         throw SemanticException("Function '{}' doesn't exist.", function_name);
diff --git a/src/query/v2/shard_request_manager.hpp b/src/query/v2/shard_request_manager.hpp
index 19fb81a08..581dfbcab 100644
--- a/src/query/v2/shard_request_manager.hpp
+++ b/src/query/v2/shard_request_manager.hpp
@@ -131,8 +131,8 @@ class ShardRequestManagerInterface {
   virtual std::optional<storage::v3::PropertyId> MaybeNameToProperty(const std::string &name) 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(LabelId label) const = 0;
-  virtual bool IsPrimaryKey(LabelId primary_label, PropertyId property) 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
diff --git a/tests/unit/query_v2_expression_evaluator.cpp b/tests/unit/query_v2_expression_evaluator.cpp
index de324ea2b..c2e0beee7 100644
--- a/tests/unit/query_v2_expression_evaluator.cpp
+++ b/tests/unit/query_v2_expression_evaluator.cpp
@@ -66,7 +66,7 @@ using memgraph::functions::FunctionRuntimeException;
 
 namespace memgraph::query::v2::tests {
 
-class MockedShardRequestManager : public memgraph::msgs::ShardRequestManagerInterface {
+class MockedShardRequestManager : public ShardRequestManagerInterface {
  public:
   using VertexAccessor = accessors::VertexAccessor;
   explicit MockedShardRequestManager(ShardMap shard_map) : shards_map_(std::move(shard_map)) { SetUpNameIdMappers(); }
@@ -83,22 +83,20 @@ class MockedShardRequestManager : public memgraph::msgs::ShardRequestManagerInte
   }
   void StartTransaction() override {}
   void Commit() override {}
-  std::vector<VertexAccessor> Request(
-      memgraph::msgs::ExecutionState<memgraph::msgs::ScanVerticesRequest> &state) override {
+  std::vector<VertexAccessor> Request(ExecutionState<memgraph::msgs::ScanVerticesRequest> &state) override {
     return {};
   }
 
-  std::vector<CreateVerticesResponse> Request(memgraph::msgs::ExecutionState<CreateVerticesRequest> &state,
+  std::vector<CreateVerticesResponse> Request(ExecutionState<CreateVerticesRequest> &state,
                                               std::vector<memgraph::msgs::NewVertex> new_vertices) override {
     return {};
   }
 
-  std::vector<ExpandOneResultRow> Request(memgraph::msgs::ExecutionState<ExpandOneRequest> &state,
-                                          ExpandOneRequest request) override {
+  std::vector<ExpandOneResultRow> Request(ExecutionState<ExpandOneRequest> &state, ExpandOneRequest request) override {
     return {};
   }
 
-  std::vector<CreateExpandResponse> Request(memgraph::msgs::ExecutionState<CreateExpandRequest> &state,
+  std::vector<CreateExpandResponse> Request(ExecutionState<CreateExpandRequest> &state,
                                             std::vector<NewExpand> new_edges) override {
     return {};
   }
@@ -218,7 +216,7 @@ class ExpressionEvaluatorTest : public ::testing::Test {
   SymbolTable symbol_table;
 
   Frame frame{128};
-  std::unique_ptr<memgraph::msgs::ShardRequestManagerInterface> shard_manager =
+  std::unique_ptr<ShardRequestManagerInterface> shard_manager =
       std::make_unique<MockedShardRequestManager>(CreateDummyShardmap());
   ExpressionEvaluator eval{&frame, symbol_table, ctx, shard_manager.get(), memgraph::storage::v3::View::OLD};
 
@@ -546,13 +544,13 @@ using VertexId = memgraph::msgs::VertexId;
 using Label = memgraph::msgs::Label;
 
 accessors::VertexAccessor CreateVertex(std::vector<std::pair<PropertyId, Value>> props,
-                                       const memgraph::msgs::ShardRequestManagerInterface *manager, Label label = {}) {
+                                       const ShardRequestManagerInterface *manager, Label label = {}) {
   static int64_t id = 0;
   return {Vertex{VertexId{label, {memgraph::msgs::Value(id++)}}, {label}}, std::move(props), manager};
 }
 
 accessors::EdgeAccessor CreateEdge(std::vector<std::pair<PropertyId, Value>> props,
-                                   const memgraph::msgs::ShardRequestManagerInterface *manager) {
+                                   const ShardRequestManagerInterface *manager) {
   auto edge = Edge{.src = VertexId{{}, {}},
                    .dst = VertexId{{}, {}},
                    .properties = std::move(props),

From 82db1d4ad8ddfa2765ebaa021ae4f7e0253a9b61 Mon Sep 17 00:00:00 2001
From: Tyler Neely <t@jujit.su>
Date: Mon, 28 Nov 2022 12:38:38 +0000
Subject: [PATCH 13/26] Rename ShardRequestManager to RequestRouter

---
 src/glue/v2/communication.cpp                 | 30 +++---
 src/glue/v2/communication.hpp                 | 24 ++---
 src/memgraph.cpp                              | 13 ++-
 src/query/v2/accessors.cpp                    | 11 +--
 src/query/v2/accessors.hpp                    | 15 ++-
 src/query/v2/bindings/eval.hpp                | 11 +--
 src/query/v2/context.hpp                      | 16 ++--
 src/query/v2/conversions.hpp                  |  4 +-
 src/query/v2/cypher_query_interpreter.cpp     |  6 +-
 src/query/v2/cypher_query_interpreter.hpp     |  4 +-
 .../interpret/awesome_memgraph_functions.cpp  |  2 +-
 .../interpret/awesome_memgraph_functions.hpp  |  6 +-
 src/query/v2/interpreter.cpp                  | 96 +++++++++----------
 src/query/v2/interpreter.hpp                  |  4 +-
 src/query/v2/plan/operator.cpp                | 66 ++++++-------
 src/query/v2/plan/pretty_print.cpp            | 21 ++--
 src/query/v2/plan/pretty_print.hpp            | 31 +++---
 src/query/v2/plan/rule_based_planner.hpp      |  2 +-
 src/query/v2/plan/vertex_count_cache.hpp      | 14 +--
 ...request_manager.hpp => request_router.hpp} | 35 ++++---
 ...request_manager.cpp => request_router.cpp} | 22 ++---
 tests/simulation/test_cluster.hpp             | 23 +++--
 tests/unit/high_density_shard_create_scan.cpp | 25 +++--
 tests/unit/machine_manager.cpp                | 47 +++++----
 24 files changed, 255 insertions(+), 273 deletions(-)
 rename src/query/v2/{shard_request_manager.hpp => request_router.hpp} (96%)
 rename tests/simulation/{shard_request_manager.cpp => request_router.cpp} (94%)

diff --git a/src/glue/v2/communication.cpp b/src/glue/v2/communication.cpp
index 3406105b0..42228652f 100644
--- a/src/glue/v2/communication.cpp
+++ b/src/glue/v2/communication.cpp
@@ -18,8 +18,8 @@
 #include "common/errors.hpp"
 #include "coordinator/shard_map.hpp"
 #include "query/v2/accessors.hpp"
+#include "query/v2/request_router.hpp"
 #include "query/v2/requests.hpp"
-#include "query/v2/shard_request_manager.hpp"
 #include "storage/v3/edge_accessor.hpp"
 #include "storage/v3/id_types.hpp"
 #include "storage/v3/shard.hpp"
@@ -72,7 +72,7 @@ query::v2::TypedValue ToTypedValue(const Value &value) {
 }
 
 communication::bolt::Vertex ToBoltVertex(const query::v2::accessors::VertexAccessor &vertex,
-                                         const query::v2::ShardRequestManagerInterface *shard_request_manager,
+                                         const query::v2::RequestRouterInterface *request_router,
                                          storage::v3::View /*view*/) {
   auto id = communication::bolt::Id::FromUint(0);
 
@@ -80,44 +80,44 @@ communication::bolt::Vertex ToBoltVertex(const query::v2::accessors::VertexAcces
   std::vector<std::string> new_labels;
   new_labels.reserve(labels.size());
   for (const auto &label : labels) {
-    new_labels.push_back(shard_request_manager->LabelToName(label.id));
+    new_labels.push_back(request_router->LabelToName(label.id));
   }
 
   auto properties = vertex.Properties();
   std::map<std::string, Value> new_properties;
   for (const auto &[prop, property_value] : properties) {
-    new_properties[shard_request_manager->PropertyToName(prop)] = ToBoltValue(property_value);
+    new_properties[request_router->PropertyToName(prop)] = ToBoltValue(property_value);
   }
   return communication::bolt::Vertex{id, new_labels, new_properties};
 }
 
 communication::bolt::Edge ToBoltEdge(const query::v2::accessors::EdgeAccessor &edge,
-                                     const query::v2::ShardRequestManagerInterface *shard_request_manager,
+                                     const query::v2::RequestRouterInterface *request_router,
                                      storage::v3::View /*view*/) {
   // TODO(jbajic) Fix bolt communication
   auto id = communication::bolt::Id::FromUint(0);
   auto from = communication::bolt::Id::FromUint(0);
   auto to = communication::bolt::Id::FromUint(0);
-  const auto &type = shard_request_manager->EdgeTypeToName(edge.EdgeType());
+  const auto &type = request_router->EdgeTypeToName(edge.EdgeType());
 
   auto properties = edge.Properties();
   std::map<std::string, Value> new_properties;
   for (const auto &[prop, property_value] : properties) {
-    new_properties[shard_request_manager->PropertyToName(prop)] = ToBoltValue(property_value);
+    new_properties[request_router->PropertyToName(prop)] = ToBoltValue(property_value);
   }
   return communication::bolt::Edge{id, from, to, type, new_properties};
 }
 
 communication::bolt::Path ToBoltPath(const query::v2::accessors::Path & /*edge*/,
-                                     const query::v2::ShardRequestManagerInterface * /*shard_request_manager*/,
+                                     const query::v2::RequestRouterInterface * /*request_router*/,
                                      storage::v3::View /*view*/) {
   // TODO(jbajic) Fix bolt communication
   MG_ASSERT(false, "Path is unimplemented!");
   return {};
 }
 
-Value ToBoltValue(const query::v2::TypedValue &value,
-                  const query::v2::ShardRequestManagerInterface *shard_request_manager, storage::v3::View view) {
+Value ToBoltValue(const query::v2::TypedValue &value, const query::v2::RequestRouterInterface *request_router,
+                  storage::v3::View view) {
   switch (value.type()) {
     case query::v2::TypedValue::Type::Null:
       return {};
@@ -133,7 +133,7 @@ Value ToBoltValue(const query::v2::TypedValue &value,
       std::vector<Value> values;
       values.reserve(value.ValueList().size());
       for (const auto &v : value.ValueList()) {
-        auto value = ToBoltValue(v, shard_request_manager, view);
+        auto value = ToBoltValue(v, request_router, view);
         values.emplace_back(std::move(value));
       }
       return {std::move(values)};
@@ -141,21 +141,21 @@ Value ToBoltValue(const query::v2::TypedValue &value,
     case query::v2::TypedValue::Type::Map: {
       std::map<std::string, Value> map;
       for (const auto &kv : value.ValueMap()) {
-        auto value = ToBoltValue(kv.second, shard_request_manager, view);
+        auto value = ToBoltValue(kv.second, request_router, view);
         map.emplace(kv.first, std::move(value));
       }
       return {std::move(map)};
     }
     case query::v2::TypedValue::Type::Vertex: {
-      auto vertex = ToBoltVertex(value.ValueVertex(), shard_request_manager, view);
+      auto vertex = ToBoltVertex(value.ValueVertex(), request_router, view);
       return {std::move(vertex)};
     }
     case query::v2::TypedValue::Type::Edge: {
-      auto edge = ToBoltEdge(value.ValueEdge(), shard_request_manager, view);
+      auto edge = ToBoltEdge(value.ValueEdge(), request_router, view);
       return {std::move(edge)};
     }
     case query::v2::TypedValue::Type::Path: {
-      auto path = ToBoltPath(value.ValuePath(), shard_request_manager, view);
+      auto path = ToBoltPath(value.ValuePath(), request_router, view);
       return {std::move(path)};
     }
     case query::v2::TypedValue::Type::Date:
diff --git a/src/glue/v2/communication.hpp b/src/glue/v2/communication.hpp
index 817ff02bd..c1661b521 100644
--- a/src/glue/v2/communication.hpp
+++ b/src/glue/v2/communication.hpp
@@ -15,7 +15,7 @@
 #include "communication/bolt/v1/value.hpp"
 #include "coordinator/shard_map.hpp"
 #include "query/v2/bindings/typed_value.hpp"
-#include "query/v2/shard_request_manager.hpp"
+#include "query/v2/request_router.hpp"
 #include "storage/v3/property_value.hpp"
 #include "storage/v3/result.hpp"
 #include "storage/v3/shard.hpp"
@@ -32,40 +32,37 @@ namespace memgraph::glue::v2 {
 
 /// @param storage::v3::VertexAccessor for converting to
 ///        communication::bolt::Vertex.
-/// @param query::v2::ShardRequestManagerInterface *shard_request_manager getting label and property names.
+/// @param query::v2::RequestRouterInterface *request_router getting label and property names.
 /// @param storage::v3::View for deciding which vertex attributes are visible.
 ///
 /// @throw std::bad_alloc
 communication::bolt::Vertex ToBoltVertex(const storage::v3::VertexAccessor &vertex,
-                                         const query::v2::ShardRequestManagerInterface *shard_request_manager,
+                                         const query::v2::RequestRouterInterface *request_router,
                                          storage::v3::View view);
 
 /// @param storage::v3::EdgeAccessor for converting to communication::bolt::Edge.
-/// @param query::v2::ShardRequestManagerInterface *shard_request_manager getting edge type and property names.
+/// @param query::v2::RequestRouterInterface *request_router getting edge type and property names.
 /// @param storage::v3::View for deciding which edge attributes are visible.
 ///
 /// @throw std::bad_alloc
 communication::bolt::Edge ToBoltEdge(const storage::v3::EdgeAccessor &edge,
-                                     const query::v2::ShardRequestManagerInterface *shard_request_manager,
-                                     storage::v3::View view);
+                                     const query::v2::RequestRouterInterface *request_router, storage::v3::View view);
 
 /// @param query::v2::Path for converting to communication::bolt::Path.
-/// @param query::v2::ShardRequestManagerInterface *shard_request_manager ToBoltVertex and ToBoltEdge.
+/// @param query::v2::RequestRouterInterface *request_router ToBoltVertex and ToBoltEdge.
 /// @param storage::v3::View for ToBoltVertex and ToBoltEdge.
 ///
 /// @throw std::bad_alloc
 communication::bolt::Path ToBoltPath(const query::v2::accessors::Path &path,
-                                     const query::v2::ShardRequestManagerInterface *shard_request_manager,
-                                     storage::v3::View view);
+                                     const query::v2::RequestRouterInterface *request_router, storage::v3::View view);
 
 /// @param query::v2::TypedValue for converting to communication::bolt::Value.
-/// @param query::v2::ShardRequestManagerInterface *shard_request_manager ToBoltVertex and ToBoltEdge.
+/// @param query::v2::RequestRouterInterface *request_router ToBoltVertex and ToBoltEdge.
 /// @param storage::v3::View for ToBoltVertex and ToBoltEdge.
 ///
 /// @throw std::bad_alloc
 communication::bolt::Value ToBoltValue(const query::v2::TypedValue &value,
-                                       const query::v2::ShardRequestManagerInterface *shard_request_manager,
-                                       storage::v3::View view);
+                                       const query::v2::RequestRouterInterface *request_router, storage::v3::View view);
 
 query::v2::TypedValue ToTypedValue(const communication::bolt::Value &value);
 
@@ -75,8 +72,7 @@ storage::v3::PropertyValue ToPropertyValue(const communication::bolt::Value &val
 
 communication::bolt::Value ToBoltValue(msgs::Value value);
 
-communication::bolt::Value ToBoltValue(msgs::Value value,
-                                       const query::v2::ShardRequestManagerInterface *shard_request_manager,
+communication::bolt::Value ToBoltValue(msgs::Value value, const query::v2::RequestRouterInterface *request_router,
                                        storage::v3::View view);
 
 }  // namespace memgraph::glue::v2
diff --git a/src/memgraph.cpp b/src/memgraph.cpp
index 565f9940c..d825cc0e7 100644
--- a/src/memgraph.cpp
+++ b/src/memgraph.cpp
@@ -454,7 +454,7 @@ class BoltSession final : public memgraph::communication::bolt::Session<memgraph
 
   std::map<std::string, memgraph::communication::bolt::Value> Pull(TEncoder *encoder, std::optional<int> n,
                                                                    std::optional<int> qid) override {
-    TypedValueResultStream stream(encoder, interpreter_.GetShardRequestManager());
+    TypedValueResultStream stream(encoder, interpreter_.GetRequestRouter());
     return PullResults(stream, n, qid);
   }
 
@@ -481,7 +481,7 @@ class BoltSession final : public memgraph::communication::bolt::Session<memgraph
       const auto &summary = interpreter_.Pull(&stream, n, qid);
       std::map<std::string, memgraph::communication::bolt::Value> decoded_summary;
       for (const auto &kv : summary) {
-        auto bolt_value = memgraph::glue::v2::ToBoltValue(kv.second, interpreter_.GetShardRequestManager(),
+        auto bolt_value = memgraph::glue::v2::ToBoltValue(kv.second, interpreter_.GetRequestRouter(),
                                                           memgraph::storage::v3::View::NEW);
         decoded_summary.emplace(kv.first, std::move(bolt_value));
       }
@@ -497,15 +497,14 @@ class BoltSession final : public memgraph::communication::bolt::Session<memgraph
   /// before forwarding the calls to original TEncoder.
   class TypedValueResultStream {
    public:
-    TypedValueResultStream(TEncoder *encoder,
-                           const memgraph::query::v2::ShardRequestManagerInterface *shard_request_manager)
-        : encoder_(encoder), shard_request_manager_(shard_request_manager) {}
+    TypedValueResultStream(TEncoder *encoder, const memgraph::query::v2::RequestRouterInterface *request_router)
+        : encoder_(encoder), request_router_(request_router) {}
 
     void Result(const std::vector<memgraph::query::v2::TypedValue> &values) {
       std::vector<memgraph::communication::bolt::Value> decoded_values;
       decoded_values.reserve(values.size());
       for (const auto &v : values) {
-        auto bolt_value = memgraph::glue::v2::ToBoltValue(v, shard_request_manager_, memgraph::storage::v3::View::NEW);
+        auto bolt_value = memgraph::glue::v2::ToBoltValue(v, request_router_, memgraph::storage::v3::View::NEW);
         decoded_values.emplace_back(std::move(bolt_value));
       }
       encoder_->MessageRecord(decoded_values);
@@ -513,7 +512,7 @@ class BoltSession final : public memgraph::communication::bolt::Session<memgraph
 
    private:
     TEncoder *encoder_;
-    const memgraph::query::v2::ShardRequestManagerInterface *shard_request_manager_{nullptr};
+    const memgraph::query::v2::RequestRouterInterface *request_router_{nullptr};
   };
   memgraph::query::v2::Interpreter interpreter_;
   memgraph::communication::v2::ServerEndpoint endpoint_;
diff --git a/src/query/v2/accessors.cpp b/src/query/v2/accessors.cpp
index 4f6e0d0d7..a28df0fe5 100644
--- a/src/query/v2/accessors.cpp
+++ b/src/query/v2/accessors.cpp
@@ -10,12 +10,12 @@
 // licenses/APL.txt.
 
 #include "query/v2/accessors.hpp"
+#include "query/v2/request_router.hpp"
 #include "query/v2/requests.hpp"
-#include "query/v2/shard_request_manager.hpp"
 #include "storage/v3/id_types.hpp"
 
 namespace memgraph::query::v2::accessors {
-EdgeAccessor::EdgeAccessor(Edge edge, const ShardRequestManagerInterface *manager)
+EdgeAccessor::EdgeAccessor(Edge edge, const RequestRouterInterface *manager)
     : edge(std::move(edge)), manager_(manager) {}
 
 EdgeTypeId EdgeAccessor::EdgeType() const { return edge.type.id; }
@@ -44,11 +44,10 @@ VertexAccessor EdgeAccessor::From() const {
 }
 
 VertexAccessor::VertexAccessor(Vertex v, std::vector<std::pair<PropertyId, Value>> props,
-                               const ShardRequestManagerInterface *manager)
+                               const RequestRouterInterface *manager)
     : vertex(std::move(v)), properties(std::move(props)), manager_(manager) {}
 
-VertexAccessor::VertexAccessor(Vertex v, std::map<PropertyId, Value> &&props,
-                               const ShardRequestManagerInterface *manager)
+VertexAccessor::VertexAccessor(Vertex v, std::map<PropertyId, Value> &&props, const RequestRouterInterface *manager)
     : vertex(std::move(v)), manager_(manager) {
   properties.reserve(props.size());
   for (auto &[id, value] : props) {
@@ -57,7 +56,7 @@ VertexAccessor::VertexAccessor(Vertex v, std::map<PropertyId, Value> &&props,
 }
 
 VertexAccessor::VertexAccessor(Vertex v, const std::map<PropertyId, Value> &props,
-                               const ShardRequestManagerInterface *manager)
+                               const RequestRouterInterface *manager)
     : vertex(std::move(v)), manager_(manager) {
   properties.reserve(props.size());
   for (const auto &[id, value] : props) {
diff --git a/src/query/v2/accessors.hpp b/src/query/v2/accessors.hpp
index ca7ec999d..b5585953f 100644
--- a/src/query/v2/accessors.hpp
+++ b/src/query/v2/accessors.hpp
@@ -25,7 +25,7 @@
 #include "utils/memory_tracker.hpp"
 
 namespace memgraph::query::v2 {
-class ShardRequestManagerInterface;
+class RequestRouterInterface;
 }  // namespace memgraph::query::v2
 
 namespace memgraph::query::v2::accessors {
@@ -41,7 +41,7 @@ class VertexAccessor;
 
 class EdgeAccessor final {
  public:
-  explicit EdgeAccessor(Edge edge, const ShardRequestManagerInterface *manager);
+  explicit EdgeAccessor(Edge edge, const RequestRouterInterface *manager);
 
   [[nodiscard]] EdgeTypeId EdgeType() const;
 
@@ -69,7 +69,7 @@ class EdgeAccessor final {
 
  private:
   Edge edge;
-  const ShardRequestManagerInterface *manager_;
+  const RequestRouterInterface *manager_;
 };
 
 class VertexAccessor final {
@@ -77,11 +77,10 @@ class VertexAccessor final {
   using PropertyId = msgs::PropertyId;
   using Label = msgs::Label;
   using VertexId = msgs::VertexId;
-  VertexAccessor(Vertex v, std::vector<std::pair<PropertyId, Value>> props,
-                 const ShardRequestManagerInterface *manager);
+  VertexAccessor(Vertex v, std::vector<std::pair<PropertyId, Value>> props, const RequestRouterInterface *manager);
 
-  VertexAccessor(Vertex v, std::map<PropertyId, Value> &&props, const ShardRequestManagerInterface *manager);
-  VertexAccessor(Vertex v, const std::map<PropertyId, Value> &props, const ShardRequestManagerInterface *manager);
+  VertexAccessor(Vertex v, std::map<PropertyId, Value> &&props, const RequestRouterInterface *manager);
+  VertexAccessor(Vertex v, const std::map<PropertyId, Value> &props, const RequestRouterInterface *manager);
 
   [[nodiscard]] Label PrimaryLabel() const;
 
@@ -150,7 +149,7 @@ class VertexAccessor final {
  private:
   Vertex vertex;
   std::vector<std::pair<PropertyId, Value>> properties;
-  const ShardRequestManagerInterface *manager_;
+  const RequestRouterInterface *manager_;
 };
 
 // inline VertexAccessor EdgeAccessor::To() const { return VertexAccessor(impl_.ToVertex()); }
diff --git a/src/query/v2/bindings/eval.hpp b/src/query/v2/bindings/eval.hpp
index 584e88922..912850e87 100644
--- a/src/query/v2/bindings/eval.hpp
+++ b/src/query/v2/bindings/eval.hpp
@@ -26,7 +26,7 @@
 
 namespace memgraph::query::v2 {
 
-class ShardRequestManagerInterface;
+class RequestRouterInterface;
 
 inline const auto lam = [](const auto &val) { return ValueToTypedValue(val); };
 namespace detail {
@@ -35,15 +35,14 @@ class Callable {
   auto operator()(const storage::v3::PropertyValue &val) const {
     return storage::v3::PropertyToTypedValue<TypedValue>(val);
   };
-  auto operator()(const msgs::Value &val, ShardRequestManagerInterface *manager) const {
+  auto operator()(const msgs::Value &val, RequestRouterInterface *manager) const {
     return ValueToTypedValue(val, manager);
   };
 };
 
 }  // namespace detail
-using ExpressionEvaluator =
-    expr::ExpressionEvaluator<TypedValue, query::v2::EvaluationContext, ShardRequestManagerInterface, storage::v3::View,
-                              storage::v3::LabelId, msgs::Value, detail::Callable, common::ErrorCode,
-                              expr::QueryEngineTag>;
+using ExpressionEvaluator = expr::ExpressionEvaluator<TypedValue, query::v2::EvaluationContext, RequestRouterInterface,
+                                                      storage::v3::View, storage::v3::LabelId, msgs::Value,
+                                                      detail::Callable, common::ErrorCode, expr::QueryEngineTag>;
 
 }  // namespace memgraph::query::v2
diff --git a/src/query/v2/context.hpp b/src/query/v2/context.hpp
index 388342349..cb30a9ced 100644
--- a/src/query/v2/context.hpp
+++ b/src/query/v2/context.hpp
@@ -20,7 +20,7 @@
 #include "query/v2/parameters.hpp"
 #include "query/v2/plan/profile.hpp"
 //#include "query/v2/trigger.hpp"
-#include "query/v2/shard_request_manager.hpp"
+#include "query/v2/request_router.hpp"
 #include "utils/async_timer.hpp"
 
 namespace memgraph::query::v2 {
@@ -61,26 +61,26 @@ struct EvaluationContext {
 };
 
 inline std::vector<storage::v3::PropertyId> NamesToProperties(const std::vector<std::string> &property_names,
-                                                              ShardRequestManagerInterface *shard_request_manager) {
+                                                              RequestRouterInterface *request_router) {
   std::vector<storage::v3::PropertyId> properties;
   // TODO Fix by using reference
   properties.reserve(property_names.size());
-  if (shard_request_manager != nullptr) {
+  if (request_router != nullptr) {
     for (const auto &name : property_names) {
-      properties.push_back(shard_request_manager->NameToProperty(name));
+      properties.push_back(request_router->NameToProperty(name));
     }
   }
   return properties;
 }
 
 inline std::vector<storage::v3::LabelId> NamesToLabels(const std::vector<std::string> &label_names,
-                                                       ShardRequestManagerInterface *shard_request_manager) {
+                                                       RequestRouterInterface *request_router) {
   std::vector<storage::v3::LabelId> labels;
   labels.reserve(label_names.size());
   // TODO Fix by using reference
-  if (shard_request_manager != nullptr) {
+  if (request_router != nullptr) {
     for (const auto &name : label_names) {
-      labels.push_back(shard_request_manager->NameToLabel(name));
+      labels.push_back(request_router->NameToLabel(name));
     }
   }
   return labels;
@@ -97,7 +97,7 @@ struct ExecutionContext {
   plan::ProfilingStats *stats_root{nullptr};
   ExecutionStats execution_stats;
   utils::AsyncTimer timer;
-  ShardRequestManagerInterface *shard_request_manager{nullptr};
+  RequestRouterInterface *request_router{nullptr};
   IdAllocator *edge_ids_alloc;
 };
 
diff --git a/src/query/v2/conversions.hpp b/src/query/v2/conversions.hpp
index c18ba8cc0..161f89979 100644
--- a/src/query/v2/conversions.hpp
+++ b/src/query/v2/conversions.hpp
@@ -12,12 +12,12 @@
 #pragma once
 #include "bindings/typed_value.hpp"
 #include "query/v2/accessors.hpp"
+#include "query/v2/request_router.hpp"
 #include "query/v2/requests.hpp"
-#include "query/v2/shard_request_manager.hpp"
 
 namespace memgraph::query::v2 {
 
-inline TypedValue ValueToTypedValue(const msgs::Value &value, ShardRequestManagerInterface *manager) {
+inline TypedValue ValueToTypedValue(const msgs::Value &value, RequestRouterInterface *manager) {
   using Value = msgs::Value;
   switch (value.type) {
     case Value::Type::Null:
diff --git a/src/query/v2/cypher_query_interpreter.cpp b/src/query/v2/cypher_query_interpreter.cpp
index 908ee36cb..880165ad8 100644
--- a/src/query/v2/cypher_query_interpreter.cpp
+++ b/src/query/v2/cypher_query_interpreter.cpp
@@ -11,7 +11,7 @@
 
 #include "query/v2/cypher_query_interpreter.hpp"
 #include "query/v2/bindings/symbol_generator.hpp"
-#include "query/v2/shard_request_manager.hpp"
+#include "query/v2/request_router.hpp"
 
 // NOLINTNEXTLINE (cppcoreguidelines-avoid-non-const-global-variables)
 DEFINE_HIDDEN_bool(query_cost_planner, true, "Use the cost-estimating query planner.");
@@ -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,
-                                             ShardRequestManagerInterface *shard_manager,
+                                             RequestRouterInterface *shard_manager,
                                              const std::vector<Identifier *> &predefined_identifiers) {
   auto vertex_counts = plan::MakeVertexCountCache(shard_manager);
   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,
                                               const Parameters &parameters, utils::SkipList<PlanCacheEntry> *plan_cache,
-                                              ShardRequestManagerInterface *shard_manager,
+                                              RequestRouterInterface *shard_manager,
                                               const std::vector<Identifier *> &predefined_identifiers) {
   std::optional<utils::SkipList<PlanCacheEntry>::Accessor> plan_cache_access;
   if (plan_cache) {
diff --git a/src/query/v2/cypher_query_interpreter.hpp b/src/query/v2/cypher_query_interpreter.hpp
index b7f63ab8f..c9d65047c 100644
--- a/src/query/v2/cypher_query_interpreter.hpp
+++ b/src/query/v2/cypher_query_interpreter.hpp
@@ -132,7 +132,7 @@ class SingleNodeLogicalPlan final : public LogicalPlan {
 };
 
 std::unique_ptr<LogicalPlan> MakeLogicalPlan(AstStorage ast_storage, CypherQuery *query, const Parameters &parameters,
-                                             ShardRequestManagerInterface *shard_manager,
+                                             RequestRouterInterface *shard_manager,
                                              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,
                                               const Parameters &parameters, utils::SkipList<PlanCacheEntry> *plan_cache,
-                                              ShardRequestManagerInterface *shard_manager,
+                                              RequestRouterInterface *shard_manager,
                                               const std::vector<Identifier *> &predefined_identifiers = {});
 
 }  // namespace memgraph::query::v2
diff --git a/src/query/v2/interpret/awesome_memgraph_functions.cpp b/src/query/v2/interpret/awesome_memgraph_functions.cpp
index 8768736b2..54fcd4468 100644
--- a/src/query/v2/interpret/awesome_memgraph_functions.cpp
+++ b/src/query/v2/interpret/awesome_memgraph_functions.cpp
@@ -23,7 +23,7 @@
 #include "query/v2/bindings/typed_value.hpp"
 #include "query/v2/conversions.hpp"
 #include "query/v2/exceptions.hpp"
-#include "query/v2/shard_request_manager.hpp"
+#include "query/v2/request_router.hpp"
 #include "storage/v3/conversions.hpp"
 #include "utils/string.hpp"
 #include "utils/temporal.hpp"
diff --git a/src/query/v2/interpret/awesome_memgraph_functions.hpp b/src/query/v2/interpret/awesome_memgraph_functions.hpp
index 1fd351cd8..35ed1d797 100644
--- a/src/query/v2/interpret/awesome_memgraph_functions.hpp
+++ b/src/query/v2/interpret/awesome_memgraph_functions.hpp
@@ -22,7 +22,7 @@
 
 namespace memgraph::query::v2 {
 
-class ShardRequestManagerInterface;
+class RequestRouterInterface;
 
 namespace {
 const char kStartsWith[] = "STARTSWITH";
@@ -32,9 +32,9 @@ const char kId[] = "ID";
 }  // namespace
 
 struct FunctionContext {
-  // TODO(kostasrim) consider optional here. ShardRequestManager does not exist on the storage.
+  // TODO(kostasrim) consider optional here. RequestRouter does not exist on the storage.
   // DbAccessor *db_accessor;
-  ShardRequestManagerInterface *manager;
+  RequestRouterInterface *manager;
   utils::MemoryResource *memory;
   int64_t timestamp;
   std::unordered_map<std::string, int64_t> *counters;
diff --git a/src/query/v2/interpreter.cpp b/src/query/v2/interpreter.cpp
index f9dc37184..94ff7a8ff 100644
--- a/src/query/v2/interpreter.cpp
+++ b/src/query/v2/interpreter.cpp
@@ -44,7 +44,7 @@
 #include "query/v2/plan/planner.hpp"
 #include "query/v2/plan/profile.hpp"
 #include "query/v2/plan/vertex_count_cache.hpp"
-#include "query/v2/shard_request_manager.hpp"
+#include "query/v2/request_router.hpp"
 #include "storage/v3/property_value.hpp"
 #include "storage/v3/shard.hpp"
 #include "utils/algorithm.hpp"
@@ -143,7 +143,7 @@ class ReplQueryHandler final : public query::v2::ReplicationQueryHandler {
 /// @throw QueryRuntimeException if an error ocurred.
 
 Callback HandleAuthQuery(AuthQuery *auth_query, AuthQueryHandler *auth, const Parameters &parameters,
-                         ShardRequestManagerInterface *manager) {
+                         RequestRouterInterface *manager) {
   // Empty frame for evaluation of password expression. This is OK since
   // password should be either null or string literal and it's evaluation
   // should not depend on frame.
@@ -312,7 +312,7 @@ Callback HandleAuthQuery(AuthQuery *auth_query, AuthQueryHandler *auth, const Pa
 }
 
 Callback HandleReplicationQuery(ReplicationQuery *repl_query, const Parameters &parameters,
-                                InterpreterContext *interpreter_context, ShardRequestManagerInterface *manager,
+                                InterpreterContext *interpreter_context, RequestRouterInterface *manager,
                                 std::vector<Notification> *notifications) {
   expr::Frame<TypedValue> frame(0);
   SymbolTable symbol_table;
@@ -448,7 +448,7 @@ Callback HandleReplicationQuery(ReplicationQuery *repl_query, const Parameters &
 }
 
 Callback HandleSettingQuery(SettingQuery *setting_query, const Parameters &parameters,
-                            ShardRequestManagerInterface *manager) {
+                            RequestRouterInterface *manager) {
   expr::Frame<TypedValue> frame(0);
   SymbolTable symbol_table;
   EvaluationContext evaluation_context;
@@ -649,7 +649,7 @@ struct PullPlanVector {
 struct PullPlan {
   explicit PullPlan(std::shared_ptr<CachedPlan> plan, const Parameters &parameters, bool is_profile_query,
                     DbAccessor *dba, InterpreterContext *interpreter_context, utils::MemoryResource *execution_memory,
-                    ShardRequestManagerInterface *shard_request_manager = nullptr,
+                    RequestRouterInterface *request_router = nullptr,
                     //                    TriggerContextCollector *trigger_context_collector = nullptr,
                     std::optional<size_t> memory_limit = {});
   std::optional<plan::ProfilingStatsWithTotalTime> Pull(AnyStream *stream, std::optional<int> n,
@@ -679,7 +679,7 @@ struct PullPlan {
 
 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,
-                   ShardRequestManagerInterface *shard_request_manager, const std::optional<size_t> memory_limit)
+                   RequestRouterInterface *request_router, const std::optional<size_t> memory_limit)
     : plan_(plan),
       cursor_(plan->plan().MakeCursor(execution_memory)),
       frame_(plan->symbol_table().max_position(), execution_memory),
@@ -688,14 +688,14 @@ PullPlan::PullPlan(const std::shared_ptr<CachedPlan> plan, const Parameters &par
   ctx_.symbol_table = plan->symbol_table();
   ctx_.evaluation_context.timestamp = QueryTimestamp();
   ctx_.evaluation_context.parameters = parameters;
-  ctx_.evaluation_context.properties = NamesToProperties(plan->ast_storage().properties_, shard_request_manager);
-  ctx_.evaluation_context.labels = NamesToLabels(plan->ast_storage().labels_, shard_request_manager);
+  ctx_.evaluation_context.properties = NamesToProperties(plan->ast_storage().properties_, request_router);
+  ctx_.evaluation_context.labels = NamesToLabels(plan->ast_storage().labels_, request_router);
   if (interpreter_context->config.execution_timeout_sec > 0) {
     ctx_.timer = utils::AsyncTimer{interpreter_context->config.execution_timeout_sec};
   }
   ctx_.is_shutting_down = &interpreter_context->is_shutting_down;
   ctx_.is_profile_query = is_profile_query;
-  ctx_.shard_request_manager = shard_request_manager;
+  ctx_.request_router = request_router;
   ctx_.edge_ids_alloc = &interpreter_context->edge_ids_alloc;
 }
 
@@ -804,7 +804,7 @@ Interpreter::Interpreter(InterpreterContext *interpreter_context) : interpreter_
   auto random_uuid = boost::uuids::uuid{boost::uuids::random_generator()()};
   auto query_io = interpreter_context_->io.ForkLocal(random_uuid);
 
-  shard_request_manager_ = std::make_unique<ShardRequestManager<io::local_transport::LocalTransport>>(
+  request_router_ = std::make_unique<RequestRouter<io::local_transport::LocalTransport>>(
       coordinator::CoordinatorClient<io::local_transport::LocalTransport>(
           query_io, interpreter_context_->coordinator_address, std::vector{interpreter_context_->coordinator_address}),
       std::move(query_io));
@@ -881,7 +881,7 @@ PreparedQuery Interpreter::PrepareTransactionQuery(std::string_view query_upper)
 PreparedQuery PrepareCypherQuery(ParsedQuery parsed_query, std::map<std::string, TypedValue> *summary,
                                  InterpreterContext *interpreter_context, DbAccessor *dba,
                                  utils::MemoryResource *execution_memory, std::vector<Notification> *notifications,
-                                 ShardRequestManagerInterface *shard_request_manager) {
+                                 RequestRouterInterface *request_router) {
   //                                 TriggerContextCollector *trigger_context_collector = nullptr) {
   auto *cypher_query = utils::Downcast<CypherQuery>(parsed_query.query);
 
@@ -890,8 +890,7 @@ PreparedQuery PrepareCypherQuery(ParsedQuery parsed_query, std::map<std::string,
   EvaluationContext evaluation_context;
   evaluation_context.timestamp = QueryTimestamp();
   evaluation_context.parameters = parsed_query.parameters;
-  ExpressionEvaluator evaluator(&frame, symbol_table, evaluation_context, shard_request_manager,
-                                storage::v3::View::OLD);
+  ExpressionEvaluator evaluator(&frame, symbol_table, evaluation_context, request_router, storage::v3::View::OLD);
   const auto memory_limit =
       expr::EvaluateMemoryLimit(&evaluator, cypher_query->memory_limit_, cypher_query->memory_scale_);
   if (memory_limit) {
@@ -906,9 +905,9 @@ PreparedQuery PrepareCypherQuery(ParsedQuery parsed_query, std::map<std::string,
         "convert the parsed row values to the appropriate type. This can be done using the built-in "
         "conversion functions such as ToInteger, ToFloat, ToBoolean etc.");
   }
-  auto plan = CypherQueryToPlan(
-      parsed_query.stripped_query.hash(), std::move(parsed_query.ast_storage), cypher_query, parsed_query.parameters,
-      parsed_query.is_cacheable ? &interpreter_context->plan_cache : nullptr, shard_request_manager);
+  auto plan = CypherQueryToPlan(parsed_query.stripped_query.hash(), std::move(parsed_query.ast_storage), cypher_query,
+                                parsed_query.parameters,
+                                parsed_query.is_cacheable ? &interpreter_context->plan_cache : nullptr, request_router);
 
   summary->insert_or_assign("cost_estimate", plan->cost());
   auto rw_type_checker = plan::ReadWriteTypeChecker();
@@ -927,7 +926,7 @@ PreparedQuery PrepareCypherQuery(ParsedQuery parsed_query, std::map<std::string,
         utils::FindOr(parsed_query.stripped_query.named_expressions(), symbol.token_position(), symbol.name()).first);
   }
   auto pull_plan = std::make_shared<PullPlan>(plan, parsed_query.parameters, false, dba, interpreter_context,
-                                              execution_memory, shard_request_manager, memory_limit);
+                                              execution_memory, request_router, memory_limit);
   //                                              execution_memory, trigger_context_collector, memory_limit);
   return PreparedQuery{std::move(header), std::move(parsed_query.required_privileges),
                        [pull_plan = std::move(pull_plan), output_symbols = std::move(output_symbols), summary](
@@ -941,8 +940,7 @@ PreparedQuery PrepareCypherQuery(ParsedQuery parsed_query, std::map<std::string,
 }
 
 PreparedQuery PrepareExplainQuery(ParsedQuery parsed_query, std::map<std::string, TypedValue> *summary,
-                                  InterpreterContext *interpreter_context,
-                                  ShardRequestManagerInterface *shard_request_manager,
+                                  InterpreterContext *interpreter_context, RequestRouterInterface *request_router,
                                   utils::MemoryResource *execution_memory) {
   const std::string kExplainQueryStart = "explain ";
   MG_ASSERT(utils::StartsWith(utils::ToLowerCase(parsed_query.stripped_query.query()), kExplainQueryStart),
@@ -961,20 +959,20 @@ PreparedQuery PrepareExplainQuery(ParsedQuery parsed_query, std::map<std::string
   auto *cypher_query = utils::Downcast<CypherQuery>(parsed_inner_query.query);
   MG_ASSERT(cypher_query, "Cypher grammar should not allow other queries in EXPLAIN");
 
-  auto cypher_query_plan = CypherQueryToPlan(
-      parsed_inner_query.stripped_query.hash(), std::move(parsed_inner_query.ast_storage), cypher_query,
-      parsed_inner_query.parameters, parsed_inner_query.is_cacheable ? &interpreter_context->plan_cache : nullptr,
-      shard_request_manager);
+  auto cypher_query_plan =
+      CypherQueryToPlan(parsed_inner_query.stripped_query.hash(), std::move(parsed_inner_query.ast_storage),
+                        cypher_query, parsed_inner_query.parameters,
+                        parsed_inner_query.is_cacheable ? &interpreter_context->plan_cache : nullptr, request_router);
 
   std::stringstream printed_plan;
-  plan::PrettyPrint(*shard_request_manager, &cypher_query_plan->plan(), &printed_plan);
+  plan::PrettyPrint(*request_router, &cypher_query_plan->plan(), &printed_plan);
 
   std::vector<std::vector<TypedValue>> printed_plan_rows;
   for (const auto &row : utils::Split(utils::RTrim(printed_plan.str()), "\n")) {
     printed_plan_rows.push_back(std::vector<TypedValue>{TypedValue(row)});
   }
 
-  summary->insert_or_assign("explain", plan::PlanToJson(*shard_request_manager, &cypher_query_plan->plan()).dump());
+  summary->insert_or_assign("explain", plan::PlanToJson(*request_router, &cypher_query_plan->plan()).dump());
 
   return PreparedQuery{{"QUERY PLAN"},
                        std::move(parsed_query.required_privileges),
@@ -991,7 +989,7 @@ PreparedQuery PrepareExplainQuery(ParsedQuery parsed_query, std::map<std::string
 PreparedQuery PrepareProfileQuery(ParsedQuery parsed_query, bool in_explicit_transaction,
                                   std::map<std::string, TypedValue> *summary, InterpreterContext *interpreter_context,
                                   DbAccessor *dba, utils::MemoryResource *execution_memory,
-                                  ShardRequestManagerInterface *shard_request_manager = nullptr) {
+                                  RequestRouterInterface *request_router = nullptr) {
   const std::string kProfileQueryStart = "profile ";
 
   MG_ASSERT(utils::StartsWith(utils::ToLowerCase(parsed_query.stripped_query.query()), kProfileQueryStart),
@@ -1034,22 +1032,21 @@ PreparedQuery PrepareProfileQuery(ParsedQuery parsed_query, bool in_explicit_tra
   EvaluationContext evaluation_context;
   evaluation_context.timestamp = QueryTimestamp();
   evaluation_context.parameters = parsed_inner_query.parameters;
-  ExpressionEvaluator evaluator(&frame, symbol_table, evaluation_context, shard_request_manager,
-                                storage::v3::View::OLD);
+  ExpressionEvaluator evaluator(&frame, symbol_table, evaluation_context, request_router, storage::v3::View::OLD);
   const auto memory_limit =
       expr::EvaluateMemoryLimit(&evaluator, cypher_query->memory_limit_, cypher_query->memory_scale_);
 
-  auto cypher_query_plan = CypherQueryToPlan(
-      parsed_inner_query.stripped_query.hash(), std::move(parsed_inner_query.ast_storage), cypher_query,
-      parsed_inner_query.parameters, parsed_inner_query.is_cacheable ? &interpreter_context->plan_cache : nullptr,
-      shard_request_manager);
+  auto cypher_query_plan =
+      CypherQueryToPlan(parsed_inner_query.stripped_query.hash(), std::move(parsed_inner_query.ast_storage),
+                        cypher_query, parsed_inner_query.parameters,
+                        parsed_inner_query.is_cacheable ? &interpreter_context->plan_cache : nullptr, request_router);
   auto rw_type_checker = plan::ReadWriteTypeChecker();
   rw_type_checker.InferRWType(const_cast<plan::LogicalOperator &>(cypher_query_plan->plan()));
 
   return PreparedQuery{{"OPERATOR", "ACTUAL HITS", "RELATIVE TIME", "ABSOLUTE TIME", "CUSTOM DATA"},
                        std::move(parsed_query.required_privileges),
                        [plan = std::move(cypher_query_plan), parameters = std::move(parsed_inner_query.parameters),
-                        summary, dba, interpreter_context, execution_memory, memory_limit, shard_request_manager,
+                        summary, dba, interpreter_context, execution_memory, memory_limit, request_router,
                         // We want to execute the query we are profiling lazily, so we delay
                         // the construction of the corresponding context.
                         stats_and_total_time = std::optional<plan::ProfilingStatsWithTotalTime>{},
@@ -1058,7 +1055,7 @@ PreparedQuery PrepareProfileQuery(ParsedQuery parsed_query, bool in_explicit_tra
                          // No output symbols are given so that nothing is streamed.
                          if (!stats_and_total_time) {
                            stats_and_total_time = PullPlan(plan, parameters, true, dba, interpreter_context,
-                                                           execution_memory, shard_request_manager, memory_limit)
+                                                           execution_memory, request_router, memory_limit)
                                                       .Pull(stream, {}, {}, summary);
                            pull_plan = std::make_shared<PullPlanVector>(ProfilingStatsToTable(*stats_and_total_time));
                          }
@@ -1185,7 +1182,7 @@ PreparedQuery PrepareIndexQuery(ParsedQuery parsed_query, bool in_explicit_trans
 PreparedQuery PrepareAuthQuery(ParsedQuery parsed_query, bool in_explicit_transaction,
                                std::map<std::string, TypedValue> *summary, InterpreterContext *interpreter_context,
                                DbAccessor *dba, utils::MemoryResource *execution_memory,
-                               ShardRequestManagerInterface *manager) {
+                               RequestRouterInterface *manager) {
   if (in_explicit_transaction) {
     throw UserModificationInMulticommandTxException();
   }
@@ -1221,7 +1218,7 @@ PreparedQuery PrepareAuthQuery(ParsedQuery parsed_query, bool in_explicit_transa
 
 PreparedQuery PrepareReplicationQuery(ParsedQuery parsed_query, const bool in_explicit_transaction,
                                       std::vector<Notification> *notifications, InterpreterContext *interpreter_context,
-                                      ShardRequestManagerInterface *manager) {
+                                      RequestRouterInterface *manager) {
   if (in_explicit_transaction) {
     throw ReplicationModificationInMulticommandTxException();
   }
@@ -1317,7 +1314,7 @@ PreparedQuery PrepareCreateSnapshotQuery(ParsedQuery parsed_query, bool in_expli
 }
 
 PreparedQuery PrepareSettingQuery(ParsedQuery parsed_query, const bool in_explicit_transaction,
-                                  ShardRequestManagerInterface *manager) {
+                                  RequestRouterInterface *manager) {
   if (in_explicit_transaction) {
     throw SettingConfigInMulticommandTxException{};
   }
@@ -1521,7 +1518,7 @@ Interpreter::PrepareResult Interpreter::Prepare(const std::string &query_string,
     if (!in_explicit_transaction_ &&
         (utils::Downcast<CypherQuery>(parsed_query.query) || utils::Downcast<ExplainQuery>(parsed_query.query) ||
          utils::Downcast<ProfileQuery>(parsed_query.query))) {
-      shard_request_manager_->StartTransaction();
+      request_router_->StartTransaction();
     }
 
     utils::Timer planning_timer;
@@ -1530,14 +1527,14 @@ Interpreter::PrepareResult Interpreter::Prepare(const std::string &query_string,
     if (utils::Downcast<CypherQuery>(parsed_query.query)) {
       prepared_query = PrepareCypherQuery(std::move(parsed_query), &query_execution->summary, interpreter_context_,
                                           &*execution_db_accessor_, &query_execution->execution_memory,
-                                          &query_execution->notifications, shard_request_manager_.get());
+                                          &query_execution->notifications, request_router_.get());
     } else if (utils::Downcast<ExplainQuery>(parsed_query.query)) {
       prepared_query = PrepareExplainQuery(std::move(parsed_query), &query_execution->summary, interpreter_context_,
-                                           &*shard_request_manager_, &query_execution->execution_memory_with_exception);
+                                           &*request_router_, &query_execution->execution_memory_with_exception);
     } else if (utils::Downcast<ProfileQuery>(parsed_query.query)) {
-      prepared_query = PrepareProfileQuery(
-          std::move(parsed_query), in_explicit_transaction_, &query_execution->summary, interpreter_context_,
-          &*execution_db_accessor_, &query_execution->execution_memory_with_exception, shard_request_manager_.get());
+      prepared_query = PrepareProfileQuery(std::move(parsed_query), in_explicit_transaction_, &query_execution->summary,
+                                           interpreter_context_, &*execution_db_accessor_,
+                                           &query_execution->execution_memory_with_exception, request_router_.get());
     } else if (utils::Downcast<DumpQuery>(parsed_query.query)) {
       prepared_query = PrepareDumpQuery(std::move(parsed_query), &query_execution->summary, &*execution_db_accessor_,
                                         &query_execution->execution_memory);
@@ -1545,9 +1542,9 @@ Interpreter::PrepareResult Interpreter::Prepare(const std::string &query_string,
       prepared_query = PrepareIndexQuery(std::move(parsed_query), in_explicit_transaction_,
                                          &query_execution->notifications, interpreter_context_);
     } else if (utils::Downcast<AuthQuery>(parsed_query.query)) {
-      prepared_query = PrepareAuthQuery(
-          std::move(parsed_query), in_explicit_transaction_, &query_execution->summary, interpreter_context_,
-          &*execution_db_accessor_, &query_execution->execution_memory_with_exception, shard_request_manager_.get());
+      prepared_query = PrepareAuthQuery(std::move(parsed_query), in_explicit_transaction_, &query_execution->summary,
+                                        interpreter_context_, &*execution_db_accessor_,
+                                        &query_execution->execution_memory_with_exception, request_router_.get());
     } else if (utils::Downcast<InfoQuery>(parsed_query.query)) {
       prepared_query = PrepareInfoQuery(std::move(parsed_query), in_explicit_transaction_, &query_execution->summary,
                                         interpreter_context_, interpreter_context_->db,
@@ -1558,7 +1555,7 @@ Interpreter::PrepareResult Interpreter::Prepare(const std::string &query_string,
     } else if (utils::Downcast<ReplicationQuery>(parsed_query.query)) {
       prepared_query =
           PrepareReplicationQuery(std::move(parsed_query), in_explicit_transaction_, &query_execution->notifications,
-                                  interpreter_context_, shard_request_manager_.get());
+                                  interpreter_context_, request_router_.get());
     } else if (utils::Downcast<LockPathQuery>(parsed_query.query)) {
       prepared_query = PrepareLockPathQuery(std::move(parsed_query), in_explicit_transaction_, interpreter_context_,
                                             &*execution_db_accessor_);
@@ -1575,8 +1572,7 @@ Interpreter::PrepareResult Interpreter::Prepare(const std::string &query_string,
       prepared_query =
           PrepareCreateSnapshotQuery(std::move(parsed_query), in_explicit_transaction_, interpreter_context_);
     } else if (utils::Downcast<SettingQuery>(parsed_query.query)) {
-      prepared_query =
-          PrepareSettingQuery(std::move(parsed_query), in_explicit_transaction_, shard_request_manager_.get());
+      prepared_query = PrepareSettingQuery(std::move(parsed_query), in_explicit_transaction_, request_router_.get());
     } else if (utils::Downcast<VersionQuery>(parsed_query.query)) {
       prepared_query = PrepareVersionQuery(std::move(parsed_query), in_explicit_transaction_);
     } else if (utils::Downcast<SchemaQuery>(parsed_query.query)) {
@@ -1617,7 +1613,7 @@ void Interpreter::Commit() {
   // For now, we will not check if there are some unfinished queries.
   // We should document clearly that all results should be pulled to complete
   // a query.
-  shard_request_manager_->Commit();
+  request_router_->Commit();
   if (!db_accessor_) return;
 
   const auto reset_necessary_members = [this]() {
diff --git a/src/query/v2/interpreter.hpp b/src/query/v2/interpreter.hpp
index afc298a0c..985c9a90c 100644
--- a/src/query/v2/interpreter.hpp
+++ b/src/query/v2/interpreter.hpp
@@ -296,7 +296,7 @@ class Interpreter final {
    */
   void Abort();
 
-  const ShardRequestManagerInterface *GetShardRequestManager() const { return shard_request_manager_.get(); }
+  const RequestRouterInterface *GetRequestRouter() const { return request_router_.get(); }
 
  private:
   struct QueryExecution {
@@ -342,7 +342,7 @@ class Interpreter final {
   // move this unique_ptr into a shared_ptr.
   std::unique_ptr<storage::v3::Shard::Accessor> db_accessor_;
   std::optional<DbAccessor> execution_db_accessor_;
-  std::unique_ptr<ShardRequestManagerInterface> shard_request_manager_;
+  std::unique_ptr<RequestRouterInterface> request_router_;
   bool in_explicit_transaction_{false};
   bool expect_rollback_{false};
 
diff --git a/src/query/v2/plan/operator.cpp b/src/query/v2/plan/operator.cpp
index 30db1012e..2d2849f0d 100644
--- a/src/query/v2/plan/operator.cpp
+++ b/src/query/v2/plan/operator.cpp
@@ -39,8 +39,8 @@
 #include "query/v2/frontend/ast/ast.hpp"
 #include "query/v2/path.hpp"
 #include "query/v2/plan/scoped_profile.hpp"
+#include "query/v2/request_router.hpp"
 #include "query/v2/requests.hpp"
-#include "query/v2/shard_request_manager.hpp"
 #include "storage/v3/conversions.hpp"
 #include "storage/v3/property_value.hpp"
 #include "utils/algorithm.hpp"
@@ -177,7 +177,7 @@ class DistributedCreateNodeCursor : public Cursor {
   bool Pull(Frame &frame, ExecutionContext &context) override {
     SCOPED_PROFILE_OP("CreateNode");
     if (input_cursor_->Pull(frame, context)) {
-      auto &shard_manager = context.shard_request_manager;
+      auto &shard_manager = context.request_router;
       {
         SCOPED_REQUEST_WAIT_PROFILE;
         shard_manager->Request(state_, NodeCreationInfoToRequest(context, frame));
@@ -197,8 +197,8 @@ class DistributedCreateNodeCursor : public Cursor {
     // TODO(kostasrim) Make this work with batching
     const auto primary_label = msgs::Label{.id = nodes_info_[0]->labels[0]};
     msgs::Vertex v{.id = std::make_pair(primary_label, primary_keys_[0])};
-    frame[nodes_info_.front()->symbol] = TypedValue(
-        query::v2::accessors::VertexAccessor(std::move(v), src_vertex_props_[0], context.shard_request_manager));
+    frame[nodes_info_.front()->symbol] =
+        TypedValue(query::v2::accessors::VertexAccessor(std::move(v), src_vertex_props_[0], context.request_router));
   }
 
   std::vector<msgs::NewVertex> NodeCreationInfoToRequest(ExecutionContext &context, Frame &frame) {
@@ -218,7 +218,7 @@ class DistributedCreateNodeCursor : public Cursor {
       if (const auto *node_info_properties = std::get_if<PropertiesMapList>(&node_info->properties)) {
         for (const auto &[key, value_expression] : *node_info_properties) {
           TypedValue val = value_expression->Accept(evaluator);
-          if (context.shard_request_manager->IsPrimaryKey(primary_label, key)) {
+          if (context.request_router->IsPrimaryKey(primary_label, key)) {
             rqst.primary_key.push_back(TypedValueToValue(val));
             pk.push_back(TypedValueToValue(val));
           }
@@ -227,8 +227,8 @@ class DistributedCreateNodeCursor : public Cursor {
         auto property_map = evaluator.Visit(*std::get<ParameterLookup *>(node_info->properties)).ValueMap();
         for (const auto &[key, value] : property_map) {
           auto key_str = std::string(key);
-          auto property_id = context.shard_request_manager->NameToProperty(key_str);
-          if (context.shard_request_manager->IsPrimaryKey(primary_label, property_id)) {
+          auto property_id = context.request_router->NameToProperty(key_str);
+          if (context.request_router->IsPrimaryKey(primary_label, property_id)) {
             rqst.primary_key.push_back(TypedValueToValue(value));
             pk.push_back(TypedValueToValue(value));
           }
@@ -386,7 +386,7 @@ class DistributedScanAllAndFilterCursor : public Cursor {
 
   using VertexAccessor = accessors::VertexAccessor;
 
-  bool MakeRequest(ShardRequestManagerInterface &shard_manager, ExecutionContext &context) {
+  bool MakeRequest(RequestRouterInterface &shard_manager, ExecutionContext &context) {
     {
       SCOPED_REQUEST_WAIT_PROFILE;
       current_batch = shard_manager.Request(request_state_);
@@ -398,7 +398,7 @@ class DistributedScanAllAndFilterCursor : public Cursor {
   bool Pull(Frame &frame, ExecutionContext &context) override {
     SCOPED_PROFILE_OP(op_name_);
 
-    auto &shard_manager = *context.shard_request_manager;
+    auto &shard_manager = *context.request_router;
     while (true) {
       if (MustAbort(context)) {
         throw HintedAbortError();
@@ -696,7 +696,7 @@ bool Filter::FilterCursor::Pull(Frame &frame, ExecutionContext &context) {
 
   // Like all filters, newly set values should not affect filtering of old
   // nodes and edges.
-  ExpressionEvaluator evaluator(&frame, context.symbol_table, context.evaluation_context, context.shard_request_manager,
+  ExpressionEvaluator evaluator(&frame, context.symbol_table, context.evaluation_context, context.request_router,
                                 storage::v3::View::OLD);
   while (input_cursor_->Pull(frame, context)) {
     if (EvaluateFilter(evaluator, self_.expression_)) return true;
@@ -737,8 +737,8 @@ bool Produce::ProduceCursor::Pull(Frame &frame, ExecutionContext &context) {
 
   if (input_cursor_->Pull(frame, context)) {
     // Produce should always yield the latest results.
-    ExpressionEvaluator evaluator(&frame, context.symbol_table, context.evaluation_context,
-                                  context.shard_request_manager, storage::v3::View::NEW);
+    ExpressionEvaluator evaluator(&frame, context.symbol_table, context.evaluation_context, context.request_router,
+                                  storage::v3::View::NEW);
     for (auto named_expr : self_.named_expressions_) named_expr->Accept(evaluator);
 
     return true;
@@ -1122,8 +1122,8 @@ class AggregateCursor : public Cursor {
    * aggregation results, and not on the number of inputs.
    */
   void ProcessAll(Frame *frame, ExecutionContext *context) {
-    ExpressionEvaluator evaluator(frame, context->symbol_table, context->evaluation_context,
-                                  context->shard_request_manager, storage::v3::View::NEW);
+    ExpressionEvaluator evaluator(frame, context->symbol_table, context->evaluation_context, context->request_router,
+                                  storage::v3::View::NEW);
     while (input_cursor_->Pull(*frame, *context)) {
       ProcessOne(*frame, &evaluator);
     }
@@ -1343,8 +1343,8 @@ bool Skip::SkipCursor::Pull(Frame &frame, ExecutionContext &context) {
       // First successful pull from the input, evaluate the skip expression.
       // The skip expression doesn't contain identifiers so graph view
       // parameter is not important.
-      ExpressionEvaluator evaluator(&frame, context.symbol_table, context.evaluation_context,
-                                    context.shard_request_manager, storage::v3::View::OLD);
+      ExpressionEvaluator evaluator(&frame, context.symbol_table, context.evaluation_context, context.request_router,
+                                    storage::v3::View::OLD);
       TypedValue to_skip = self_.expression_->Accept(evaluator);
       if (to_skip.type() != TypedValue::Type::Int)
         throw QueryRuntimeException("Number of elements to skip must be an integer.");
@@ -1398,8 +1398,8 @@ bool Limit::LimitCursor::Pull(Frame &frame, ExecutionContext &context) {
   if (limit_ == -1) {
     // Limit expression doesn't contain identifiers so graph view is not
     // important.
-    ExpressionEvaluator evaluator(&frame, context.symbol_table, context.evaluation_context,
-                                  context.shard_request_manager, storage::v3::View::OLD);
+    ExpressionEvaluator evaluator(&frame, context.symbol_table, context.evaluation_context, context.request_router,
+                                  storage::v3::View::OLD);
     TypedValue limit = self_.expression_->Accept(evaluator);
     if (limit.type() != TypedValue::Type::Int)
       throw QueryRuntimeException("Limit on number of returned elements must be an integer.");
@@ -1454,8 +1454,8 @@ class OrderByCursor : public Cursor {
     SCOPED_PROFILE_OP("OrderBy");
 
     if (!did_pull_all_) {
-      ExpressionEvaluator evaluator(&frame, context.symbol_table, context.evaluation_context,
-                                    context.shard_request_manager, storage::v3::View::OLD);
+      ExpressionEvaluator evaluator(&frame, context.symbol_table, context.evaluation_context, context.request_router,
+                                    storage::v3::View::OLD);
       auto *mem = cache_.get_allocator().GetMemoryResource();
       while (input_cursor_->Pull(frame, context)) {
         // collect the order_by elements
@@ -1712,8 +1712,8 @@ class UnwindCursor : public Cursor {
         if (!input_cursor_->Pull(frame, context)) return false;
 
         // successful pull from input, initialize value and iterator
-        ExpressionEvaluator evaluator(&frame, context.symbol_table, context.evaluation_context,
-                                      context.shard_request_manager, storage::v3::View::OLD);
+        ExpressionEvaluator evaluator(&frame, context.symbol_table, context.evaluation_context, context.request_router,
+                                      storage::v3::View::OLD);
         TypedValue input_value = self_.input_expression_->Accept(evaluator);
         if (input_value.type() != TypedValue::Type::List)
           throw QueryRuntimeException("Argument of UNWIND must be a list, but '{}' was provided.", input_value.type());
@@ -2224,7 +2224,7 @@ class LoadCsvCursor : public Cursor {
     Frame frame(0);
     SymbolTable symbol_table;
     auto evaluator =
-        ExpressionEvaluator(&frame, symbol_table, eval_context, context.shard_request_manager, storage::v3::View::OLD);
+        ExpressionEvaluator(&frame, symbol_table, eval_context, context.request_router, storage::v3::View::OLD);
 
     auto maybe_file = ToOptionalString(&evaluator, self_->file_);
     auto maybe_delim = ToOptionalString(&evaluator, self_->delimiter_);
@@ -2261,8 +2261,8 @@ class ForeachCursor : public Cursor {
       return false;
     }
 
-    ExpressionEvaluator evaluator(&frame, context.symbol_table, context.evaluation_context,
-                                  context.shard_request_manager, storage::v3::View::NEW);
+    ExpressionEvaluator evaluator(&frame, context.symbol_table, context.evaluation_context, context.request_router,
+                                  storage::v3::View::NEW);
     TypedValue expr_result = expression->Accept(evaluator);
 
     if (expr_result.IsNull()) {
@@ -2338,7 +2338,7 @@ class DistributedCreateExpandCursor : public Cursor {
     if (!input_cursor_->Pull(frame, context)) {
       return false;
     }
-    auto &shard_manager = context.shard_request_manager;
+    auto &shard_manager = context.request_router;
     ResetExecutionState();
     {
       SCOPED_REQUEST_WAIT_PROFILE;
@@ -2379,7 +2379,7 @@ class DistributedCreateExpandCursor : public Cursor {
         // handle parameter
         auto property_map = evaluator.Visit(*std::get<ParameterLookup *>(edge_info.properties)).ValueMap();
         for (const auto &[property, value] : property_map) {
-          const auto property_id = context.shard_request_manager->NameToProperty(std::string(property));
+          const auto property_id = context.request_router->NameToProperty(std::string(property));
           request.properties.emplace_back(property_id, storage::v3::TypedValueToValue(value));
         }
       }
@@ -2394,7 +2394,7 @@ class DistributedCreateExpandCursor : public Cursor {
       const auto set_vertex = [&context](const auto &vertex, auto &vertex_id) {
         vertex_id.first = vertex.PrimaryLabel();
         for (const auto &[key, val] : vertex.Properties()) {
-          if (context.shard_request_manager->IsPrimaryKey(vertex_id.first.id, key)) {
+          if (context.request_router->IsPrimaryKey(vertex_id.first.id, key)) {
             vertex_id.second.push_back(val);
           }
         }
@@ -2474,11 +2474,11 @@ class DistributedExpandCursor : public Cursor {
     request.src_vertices.push_back(get_dst_vertex(edge, direction));
     request.direction = (direction == EdgeAtom::Direction::IN) ? msgs::EdgeDirection::OUT : msgs::EdgeDirection::IN;
     ExecutionState<msgs::ExpandOneRequest> request_state;
-    auto result_rows = context.shard_request_manager->Request(request_state, std::move(request));
+    auto result_rows = context.request_router->Request(request_state, std::move(request));
     MG_ASSERT(result_rows.size() == 1);
     auto &result_row = result_rows.front();
     frame[self_.common_.node_symbol] = accessors::VertexAccessor(
-        msgs::Vertex{result_row.src_vertex}, result_row.src_vertex_properties, context.shard_request_manager);
+        msgs::Vertex{result_row.src_vertex}, result_row.src_vertex_properties, context.request_router);
   }
 
   bool InitEdges(Frame &frame, ExecutionContext &context) {
@@ -2502,7 +2502,7 @@ class DistributedExpandCursor : public Cursor {
       ExecutionState<msgs::ExpandOneRequest> request_state;
       auto result_rows = std::invoke([&context, &request_state, &request]() mutable {
         SCOPED_REQUEST_WAIT_PROFILE;
-        return context.shard_request_manager->Request(request_state, std::move(request));
+        return context.request_router->Request(request_state, std::move(request));
       });
       MG_ASSERT(result_rows.size() == 1);
       auto &result_row = result_rows.front();
@@ -2525,14 +2525,14 @@ class DistributedExpandCursor : public Cursor {
           case EdgeAtom::Direction::IN: {
             for (auto &edge : edge_messages) {
               edge_accessors.emplace_back(msgs::Edge{std::move(edge.other_end), vertex.Id(), {}, {edge.gid}, edge.type},
-                                          context.shard_request_manager);
+                                          context.request_router);
             }
             break;
           }
           case EdgeAtom::Direction::OUT: {
             for (auto &edge : edge_messages) {
               edge_accessors.emplace_back(msgs::Edge{vertex.Id(), std::move(edge.other_end), {}, {edge.gid}, edge.type},
-                                          context.shard_request_manager);
+                                          context.request_router);
             }
             break;
           }
diff --git a/src/query/v2/plan/pretty_print.cpp b/src/query/v2/plan/pretty_print.cpp
index b7ab6da6e..0e8d09e2b 100644
--- a/src/query/v2/plan/pretty_print.cpp
+++ b/src/query/v2/plan/pretty_print.cpp
@@ -14,12 +14,12 @@
 
 #include "query/v2/bindings/pretty_print.hpp"
 #include "query/v2/db_accessor.hpp"
-#include "query/v2/shard_request_manager.hpp"
+#include "query/v2/request_router.hpp"
 #include "utils/string.hpp"
 
 namespace memgraph::query::v2::plan {
 
-PlanPrinter::PlanPrinter(const ShardRequestManagerInterface *request_manager, std::ostream *out)
+PlanPrinter::PlanPrinter(const RequestRouterInterface *request_manager, std::ostream *out)
     : request_manager_(request_manager), out_(out) {}
 
 #define PRE_VISIT(TOp)                                   \
@@ -263,14 +263,13 @@ void PlanPrinter::Branch(query::v2::plan::LogicalOperator &op, const std::string
   --depth_;
 }
 
-void PrettyPrint(const ShardRequestManagerInterface &request_manager, const LogicalOperator *plan_root,
-                 std::ostream *out) {
+void PrettyPrint(const RequestRouterInterface &request_manager, const LogicalOperator *plan_root, std::ostream *out) {
   PlanPrinter printer(&request_manager, out);
   // FIXME(mtomic): We should make visitors that take const arguments.
   const_cast<LogicalOperator *>(plan_root)->Accept(printer);
 }
 
-nlohmann::json PlanToJson(const ShardRequestManagerInterface &request_manager, const LogicalOperator *plan_root) {
+nlohmann::json PlanToJson(const RequestRouterInterface &request_manager, const LogicalOperator *plan_root) {
   impl::PlanToJsonVisitor visitor(&request_manager);
   // FIXME(mtomic): We should make visitors that take const arguments.
   const_cast<LogicalOperator *>(plan_root)->Accept(visitor);
@@ -349,15 +348,15 @@ json ToJson(const utils::Bound<Expression *> &bound) {
 
 json ToJson(const Symbol &symbol) { return symbol.name(); }
 
-json ToJson(storage::v3::EdgeTypeId edge_type, const ShardRequestManagerInterface &request_manager) {
+json ToJson(storage::v3::EdgeTypeId edge_type, const RequestRouterInterface &request_manager) {
   return request_manager.EdgeTypeToName(edge_type);
 }
 
-json ToJson(storage::v3::LabelId label, const ShardRequestManagerInterface &request_manager) {
+json ToJson(storage::v3::LabelId label, const RequestRouterInterface &request_manager) {
   return request_manager.LabelToName(label);
 }
 
-json ToJson(storage::v3::PropertyId property, const ShardRequestManagerInterface &request_manager) {
+json ToJson(storage::v3::PropertyId property, const RequestRouterInterface &request_manager) {
   return request_manager.PropertyToName(property);
 }
 
@@ -369,7 +368,7 @@ json ToJson(NamedExpression *nexpr) {
 }
 
 json ToJson(const std::vector<std::pair<storage::v3::PropertyId, Expression *>> &properties,
-            const ShardRequestManagerInterface &request_manager) {
+            const RequestRouterInterface &request_manager) {
   json json;
   for (const auto &prop_pair : properties) {
     json.emplace(ToJson(prop_pair.first, request_manager), ToJson(prop_pair.second));
@@ -377,7 +376,7 @@ json ToJson(const std::vector<std::pair<storage::v3::PropertyId, Expression *>>
   return json;
 }
 
-json ToJson(const NodeCreationInfo &node_info, const ShardRequestManagerInterface &request_manager) {
+json ToJson(const NodeCreationInfo &node_info, const RequestRouterInterface &request_manager) {
   json self;
   self["symbol"] = ToJson(node_info.symbol);
   self["labels"] = ToJson(node_info.labels, request_manager);
@@ -386,7 +385,7 @@ json ToJson(const NodeCreationInfo &node_info, const ShardRequestManagerInterfac
   return self;
 }
 
-json ToJson(const EdgeCreationInfo &edge_info, const ShardRequestManagerInterface &request_manager) {
+json ToJson(const EdgeCreationInfo &edge_info, const RequestRouterInterface &request_manager) {
   json self;
   self["symbol"] = ToJson(edge_info.symbol);
   const auto *props = std::get_if<PropertiesMapList>(&edge_info.properties);
diff --git a/src/query/v2/plan/pretty_print.hpp b/src/query/v2/plan/pretty_print.hpp
index 8485723a3..7e97de3ff 100644
--- a/src/query/v2/plan/pretty_print.hpp
+++ b/src/query/v2/plan/pretty_print.hpp
@@ -18,7 +18,7 @@
 
 #include "query/v2/frontend/ast/ast.hpp"
 #include "query/v2/plan/operator.hpp"
-#include "query/v2/shard_request_manager.hpp"
+#include "query/v2/request_router.hpp"
 
 namespace memgraph::query::v2 {
 
@@ -27,20 +27,19 @@ namespace plan {
 class LogicalOperator;
 
 /// Pretty print a `LogicalOperator` plan to a `std::ostream`.
-/// ShardRequestManager is needed for resolving label and property names.
+/// RequestRouter is needed for resolving label and property names.
 /// 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.
-void PrettyPrint(const ShardRequestManagerInterface &request_manager, const LogicalOperator *plan_root,
-                 std::ostream *out);
+void PrettyPrint(const RequestRouterInterface &request_manager, const LogicalOperator *plan_root, std::ostream *out);
 
 /// Overload of `PrettyPrint` which defaults the `std::ostream` to `std::cout`.
-inline void PrettyPrint(const ShardRequestManagerInterface &request_manager, const LogicalOperator *plan_root) {
+inline void PrettyPrint(const RequestRouterInterface &request_manager, const LogicalOperator *plan_root) {
   PrettyPrint(request_manager, plan_root, &std::cout);
 }
 
 /// Convert a `LogicalOperator` plan to a JSON representation.
 /// DbAccessor is needed for resolving label and property names.
-nlohmann::json PlanToJson(const ShardRequestManagerInterface &request_manager, const LogicalOperator *plan_root);
+nlohmann::json PlanToJson(const RequestRouterInterface &request_manager, const LogicalOperator *plan_root);
 
 class PlanPrinter : public virtual HierarchicalLogicalOperatorVisitor {
  public:
@@ -48,7 +47,7 @@ class PlanPrinter : public virtual HierarchicalLogicalOperatorVisitor {
   using HierarchicalLogicalOperatorVisitor::PreVisit;
   using HierarchicalLogicalOperatorVisitor::Visit;
 
-  PlanPrinter(const ShardRequestManagerInterface *request_manager, std::ostream *out);
+  PlanPrinter(const RequestRouterInterface *request_manager, std::ostream *out);
 
   bool DefaultPreVisit() override;
 
@@ -115,7 +114,7 @@ class PlanPrinter : public virtual HierarchicalLogicalOperatorVisitor {
   void Branch(LogicalOperator &op, const std::string &branch_name = "");
 
   int64_t depth_{0};
-  const ShardRequestManagerInterface *request_manager_{nullptr};
+  const RequestRouterInterface *request_manager_{nullptr};
   std::ostream *out_{nullptr};
 };
 
@@ -133,20 +132,20 @@ nlohmann::json ToJson(const utils::Bound<Expression *> &bound);
 
 nlohmann::json ToJson(const Symbol &symbol);
 
-nlohmann::json ToJson(storage::v3::EdgeTypeId edge_type, const ShardRequestManagerInterface &request_manager);
+nlohmann::json ToJson(storage::v3::EdgeTypeId edge_type, const RequestRouterInterface &request_manager);
 
-nlohmann::json ToJson(storage::v3::LabelId label, const ShardRequestManagerInterface &request_manager);
+nlohmann::json ToJson(storage::v3::LabelId label, const RequestRouterInterface &request_manager);
 
-nlohmann::json ToJson(storage::v3::PropertyId property, const ShardRequestManagerInterface &request_manager);
+nlohmann::json ToJson(storage::v3::PropertyId property, const RequestRouterInterface &request_manager);
 
 nlohmann::json ToJson(NamedExpression *nexpr);
 
 nlohmann::json ToJson(const std::vector<std::pair<storage::v3::PropertyId, Expression *>> &properties,
-                      const ShardRequestManagerInterface &request_manager);
+                      const RequestRouterInterface &request_manager);
 
-nlohmann::json ToJson(const NodeCreationInfo &node_info, const ShardRequestManagerInterface &request_manager);
+nlohmann::json ToJson(const NodeCreationInfo &node_info, const RequestRouterInterface &request_manager);
 
-nlohmann::json ToJson(const EdgeCreationInfo &edge_info, const ShardRequestManagerInterface &request_manager);
+nlohmann::json ToJson(const EdgeCreationInfo &edge_info, const RequestRouterInterface &request_manager);
 
 nlohmann::json ToJson(const Aggregate::Element &elem);
 
@@ -161,7 +160,7 @@ nlohmann::json ToJson(const std::vector<T> &items, Args &&...args) {
 
 class PlanToJsonVisitor : public virtual HierarchicalLogicalOperatorVisitor {
  public:
-  explicit PlanToJsonVisitor(const ShardRequestManagerInterface *request_manager) : request_manager_(request_manager) {}
+  explicit PlanToJsonVisitor(const RequestRouterInterface *request_manager) : request_manager_(request_manager) {}
 
   using HierarchicalLogicalOperatorVisitor::PostVisit;
   using HierarchicalLogicalOperatorVisitor::PreVisit;
@@ -217,7 +216,7 @@ class PlanToJsonVisitor : public virtual HierarchicalLogicalOperatorVisitor {
 
  protected:
   nlohmann::json output_;
-  const ShardRequestManagerInterface *request_manager_;
+  const RequestRouterInterface *request_manager_;
 
   nlohmann::json PopOutput() {
     nlohmann::json tmp;
diff --git a/src/query/v2/plan/rule_based_planner.hpp b/src/query/v2/plan/rule_based_planner.hpp
index 884693c2f..2b6857aea 100644
--- a/src/query/v2/plan/rule_based_planner.hpp
+++ b/src/query/v2/plan/rule_based_planner.hpp
@@ -272,7 +272,7 @@ class RuleBasedPlanner {
           PropertiesMapList vector_props;
           vector_props.reserve(node_properties->size());
           for (const auto &kv : *node_properties) {
-            // TODO(kostasrim) GetProperty should be implemented in terms of ShardRequestManager NameToProperty
+            // TODO(kostasrim) GetProperty should be implemented in terms of RequestRouter NameToProperty
             vector_props.push_back({GetProperty(kv.first), kv.second});
           }
           return std::move(vector_props);
diff --git a/src/query/v2/plan/vertex_count_cache.hpp b/src/query/v2/plan/vertex_count_cache.hpp
index 47a10ba3e..e68ce1220 100644
--- a/src/query/v2/plan/vertex_count_cache.hpp
+++ b/src/query/v2/plan/vertex_count_cache.hpp
@@ -15,7 +15,7 @@
 #include <optional>
 
 #include "query/v2/bindings/typed_value.hpp"
-#include "query/v2/shard_request_manager.hpp"
+#include "query/v2/request_router.hpp"
 #include "storage/v3/conversions.hpp"
 #include "storage/v3/id_types.hpp"
 #include "storage/v3/property_value.hpp"
@@ -29,11 +29,11 @@ namespace memgraph::query::v2::plan {
 template <class TDbAccessor>
 class VertexCountCache {
  public:
-  explicit VertexCountCache(TDbAccessor *shard_request_manager) : shard_request_manager_{shard_request_manager} {}
+  explicit VertexCountCache(TDbAccessor *request_router) : request_router_{request_router} {}
 
-  auto NameToLabel(const std::string &name) { return shard_request_manager_->NameToLabel(name); }
-  auto NameToProperty(const std::string &name) { return shard_request_manager_->NameToProperty(name); }
-  auto NameToEdgeType(const std::string &name) { return shard_request_manager_->NameToEdgeType(name); }
+  auto NameToLabel(const std::string &name) { return request_router_->NameToLabel(name); }
+  auto NameToProperty(const std::string &name) { return request_router_->NameToProperty(name); }
+  auto NameToEdgeType(const std::string &name) { return request_router_->NameToEdgeType(name); }
 
   int64_t VerticesCount() { return 1; }
 
@@ -53,11 +53,11 @@ class VertexCountCache {
   }
 
   // For now return true if label is primary label
-  bool LabelIndexExists(storage::v3::LabelId label) { return shard_request_manager_->IsPrimaryLabel(label); }
+  bool LabelIndexExists(storage::v3::LabelId label) { return request_router_->IsPrimaryLabel(label); }
 
   bool LabelPropertyIndexExists(storage::v3::LabelId /*label*/, storage::v3::PropertyId /*property*/) { return false; }
 
-  ShardRequestManagerInterface *shard_request_manager_;
+  RequestRouterInterface *request_router_;
 };
 
 template <class TDbAccessor>
diff --git a/src/query/v2/shard_request_manager.hpp b/src/query/v2/request_router.hpp
similarity index 96%
rename from src/query/v2/shard_request_manager.hpp
rename to src/query/v2/request_router.hpp
index 68a10f384..86aae6bcc 100644
--- a/src/query/v2/shard_request_manager.hpp
+++ b/src/query/v2/request_router.hpp
@@ -83,10 +83,10 @@ struct ExecutionState {
   // CompoundKey is optional because some operators require to iterate over all the available keys
   // of a shard. One example is ScanAll, where we only require the field label.
   std::optional<CompoundKey> key;
-  // Transaction id to be filled by the ShardRequestManager implementation
+  // Transaction id to be filled by the RequestRouter implementation
   coordinator::Hlc transaction_id;
-  // 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
+  // Initialized by RequestRouter implementation. This vector is filled with the shards that
+  // the RequestRouter 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
   // empty, it means that all of the requests have completed succefully.
   // TODO(gvolfing)
@@ -101,16 +101,16 @@ struct ExecutionState {
   State state = INITIALIZING;
 };
 
-class ShardRequestManagerInterface {
+class RequestRouterInterface {
  public:
   using VertexAccessor = query::v2::accessors::VertexAccessor;
-  ShardRequestManagerInterface() = default;
-  ShardRequestManagerInterface(const ShardRequestManagerInterface &) = delete;
-  ShardRequestManagerInterface(ShardRequestManagerInterface &&) = delete;
-  ShardRequestManagerInterface &operator=(const ShardRequestManagerInterface &) = delete;
-  ShardRequestManagerInterface &&operator=(ShardRequestManagerInterface &&) = delete;
+  RequestRouterInterface() = default;
+  RequestRouterInterface(const RequestRouterInterface &) = delete;
+  RequestRouterInterface(RequestRouterInterface &&) = delete;
+  RequestRouterInterface &operator=(const RequestRouterInterface &) = delete;
+  RequestRouterInterface &&operator=(RequestRouterInterface &&) = delete;
 
-  virtual ~ShardRequestManagerInterface() = default;
+  virtual ~RequestRouterInterface() = default;
 
   virtual void StartTransaction() = 0;
   virtual void Commit() = 0;
@@ -134,7 +134,7 @@ class ShardRequestManagerInterface {
 
 // TODO(kostasrim)rename this class template
 template <typename TTransport>
-class ShardRequestManager : public ShardRequestManagerInterface {
+class RequestRouter : public RequestRouterInterface {
  public:
   using StorageClient = coordinator::RsmClient<TTransport, msgs::WriteRequests, msgs::WriteResponses,
                                                msgs::ReadRequests, msgs::ReadResponses>;
@@ -145,15 +145,14 @@ class ShardRequestManager : public ShardRequestManagerInterface {
   using ShardMap = coordinator::ShardMap;
   using CompoundKey = coordinator::PrimaryKey;
   using VertexAccessor = query::v2::accessors::VertexAccessor;
-  ShardRequestManager(CoordinatorClient coord, io::Io<TTransport> &&io)
-      : coord_cli_(std::move(coord)), io_(std::move(io)) {}
+  RequestRouter(CoordinatorClient coord, io::Io<TTransport> &&io) : coord_cli_(std::move(coord)), io_(std::move(io)) {}
 
-  ShardRequestManager(const ShardRequestManager &) = delete;
-  ShardRequestManager(ShardRequestManager &&) = delete;
-  ShardRequestManager &operator=(const ShardRequestManager &) = delete;
-  ShardRequestManager &operator=(ShardRequestManager &&) = delete;
+  RequestRouter(const RequestRouter &) = delete;
+  RequestRouter(RequestRouter &&) = delete;
+  RequestRouter &operator=(const RequestRouter &) = delete;
+  RequestRouter &operator=(RequestRouter &&) = delete;
 
-  ~ShardRequestManager() override {}
+  ~RequestRouter() override {}
 
   void StartTransaction() override {
     coordinator::HlcRequest req{.last_shard_map_version = shards_map_.GetHlc()};
diff --git a/tests/simulation/shard_request_manager.cpp b/tests/simulation/request_router.cpp
similarity index 94%
rename from tests/simulation/shard_request_manager.cpp
rename to tests/simulation/request_router.cpp
index 9db18659e..ddd9351ae 100644
--- a/tests/simulation/shard_request_manager.cpp
+++ b/tests/simulation/request_router.cpp
@@ -31,8 +31,8 @@
 #include "io/simulator/simulator_transport.hpp"
 #include "query/v2/accessors.hpp"
 #include "query/v2/conversions.hpp"
+#include "query/v2/request_router.hpp"
 #include "query/v2/requests.hpp"
-#include "query/v2/shard_request_manager.hpp"
 #include "storage/v3/property_value.hpp"
 #include "utils/result.hpp"
 
@@ -151,7 +151,7 @@ void RunStorageRaft(Raft<IoImpl, MockedShardRsm, WriteRequests, WriteResponses,
   server.Run();
 }
 
-void TestScanVertices(query::v2::ShardRequestManagerInterface &io) {
+void TestScanVertices(query::v2::RequestRouterInterface &io) {
   msgs::ExecutionState<ScanVerticesRequest> state{.label = "test_label"};
 
   auto result = io.Request(state);
@@ -171,7 +171,7 @@ void TestScanVertices(query::v2::ShardRequestManagerInterface &io) {
   }
 }
 
-void TestCreateVertices(query::v2::ShardRequestManagerInterface &io) {
+void TestCreateVertices(query::v2::RequestRouterInterface &io) {
   using PropVal = msgs::Value;
   msgs::ExecutionState<CreateVerticesRequest> state;
   std::vector<msgs::NewVertex> new_vertices;
@@ -187,7 +187,7 @@ void TestCreateVertices(query::v2::ShardRequestManagerInterface &io) {
   MG_ASSERT(result.size() == 2);
 }
 
-void TestCreateExpand(query::v2::ShardRequestManagerInterface &io) {
+void TestCreateExpand(query::v2::RequestRouterInterface &io) {
   using PropVal = msgs::Value;
   msgs::ExecutionState<msgs::CreateExpandRequest> state;
   std::vector<msgs::NewExpand> new_expands;
@@ -209,20 +209,20 @@ void TestCreateExpand(query::v2::ShardRequestManagerInterface &io) {
   MG_ASSERT(responses[1].success);
 }
 
-void TestExpandOne(query::v2::ShardRequestManagerInterface &shard_request_manager) {
+void TestExpandOne(query::v2::RequestRouterInterface &request_router) {
   msgs::ExecutionState<msgs::ExpandOneRequest> state{};
   msgs::ExpandOneRequest request;
-  const auto edge_type_id = shard_request_manager.NameToEdgeType("edge_type");
-  const auto label = msgs::Label{shard_request_manager.NameToLabel("test_label")};
+  const auto edge_type_id = request_router.NameToEdgeType("edge_type");
+  const auto label = msgs::Label{request_router.NameToLabel("test_label")};
   request.src_vertices.push_back(msgs::VertexId{label, {msgs::Value(int64_t(0)), msgs::Value(int64_t(0))}});
   request.edge_types.push_back(msgs::EdgeType{edge_type_id});
   request.direction = msgs::EdgeDirection::BOTH;
-  auto result_rows = shard_request_manager.Request(state, std::move(request));
+  auto result_rows = request_router.Request(state, std::move(request));
   MG_ASSERT(result_rows.size() == 2);
 }
 
-template <typename ShardRequestManager>
-void TestAggregate(ShardRequestManager &io) {}
+template <typename RequestRouter>
+void TestAggregate(RequestRouter &io) {}
 
 void DoTest() {
   SimulatorConfig config{
@@ -337,7 +337,7 @@ void DoTest() {
   // also get the current shard map
   CoordinatorClient<SimulatorTransport> coordinator_client(cli_io, c_addrs[0], c_addrs);
 
-  query::v2::ShardRequestManager<SimulatorTransport> io(std::move(coordinator_client), std::move(cli_io));
+  query::v2::RequestRouter<SimulatorTransport> io(std::move(coordinator_client), std::move(cli_io));
 
   io.StartTransaction();
   TestScanVertices(io);
diff --git a/tests/simulation/test_cluster.hpp b/tests/simulation/test_cluster.hpp
index fd62b99f9..99f617cda 100644
--- a/tests/simulation/test_cluster.hpp
+++ b/tests/simulation/test_cluster.hpp
@@ -30,8 +30,8 @@
 #include "io/simulator/simulator_transport.hpp"
 #include "machine_manager/machine_config.hpp"
 #include "machine_manager/machine_manager.hpp"
+#include "query/v2/request_router.hpp"
 #include "query/v2/requests.hpp"
-#include "query/v2/shard_request_manager.hpp"
 #include "testing_constants.hpp"
 #include "utils/print_helpers.hpp"
 #include "utils/variant_helpers.hpp"
@@ -151,8 +151,8 @@ ShardMap TestShardMap(int n_splits, int replication_factor) {
   return sm;
 }
 
-void ExecuteOp(query::v2::ShardRequestManager<SimulatorTransport> &shard_request_manager,
-               std::set<CompoundKey> &correctness_model, CreateVertex create_vertex) {
+void ExecuteOp(query::v2::RequestRouter<SimulatorTransport> &request_router, std::set<CompoundKey> &correctness_model,
+               CreateVertex create_vertex) {
   const auto key1 = memgraph::storage::v3::PropertyValue(create_vertex.first);
   const auto key2 = memgraph::storage::v3::PropertyValue(create_vertex.second);
 
@@ -166,7 +166,7 @@ void ExecuteOp(query::v2::ShardRequestManager<SimulatorTransport> &shard_request
 
   query::v2::ExecutionState<msgs::CreateVerticesRequest> state;
 
-  auto label_id = shard_request_manager.NameToLabel("test_label");
+  auto label_id = request_router.NameToLabel("test_label");
 
   msgs::NewVertex nv{.primary_key = primary_key};
   nv.label_ids.push_back({label_id});
@@ -174,7 +174,7 @@ void ExecuteOp(query::v2::ShardRequestManager<SimulatorTransport> &shard_request
   std::vector<msgs::NewVertex> new_vertices;
   new_vertices.push_back(std::move(nv));
 
-  auto result = shard_request_manager.Request(state, std::move(new_vertices));
+  auto result = request_router.Request(state, std::move(new_vertices));
 
   RC_ASSERT(result.size() == 1);
   RC_ASSERT(!result[0].error.has_value());
@@ -182,11 +182,11 @@ void ExecuteOp(query::v2::ShardRequestManager<SimulatorTransport> &shard_request
   correctness_model.emplace(std::make_pair(create_vertex.first, create_vertex.second));
 }
 
-void ExecuteOp(query::v2::ShardRequestManager<SimulatorTransport> &shard_request_manager,
-               std::set<CompoundKey> &correctness_model, ScanAll scan_all) {
+void ExecuteOp(query::v2::RequestRouter<SimulatorTransport> &request_router, std::set<CompoundKey> &correctness_model,
+               ScanAll scan_all) {
   query::v2::ExecutionState<msgs::ScanVerticesRequest> request{.label = "test_label"};
 
-  auto results = shard_request_manager.Request(request);
+  auto results = request_router.Request(request);
 
   RC_ASSERT(results.size() == correctness_model.size());
 
@@ -247,15 +247,14 @@ std::pair<SimulatorStats, LatencyHistogramSummaries> RunClusterSimulation(const
   CoordinatorClient<SimulatorTransport> coordinator_client(cli_io, coordinator_address, {coordinator_address});
   WaitForShardsToInitialize(coordinator_client);
 
-  query::v2::ShardRequestManager<SimulatorTransport> shard_request_manager(std::move(coordinator_client),
-                                                                           std::move(cli_io));
+  query::v2::RequestRouter<SimulatorTransport> request_router(std::move(coordinator_client), std::move(cli_io));
 
-  shard_request_manager.StartTransaction();
+  request_router.StartTransaction();
 
   auto correctness_model = std::set<CompoundKey>{};
 
   for (const Op &op : ops) {
-    std::visit([&](auto &o) { ExecuteOp(shard_request_manager, correctness_model, o); }, op.inner);
+    std::visit([&](auto &o) { ExecuteOp(request_router, correctness_model, o); }, op.inner);
   }
 
   // We have now completed our workload without failing any assertions, so we can
diff --git a/tests/unit/high_density_shard_create_scan.cpp b/tests/unit/high_density_shard_create_scan.cpp
index e586a3556..22af9c702 100644
--- a/tests/unit/high_density_shard_create_scan.cpp
+++ b/tests/unit/high_density_shard_create_scan.cpp
@@ -29,8 +29,8 @@
 #include "io/simulator/simulator_transport.hpp"
 #include "machine_manager/machine_config.hpp"
 #include "machine_manager/machine_manager.hpp"
+#include "query/v2/request_router.hpp"
 #include "query/v2/requests.hpp"
-#include "query/v2/shard_request_manager.hpp"
 #include "utils/variant_helpers.hpp"
 
 namespace memgraph::tests::simulation {
@@ -161,8 +161,8 @@ ShardMap TestShardMap(int shards, int replication_factor, int gap_between_shards
   return sm;
 }
 
-void ExecuteOp(query::v2::ShardRequestManager<LocalTransport> &shard_request_manager,
-               std::set<CompoundKey> &correctness_model, CreateVertex create_vertex) {
+void ExecuteOp(query::v2::RequestRouter<LocalTransport> &request_router, std::set<CompoundKey> &correctness_model,
+               CreateVertex create_vertex) {
   const auto key1 = memgraph::storage::v3::PropertyValue(create_vertex.first);
   const auto key2 = memgraph::storage::v3::PropertyValue(create_vertex.second);
 
@@ -176,7 +176,7 @@ void ExecuteOp(query::v2::ShardRequestManager<LocalTransport> &shard_request_man
 
   query::v2::ExecutionState<msgs::CreateVerticesRequest> state;
 
-  auto label_id = shard_request_manager.NameToLabel("test_label");
+  auto label_id = request_router.NameToLabel("test_label");
 
   msgs::NewVertex nv{.primary_key = primary_key};
   nv.label_ids.push_back({label_id});
@@ -184,7 +184,7 @@ void ExecuteOp(query::v2::ShardRequestManager<LocalTransport> &shard_request_man
   std::vector<msgs::NewVertex> new_vertices;
   new_vertices.push_back(std::move(nv));
 
-  auto result = shard_request_manager.Request(state, std::move(new_vertices));
+  auto result = request_router.Request(state, std::move(new_vertices));
 
   MG_ASSERT(result.size() == 1);
   MG_ASSERT(!result[0].error.has_value());
@@ -192,11 +192,11 @@ void ExecuteOp(query::v2::ShardRequestManager<LocalTransport> &shard_request_man
   correctness_model.emplace(std::make_pair(create_vertex.first, create_vertex.second));
 }
 
-void ExecuteOp(query::v2::ShardRequestManager<LocalTransport> &shard_request_manager,
-               std::set<CompoundKey> &correctness_model, ScanAll scan_all) {
+void ExecuteOp(query::v2::RequestRouter<LocalTransport> &request_router, std::set<CompoundKey> &correctness_model,
+               ScanAll scan_all) {
   query::v2::ExecutionState<msgs::ScanVerticesRequest> request{.label = "test_label"};
 
-  auto results = shard_request_manager.Request(request);
+  auto results = request_router.Request(request);
 
   MG_ASSERT(results.size() == correctness_model.size());
 
@@ -245,23 +245,22 @@ void RunWorkload(int shards, int replication_factor, int create_ops, int scan_op
   WaitForShardsToInitialize(coordinator_client);
   auto time_after_shard_stabilization = cli_io_2.Now();
 
-  query::v2::ShardRequestManager<LocalTransport> shard_request_manager(std::move(coordinator_client),
-                                                                       std::move(cli_io));
+  query::v2::RequestRouter<LocalTransport> request_router(std::move(coordinator_client), std::move(cli_io));
 
-  shard_request_manager.StartTransaction();
+  request_router.StartTransaction();
 
   auto correctness_model = std::set<CompoundKey>{};
 
   auto time_before_creates = cli_io_2.Now();
 
   for (int i = 0; i < create_ops; i++) {
-    ExecuteOp(shard_request_manager, correctness_model, CreateVertex{.first = i, .second = i});
+    ExecuteOp(request_router, correctness_model, CreateVertex{.first = i, .second = i});
   }
 
   auto time_after_creates = cli_io_2.Now();
 
   for (int i = 0; i < scan_ops; i++) {
-    ExecuteOp(shard_request_manager, correctness_model, ScanAll{});
+    ExecuteOp(request_router, correctness_model, ScanAll{});
   }
 
   auto time_after_scan = cli_io_2.Now();
diff --git a/tests/unit/machine_manager.cpp b/tests/unit/machine_manager.cpp
index 834523fee..0b081e5a1 100644
--- a/tests/unit/machine_manager.cpp
+++ b/tests/unit/machine_manager.cpp
@@ -27,7 +27,7 @@
 #include <machine_manager/machine_manager.hpp>
 #include <query/v2/requests.hpp>
 #include "io/rsm/rsm_client.hpp"
-#include "query/v2/shard_request_manager.hpp"
+#include "query/v2/request_router.hpp"
 #include "storage/v3/id_types.hpp"
 #include "storage/v3/schemas.hpp"
 
@@ -109,19 +109,19 @@ ShardMap TestShardMap() {
   return sm;
 }
 
-template <typename ShardRequestManager>
-void TestScanAll(ShardRequestManager &shard_request_manager) {
+template <typename RequestRouter>
+void TestScanAll(RequestRouter &request_router) {
   query::v2::ExecutionState<msgs::ScanVerticesRequest> state{.label = kLabelName};
 
-  auto result = shard_request_manager.Request(state);
+  auto result = request_router.Request(state);
   EXPECT_EQ(result.size(), 2);
 }
 
-void TestCreateVertices(query::v2::ShardRequestManagerInterface &shard_request_manager) {
+void TestCreateVertices(query::v2::RequestRouterInterface &request_router) {
   using PropVal = msgs::Value;
   query::v2::ExecutionState<msgs::CreateVerticesRequest> state;
   std::vector<msgs::NewVertex> new_vertices;
-  auto label_id = shard_request_manager.NameToLabel(kLabelName);
+  auto label_id = request_router.NameToLabel(kLabelName);
   msgs::NewVertex a1{.primary_key = {PropVal(int64_t(0)), PropVal(int64_t(0))}};
   a1.label_ids.push_back({label_id});
   msgs::NewVertex a2{.primary_key = {PropVal(int64_t(13)), PropVal(int64_t(13))}};
@@ -129,18 +129,18 @@ void TestCreateVertices(query::v2::ShardRequestManagerInterface &shard_request_m
   new_vertices.push_back(std::move(a1));
   new_vertices.push_back(std::move(a2));
 
-  auto result = shard_request_manager.Request(state, std::move(new_vertices));
+  auto result = request_router.Request(state, std::move(new_vertices));
   EXPECT_EQ(result.size(), 1);
   EXPECT_FALSE(result[0].error.has_value()) << result[0].error->message;
 }
 
-void TestCreateExpand(query::v2::ShardRequestManagerInterface &shard_request_manager) {
+void TestCreateExpand(query::v2::RequestRouterInterface &request_router) {
   using PropVal = msgs::Value;
   query::v2::ExecutionState<msgs::CreateExpandRequest> state;
   std::vector<msgs::NewExpand> new_expands;
 
-  const auto edge_type_id = shard_request_manager.NameToEdgeType("edge_type");
-  const auto label = msgs::Label{shard_request_manager.NameToLabel("test_label")};
+  const auto edge_type_id = request_router.NameToEdgeType("edge_type");
+  const auto label = msgs::Label{request_router.NameToLabel("test_label")};
   const msgs::VertexId vertex_id_1{label, {PropVal(int64_t(0)), PropVal(int64_t(0))}};
   const msgs::VertexId vertex_id_2{label, {PropVal(int64_t(13)), PropVal(int64_t(13))}};
   msgs::NewExpand expand_1{
@@ -150,27 +150,27 @@ void TestCreateExpand(query::v2::ShardRequestManagerInterface &shard_request_man
   new_expands.push_back(std::move(expand_1));
   new_expands.push_back(std::move(expand_2));
 
-  auto responses = shard_request_manager.Request(state, std::move(new_expands));
+  auto responses = request_router.Request(state, std::move(new_expands));
   MG_ASSERT(responses.size() == 1);
   MG_ASSERT(!responses[0].error.has_value());
 }
 
-void TestExpandOne(query::v2::ShardRequestManagerInterface &shard_request_manager) {
+void TestExpandOne(query::v2::RequestRouterInterface &request_router) {
   query::v2::ExecutionState<msgs::ExpandOneRequest> state{};
   msgs::ExpandOneRequest request;
-  const auto edge_type_id = shard_request_manager.NameToEdgeType("edge_type");
-  const auto label = msgs::Label{shard_request_manager.NameToLabel("test_label")};
+  const auto edge_type_id = request_router.NameToEdgeType("edge_type");
+  const auto label = msgs::Label{request_router.NameToLabel("test_label")};
   request.src_vertices.push_back(msgs::VertexId{label, {msgs::Value(int64_t(0)), msgs::Value(int64_t(0))}});
   request.edge_types.push_back(msgs::EdgeType{edge_type_id});
   request.direction = msgs::EdgeDirection::BOTH;
-  auto result_rows = shard_request_manager.Request(state, std::move(request));
+  auto result_rows = request_router.Request(state, std::move(request));
   MG_ASSERT(result_rows.size() == 1);
   MG_ASSERT(result_rows[0].in_edges_with_all_properties.size() == 1);
   MG_ASSERT(result_rows[0].out_edges_with_all_properties.size() == 1);
 }
 
-template <typename ShardRequestManager>
-void TestAggregate(ShardRequestManager &shard_request_manager) {}
+template <typename RequestRouter>
+void TestAggregate(RequestRouter &request_router) {}
 
 MachineManager<LocalTransport> MkMm(LocalSystem &local_system, std::vector<Address> coordinator_addresses, Address addr,
                                     ShardMap shard_map) {
@@ -226,14 +226,13 @@ TEST(MachineManager, BasicFunctionality) {
 
   CoordinatorClient<LocalTransport> coordinator_client(cli_io, coordinator_address, {coordinator_address});
 
-  query::v2::ShardRequestManager<LocalTransport> shard_request_manager(std::move(coordinator_client),
-                                                                       std::move(cli_io));
+  query::v2::RequestRouter<LocalTransport> request_router(std::move(coordinator_client), std::move(cli_io));
 
-  shard_request_manager.StartTransaction();
-  TestCreateVertices(shard_request_manager);
-  TestScanAll(shard_request_manager);
-  TestCreateExpand(shard_request_manager);
-  TestExpandOne(shard_request_manager);
+  request_router.StartTransaction();
+  TestCreateVertices(request_router);
+  TestScanAll(request_router);
+  TestCreateExpand(request_router);
+  TestExpandOne(request_router);
   local_system.ShutDown();
 };
 

From 9fc7f9dcedb42eb233eefc3ff3ca2aabba42ed59 Mon Sep 17 00:00:00 2001
From: Tyler Neely <t@jujit.su>
Date: Mon, 28 Nov 2022 13:03:07 +0000
Subject: [PATCH 14/26] Standardize RequestRouter variable names as
 request_router

---
 src/query/v2/accessors.cpp                    | 25 ++---
 src/query/v2/accessors.hpp                    | 13 +--
 src/query/v2/bindings/eval.hpp                |  4 +-
 src/query/v2/conversions.hpp                  | 10 +-
 src/query/v2/cypher_query_interpreter.cpp     |  8 +-
 src/query/v2/cypher_query_interpreter.hpp     |  4 +-
 .../interpret/awesome_memgraph_functions.hpp  |  2 +-
 src/query/v2/interpreter.cpp                  | 26 +++---
 src/query/v2/plan/operator.cpp                | 19 ++--
 src/query/v2/plan/pretty_print.cpp            | 92 +++++++++----------
 src/query/v2/plan/pretty_print.hpp            | 28 +++---
 tests/simulation/request_router.cpp           | 32 +++----
 12 files changed, 133 insertions(+), 130 deletions(-)

diff --git a/src/query/v2/accessors.cpp b/src/query/v2/accessors.cpp
index a28df0fe5..2eedfcf4d 100644
--- a/src/query/v2/accessors.cpp
+++ b/src/query/v2/accessors.cpp
@@ -15,15 +15,15 @@
 #include "storage/v3/id_types.hpp"
 
 namespace memgraph::query::v2::accessors {
-EdgeAccessor::EdgeAccessor(Edge edge, const RequestRouterInterface *manager)
-    : edge(std::move(edge)), manager_(manager) {}
+EdgeAccessor::EdgeAccessor(Edge edge, const RequestRouterInterface *request_router)
+    : edge(std::move(edge)), request_router_(request_router) {}
 
 EdgeTypeId EdgeAccessor::EdgeType() const { return edge.type.id; }
 
 const std::vector<std::pair<PropertyId, Value>> &EdgeAccessor::Properties() const { return edge.properties; }
 
 Value EdgeAccessor::GetProperty(const std::string &prop_name) const {
-  auto prop_id = manager_->NameToProperty(prop_name);
+  auto prop_id = request_router_->NameToProperty(prop_name);
   auto it = std::find_if(edge.properties.begin(), edge.properties.end(), [&](auto &pr) { return prop_id == pr.first; });
   if (it == edge.properties.end()) {
     return {};
@@ -36,19 +36,20 @@ const Edge &EdgeAccessor::GetEdge() const { return edge; }
 bool EdgeAccessor::IsCycle() const { return edge.src == edge.dst; };
 
 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>>{}, request_router_);
 }
 
 VertexAccessor EdgeAccessor::From() const {
-  return VertexAccessor(Vertex{edge.src}, std::vector<std::pair<PropertyId, msgs::Value>>{}, manager_);
+  return VertexAccessor(Vertex{edge.src}, std::vector<std::pair<PropertyId, msgs::Value>>{}, request_router_);
 }
 
 VertexAccessor::VertexAccessor(Vertex v, std::vector<std::pair<PropertyId, Value>> props,
-                               const RequestRouterInterface *manager)
-    : vertex(std::move(v)), properties(std::move(props)), manager_(manager) {}
+                               const RequestRouterInterface *request_router)
+    : vertex(std::move(v)), properties(std::move(props)), request_router_(request_router) {}
 
-VertexAccessor::VertexAccessor(Vertex v, std::map<PropertyId, Value> &&props, const RequestRouterInterface *manager)
-    : vertex(std::move(v)), manager_(manager) {
+VertexAccessor::VertexAccessor(Vertex v, std::map<PropertyId, Value> &&props,
+                               const RequestRouterInterface *request_router)
+    : vertex(std::move(v)), request_router_(request_router) {
   properties.reserve(props.size());
   for (auto &[id, value] : props) {
     properties.emplace_back(std::make_pair(id, std::move(value)));
@@ -56,8 +57,8 @@ VertexAccessor::VertexAccessor(Vertex v, std::map<PropertyId, Value> &&props, co
 }
 
 VertexAccessor::VertexAccessor(Vertex v, const std::map<PropertyId, Value> &props,
-                               const RequestRouterInterface *manager)
-    : vertex(std::move(v)), manager_(manager) {
+                               const RequestRouterInterface *request_router)
+    : vertex(std::move(v)), request_router_(request_router) {
   properties.reserve(props.size());
   for (const auto &[id, value] : props) {
     properties.emplace_back(std::make_pair(id, value));
@@ -87,7 +88,7 @@ Value VertexAccessor::GetProperty(PropertyId prop_id) const {
 
 // NOLINTNEXTLINE(readability-convert-member-functions-to-static)
 Value VertexAccessor::GetProperty(const std::string &prop_name) const {
-  return GetProperty(manager_->NameToProperty(prop_name));
+  return GetProperty(request_router_->NameToProperty(prop_name));
 }
 
 msgs::Vertex VertexAccessor::GetVertex() const { return vertex; }
diff --git a/src/query/v2/accessors.hpp b/src/query/v2/accessors.hpp
index b5585953f..db22d29cc 100644
--- a/src/query/v2/accessors.hpp
+++ b/src/query/v2/accessors.hpp
@@ -41,7 +41,7 @@ class VertexAccessor;
 
 class EdgeAccessor final {
  public:
-  explicit EdgeAccessor(Edge edge, const RequestRouterInterface *manager);
+  explicit EdgeAccessor(Edge edge, const RequestRouterInterface *request_router);
 
   [[nodiscard]] EdgeTypeId EdgeType() const;
 
@@ -69,7 +69,7 @@ class EdgeAccessor final {
 
  private:
   Edge edge;
-  const RequestRouterInterface *manager_;
+  const RequestRouterInterface *request_router_;
 };
 
 class VertexAccessor final {
@@ -77,10 +77,11 @@ class VertexAccessor final {
   using PropertyId = msgs::PropertyId;
   using Label = msgs::Label;
   using VertexId = msgs::VertexId;
-  VertexAccessor(Vertex v, std::vector<std::pair<PropertyId, Value>> props, const RequestRouterInterface *manager);
+  VertexAccessor(Vertex v, std::vector<std::pair<PropertyId, Value>> props,
+                 const RequestRouterInterface *request_router);
 
-  VertexAccessor(Vertex v, std::map<PropertyId, Value> &&props, const RequestRouterInterface *manager);
-  VertexAccessor(Vertex v, const std::map<PropertyId, Value> &props, const RequestRouterInterface *manager);
+  VertexAccessor(Vertex v, std::map<PropertyId, Value> &&props, const RequestRouterInterface *request_router);
+  VertexAccessor(Vertex v, const std::map<PropertyId, Value> &props, const RequestRouterInterface *request_router);
 
   [[nodiscard]] Label PrimaryLabel() const;
 
@@ -149,7 +150,7 @@ class VertexAccessor final {
  private:
   Vertex vertex;
   std::vector<std::pair<PropertyId, Value>> properties;
-  const RequestRouterInterface *manager_;
+  const RequestRouterInterface *request_router_;
 };
 
 // inline VertexAccessor EdgeAccessor::To() const { return VertexAccessor(impl_.ToVertex()); }
diff --git a/src/query/v2/bindings/eval.hpp b/src/query/v2/bindings/eval.hpp
index 912850e87..c7f52f201 100644
--- a/src/query/v2/bindings/eval.hpp
+++ b/src/query/v2/bindings/eval.hpp
@@ -35,8 +35,8 @@ class Callable {
   auto operator()(const storage::v3::PropertyValue &val) const {
     return storage::v3::PropertyToTypedValue<TypedValue>(val);
   };
-  auto operator()(const msgs::Value &val, RequestRouterInterface *manager) const {
-    return ValueToTypedValue(val, manager);
+  auto operator()(const msgs::Value &val, RequestRouterInterface *request_router) const {
+    return ValueToTypedValue(val, request_router);
   };
 };
 
diff --git a/src/query/v2/conversions.hpp b/src/query/v2/conversions.hpp
index 161f89979..ac052327d 100644
--- a/src/query/v2/conversions.hpp
+++ b/src/query/v2/conversions.hpp
@@ -17,7 +17,7 @@
 
 namespace memgraph::query::v2 {
 
-inline TypedValue ValueToTypedValue(const msgs::Value &value, RequestRouterInterface *manager) {
+inline TypedValue ValueToTypedValue(const msgs::Value &value, RequestRouterInterface *request_router) {
   using Value = msgs::Value;
   switch (value.type) {
     case Value::Type::Null:
@@ -35,7 +35,7 @@ inline TypedValue ValueToTypedValue(const msgs::Value &value, RequestRouterInter
       std::vector<TypedValue> dst;
       dst.reserve(lst.size());
       for (const auto &elem : lst) {
-        dst.push_back(ValueToTypedValue(elem, manager));
+        dst.push_back(ValueToTypedValue(elem, request_router));
       }
       return TypedValue(std::move(dst));
     }
@@ -43,15 +43,15 @@ inline TypedValue ValueToTypedValue(const msgs::Value &value, RequestRouterInter
       const auto &value_map = value.map_v;
       std::map<std::string, TypedValue> dst;
       for (const auto &[key, val] : value_map) {
-        dst[key] = ValueToTypedValue(val, manager);
+        dst[key] = ValueToTypedValue(val, request_router);
       }
       return TypedValue(std::move(dst));
     }
     case Value::Type::Vertex:
       return TypedValue(accessors::VertexAccessor(
-          value.vertex_v, std::vector<std::pair<storage::v3::PropertyId, msgs::Value>>{}, manager));
+          value.vertex_v, std::vector<std::pair<storage::v3::PropertyId, msgs::Value>>{}, request_router));
     case Value::Type::Edge:
-      return TypedValue(accessors::EdgeAccessor(value.edge_v, manager));
+      return TypedValue(accessors::EdgeAccessor(value.edge_v, request_router));
   }
   throw std::runtime_error("Incorrect type in conversion");
 }
diff --git a/src/query/v2/cypher_query_interpreter.cpp b/src/query/v2/cypher_query_interpreter.cpp
index 880165ad8..f3f8e48d7 100644
--- a/src/query/v2/cypher_query_interpreter.cpp
+++ b/src/query/v2/cypher_query_interpreter.cpp
@@ -118,9 +118,9 @@ 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,
-                                             RequestRouterInterface *shard_manager,
+                                             RequestRouterInterface *request_router,
                                              const std::vector<Identifier *> &predefined_identifiers) {
-  auto vertex_counts = plan::MakeVertexCountCache(shard_manager);
+  auto vertex_counts = plan::MakeVertexCountCache(request_router);
   auto symbol_table = expr::MakeSymbolTable(query, predefined_identifiers);
   auto planning_context = plan::MakePlanningContext(&ast_storage, &symbol_table, query, &vertex_counts);
   auto [root, cost] = plan::MakeLogicalPlan(&planning_context, parameters, FLAGS_query_cost_planner);
@@ -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,
                                               const Parameters &parameters, utils::SkipList<PlanCacheEntry> *plan_cache,
-                                              RequestRouterInterface *shard_manager,
+                                              RequestRouterInterface *request_router,
                                               const std::vector<Identifier *> &predefined_identifiers) {
   std::optional<utils::SkipList<PlanCacheEntry>::Accessor> plan_cache_access;
   if (plan_cache) {
@@ -146,7 +146,7 @@ std::shared_ptr<CachedPlan> CypherQueryToPlan(uint64_t hash, AstStorage ast_stor
   }
 
   auto plan = std::make_shared<CachedPlan>(
-      MakeLogicalPlan(std::move(ast_storage), query, parameters, shard_manager, predefined_identifiers));
+      MakeLogicalPlan(std::move(ast_storage), query, parameters, request_router, predefined_identifiers));
   if (plan_cache_access) {
     plan_cache_access->insert({hash, plan});
   }
diff --git a/src/query/v2/cypher_query_interpreter.hpp b/src/query/v2/cypher_query_interpreter.hpp
index c9d65047c..688e52fed 100644
--- a/src/query/v2/cypher_query_interpreter.hpp
+++ b/src/query/v2/cypher_query_interpreter.hpp
@@ -132,7 +132,7 @@ class SingleNodeLogicalPlan final : public LogicalPlan {
 };
 
 std::unique_ptr<LogicalPlan> MakeLogicalPlan(AstStorage ast_storage, CypherQuery *query, const Parameters &parameters,
-                                             RequestRouterInterface *shard_manager,
+                                             RequestRouterInterface *request_router,
                                              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,
                                               const Parameters &parameters, utils::SkipList<PlanCacheEntry> *plan_cache,
-                                              RequestRouterInterface *shard_manager,
+                                              RequestRouterInterface *request_router,
                                               const std::vector<Identifier *> &predefined_identifiers = {});
 
 }  // namespace memgraph::query::v2
diff --git a/src/query/v2/interpret/awesome_memgraph_functions.hpp b/src/query/v2/interpret/awesome_memgraph_functions.hpp
index 35ed1d797..8ca3eacb3 100644
--- a/src/query/v2/interpret/awesome_memgraph_functions.hpp
+++ b/src/query/v2/interpret/awesome_memgraph_functions.hpp
@@ -34,7 +34,7 @@ const char kId[] = "ID";
 struct FunctionContext {
   // TODO(kostasrim) consider optional here. RequestRouter does not exist on the storage.
   // DbAccessor *db_accessor;
-  RequestRouterInterface *manager;
+  RequestRouterInterface *request_router;
   utils::MemoryResource *memory;
   int64_t timestamp;
   std::unordered_map<std::string, int64_t> *counters;
diff --git a/src/query/v2/interpreter.cpp b/src/query/v2/interpreter.cpp
index 94ff7a8ff..1c2d6dadf 100644
--- a/src/query/v2/interpreter.cpp
+++ b/src/query/v2/interpreter.cpp
@@ -143,7 +143,7 @@ class ReplQueryHandler final : public query::v2::ReplicationQueryHandler {
 /// @throw QueryRuntimeException if an error ocurred.
 
 Callback HandleAuthQuery(AuthQuery *auth_query, AuthQueryHandler *auth, const Parameters &parameters,
-                         RequestRouterInterface *manager) {
+                         RequestRouterInterface *request_router) {
   // Empty frame for evaluation of password expression. This is OK since
   // password should be either null or string literal and it's evaluation
   // should not depend on frame.
@@ -154,7 +154,7 @@ Callback HandleAuthQuery(AuthQuery *auth_query, AuthQueryHandler *auth, const Pa
   // the argument to Callback.
   evaluation_context.timestamp = QueryTimestamp();
   evaluation_context.parameters = parameters;
-  ExpressionEvaluator evaluator(&frame, symbol_table, evaluation_context, manager, storage::v3::View::OLD);
+  ExpressionEvaluator evaluator(&frame, symbol_table, evaluation_context, request_router, storage::v3::View::OLD);
 
   std::string username = auth_query->user_;
   std::string rolename = auth_query->role_;
@@ -312,7 +312,7 @@ Callback HandleAuthQuery(AuthQuery *auth_query, AuthQueryHandler *auth, const Pa
 }
 
 Callback HandleReplicationQuery(ReplicationQuery *repl_query, const Parameters &parameters,
-                                InterpreterContext *interpreter_context, RequestRouterInterface *manager,
+                                InterpreterContext *interpreter_context, RequestRouterInterface *request_router,
                                 std::vector<Notification> *notifications) {
   expr::Frame<TypedValue> frame(0);
   SymbolTable symbol_table;
@@ -321,7 +321,7 @@ Callback HandleReplicationQuery(ReplicationQuery *repl_query, const Parameters &
   // the argument to Callback.
   evaluation_context.timestamp = QueryTimestamp();
   evaluation_context.parameters = parameters;
-  ExpressionEvaluator evaluator(&frame, symbol_table, evaluation_context, manager, storage::v3::View::OLD);
+  ExpressionEvaluator evaluator(&frame, symbol_table, evaluation_context, request_router, storage::v3::View::OLD);
 
   Callback callback;
   switch (repl_query->action_) {
@@ -448,7 +448,7 @@ Callback HandleReplicationQuery(ReplicationQuery *repl_query, const Parameters &
 }
 
 Callback HandleSettingQuery(SettingQuery *setting_query, const Parameters &parameters,
-                            RequestRouterInterface *manager) {
+                            RequestRouterInterface *request_router) {
   expr::Frame<TypedValue> frame(0);
   SymbolTable symbol_table;
   EvaluationContext evaluation_context;
@@ -458,7 +458,7 @@ Callback HandleSettingQuery(SettingQuery *setting_query, const Parameters &param
       std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch())
           .count();
   evaluation_context.parameters = parameters;
-  ExpressionEvaluator evaluator(&frame, symbol_table, evaluation_context, manager, storage::v3::View::OLD);
+  ExpressionEvaluator evaluator(&frame, symbol_table, evaluation_context, request_router, storage::v3::View::OLD);
 
   Callback callback;
   switch (setting_query->action_) {
@@ -1182,14 +1182,14 @@ PreparedQuery PrepareIndexQuery(ParsedQuery parsed_query, bool in_explicit_trans
 PreparedQuery PrepareAuthQuery(ParsedQuery parsed_query, bool in_explicit_transaction,
                                std::map<std::string, TypedValue> *summary, InterpreterContext *interpreter_context,
                                DbAccessor *dba, utils::MemoryResource *execution_memory,
-                               RequestRouterInterface *manager) {
+                               RequestRouterInterface *request_router) {
   if (in_explicit_transaction) {
     throw UserModificationInMulticommandTxException();
   }
 
   auto *auth_query = utils::Downcast<AuthQuery>(parsed_query.query);
 
-  auto callback = HandleAuthQuery(auth_query, interpreter_context->auth, parsed_query.parameters, manager);
+  auto callback = HandleAuthQuery(auth_query, interpreter_context->auth, parsed_query.parameters, request_router);
 
   SymbolTable symbol_table;
   std::vector<Symbol> output_symbols;
@@ -1218,14 +1218,14 @@ PreparedQuery PrepareAuthQuery(ParsedQuery parsed_query, bool in_explicit_transa
 
 PreparedQuery PrepareReplicationQuery(ParsedQuery parsed_query, const bool in_explicit_transaction,
                                       std::vector<Notification> *notifications, InterpreterContext *interpreter_context,
-                                      RequestRouterInterface *manager) {
+                                      RequestRouterInterface *request_router) {
   if (in_explicit_transaction) {
     throw ReplicationModificationInMulticommandTxException();
   }
 
   auto *replication_query = utils::Downcast<ReplicationQuery>(parsed_query.query);
-  auto callback =
-      HandleReplicationQuery(replication_query, parsed_query.parameters, interpreter_context, manager, notifications);
+  auto callback = HandleReplicationQuery(replication_query, parsed_query.parameters, interpreter_context,
+                                         request_router, notifications);
 
   return PreparedQuery{callback.header, std::move(parsed_query.required_privileges),
                        [callback_fn = std::move(callback.fn), pull_plan = std::shared_ptr<PullPlanVector>{nullptr}](
@@ -1314,14 +1314,14 @@ PreparedQuery PrepareCreateSnapshotQuery(ParsedQuery parsed_query, bool in_expli
 }
 
 PreparedQuery PrepareSettingQuery(ParsedQuery parsed_query, const bool in_explicit_transaction,
-                                  RequestRouterInterface *manager) {
+                                  RequestRouterInterface *request_router) {
   if (in_explicit_transaction) {
     throw SettingConfigInMulticommandTxException{};
   }
 
   auto *setting_query = utils::Downcast<SettingQuery>(parsed_query.query);
   MG_ASSERT(setting_query);
-  auto callback = HandleSettingQuery(setting_query, parsed_query.parameters, manager);
+  auto callback = HandleSettingQuery(setting_query, parsed_query.parameters, request_router);
 
   return PreparedQuery{std::move(callback.header), std::move(parsed_query.required_privileges),
                        [callback_fn = std::move(callback.fn), pull_plan = std::shared_ptr<PullPlanVector>{nullptr}](
diff --git a/src/query/v2/plan/operator.cpp b/src/query/v2/plan/operator.cpp
index 2d2849f0d..014be0d62 100644
--- a/src/query/v2/plan/operator.cpp
+++ b/src/query/v2/plan/operator.cpp
@@ -177,10 +177,10 @@ class DistributedCreateNodeCursor : public Cursor {
   bool Pull(Frame &frame, ExecutionContext &context) override {
     SCOPED_PROFILE_OP("CreateNode");
     if (input_cursor_->Pull(frame, context)) {
-      auto &shard_manager = context.request_router;
+      auto &request_router = context.request_router;
       {
         SCOPED_REQUEST_WAIT_PROFILE;
-        shard_manager->Request(state_, NodeCreationInfoToRequest(context, frame));
+        request_router->Request(state_, NodeCreationInfoToRequest(context, frame));
       }
       PlaceNodeOnTheFrame(frame, context);
       return true;
@@ -386,10 +386,10 @@ class DistributedScanAllAndFilterCursor : public Cursor {
 
   using VertexAccessor = accessors::VertexAccessor;
 
-  bool MakeRequest(RequestRouterInterface &shard_manager, ExecutionContext &context) {
+  bool MakeRequest(RequestRouterInterface &request_router, ExecutionContext &context) {
     {
       SCOPED_REQUEST_WAIT_PROFILE;
-      current_batch = shard_manager.Request(request_state_);
+      current_batch = request_router.Request(request_state_);
     }
     current_vertex_it = current_batch.begin();
     return !current_batch.empty();
@@ -398,7 +398,7 @@ class DistributedScanAllAndFilterCursor : public Cursor {
   bool Pull(Frame &frame, ExecutionContext &context) override {
     SCOPED_PROFILE_OP(op_name_);
 
-    auto &shard_manager = *context.request_router;
+    auto &request_router = *context.request_router;
     while (true) {
       if (MustAbort(context)) {
         throw HintedAbortError();
@@ -411,10 +411,11 @@ class DistributedScanAllAndFilterCursor : public Cursor {
         }
       }
 
-      request_state_.label = label_.has_value() ? std::make_optional(shard_manager.LabelToName(*label_)) : std::nullopt;
+      request_state_.label =
+          label_.has_value() ? std::make_optional(request_router.LabelToName(*label_)) : std::nullopt;
 
       if (current_vertex_it == current_batch.end() &&
-          (request_state_.state == State::COMPLETED || !MakeRequest(shard_manager, context))) {
+          (request_state_.state == State::COMPLETED || !MakeRequest(request_router, context))) {
         ResetExecutionState();
         continue;
       }
@@ -2338,11 +2339,11 @@ class DistributedCreateExpandCursor : public Cursor {
     if (!input_cursor_->Pull(frame, context)) {
       return false;
     }
-    auto &shard_manager = context.request_router;
+    auto &request_router = context.request_router;
     ResetExecutionState();
     {
       SCOPED_REQUEST_WAIT_PROFILE;
-      shard_manager->Request(state_, ExpandCreationInfoToRequest(context, frame));
+      request_router->Request(state_, ExpandCreationInfoToRequest(context, frame));
     }
     return true;
   }
diff --git a/src/query/v2/plan/pretty_print.cpp b/src/query/v2/plan/pretty_print.cpp
index 0e8d09e2b..bc30a3890 100644
--- a/src/query/v2/plan/pretty_print.cpp
+++ b/src/query/v2/plan/pretty_print.cpp
@@ -19,8 +19,8 @@
 
 namespace memgraph::query::v2::plan {
 
-PlanPrinter::PlanPrinter(const RequestRouterInterface *request_manager, std::ostream *out)
-    : request_manager_(request_manager), out_(out) {}
+PlanPrinter::PlanPrinter(const RequestRouterInterface *request_router, std::ostream *out)
+    : request_router_(request_router), out_(out) {}
 
 #define PRE_VISIT(TOp)                                   \
   bool PlanPrinter::PreVisit(TOp &) {                    \
@@ -34,7 +34,7 @@ bool PlanPrinter::PreVisit(CreateExpand &op) {
   WithPrintLn([&](auto &out) {
     out << "* CreateExpand (" << op.input_symbol_.name() << ")"
         << (op.edge_info_.direction == query::v2::EdgeAtom::Direction::IN ? "<-" : "-") << "["
-        << op.edge_info_.symbol.name() << ":" << request_manager_->EdgeTypeToName(op.edge_info_.edge_type) << "]"
+        << op.edge_info_.symbol.name() << ":" << request_router_->EdgeTypeToName(op.edge_info_.edge_type) << "]"
         << (op.edge_info_.direction == query::v2::EdgeAtom::Direction::OUT ? "->" : "-") << "("
         << op.node_info_.symbol.name() << ")";
   });
@@ -54,7 +54,7 @@ bool PlanPrinter::PreVisit(query::v2::plan::ScanAll &op) {
 bool PlanPrinter::PreVisit(query::v2::plan::ScanAllByLabel &op) {
   WithPrintLn([&](auto &out) {
     out << "* ScanAllByLabel"
-        << " (" << op.output_symbol_.name() << " :" << request_manager_->LabelToName(op.label_) << ")";
+        << " (" << op.output_symbol_.name() << " :" << request_router_->LabelToName(op.label_) << ")";
   });
   return true;
 }
@@ -62,8 +62,8 @@ bool PlanPrinter::PreVisit(query::v2::plan::ScanAllByLabel &op) {
 bool PlanPrinter::PreVisit(query::v2::plan::ScanAllByLabelPropertyValue &op) {
   WithPrintLn([&](auto &out) {
     out << "* ScanAllByLabelPropertyValue"
-        << " (" << op.output_symbol_.name() << " :" << request_manager_->LabelToName(op.label_) << " {"
-        << request_manager_->PropertyToName(op.property_) << "})";
+        << " (" << op.output_symbol_.name() << " :" << request_router_->LabelToName(op.label_) << " {"
+        << request_router_->PropertyToName(op.property_) << "})";
   });
   return true;
 }
@@ -71,8 +71,8 @@ bool PlanPrinter::PreVisit(query::v2::plan::ScanAllByLabelPropertyValue &op) {
 bool PlanPrinter::PreVisit(query::v2::plan::ScanAllByLabelPropertyRange &op) {
   WithPrintLn([&](auto &out) {
     out << "* ScanAllByLabelPropertyRange"
-        << " (" << op.output_symbol_.name() << " :" << request_manager_->LabelToName(op.label_) << " {"
-        << request_manager_->PropertyToName(op.property_) << "})";
+        << " (" << op.output_symbol_.name() << " :" << request_router_->LabelToName(op.label_) << " {"
+        << request_router_->PropertyToName(op.property_) << "})";
   });
   return true;
 }
@@ -80,8 +80,8 @@ bool PlanPrinter::PreVisit(query::v2::plan::ScanAllByLabelPropertyRange &op) {
 bool PlanPrinter::PreVisit(query::v2::plan::ScanAllByLabelProperty &op) {
   WithPrintLn([&](auto &out) {
     out << "* ScanAllByLabelProperty"
-        << " (" << op.output_symbol_.name() << " :" << request_manager_->LabelToName(op.label_) << " {"
-        << request_manager_->PropertyToName(op.property_) << "})";
+        << " (" << op.output_symbol_.name() << " :" << request_router_->LabelToName(op.label_) << " {"
+        << request_router_->PropertyToName(op.property_) << "})";
   });
   return true;
 }
@@ -100,7 +100,7 @@ bool PlanPrinter::PreVisit(query::v2::plan::Expand &op) {
           << (op.common_.direction == query::v2::EdgeAtom::Direction::IN ? "<-" : "-") << "["
           << op.common_.edge_symbol.name();
     utils::PrintIterable(*out_, op.common_.edge_types, "|", [this](auto &stream, const auto &edge_type) {
-      stream << ":" << request_manager_->EdgeTypeToName(edge_type);
+      stream << ":" << request_router_->EdgeTypeToName(edge_type);
     });
     *out_ << "]" << (op.common_.direction == query::v2::EdgeAtom::Direction::OUT ? "->" : "-") << "("
           << op.common_.node_symbol.name() << ")";
@@ -129,7 +129,7 @@ bool PlanPrinter::PreVisit(query::v2::plan::ExpandVariable &op) {
           << (op.common_.direction == query::v2::EdgeAtom::Direction::IN ? "<-" : "-") << "["
           << op.common_.edge_symbol.name();
     utils::PrintIterable(*out_, op.common_.edge_types, "|", [this](auto &stream, const auto &edge_type) {
-      stream << ":" << request_manager_->EdgeTypeToName(edge_type);
+      stream << ":" << request_router_->EdgeTypeToName(edge_type);
     });
     *out_ << "]" << (op.common_.direction == query::v2::EdgeAtom::Direction::OUT ? "->" : "-") << "("
           << op.common_.node_symbol.name() << ")";
@@ -263,14 +263,14 @@ void PlanPrinter::Branch(query::v2::plan::LogicalOperator &op, const std::string
   --depth_;
 }
 
-void PrettyPrint(const RequestRouterInterface &request_manager, const LogicalOperator *plan_root, std::ostream *out) {
-  PlanPrinter printer(&request_manager, out);
+void PrettyPrint(const RequestRouterInterface &request_router, const LogicalOperator *plan_root, std::ostream *out) {
+  PlanPrinter printer(&request_router, out);
   // FIXME(mtomic): We should make visitors that take const arguments.
   const_cast<LogicalOperator *>(plan_root)->Accept(printer);
 }
 
-nlohmann::json PlanToJson(const RequestRouterInterface &request_manager, const LogicalOperator *plan_root) {
-  impl::PlanToJsonVisitor visitor(&request_manager);
+nlohmann::json PlanToJson(const RequestRouterInterface &request_router, const LogicalOperator *plan_root) {
+  impl::PlanToJsonVisitor visitor(&request_router);
   // FIXME(mtomic): We should make visitors that take const arguments.
   const_cast<LogicalOperator *>(plan_root)->Accept(visitor);
   return visitor.output();
@@ -348,16 +348,16 @@ json ToJson(const utils::Bound<Expression *> &bound) {
 
 json ToJson(const Symbol &symbol) { return symbol.name(); }
 
-json ToJson(storage::v3::EdgeTypeId edge_type, const RequestRouterInterface &request_manager) {
-  return request_manager.EdgeTypeToName(edge_type);
+json ToJson(storage::v3::EdgeTypeId edge_type, const RequestRouterInterface &request_router) {
+  return request_router.EdgeTypeToName(edge_type);
 }
 
-json ToJson(storage::v3::LabelId label, const RequestRouterInterface &request_manager) {
-  return request_manager.LabelToName(label);
+json ToJson(storage::v3::LabelId label, const RequestRouterInterface &request_router) {
+  return request_router.LabelToName(label);
 }
 
-json ToJson(storage::v3::PropertyId property, const RequestRouterInterface &request_manager) {
-  return request_manager.PropertyToName(property);
+json ToJson(storage::v3::PropertyId property, const RequestRouterInterface &request_router) {
+  return request_router.PropertyToName(property);
 }
 
 json ToJson(NamedExpression *nexpr) {
@@ -368,29 +368,29 @@ json ToJson(NamedExpression *nexpr) {
 }
 
 json ToJson(const std::vector<std::pair<storage::v3::PropertyId, Expression *>> &properties,
-            const RequestRouterInterface &request_manager) {
+            const RequestRouterInterface &request_router) {
   json json;
   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_router), ToJson(prop_pair.second));
   }
   return json;
 }
 
-json ToJson(const NodeCreationInfo &node_info, const RequestRouterInterface &request_manager) {
+json ToJson(const NodeCreationInfo &node_info, const RequestRouterInterface &request_router) {
   json self;
   self["symbol"] = ToJson(node_info.symbol);
-  self["labels"] = ToJson(node_info.labels, request_manager);
+  self["labels"] = ToJson(node_info.labels, request_router);
   const auto *props = std::get_if<PropertiesMapList>(&node_info.properties);
-  self["properties"] = ToJson(props ? *props : PropertiesMapList{}, request_manager);
+  self["properties"] = ToJson(props ? *props : PropertiesMapList{}, request_router);
   return self;
 }
 
-json ToJson(const EdgeCreationInfo &edge_info, const RequestRouterInterface &request_manager) {
+json ToJson(const EdgeCreationInfo &edge_info, const RequestRouterInterface &request_router) {
   json self;
   self["symbol"] = ToJson(edge_info.symbol);
   const auto *props = std::get_if<PropertiesMapList>(&edge_info.properties);
-  self["properties"] = ToJson(props ? *props : PropertiesMapList{}, request_manager);
-  self["edge_type"] = ToJson(edge_info.edge_type, request_manager);
+  self["properties"] = ToJson(props ? *props : PropertiesMapList{}, request_router);
+  self["edge_type"] = ToJson(edge_info.edge_type, request_router);
   self["direction"] = ToString(edge_info.direction);
   return self;
 }
@@ -432,7 +432,7 @@ bool PlanToJsonVisitor::PreVisit(ScanAll &op) {
 bool PlanToJsonVisitor::PreVisit(ScanAllByLabel &op) {
   json self;
   self["name"] = "ScanAllByLabel";
-  self["label"] = ToJson(op.label_, *request_manager_);
+  self["label"] = ToJson(op.label_, *request_router_);
   self["output_symbol"] = ToJson(op.output_symbol_);
 
   op.input_->Accept(*this);
@@ -445,8 +445,8 @@ bool PlanToJsonVisitor::PreVisit(ScanAllByLabel &op) {
 bool PlanToJsonVisitor::PreVisit(ScanAllByLabelPropertyRange &op) {
   json self;
   self["name"] = "ScanAllByLabelPropertyRange";
-  self["label"] = ToJson(op.label_, *request_manager_);
-  self["property"] = ToJson(op.property_, *request_manager_);
+  self["label"] = ToJson(op.label_, *request_router_);
+  self["property"] = ToJson(op.property_, *request_router_);
   self["lower_bound"] = op.lower_bound_ ? ToJson(*op.lower_bound_) : json();
   self["upper_bound"] = op.upper_bound_ ? ToJson(*op.upper_bound_) : json();
   self["output_symbol"] = ToJson(op.output_symbol_);
@@ -461,8 +461,8 @@ bool PlanToJsonVisitor::PreVisit(ScanAllByLabelPropertyRange &op) {
 bool PlanToJsonVisitor::PreVisit(ScanAllByLabelPropertyValue &op) {
   json self;
   self["name"] = "ScanAllByLabelPropertyValue";
-  self["label"] = ToJson(op.label_, *request_manager_);
-  self["property"] = ToJson(op.property_, *request_manager_);
+  self["label"] = ToJson(op.label_, *request_router_);
+  self["property"] = ToJson(op.property_, *request_router_);
   self["expression"] = ToJson(op.expression_);
   self["output_symbol"] = ToJson(op.output_symbol_);
 
@@ -476,8 +476,8 @@ bool PlanToJsonVisitor::PreVisit(ScanAllByLabelPropertyValue &op) {
 bool PlanToJsonVisitor::PreVisit(ScanAllByLabelProperty &op) {
   json self;
   self["name"] = "ScanAllByLabelProperty";
-  self["label"] = ToJson(op.label_, *request_manager_);
-  self["property"] = ToJson(op.property_, *request_manager_);
+  self["label"] = ToJson(op.label_, *request_router_);
+  self["property"] = ToJson(op.property_, *request_router_);
   self["output_symbol"] = ToJson(op.output_symbol_);
 
   op.input_->Accept(*this);
@@ -500,7 +500,7 @@ bool PlanToJsonVisitor::PreVisit(ScanAllById &op) {
 bool PlanToJsonVisitor::PreVisit(CreateNode &op) {
   json self;
   self["name"] = "CreateNode";
-  self["node_info"] = ToJson(op.node_info_, *request_manager_);
+  self["node_info"] = ToJson(op.node_info_, *request_router_);
 
   op.input_->Accept(*this);
   self["input"] = PopOutput();
@@ -513,8 +513,8 @@ bool PlanToJsonVisitor::PreVisit(CreateExpand &op) {
   json self;
   self["name"] = "CreateExpand";
   self["input_symbol"] = ToJson(op.input_symbol_);
-  self["node_info"] = ToJson(op.node_info_, *request_manager_);
-  self["edge_info"] = ToJson(op.edge_info_, *request_manager_);
+  self["node_info"] = ToJson(op.node_info_, *request_router_);
+  self["edge_info"] = ToJson(op.edge_info_, *request_router_);
   self["existing_node"] = op.existing_node_;
 
   op.input_->Accept(*this);
@@ -530,7 +530,7 @@ bool PlanToJsonVisitor::PreVisit(Expand &op) {
   self["input_symbol"] = ToJson(op.input_symbol_);
   self["node_symbol"] = ToJson(op.common_.node_symbol);
   self["edge_symbol"] = ToJson(op.common_.edge_symbol);
-  self["edge_types"] = ToJson(op.common_.edge_types, *request_manager_);
+  self["edge_types"] = ToJson(op.common_.edge_types, *request_router_);
   self["direction"] = ToString(op.common_.direction);
   self["existing_node"] = op.common_.existing_node;
 
@@ -547,7 +547,7 @@ bool PlanToJsonVisitor::PreVisit(ExpandVariable &op) {
   self["input_symbol"] = ToJson(op.input_symbol_);
   self["node_symbol"] = ToJson(op.common_.node_symbol);
   self["edge_symbol"] = ToJson(op.common_.edge_symbol);
-  self["edge_types"] = ToJson(op.common_.edge_types, *request_manager_);
+  self["edge_types"] = ToJson(op.common_.edge_types, *request_router_);
   self["direction"] = ToString(op.common_.direction);
   self["type"] = ToString(op.type_);
   self["is_reverse"] = op.is_reverse_;
@@ -622,7 +622,7 @@ bool PlanToJsonVisitor::PreVisit(Delete &op) {
 bool PlanToJsonVisitor::PreVisit(SetProperty &op) {
   json self;
   self["name"] = "SetProperty";
-  self["property"] = ToJson(op.property_, *request_manager_);
+  self["property"] = ToJson(op.property_, *request_router_);
   self["lhs"] = ToJson(op.lhs_);
   self["rhs"] = ToJson(op.rhs_);
 
@@ -659,7 +659,7 @@ bool PlanToJsonVisitor::PreVisit(SetLabels &op) {
   json self;
   self["name"] = "SetLabels";
   self["input_symbol"] = ToJson(op.input_symbol_);
-  self["labels"] = ToJson(op.labels_, *request_manager_);
+  self["labels"] = ToJson(op.labels_, *request_router_);
 
   op.input_->Accept(*this);
   self["input"] = PopOutput();
@@ -671,7 +671,7 @@ bool PlanToJsonVisitor::PreVisit(SetLabels &op) {
 bool PlanToJsonVisitor::PreVisit(RemoveProperty &op) {
   json self;
   self["name"] = "RemoveProperty";
-  self["property"] = ToJson(op.property_, *request_manager_);
+  self["property"] = ToJson(op.property_, *request_router_);
   self["lhs"] = ToJson(op.lhs_);
 
   op.input_->Accept(*this);
@@ -685,7 +685,7 @@ bool PlanToJsonVisitor::PreVisit(RemoveLabels &op) {
   json self;
   self["name"] = "RemoveLabels";
   self["input_symbol"] = ToJson(op.input_symbol_);
-  self["labels"] = ToJson(op.labels_, *request_manager_);
+  self["labels"] = ToJson(op.labels_, *request_router_);
 
   op.input_->Accept(*this);
   self["input"] = PopOutput();
diff --git a/src/query/v2/plan/pretty_print.hpp b/src/query/v2/plan/pretty_print.hpp
index 7e97de3ff..4094d7c81 100644
--- a/src/query/v2/plan/pretty_print.hpp
+++ b/src/query/v2/plan/pretty_print.hpp
@@ -30,16 +30,16 @@ class LogicalOperator;
 /// RequestRouter is needed for resolving label and property names.
 /// 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.
-void PrettyPrint(const RequestRouterInterface &request_manager, const LogicalOperator *plan_root, std::ostream *out);
+void PrettyPrint(const RequestRouterInterface &request_router, const LogicalOperator *plan_root, std::ostream *out);
 
 /// Overload of `PrettyPrint` which defaults the `std::ostream` to `std::cout`.
-inline void PrettyPrint(const RequestRouterInterface &request_manager, const LogicalOperator *plan_root) {
-  PrettyPrint(request_manager, plan_root, &std::cout);
+inline void PrettyPrint(const RequestRouterInterface &request_router, const LogicalOperator *plan_root) {
+  PrettyPrint(request_router, plan_root, &std::cout);
 }
 
 /// Convert a `LogicalOperator` plan to a JSON representation.
 /// DbAccessor is needed for resolving label and property names.
-nlohmann::json PlanToJson(const RequestRouterInterface &request_manager, const LogicalOperator *plan_root);
+nlohmann::json PlanToJson(const RequestRouterInterface &request_router, const LogicalOperator *plan_root);
 
 class PlanPrinter : public virtual HierarchicalLogicalOperatorVisitor {
  public:
@@ -47,7 +47,7 @@ class PlanPrinter : public virtual HierarchicalLogicalOperatorVisitor {
   using HierarchicalLogicalOperatorVisitor::PreVisit;
   using HierarchicalLogicalOperatorVisitor::Visit;
 
-  PlanPrinter(const RequestRouterInterface *request_manager, std::ostream *out);
+  PlanPrinter(const RequestRouterInterface *request_router, std::ostream *out);
 
   bool DefaultPreVisit() override;
 
@@ -114,7 +114,7 @@ class PlanPrinter : public virtual HierarchicalLogicalOperatorVisitor {
   void Branch(LogicalOperator &op, const std::string &branch_name = "");
 
   int64_t depth_{0};
-  const RequestRouterInterface *request_manager_{nullptr};
+  const RequestRouterInterface *request_router_{nullptr};
   std::ostream *out_{nullptr};
 };
 
@@ -132,20 +132,20 @@ nlohmann::json ToJson(const utils::Bound<Expression *> &bound);
 
 nlohmann::json ToJson(const Symbol &symbol);
 
-nlohmann::json ToJson(storage::v3::EdgeTypeId edge_type, const RequestRouterInterface &request_manager);
+nlohmann::json ToJson(storage::v3::EdgeTypeId edge_type, const RequestRouterInterface &request_router);
 
-nlohmann::json ToJson(storage::v3::LabelId label, const RequestRouterInterface &request_manager);
+nlohmann::json ToJson(storage::v3::LabelId label, const RequestRouterInterface &request_router);
 
-nlohmann::json ToJson(storage::v3::PropertyId property, const RequestRouterInterface &request_manager);
+nlohmann::json ToJson(storage::v3::PropertyId property, const RequestRouterInterface &request_router);
 
 nlohmann::json ToJson(NamedExpression *nexpr);
 
 nlohmann::json ToJson(const std::vector<std::pair<storage::v3::PropertyId, Expression *>> &properties,
-                      const RequestRouterInterface &request_manager);
+                      const RequestRouterInterface &request_router);
 
-nlohmann::json ToJson(const NodeCreationInfo &node_info, const RequestRouterInterface &request_manager);
+nlohmann::json ToJson(const NodeCreationInfo &node_info, const RequestRouterInterface &request_router);
 
-nlohmann::json ToJson(const EdgeCreationInfo &edge_info, const RequestRouterInterface &request_manager);
+nlohmann::json ToJson(const EdgeCreationInfo &edge_info, const RequestRouterInterface &request_router);
 
 nlohmann::json ToJson(const Aggregate::Element &elem);
 
@@ -160,7 +160,7 @@ nlohmann::json ToJson(const std::vector<T> &items, Args &&...args) {
 
 class PlanToJsonVisitor : public virtual HierarchicalLogicalOperatorVisitor {
  public:
-  explicit PlanToJsonVisitor(const RequestRouterInterface *request_manager) : request_manager_(request_manager) {}
+  explicit PlanToJsonVisitor(const RequestRouterInterface *request_router) : request_router_(request_router) {}
 
   using HierarchicalLogicalOperatorVisitor::PostVisit;
   using HierarchicalLogicalOperatorVisitor::PreVisit;
@@ -216,7 +216,7 @@ class PlanToJsonVisitor : public virtual HierarchicalLogicalOperatorVisitor {
 
  protected:
   nlohmann::json output_;
-  const RequestRouterInterface *request_manager_;
+  const RequestRouterInterface *request_router_;
 
   nlohmann::json PopOutput() {
     nlohmann::json tmp;
diff --git a/tests/simulation/request_router.cpp b/tests/simulation/request_router.cpp
index ddd9351ae..8187f138b 100644
--- a/tests/simulation/request_router.cpp
+++ b/tests/simulation/request_router.cpp
@@ -151,10 +151,10 @@ void RunStorageRaft(Raft<IoImpl, MockedShardRsm, WriteRequests, WriteResponses,
   server.Run();
 }
 
-void TestScanVertices(query::v2::RequestRouterInterface &io) {
+void TestScanVertices(query::v2::RequestRouterInterface &request_router) {
   msgs::ExecutionState<ScanVerticesRequest> state{.label = "test_label"};
 
-  auto result = io.Request(state);
+  auto result = request_router.Request(state);
   MG_ASSERT(result.size() == 2);
   {
     auto prop = result[0].GetProperty(msgs::PropertyId::FromUint(0));
@@ -163,7 +163,7 @@ void TestScanVertices(query::v2::RequestRouterInterface &io) {
     MG_ASSERT(prop.int_v == 444);
   }
 
-  result = io.Request(state);
+  result = request_router.Request(state);
   {
     MG_ASSERT(result.size() == 1);
     auto prop = result[0].GetProperty(msgs::PropertyId::FromUint(0));
@@ -171,11 +171,11 @@ void TestScanVertices(query::v2::RequestRouterInterface &io) {
   }
 }
 
-void TestCreateVertices(query::v2::RequestRouterInterface &io) {
+void TestCreateVertices(query::v2::RequestRouterInterface &request_router) {
   using PropVal = msgs::Value;
   msgs::ExecutionState<CreateVerticesRequest> state;
   std::vector<msgs::NewVertex> new_vertices;
-  auto label_id = io.NameToLabel("test_label");
+  auto label_id = request_router.NameToLabel("test_label");
   msgs::NewVertex a1{.primary_key = {PropVal(int64_t(1)), PropVal(int64_t(0))}};
   a1.label_ids.push_back({label_id});
   msgs::NewVertex a2{.primary_key = {PropVal(int64_t(13)), PropVal(int64_t(13))}};
@@ -183,17 +183,17 @@ void TestCreateVertices(query::v2::RequestRouterInterface &io) {
   new_vertices.push_back(std::move(a1));
   new_vertices.push_back(std::move(a2));
 
-  auto result = io.Request(state, std::move(new_vertices));
+  auto result = request_router.Request(state, std::move(new_vertices));
   MG_ASSERT(result.size() == 2);
 }
 
-void TestCreateExpand(query::v2::RequestRouterInterface &io) {
+void TestCreateExpand(query::v2::RequestRouterInterface &request_router) {
   using PropVal = msgs::Value;
   msgs::ExecutionState<msgs::CreateExpandRequest> state;
   std::vector<msgs::NewExpand> new_expands;
 
-  const auto edge_type_id = io.NameToEdgeType("edge_type");
-  const auto label = msgs::Label{io.NameToLabel("test_label")};
+  const auto edge_type_id = request_router.NameToEdgeType("edge_type");
+  const auto label = msgs::Label{request_router.NameToLabel("test_label")};
   const msgs::VertexId vertex_id_1{label, {PropVal(int64_t(0)), PropVal(int64_t(0))}};
   const msgs::VertexId vertex_id_2{label, {PropVal(int64_t(13)), PropVal(int64_t(13))}};
   msgs::NewExpand expand_1{
@@ -203,7 +203,7 @@ void TestCreateExpand(query::v2::RequestRouterInterface &io) {
   new_expands.push_back(std::move(expand_1));
   new_expands.push_back(std::move(expand_2));
 
-  auto responses = io.Request(state, std::move(new_expands));
+  auto responses = request_router.Request(state, std::move(new_expands));
   MG_ASSERT(responses.size() == 2);
   MG_ASSERT(responses[0].success);
   MG_ASSERT(responses[1].success);
@@ -222,7 +222,7 @@ void TestExpandOne(query::v2::RequestRouterInterface &request_router) {
 }
 
 template <typename RequestRouter>
-void TestAggregate(RequestRouter &io) {}
+void TestAggregate(RequestRouter &request_router) {}
 
 void DoTest() {
   SimulatorConfig config{
@@ -337,12 +337,12 @@ void DoTest() {
   // also get the current shard map
   CoordinatorClient<SimulatorTransport> coordinator_client(cli_io, c_addrs[0], c_addrs);
 
-  query::v2::RequestRouter<SimulatorTransport> io(std::move(coordinator_client), std::move(cli_io));
+  query::v2::RequestRouter<SimulatorTransport> request_router(std::move(coordinator_client), std::move(cli_io));
 
-  io.StartTransaction();
-  TestScanVertices(io);
-  TestCreateVertices(io);
-  TestCreateExpand(io);
+  request_router.StartTransaction();
+  TestScanVertices(request_router);
+  TestCreateVertices(request_router);
+  TestCreateExpand(request_router);
 
   simulator.ShutDown();
 

From 8fd7327fbd89375d0ec2a010f356df33909f404e Mon Sep 17 00:00:00 2001
From: Kostas Kyrimis <kostaskyrim@gmail.com>
Date: Mon, 28 Nov 2022 15:38:12 +0200
Subject: [PATCH 15/26] Address GH comments

---
 tests/unit/query_v2_expression_evaluator.cpp | 55 +++++++++++---------
 1 file changed, 30 insertions(+), 25 deletions(-)

diff --git a/tests/unit/query_v2_expression_evaluator.cpp b/tests/unit/query_v2_expression_evaluator.cpp
index c2e0beee7..1fb4cf6dd 100644
--- a/tests/unit/query_v2_expression_evaluator.cpp
+++ b/tests/unit/query_v2_expression_evaluator.cpp
@@ -20,7 +20,6 @@
 #include <gtest/gtest.h>
 
 #include "coordinator/shard_map.hpp"
-#include "exceptions.hpp"
 #include "functions/awesome_memgraph_functions.hpp"
 #include "parser/opencypher/parser.hpp"
 #include "query/v2/accessors.hpp"
@@ -539,29 +538,31 @@ TEST_F(ExpressionEvaluatorTest, MapIndexing) {
 using Vertex = memgraph::msgs::Vertex;
 using Edge = memgraph::msgs::Edge;
 using EdgeType = memgraph::msgs::EdgeType;
+using EdgeId = memgraph::msgs::EdgeId;
 using Value = memgraph::msgs::Value;
 using VertexId = memgraph::msgs::VertexId;
 using Label = memgraph::msgs::Label;
 
 accessors::VertexAccessor CreateVertex(std::vector<std::pair<PropertyId, Value>> props,
-                                       const ShardRequestManagerInterface *manager, Label label = {}) {
-  static int64_t id = 0;
-  return {Vertex{VertexId{label, {memgraph::msgs::Value(id++)}}, {label}}, std::move(props), manager};
+                                       const ShardRequestManagerInterface *manager, Vertex v = {}) {
+  return {std::move(v), std::move(props), manager};
 }
 
 accessors::EdgeAccessor CreateEdge(std::vector<std::pair<PropertyId, Value>> props,
-                                   const ShardRequestManagerInterface *manager) {
-  auto edge = Edge{.src = VertexId{{}, {}},
-                   .dst = VertexId{{}, {}},
+                                   const ShardRequestManagerInterface *manager, EdgeId edge_id = {}, VertexId src = {},
+                                   VertexId dst = {}) {
+  auto edge = Edge{.src = std::move(src),
+                   .dst = std::move(dst),
                    .properties = std::move(props),
+                   .id = edge_id,
                    .type = EdgeType{manager->NameToEdgeType("edge_type")}};
   return accessors::EdgeAccessor{std::move(edge), manager};
 }
 
 TEST_F(ExpressionEvaluatorTest, VertexAndEdgeIndexing) {
   auto prop = shard_manager->NameToProperty("prop");
-  auto vertex = CreateVertex({{prop, Value(static_cast<int64_t>(42))}}, shard_manager.get());
-  auto edge = CreateEdge({{prop, Value(static_cast<int64_t>(43))}}, shard_manager.get());
+  auto vertex = CreateVertex({{prop, Value(static_cast<int64_t>(42))}}, shard_manager.get(), {});
+  auto edge = CreateEdge({{prop, Value(static_cast<int64_t>(43))}}, shard_manager.get(), {}, {}, {});
 
   auto *vertex_id = CreateIdentifierWithValue("v1", TypedValue(vertex));
   auto *edge_id = CreateIdentifierWithValue("e11", TypedValue(edge));
@@ -741,7 +742,8 @@ TEST_F(ExpressionEvaluatorTest, IsNullOperator) {
 
 TEST_F(ExpressionEvaluatorTest, LabelsTest) {
   Label label{shard_manager->NameToLabel("label1")};
-  auto v1 = CreateVertex({}, shard_manager.get(), label);
+  Vertex vertex = {{}, {label}};
+  auto v1 = CreateVertex({}, shard_manager.get(), vertex);
   auto *identifier = storage.Create<Identifier>("n");
   auto node_symbol = symbol_table.CreateSymbol("n", true);
   identifier->MapTo(node_symbol);
@@ -1189,11 +1191,12 @@ static TypedValue MakeTypedValueList(TArgs &&...args) {
 TEST_F(FunctionTest, EndNode) {
   ASSERT_THROW(EvaluateFunction("ENDNODE"), FunctionRuntimeException);
   ASSERT_TRUE(EvaluateFunction("ENDNODE", TypedValue()).IsNull());
-  auto v1 = CreateVertex({}, shard_manager.get());
-  auto e = CreateEdge({}, shard_manager.get());
-  const auto expected = VertexId{{}, 0};
+  Label l{shard_manager->NameToLabel("label1")};
+  EdgeId e_id{10};
+  VertexId dst{l, {msgs::Value(static_cast<int64_t>(2))}};
+  auto e = CreateEdge({}, shard_manager.get(), e_id, {}, dst);
   const auto res = EvaluateFunction("ENDNODE", e).ValueVertex().Id();
-  ASSERT_EQ(res, expected);
+  ASSERT_EQ(res, dst);
   ASSERT_THROW(EvaluateFunction("ENDNODE", 2), FunctionRuntimeException);
 }
 
@@ -1259,11 +1262,12 @@ TEST_F(FunctionTest, Size) {
 TEST_F(FunctionTest, StartNode) {
   ASSERT_THROW(EvaluateFunction("STARTNODE"), FunctionRuntimeException);
   ASSERT_TRUE(EvaluateFunction("STARTNODE", TypedValue()).IsNull());
-  auto v1 = CreateVertex({}, shard_manager.get());
-  auto e = CreateEdge({}, shard_manager.get());
-  const auto expected = VertexId{{}, 0};
+  Label l{shard_manager->NameToLabel("label1")};
+  EdgeId e_id{5};
+  VertexId src{l, {msgs::Value(static_cast<int64_t>(4))}};
+  auto e = CreateEdge({}, shard_manager.get(), e_id, src);
   const auto res = EvaluateFunction("STARTNODE", e).ValueVertex().Id();
-  ASSERT_EQ(res, expected);
+  ASSERT_EQ(res, src);
   ASSERT_THROW(EvaluateFunction("STARTNODE", 2), FunctionRuntimeException);
 }
 
@@ -1329,16 +1333,13 @@ TEST_F(FunctionTest, ValueType) {
   ASSERT_EQ(EvaluateFunction("VALUETYPE", v1).ValueString(), "NODE");
   auto e = CreateEdge({}, shard_manager.get());
   ASSERT_EQ(EvaluateFunction("VALUETYPE", e).ValueString(), "RELATIONSHIP");
-  // TODO(kostasrim) Fix this when we add Path to accessors
-  //  Path p(v1, *e, v2);
-  //  ASSERT_EQ(EvaluateFunction("VALUETYPE", p).ValueString(), "PATH");
 }
 
 TEST_F(FunctionTest, Labels) {
   ASSERT_THROW(EvaluateFunction("LABELS"), FunctionRuntimeException);
   ASSERT_TRUE(EvaluateFunction("LABELS", TypedValue()).IsNull());
   Label label{shard_manager->NameToLabel("label1")};
-  auto v = CreateVertex({}, shard_manager.get(), std::move(label));
+  auto v = CreateVertex({}, shard_manager.get(), {{}, {label}});
   std::vector<std::string> labels;
   auto evaluated_labels = EvaluateFunction("LABELS", v).ValueList();
   labels.reserve(evaluated_labels.size());
@@ -1349,9 +1350,6 @@ TEST_F(FunctionTest, Labels) {
   ASSERT_THROW(EvaluateFunction("LABELS", 2), FunctionRuntimeException);
 }
 
-// TODO(kostasrim) Enable this once we fix accessors Path
-// TEST_F(FunctionTest, NodesRelationships) {}
-
 TEST_F(FunctionTest, Range) {
   EXPECT_THROW(EvaluateFunction("RANGE"), FunctionRuntimeException);
   EXPECT_TRUE(EvaluateFunction("RANGE", 1, 2, TypedValue()).IsNull());
@@ -1557,6 +1555,13 @@ TEST_F(FunctionTest, Counter) {
   EXPECT_THROW(EvaluateFunction("COUNTER", "c6", 0, 0), FunctionRuntimeException);
 }
 
+TEST_F(FunctionTest, Id) {
+  auto v = CreateVertex({}, shard_manager.get());
+  EXPECT_THROW(EvaluateFunction("ID", v), FunctionRuntimeException);
+  auto e = CreateEdge({}, shard_manager.get(), EdgeId{10});
+  EXPECT_EQ(EvaluateFunction("ID", e).ValueInt(), 10);
+}
+
 TEST_F(FunctionTest, ToStringNull) { EXPECT_TRUE(EvaluateFunction("TOSTRING", TypedValue()).IsNull()); }
 
 TEST_F(FunctionTest, ToStringString) {

From 50df0d4d53ccdc8c008931a9c9fa88a03dd0d3ad Mon Sep 17 00:00:00 2001
From: Kostas Kyrimis <kostaskyrim@gmail.com>
Date: Mon, 28 Nov 2022 17:13:58 +0200
Subject: [PATCH 16/26] Fix python imports and replace const char array with
 constexpr

---
 .github/workflows/diff.yaml                              | 2 +-
 .pre-commit-config.yaml                                  | 1 +
 src/functions/awesome_memgraph_functions.hpp             | 8 ++++----
 .../distributed_queries/awesome_memgraph_functions.py    | 9 ++++++---
 4 files changed, 12 insertions(+), 8 deletions(-)

diff --git a/.github/workflows/diff.yaml b/.github/workflows/diff.yaml
index 8b47b3bb3..a7faa7d22 100644
--- a/.github/workflows/diff.yaml
+++ b/.github/workflows/diff.yaml
@@ -99,7 +99,7 @@ jobs:
             echo ${file}
             if [[ ${file} == *.py ]]; then
               python3 -m black --check --diff ${file}
-              python3 -m isort --check-only --diff ${file}
+              python3 -m isort --check-only --profile "black" --diff ${file}
             fi
           done
 
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 5abd746c9..26b7c8e05 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -14,6 +14,7 @@ repos:
     hooks:
       - id: isort
         name: isort (python)
+        args: ["--profile", "black"]
   - repo: https://github.com/pre-commit/mirrors-clang-format
     rev: v13.0.0
     hooks:
diff --git a/src/functions/awesome_memgraph_functions.hpp b/src/functions/awesome_memgraph_functions.hpp
index 7acfa6943..7e716d970 100644
--- a/src/functions/awesome_memgraph_functions.hpp
+++ b/src/functions/awesome_memgraph_functions.hpp
@@ -56,10 +56,10 @@ template <typename TypedValueT, typename FunctionContextT, typename Tag, typenam
 std::function<TypedValueT(const TypedValueT *arguments, int64_t num_arguments, const FunctionContextT &context)>
 NameToFunction(const std::string &function_name);
 
-inline const char kStartsWith[] = "STARTSWITH";
-inline const char kEndsWith[] = "ENDSWITH";
-inline const char kContains[] = "CONTAINS";
-inline const char kId[] = "ID";
+inline constexpr char kStartsWith[] = "STARTSWITH";
+inline constexpr char kEndsWith[] = "ENDSWITH";
+inline constexpr char kContains[] = "CONTAINS";
+inline constexpr char kId[] = "ID";
 
 }  // namespace memgraph::functions
 
diff --git a/tests/e2e/distributed_queries/awesome_memgraph_functions.py b/tests/e2e/distributed_queries/awesome_memgraph_functions.py
index 1c4bc87a4..0bdaa07a4 100644
--- a/tests/e2e/distributed_queries/awesome_memgraph_functions.py
+++ b/tests/e2e/distributed_queries/awesome_memgraph_functions.py
@@ -10,13 +10,16 @@
 # licenses/APL.txt.
 
 import sys
-import time
-import typing
 
 import mgclient
 import pytest
 
-from common import *
+from common import (
+    connection,
+    execute_and_fetch_all,
+    has_n_result_row,
+    wait_for_shard_manager_to_initialize,
+)
 
 
 def test_awesome_memgraph_functions(connection):

From 4f18fa7431d9ef6a63a29e9e6da2089649fa75ed Mon Sep 17 00:00:00 2001
From: Tyler Neely <t@jujit.su>
Date: Tue, 29 Nov 2022 09:07:18 +0000
Subject: [PATCH 17/26] Fix LCP that broke with invisible merge conflict

---
 src/query/v2/frontend/ast/ast.lcp | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/src/query/v2/frontend/ast/ast.lcp b/src/query/v2/frontend/ast/ast.lcp
index dadcc9fa7..03c0c99f0 100644
--- a/src/query/v2/frontend/ast/ast.lcp
+++ b/src/query/v2/frontend/ast/ast.lcp
@@ -24,7 +24,7 @@
 #include "query/v2/bindings/typed_value.hpp"
 #include "query/v2/db_accessor.hpp"
 #include "query/v2/path.hpp"
-#include "query/v2/shard_request_manager.hpp"
+#include "query/v2/request_router.hpp"
 #include "utils/typeinfo.hpp"
 #include "query/v2/conversions.hpp"
 
@@ -838,14 +838,14 @@ cpp<#
               :slk-load (slk-load-ast-vector "Expression"))
    (function-name "std::string" :scope :public)
    (function "std::function<TypedValue(const TypedValue *, int64_t,
-                                       const functions::FunctionContext<ShardRequestManagerInterface> &)>"
+                                       const functions::FunctionContext<RequestRouterInterface> &)>"
              :scope :public
              :dont-save t
              :clone :copy
              :slk-load (lambda (member)
                         #>cpp
                         self->${member} = functions::NameToFunction<TypedValue,
-                                            functions::FunctionContext<ShardRequestManagerInterface>,
+                                            functions::FunctionContext<RequestRouterInterface>,
                                             functions::QueryEngineTag, decltype(ValueToTypedValueFunctor)>(self->function_name_);
                         cpp<#)))
   (:public
@@ -869,7 +869,7 @@ cpp<#
              const std::vector<Expression *> &arguments)
         : arguments_(arguments),
           function_name_(function_name),
-          function_(functions::NameToFunction<TypedValue, functions::FunctionContext<ShardRequestManagerInterface>,
+          function_(functions::NameToFunction<TypedValue, functions::FunctionContext<RequestRouterInterface>,
                                               functions::QueryEngineTag, decltype(ValueToTypedValueFunctor)>(function_name_)) {
       if (!function_) {
         throw SemanticException("Function '{}' doesn't exist.", function_name);

From a308ee501aaf9a6aa6f5081b7b6739c31629bba2 Mon Sep 17 00:00:00 2001
From: Tyler Neely <t@jujit.su>
Date: Tue, 29 Nov 2022 11:25:29 +0000
Subject: [PATCH 18/26] Unify the driving of read and write requests in the
 RequestRouter

---
 src/io/rsm/rsm_client.hpp       |   6 +-
 src/query/v2/request_router.hpp | 115 ++++++--------------------------
 2 files changed, 23 insertions(+), 98 deletions(-)

diff --git a/src/io/rsm/rsm_client.hpp b/src/io/rsm/rsm_client.hpp
index ce6781956..92cfe12ac 100644
--- a/src/io/rsm/rsm_client.hpp
+++ b/src/io/rsm/rsm_client.hpp
@@ -73,10 +73,7 @@ class RsmClient {
     size_t addr_index = io_.Rand(addr_distrib);
     leader_ = server_addrs_[addr_index];
 
-    spdlog::debug(
-        "client NOT redirected to leader server despite our success failing to be processed (it probably was sent to "
-        "a RSM Candidate) trying a random one at index {} with address {}",
-        addr_index, leader_.ToString());
+    spdlog::debug("selecting a random leader at index {} with address {}", addr_index, leader_.ToString());
   }
 
   template <typename ResponseT>
@@ -227,6 +224,7 @@ class RsmClient {
 
       if (read_get_response.success) {
         async_reads_.erase(token.GetId());
+        spdlog::debug("returning read_return for RSM request");
         return std::move(read_get_response.read_return);
       }
     } else {
diff --git a/src/query/v2/request_router.hpp b/src/query/v2/request_router.hpp
index a4e7a1462..224ea8674 100644
--- a/src/query/v2/request_router.hpp
+++ b/src/query/v2/request_router.hpp
@@ -96,13 +96,6 @@ struct ExecutionState {
   // the RequestRouter 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
   // empty, it means that all of the requests have completed succefully.
-  // TODO(gvolfing)
-  // Maybe make this into a more complex object to be able to keep track of paginated results. E.g. instead of a vector
-  // of Shards make it into a std::vector<std::pair<Shard, PaginatedResultType>> (probably a struct instead of a pair)
-  // where PaginatedResultType is an enum signaling the progress on the given request. This way we can easily check if
-  // a partial response on a shard(if there is one) is finished and we can send off the request for the next batch.
-  // 1-1 mapping with `shard_cache`.
-  // A vector that tracks request metadata for each shard (For example, next_id for a ScanAll on Shard A)
   std::vector<ShardRequestState<TRequest>> requests;
   State state = INITIALIZING;
 };
@@ -257,20 +250,10 @@ class RequestRouter : public RequestRouterInterface {
     std::vector<msgs::ScanVerticesResponse> responses;
 
     SendAllRequests(state);
-    auto all_requests_gathered = [](auto &paginated_rsp_tracker) {
-      return std::ranges::all_of(paginated_rsp_tracker, [](const auto &state) {
-        return state.second == PaginatedResponseState::PartiallyFinished;
-      });
-    };
-
-    std::map<Shard, PaginatedResponseState> paginated_response_tracker;
-    for (const auto &request : state.requests) {
-      paginated_response_tracker.insert(std::make_pair(request.shard, PaginatedResponseState::Pending));
-    }
 
     do {
-      AwaitOnPaginatedRequests(state, responses, paginated_response_tracker);
-    } while (!all_requests_gathered(paginated_response_tracker));
+      DriveReadResponses(state, responses);
+    } while (!state.requests.empty());
 
     MaybeCompleteState(state);
     // TODO(kostasrim) Before returning start prefetching the batch (this shall be done once we get MgFuture as return
@@ -289,7 +272,7 @@ class RequestRouter : public RequestRouterInterface {
 
     // 2. Block untill all the futures are exhausted
     do {
-      AwaitOnResponses(state, responses);
+      DriveWriteResponses(state, responses);
     } while (!state.requests.empty());
 
     MaybeCompleteState(state);
@@ -339,7 +322,7 @@ class RequestRouter : public RequestRouterInterface {
 
     // 2. Block untill all the futures are exhausted
     do {
-      AwaitOnResponses(state, responses);
+      DriveReadResponses(state, responses);
     } while (!state.requests.empty());
     std::vector<msgs::ExpandOneResultRow> result_rows;
     const auto total_row_count = std::accumulate(responses.begin(), responses.end(), 0,
@@ -369,8 +352,6 @@ class RequestRouter : public RequestRouterInterface {
   }
 
  private:
-  enum class PaginatedResponseState { Pending, PartiallyFinished };
-
   std::vector<VertexAccessor> PostProcess(std::vector<msgs::ScanVerticesResponse> &&responses) const {
     std::vector<VertexAccessor> accessors;
     for (auto &response : responses) {
@@ -602,33 +583,8 @@ class RequestRouter : public RequestRouterInterface {
     }
   }
 
-  void AwaitOnResponses(ExecutionState<msgs::CreateVerticesRequest> &state,
-                        std::vector<msgs::CreateVerticesResponse> &responses) {
-    for (auto &request : state.requests) {
-      auto &storage_client = GetStorageClientForShard(request.shard);
-
-      auto poll_result = storage_client.AwaitAsyncWriteRequest(request.async_request_token.value());
-      while (!poll_result) {
-        poll_result = storage_client.AwaitAsyncWriteRequest(request.async_request_token.value());
-      }
-
-      if (poll_result->HasError()) {
-        throw std::runtime_error("CreateVertices request timed out");
-      }
-
-      msgs::WriteResponses response_variant = poll_result->GetValue();
-      auto response = std::get<msgs::CreateVerticesResponse>(response_variant);
-
-      if (response.error) {
-        throw std::runtime_error("CreateVertices request did not succeed");
-      }
-      responses.push_back(response);
-    }
-    state.requests.clear();
-  }
-
-  void AwaitOnResponses(ExecutionState<msgs::ExpandOneRequest> &state,
-                        std::vector<msgs::ExpandOneResponse> &responses) {
+  template <typename RequestT, typename ResponseT>
+  void DriveReadResponses(ExecutionState<RequestT> &state, std::vector<ResponseT> &responses) {
     for (auto &request : state.requests) {
       auto &storage_client = GetStorageClientForShard(request.shard);
 
@@ -638,17 +594,13 @@ class RequestRouter : public RequestRouterInterface {
       }
 
       if (poll_result->HasError()) {
-        throw std::runtime_error("ExpandOne request timed out");
+        throw std::runtime_error("RequestRouter Read request timed out");
       }
 
       msgs::ReadResponses response_variant = poll_result->GetValue();
-      auto response = std::get<msgs::ExpandOneResponse>(response_variant);
-      // -NOTE-
-      // Currently a boolean flag for signaling the overall success of the
-      // ExpandOne request does not exist. But it should, so here we assume
-      // that it is already in place.
+      auto response = std::get<ResponseT>(response_variant);
       if (response.error) {
-        throw std::runtime_error("ExpandOne request did not succeed");
+        throw std::runtime_error("RequestRouter Read request did not succeed");
       }
 
       responses.push_back(std::move(response));
@@ -656,54 +608,29 @@ class RequestRouter : public RequestRouterInterface {
     state.requests.clear();
   }
 
-  void AwaitOnPaginatedRequests(ExecutionState<msgs::ScanVerticesRequest> &state,
-                                std::vector<msgs::ScanVerticesResponse> &responses,
-                                std::map<Shard, PaginatedResponseState> &paginated_response_tracker) {
-    std::vector<int> to_erase{};
-
-    for (int i = 0; i < state.requests.size(); i++) {
-      auto &request = state.requests[i];
-      // only operate on paginated requests
-      if (paginated_response_tracker.at(request.shard) != PaginatedResponseState::Pending) {
-        continue;
-      }
-
+  template <typename RequestT, typename ResponseT>
+  void DriveWriteResponses(ExecutionState<RequestT> &state, std::vector<ResponseT> &responses) {
+    for (auto &request : state.requests) {
       auto &storage_client = GetStorageClientForShard(request.shard);
 
-      // drive it to completion
-      auto await_result = storage_client.AwaitAsyncReadRequest(request.async_request_token.value());
-      while (!await_result) {
-        await_result = storage_client.AwaitAsyncReadRequest(request.async_request_token.value());
+      auto poll_result = storage_client.AwaitAsyncWriteRequest(request.async_request_token.value());
+      while (!poll_result) {
+        poll_result = storage_client.AwaitAsyncWriteRequest(request.async_request_token.value());
       }
 
-      if (await_result->HasError()) {
-        throw std::runtime_error("ScanAll request timed out");
+      if (poll_result->HasError()) {
+        throw std::runtime_error("RequestRouter Write request timed out");
       }
 
-      msgs::ReadResponses read_response_variant = await_result->GetValue();
-      auto response = std::get<msgs::ScanVerticesResponse>(read_response_variant);
+      msgs::WriteResponses response_variant = poll_result->GetValue();
+      auto response = std::get<ResponseT>(response_variant);
       if (response.error) {
-        throw std::runtime_error("ScanAll request did not succeed");
-      }
-
-      if (!response.next_start_id) {
-        paginated_response_tracker.erase(request.shard);
-        to_erase.push_back(i);
-      } else {
-        request.request.start_id.second = response.next_start_id->second;
-        paginated_response_tracker[request.shard] = PaginatedResponseState::PartiallyFinished;
+        throw std::runtime_error("RequestRouter Write request did not succeed");
       }
 
       responses.push_back(std::move(response));
-
-      // reverse sort to_erase to remove requests in reverse order for correctness
-      std::sort(to_erase.begin(), to_erase.end(), std::greater<>());
-
-      auto requests_begin = state.requests.begin();
-      for (int i : to_erase) {
-        state.requests.erase(requests_begin + i);
-      }
     }
+    state.requests.clear();
   }
 
   void SetUpNameIdMappers() {

From 1b77e029cab8b4c1c568ad7de008be7bd7973dac Mon Sep 17 00:00:00 2001
From: Tyler Neely <t@jujit.su>
Date: Tue, 29 Nov 2022 11:33:49 +0000
Subject: [PATCH 19/26] Use the Async methods under the hood for the blocking
 RsmClient::Send*Request methods for code-reuse

---
 src/io/rsm/rsm_client.hpp | 71 +++++++--------------------------------
 1 file changed, 12 insertions(+), 59 deletions(-)

diff --git a/src/io/rsm/rsm_client.hpp b/src/io/rsm/rsm_client.hpp
index 92cfe12ac..1e5415a90 100644
--- a/src/io/rsm/rsm_client.hpp
+++ b/src/io/rsm/rsm_client.hpp
@@ -101,68 +101,21 @@ class RsmClient {
   ~RsmClient() = default;
 
   BasicResult<TimedOut, WriteResponseT> SendWriteRequest(WriteRequestT req) {
-    WriteRequest<WriteRequestT> client_req;
-    client_req.operation = req;
-
-    const Duration overall_timeout = io_.GetDefaultTimeout();
-    const Time before = io_.Now();
-
-    do {
-      spdlog::debug("client sending WriteRequest to Leader {}", leader_.ToString());
-      ResponseFuture<WriteResponse<WriteResponseT>> response_future =
-          io_.template Request<WriteRequest<WriteRequestT>, WriteResponse<WriteResponseT>>(leader_, client_req);
-      ResponseResult<WriteResponse<WriteResponseT>> response_result = std::move(response_future).Wait();
-
-      if (response_result.HasError()) {
-        spdlog::debug("client timed out while trying to communicate with leader server {}", leader_.ToString());
-        return response_result.GetError();
-      }
-
-      ResponseEnvelope<WriteResponse<WriteResponseT>> &&response_envelope = std::move(response_result.GetValue());
-      WriteResponse<WriteResponseT> &&write_response = std::move(response_envelope.message);
-
-      if (write_response.success) {
-        return std::move(write_response.write_return);
-      }
-
-      PossiblyRedirectLeader(write_response);
-    } while (io_.Now() < before + overall_timeout);
-
-    return TimedOut{};
+    auto token = SendAsyncWriteRequest(req);
+    auto poll_result = AwaitAsyncWriteRequest(token);
+    while (!poll_result) {
+      poll_result = AwaitAsyncWriteRequest(token);
+    }
+    return poll_result.value();
   }
 
   BasicResult<TimedOut, ReadResponseT> SendReadRequest(ReadRequestT req) {
-    ReadRequest<ReadRequestT> read_req;
-    read_req.operation = req;
-
-    const Duration overall_timeout = io_.GetDefaultTimeout();
-    const Time before = io_.Now();
-
-    do {
-      spdlog::debug("client sending ReadRequest to Leader {}", leader_.ToString());
-
-      ResponseFuture<ReadResponse<ReadResponseT>> get_response_future =
-          io_.template Request<ReadRequest<ReadRequestT>, ReadResponse<ReadResponseT>>(leader_, read_req);
-
-      // receive response
-      ResponseResult<ReadResponse<ReadResponseT>> get_response_result = std::move(get_response_future).Wait();
-
-      if (get_response_result.HasError()) {
-        spdlog::debug("client timed out while trying to communicate with leader server {}", leader_.ToString());
-        return get_response_result.GetError();
-      }
-
-      ResponseEnvelope<ReadResponse<ReadResponseT>> &&get_response_envelope = std::move(get_response_result.GetValue());
-      ReadResponse<ReadResponseT> &&read_get_response = std::move(get_response_envelope.message);
-
-      if (read_get_response.success) {
-        return std::move(read_get_response.read_return);
-      }
-
-      PossiblyRedirectLeader(read_get_response);
-    } while (io_.Now() < before + overall_timeout);
-
-    return TimedOut{};
+    auto token = SendAsyncReadRequest(req);
+    auto poll_result = AwaitAsyncReadRequest(token);
+    while (!poll_result) {
+      poll_result = AwaitAsyncReadRequest(token);
+    }
+    return poll_result.value();
   }
 
   /// AsyncRead methods

From ec529da8d243cc28d9e03492e31b0218a661543f Mon Sep 17 00:00:00 2001
From: Tyler Neely <t@jujit.su>
Date: Tue, 29 Nov 2022 12:28:19 +0000
Subject: [PATCH 20/26] Address clang-tidy feedback

---
 src/io/rsm/rsm_client.hpp | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/io/rsm/rsm_client.hpp b/src/io/rsm/rsm_client.hpp
index 1e5415a90..5eb4aee5f 100644
--- a/src/io/rsm/rsm_client.hpp
+++ b/src/io/rsm/rsm_client.hpp
@@ -41,7 +41,7 @@ class AsyncRequestToken {
   size_t id_;
 
  public:
-  AsyncRequestToken(size_t id) : id_(id) {}
+  explicit AsyncRequestToken(size_t id) : id_(id) {}
   size_t GetId() const { return id_; }
 };
 
@@ -132,7 +132,7 @@ class RsmClient {
 
     async_reads_.emplace(token, std::move(async_request));
 
-    return AsyncRequestToken(token);
+    return AsyncRequestToken{token};
   }
 
   void ResendAsyncReadRequest(AsyncRequestToken &token) {
@@ -203,7 +203,7 @@ class RsmClient {
 
     async_writes_.emplace(token, std::move(async_request));
 
-    return AsyncRequestToken(token);
+    return AsyncRequestToken{token};
   }
 
   void ResendAsyncWriteRequest(AsyncRequestToken &token) {

From 9144d2dccde7cb0f0cb3c1728f7956f74b63c947 Mon Sep 17 00:00:00 2001
From: Tyler Neely <t@jujit.su>
Date: Tue, 29 Nov 2022 14:30:59 +0000
Subject: [PATCH 21/26] Remove bug-prone inverted ownership of ExecutionState
 as a consideration of operators

---
 src/query/v2/plan/operator.cpp                | 40 +++++-----
 src/query/v2/request_router.hpp               | 73 ++++---------------
 tests/unit/high_density_shard_create_scan.cpp |  4 +-
 3 files changed, 33 insertions(+), 84 deletions(-)

diff --git a/src/query/v2/plan/operator.cpp b/src/query/v2/plan/operator.cpp
index 014be0d62..b45ea457e 100644
--- a/src/query/v2/plan/operator.cpp
+++ b/src/query/v2/plan/operator.cpp
@@ -180,7 +180,7 @@ class DistributedCreateNodeCursor : public Cursor {
       auto &request_router = context.request_router;
       {
         SCOPED_REQUEST_WAIT_PROFILE;
-        request_router->Request(state_, NodeCreationInfoToRequest(context, frame));
+        request_router->Request(NodeCreationInfoToRequest(context, frame));
       }
       PlaceNodeOnTheFrame(frame, context);
       return true;
@@ -191,7 +191,7 @@ class DistributedCreateNodeCursor : public Cursor {
 
   void Shutdown() override { input_cursor_->Shutdown(); }
 
-  void Reset() override { state_ = {}; }
+  void Reset() override {}
 
   void PlaceNodeOnTheFrame(Frame &frame, ExecutionContext &context) {
     // TODO(kostasrim) Make this work with batching
@@ -252,7 +252,6 @@ class DistributedCreateNodeCursor : public Cursor {
   std::vector<const NodeCreationInfo *> nodes_info_;
   std::vector<std::vector<std::pair<storage::v3::PropertyId, msgs::Value>>> src_vertex_props_;
   std::vector<msgs::PrimaryKey> primary_keys_;
-  ExecutionState<msgs::CreateVerticesRequest> state_;
 };
 
 bool Once::OnceCursor::Pull(Frame &, ExecutionContext &context) {
@@ -365,7 +364,6 @@ class ScanAllCursor : public Cursor {
   std::optional<decltype(vertices_.value().begin())> vertices_it_;
   const char *op_name_;
   std::vector<msgs::ScanVerticesResponse> current_batch;
-  ExecutionState<msgs::ScanVerticesRequest> request_state;
 };
 
 class DistributedScanAllAndFilterCursor : public Cursor {
@@ -384,14 +382,21 @@ class DistributedScanAllAndFilterCursor : public Cursor {
     ResetExecutionState();
   }
 
+  enum class State : int8_t { INITIALIZING, COMPLETED };
+
   using VertexAccessor = accessors::VertexAccessor;
 
   bool MakeRequest(RequestRouterInterface &request_router, ExecutionContext &context) {
     {
       SCOPED_REQUEST_WAIT_PROFILE;
-      current_batch = request_router.Request(request_state_);
+      std::optional<std::string> request_label = std::nullopt;
+      if (label_.has_value()) {
+        request_label = request_router.LabelToName(*label_);
+      }
+      current_batch = request_router.Request(request_label);
     }
     current_vertex_it = current_batch.begin();
+    request_state_ = State::COMPLETED;
     return !current_batch.empty();
   }
 
@@ -403,19 +408,15 @@ class DistributedScanAllAndFilterCursor : public Cursor {
       if (MustAbort(context)) {
         throw HintedAbortError();
       }
-      using State = ExecutionState<msgs::ScanVerticesRequest>;
 
-      if (request_state_.state == State::INITIALIZING) {
+      if (request_state_ == State::INITIALIZING) {
         if (!input_cursor_->Pull(frame, context)) {
           return false;
         }
       }
 
-      request_state_.label =
-          label_.has_value() ? std::make_optional(request_router.LabelToName(*label_)) : std::nullopt;
-
       if (current_vertex_it == current_batch.end() &&
-          (request_state_.state == State::COMPLETED || !MakeRequest(request_router, context))) {
+          (request_state_ == State::COMPLETED || !MakeRequest(request_router, context))) {
         ResetExecutionState();
         continue;
       }
@@ -431,7 +432,7 @@ class DistributedScanAllAndFilterCursor : public Cursor {
   void ResetExecutionState() {
     current_batch.clear();
     current_vertex_it = current_batch.end();
-    request_state_ = ExecutionState<msgs::ScanVerticesRequest>{};
+    request_state_ = State::INITIALIZING;
   }
 
   void Reset() override {
@@ -445,7 +446,7 @@ class DistributedScanAllAndFilterCursor : public Cursor {
   const char *op_name_;
   std::vector<VertexAccessor> current_batch;
   std::vector<VertexAccessor>::iterator current_vertex_it;
-  ExecutionState<msgs::ScanVerticesRequest> request_state_;
+  State request_state_ = State::INITIALIZING;
   std::optional<storage::v3::LabelId> label_;
   std::optional<std::pair<storage::v3::PropertyId, Expression *>> property_expression_pair_;
   std::optional<std::vector<Expression *>> filter_expressions_;
@@ -2343,7 +2344,7 @@ class DistributedCreateExpandCursor : public Cursor {
     ResetExecutionState();
     {
       SCOPED_REQUEST_WAIT_PROFILE;
-      request_router->Request(state_, ExpandCreationInfoToRequest(context, frame));
+      request_router->Request(ExpandCreationInfoToRequest(context, frame));
     }
     return true;
   }
@@ -2423,11 +2424,10 @@ class DistributedCreateExpandCursor : public Cursor {
   }
 
  private:
-  void ResetExecutionState() { state_ = {}; }
+  void ResetExecutionState() {}
 
   const UniqueCursorPtr input_cursor_;
   const CreateExpand &self_;
-  ExecutionState<msgs::CreateExpandRequest> state_;
 };
 
 class DistributedExpandCursor : public Cursor {
@@ -2474,8 +2474,7 @@ class DistributedExpandCursor : public Cursor {
     request.edge_properties.emplace();
     request.src_vertices.push_back(get_dst_vertex(edge, direction));
     request.direction = (direction == EdgeAtom::Direction::IN) ? msgs::EdgeDirection::OUT : msgs::EdgeDirection::IN;
-    ExecutionState<msgs::ExpandOneRequest> request_state;
-    auto result_rows = context.request_router->Request(request_state, std::move(request));
+    auto result_rows = context.request_router->Request(std::move(request));
     MG_ASSERT(result_rows.size() == 1);
     auto &result_row = result_rows.front();
     frame[self_.common_.node_symbol] = accessors::VertexAccessor(
@@ -2500,10 +2499,9 @@ class DistributedExpandCursor : public Cursor {
       // to not fetch any properties of the edges
       request.edge_properties.emplace();
       request.src_vertices.push_back(vertex.Id());
-      ExecutionState<msgs::ExpandOneRequest> request_state;
-      auto result_rows = std::invoke([&context, &request_state, &request]() mutable {
+      auto result_rows = std::invoke([&context, &request]() mutable {
         SCOPED_REQUEST_WAIT_PROFILE;
-        return context.request_router->Request(request_state, std::move(request));
+        return context.request_router->Request(std::move(request));
       });
       MG_ASSERT(result_rows.size() == 1);
       auto &result_row = result_rows.front();
diff --git a/src/query/v2/request_router.hpp b/src/query/v2/request_router.hpp
index 224ea8674..42f2da702 100644
--- a/src/query/v2/request_router.hpp
+++ b/src/query/v2/request_router.hpp
@@ -83,7 +83,6 @@ struct ExecutionState {
   using CompoundKey = io::rsm::ShardRsmKey;
   using Shard = coordinator::Shard;
 
-  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
   // on the request itself.
   std::optional<std::string> label;
@@ -97,7 +96,6 @@ struct ExecutionState {
   // it pulled all the requested data from the given Shard, it will be removed from the Vector. When the Vector becomes
   // empty, it means that all of the requests have completed succefully.
   std::vector<ShardRequestState<TRequest>> requests;
-  State state = INITIALIZING;
 };
 
 class RequestRouterInterface {
@@ -113,13 +111,10 @@ class RequestRouterInterface {
 
   virtual void StartTransaction() = 0;
   virtual void Commit() = 0;
-  virtual std::vector<VertexAccessor> Request(ExecutionState<msgs::ScanVerticesRequest> &state) = 0;
-  virtual std::vector<msgs::CreateVerticesResponse> Request(ExecutionState<msgs::CreateVerticesRequest> &state,
-                                                            std::vector<msgs::NewVertex> new_vertices) = 0;
-  virtual std::vector<msgs::ExpandOneResultRow> Request(ExecutionState<msgs::ExpandOneRequest> &state,
-                                                        msgs::ExpandOneRequest request) = 0;
-  virtual std::vector<msgs::CreateExpandResponse> Request(ExecutionState<msgs::CreateExpandRequest> &state,
-                                                          std::vector<msgs::NewExpand> new_edges) = 0;
+  virtual std::vector<VertexAccessor> Request(std::optional<std::string> &label) = 0;
+  virtual std::vector<msgs::CreateVerticesResponse> Request(std::vector<msgs::NewVertex> new_vertices) = 0;
+  virtual std::vector<msgs::ExpandOneResultRow> Request(msgs::ExpandOneRequest request) = 0;
+  virtual std::vector<msgs::CreateExpandResponse> Request(std::vector<msgs::NewExpand> new_edges) = 0;
 
   virtual storage::v3::EdgeTypeId NameToEdgeType(const std::string &name) const = 0;
   virtual storage::v3::PropertyId NameToProperty(const std::string &name) const = 0;
@@ -245,7 +240,9 @@ class RequestRouter : public RequestRouterInterface {
   bool IsPrimaryLabel(storage::v3::LabelId label) const override { return shards_map_.label_spaces.contains(label); }
 
   // TODO(kostasrim) Simplify return result
-  std::vector<VertexAccessor> Request(ExecutionState<msgs::ScanVerticesRequest> &state) override {
+  std::vector<VertexAccessor> Request(std::optional<std::string> &label) override {
+    ExecutionState<msgs::ScanVerticesRequest> state = {};
+    state.label = label;
     MaybeInitializeExecutionState(state);
     std::vector<msgs::ScanVerticesResponse> responses;
 
@@ -255,14 +252,13 @@ class RequestRouter : public RequestRouterInterface {
       DriveReadResponses(state, responses);
     } while (!state.requests.empty());
 
-    MaybeCompleteState(state);
     // TODO(kostasrim) Before returning start prefetching the batch (this shall be done once we get MgFuture as return
     // result of storage_client.SendReadRequest()).
     return PostProcess(std::move(responses));
   }
 
-  std::vector<msgs::CreateVerticesResponse> Request(ExecutionState<msgs::CreateVerticesRequest> &state,
-                                                    std::vector<msgs::NewVertex> new_vertices) override {
+  std::vector<msgs::CreateVerticesResponse> Request(std::vector<msgs::NewVertex> new_vertices) override {
+    ExecutionState<msgs::CreateVerticesRequest> state = {};
     MG_ASSERT(!new_vertices.empty());
     MaybeInitializeExecutionState(state, new_vertices);
     std::vector<msgs::CreateVerticesResponse> responses;
@@ -275,14 +271,13 @@ class RequestRouter : public RequestRouterInterface {
       DriveWriteResponses(state, responses);
     } while (!state.requests.empty());
 
-    MaybeCompleteState(state);
     // TODO(kostasrim) Before returning start prefetching the batch (this shall be done once we get MgFuture as return
     // result of storage_client.SendReadRequest()).
     return responses;
   }
 
-  std::vector<msgs::CreateExpandResponse> Request(ExecutionState<msgs::CreateExpandRequest> &state,
-                                                  std::vector<msgs::NewExpand> new_edges) override {
+  std::vector<msgs::CreateExpandResponse> Request(std::vector<msgs::NewExpand> new_edges) override {
+    ExecutionState<msgs::CreateExpandRequest> state = {};
     MG_ASSERT(!new_edges.empty());
     MaybeInitializeExecutionState(state, new_edges);
     std::vector<msgs::CreateExpandResponse> responses;
@@ -303,12 +298,11 @@ class RequestRouter : public RequestRouterInterface {
     }
     // We are done with this state
     state.requests.clear();
-    MaybeCompleteState(state);
     return responses;
   }
 
-  std::vector<msgs::ExpandOneResultRow> Request(ExecutionState<msgs::ExpandOneRequest> &state,
-                                                msgs::ExpandOneRequest request) override {
+  std::vector<msgs::ExpandOneResultRow> Request(msgs::ExpandOneRequest request) override {
+    ExecutionState<msgs::ExpandOneRequest> state = {};
     // TODO(kostasrim)Update to limit the batch size here
     // Expansions of the destination must be handled by the caller. For example
     // match (u:L1 { prop : 1 })-[:Friend]-(v:L1)
@@ -335,7 +329,6 @@ class RequestRouter : public RequestRouterInterface {
       result_rows.insert(result_rows.end(), std::make_move_iterator(response.result.begin()),
                          std::make_move_iterator(response.result.end()));
     }
-    MaybeCompleteState(state);
     return result_rows;
   }
 
@@ -362,31 +355,8 @@ class RequestRouter : public RequestRouterInterface {
     return accessors;
   }
 
-  template <typename ExecutionState>
-  void ThrowIfStateCompleted(ExecutionState &state) const {
-    if (state.state == ExecutionState::COMPLETED) [[unlikely]] {
-      throw std::runtime_error("State is completed and must be reset");
-    }
-  }
-
-  template <typename ExecutionState>
-  void MaybeCompleteState(ExecutionState &state) const {
-    if (state.requests.empty()) {
-      state.state = ExecutionState::COMPLETED;
-    }
-  }
-
-  template <typename ExecutionState>
-  bool ShallNotInitializeState(ExecutionState &state) const {
-    return state.state != ExecutionState::INITIALIZING;
-  }
-
   void MaybeInitializeExecutionState(ExecutionState<msgs::CreateVerticesRequest> &state,
                                      std::vector<msgs::NewVertex> new_vertices) {
-    ThrowIfStateCompleted(state);
-    if (ShallNotInitializeState(state)) {
-      return;
-    }
     state.transaction_id = transaction_id_;
 
     std::map<Shard, msgs::CreateVerticesRequest> per_shard_request_table;
@@ -410,15 +380,10 @@ class RequestRouter : public RequestRouterInterface {
       };
       state.requests.emplace_back(std::move(shard_request_state));
     }
-    state.state = ExecutionState<msgs::CreateVerticesRequest>::EXECUTING;
   }
 
   void MaybeInitializeExecutionState(ExecutionState<msgs::CreateExpandRequest> &state,
                                      std::vector<msgs::NewExpand> new_expands) {
-    ThrowIfStateCompleted(state);
-    if (ShallNotInitializeState(state)) {
-      return;
-    }
     state.transaction_id = transaction_id_;
 
     std::map<Shard, msgs::CreateExpandRequest> per_shard_request_table;
@@ -453,15 +418,9 @@ class RequestRouter : public RequestRouterInterface {
       };
       state.requests.emplace_back(std::move(shard_request_state));
     }
-    state.state = ExecutionState<msgs::CreateExpandRequest>::EXECUTING;
   }
 
   void MaybeInitializeExecutionState(ExecutionState<msgs::ScanVerticesRequest> &state) {
-    ThrowIfStateCompleted(state);
-    if (ShallNotInitializeState(state)) {
-      return;
-    }
-
     std::vector<coordinator::Shards> multi_shards;
     state.transaction_id = transaction_id_;
     if (!state.label) {
@@ -489,14 +448,9 @@ class RequestRouter : public RequestRouterInterface {
         state.requests.emplace_back(std::move(shard_request_state));
       }
     }
-    state.state = ExecutionState<msgs::ScanVerticesRequest>::EXECUTING;
   }
 
   void MaybeInitializeExecutionState(ExecutionState<msgs::ExpandOneRequest> &state, msgs::ExpandOneRequest request) {
-    ThrowIfStateCompleted(state);
-    if (ShallNotInitializeState(state)) {
-      return;
-    }
     state.transaction_id = transaction_id_;
 
     std::map<Shard, msgs::ExpandOneRequest> per_shard_request_table;
@@ -522,7 +476,6 @@ class RequestRouter : public RequestRouterInterface {
 
       state.requests.emplace_back(std::move(shard_request_state));
     }
-    state.state = ExecutionState<msgs::ExpandOneRequest>::EXECUTING;
   }
 
   StorageClient &GetStorageClientForShard(Shard shard) {
diff --git a/tests/unit/high_density_shard_create_scan.cpp b/tests/unit/high_density_shard_create_scan.cpp
index 22af9c702..362e3525e 100644
--- a/tests/unit/high_density_shard_create_scan.cpp
+++ b/tests/unit/high_density_shard_create_scan.cpp
@@ -174,8 +174,6 @@ void ExecuteOp(query::v2::RequestRouter<LocalTransport> &request_router, std::se
     return;
   }
 
-  query::v2::ExecutionState<msgs::CreateVerticesRequest> state;
-
   auto label_id = request_router.NameToLabel("test_label");
 
   msgs::NewVertex nv{.primary_key = primary_key};
@@ -184,7 +182,7 @@ void ExecuteOp(query::v2::RequestRouter<LocalTransport> &request_router, std::se
   std::vector<msgs::NewVertex> new_vertices;
   new_vertices.push_back(std::move(nv));
 
-  auto result = request_router.Request(state, std::move(new_vertices));
+  auto result = request_router.Request(std::move(new_vertices));
 
   MG_ASSERT(result.size() == 1);
   MG_ASSERT(!result[0].error.has_value());

From 8f08d986cb882ce4af7a79aac17d71bcab869021 Mon Sep 17 00:00:00 2001
From: Tyler Neely <t@jujit.su>
Date: Tue, 29 Nov 2022 14:47:32 +0000
Subject: [PATCH 22/26] Make method names clear for RequestRouter requests,
 avoid unnecessary overloading

---
 src/query/v2/plan/operator.cpp                | 10 ++---
 src/query/v2/request_router.hpp               | 39 +++++++++----------
 tests/simulation/test_cluster.hpp             |  8 +---
 tests/unit/high_density_shard_create_scan.cpp |  4 +-
 tests/unit/machine_manager.cpp                | 13 ++-----
 tests/unit/query_v2_expression_evaluator.cpp  | 18 +++------
 6 files changed, 36 insertions(+), 56 deletions(-)

diff --git a/src/query/v2/plan/operator.cpp b/src/query/v2/plan/operator.cpp
index b45ea457e..21440a42d 100644
--- a/src/query/v2/plan/operator.cpp
+++ b/src/query/v2/plan/operator.cpp
@@ -180,7 +180,7 @@ class DistributedCreateNodeCursor : public Cursor {
       auto &request_router = context.request_router;
       {
         SCOPED_REQUEST_WAIT_PROFILE;
-        request_router->Request(NodeCreationInfoToRequest(context, frame));
+        request_router->CreateVertices(NodeCreationInfoToRequest(context, frame));
       }
       PlaceNodeOnTheFrame(frame, context);
       return true;
@@ -393,7 +393,7 @@ class DistributedScanAllAndFilterCursor : public Cursor {
       if (label_.has_value()) {
         request_label = request_router.LabelToName(*label_);
       }
-      current_batch = request_router.Request(request_label);
+      current_batch = request_router.ScanVertices(request_label);
     }
     current_vertex_it = current_batch.begin();
     request_state_ = State::COMPLETED;
@@ -2344,7 +2344,7 @@ class DistributedCreateExpandCursor : public Cursor {
     ResetExecutionState();
     {
       SCOPED_REQUEST_WAIT_PROFILE;
-      request_router->Request(ExpandCreationInfoToRequest(context, frame));
+      request_router->CreateExpand(ExpandCreationInfoToRequest(context, frame));
     }
     return true;
   }
@@ -2474,7 +2474,7 @@ class DistributedExpandCursor : public Cursor {
     request.edge_properties.emplace();
     request.src_vertices.push_back(get_dst_vertex(edge, direction));
     request.direction = (direction == EdgeAtom::Direction::IN) ? msgs::EdgeDirection::OUT : msgs::EdgeDirection::IN;
-    auto result_rows = context.request_router->Request(std::move(request));
+    auto result_rows = context.request_router->ExpandOne(std::move(request));
     MG_ASSERT(result_rows.size() == 1);
     auto &result_row = result_rows.front();
     frame[self_.common_.node_symbol] = accessors::VertexAccessor(
@@ -2501,7 +2501,7 @@ class DistributedExpandCursor : public Cursor {
       request.src_vertices.push_back(vertex.Id());
       auto result_rows = std::invoke([&context, &request]() mutable {
         SCOPED_REQUEST_WAIT_PROFILE;
-        return context.request_router->Request(std::move(request));
+        return context.request_router->ExpandOne(std::move(request));
       });
       MG_ASSERT(result_rows.size() == 1);
       auto &result_row = result_rows.front();
diff --git a/src/query/v2/request_router.hpp b/src/query/v2/request_router.hpp
index 42f2da702..05ce6eb2c 100644
--- a/src/query/v2/request_router.hpp
+++ b/src/query/v2/request_router.hpp
@@ -86,9 +86,6 @@ struct ExecutionState {
   // label is optional because some operators can create/remove etc, vertices. These kind of requests contain the label
   // on the request itself.
   std::optional<std::string> label;
-  // CompoundKey is optional because some operators require to iterate over all the available keys
-  // of a shard. One example is ScanAll, where we only require the field label.
-  std::optional<CompoundKey> key;
   // Transaction id to be filled by the RequestRouter implementation
   coordinator::Hlc transaction_id;
   // Initialized by RequestRouter implementation. This vector is filled with the shards that
@@ -111,10 +108,10 @@ class RequestRouterInterface {
 
   virtual void StartTransaction() = 0;
   virtual void Commit() = 0;
-  virtual std::vector<VertexAccessor> Request(std::optional<std::string> &label) = 0;
-  virtual std::vector<msgs::CreateVerticesResponse> Request(std::vector<msgs::NewVertex> new_vertices) = 0;
-  virtual std::vector<msgs::ExpandOneResultRow> Request(msgs::ExpandOneRequest request) = 0;
-  virtual std::vector<msgs::CreateExpandResponse> Request(std::vector<msgs::NewExpand> new_edges) = 0;
+  virtual std::vector<VertexAccessor> ScanVertices(std::optional<std::string> label) = 0;
+  virtual std::vector<msgs::CreateVerticesResponse> CreateVertices(std::vector<msgs::NewVertex> new_vertices) = 0;
+  virtual std::vector<msgs::ExpandOneResultRow> ExpandOne(msgs::ExpandOneRequest request) = 0;
+  virtual std::vector<msgs::CreateExpandResponse> CreateExpand(std::vector<msgs::NewExpand> new_edges) = 0;
 
   virtual storage::v3::EdgeTypeId NameToEdgeType(const std::string &name) const = 0;
   virtual storage::v3::PropertyId NameToProperty(const std::string &name) const = 0;
@@ -240,10 +237,10 @@ class RequestRouter : public RequestRouterInterface {
   bool IsPrimaryLabel(storage::v3::LabelId label) const override { return shards_map_.label_spaces.contains(label); }
 
   // TODO(kostasrim) Simplify return result
-  std::vector<VertexAccessor> Request(std::optional<std::string> &label) override {
+  std::vector<VertexAccessor> ScanVertices(std::optional<std::string> label) override {
     ExecutionState<msgs::ScanVerticesRequest> state = {};
     state.label = label;
-    MaybeInitializeExecutionState(state);
+    InitializeExecutionState(state);
     std::vector<msgs::ScanVerticesResponse> responses;
 
     SendAllRequests(state);
@@ -257,10 +254,10 @@ class RequestRouter : public RequestRouterInterface {
     return PostProcess(std::move(responses));
   }
 
-  std::vector<msgs::CreateVerticesResponse> Request(std::vector<msgs::NewVertex> new_vertices) override {
+  std::vector<msgs::CreateVerticesResponse> CreateVertices(std::vector<msgs::NewVertex> new_vertices) override {
     ExecutionState<msgs::CreateVerticesRequest> state = {};
     MG_ASSERT(!new_vertices.empty());
-    MaybeInitializeExecutionState(state, new_vertices);
+    InitializeExecutionState(state, new_vertices);
     std::vector<msgs::CreateVerticesResponse> responses;
 
     // 1. Send the requests.
@@ -276,10 +273,10 @@ class RequestRouter : public RequestRouterInterface {
     return responses;
   }
 
-  std::vector<msgs::CreateExpandResponse> Request(std::vector<msgs::NewExpand> new_edges) override {
+  std::vector<msgs::CreateExpandResponse> CreateExpand(std::vector<msgs::NewExpand> new_edges) override {
     ExecutionState<msgs::CreateExpandRequest> state = {};
     MG_ASSERT(!new_edges.empty());
-    MaybeInitializeExecutionState(state, new_edges);
+    InitializeExecutionState(state, new_edges);
     std::vector<msgs::CreateExpandResponse> responses;
     for (auto &request : state.requests) {
       auto &storage_client = GetStorageClientForShard(request.shard);
@@ -301,14 +298,14 @@ class RequestRouter : public RequestRouterInterface {
     return responses;
   }
 
-  std::vector<msgs::ExpandOneResultRow> Request(msgs::ExpandOneRequest request) override {
+  std::vector<msgs::ExpandOneResultRow> ExpandOne(msgs::ExpandOneRequest request) override {
     ExecutionState<msgs::ExpandOneRequest> state = {};
     // TODO(kostasrim)Update to limit the batch size here
     // Expansions of the destination must be handled by the caller. For example
     // 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
     // must be fetched again with an ExpandOne(Edges.dst)
-    MaybeInitializeExecutionState(state, std::move(request));
+    InitializeExecutionState(state, std::move(request));
     std::vector<msgs::ExpandOneResponse> responses;
 
     // 1. Send the requests.
@@ -355,8 +352,8 @@ class RequestRouter : public RequestRouterInterface {
     return accessors;
   }
 
-  void MaybeInitializeExecutionState(ExecutionState<msgs::CreateVerticesRequest> &state,
-                                     std::vector<msgs::NewVertex> new_vertices) {
+  void InitializeExecutionState(ExecutionState<msgs::CreateVerticesRequest> &state,
+                                std::vector<msgs::NewVertex> new_vertices) {
     state.transaction_id = transaction_id_;
 
     std::map<Shard, msgs::CreateVerticesRequest> per_shard_request_table;
@@ -382,8 +379,8 @@ class RequestRouter : public RequestRouterInterface {
     }
   }
 
-  void MaybeInitializeExecutionState(ExecutionState<msgs::CreateExpandRequest> &state,
-                                     std::vector<msgs::NewExpand> new_expands) {
+  void InitializeExecutionState(ExecutionState<msgs::CreateExpandRequest> &state,
+                                std::vector<msgs::NewExpand> new_expands) {
     state.transaction_id = transaction_id_;
 
     std::map<Shard, msgs::CreateExpandRequest> per_shard_request_table;
@@ -420,7 +417,7 @@ class RequestRouter : public RequestRouterInterface {
     }
   }
 
-  void MaybeInitializeExecutionState(ExecutionState<msgs::ScanVerticesRequest> &state) {
+  void InitializeExecutionState(ExecutionState<msgs::ScanVerticesRequest> &state) {
     std::vector<coordinator::Shards> multi_shards;
     state.transaction_id = transaction_id_;
     if (!state.label) {
@@ -450,7 +447,7 @@ class RequestRouter : public RequestRouterInterface {
     }
   }
 
-  void MaybeInitializeExecutionState(ExecutionState<msgs::ExpandOneRequest> &state, msgs::ExpandOneRequest request) {
+  void InitializeExecutionState(ExecutionState<msgs::ExpandOneRequest> &state, msgs::ExpandOneRequest request) {
     state.transaction_id = transaction_id_;
 
     std::map<Shard, msgs::ExpandOneRequest> per_shard_request_table;
diff --git a/tests/simulation/test_cluster.hpp b/tests/simulation/test_cluster.hpp
index 99f617cda..1392a0632 100644
--- a/tests/simulation/test_cluster.hpp
+++ b/tests/simulation/test_cluster.hpp
@@ -164,8 +164,6 @@ void ExecuteOp(query::v2::RequestRouter<SimulatorTransport> &request_router, std
     return;
   }
 
-  query::v2::ExecutionState<msgs::CreateVerticesRequest> state;
-
   auto label_id = request_router.NameToLabel("test_label");
 
   msgs::NewVertex nv{.primary_key = primary_key};
@@ -174,7 +172,7 @@ void ExecuteOp(query::v2::RequestRouter<SimulatorTransport> &request_router, std
   std::vector<msgs::NewVertex> new_vertices;
   new_vertices.push_back(std::move(nv));
 
-  auto result = request_router.Request(state, std::move(new_vertices));
+  auto result = request_router.CreateVertices(std::move(new_vertices));
 
   RC_ASSERT(result.size() == 1);
   RC_ASSERT(!result[0].error.has_value());
@@ -184,9 +182,7 @@ void ExecuteOp(query::v2::RequestRouter<SimulatorTransport> &request_router, std
 
 void ExecuteOp(query::v2::RequestRouter<SimulatorTransport> &request_router, std::set<CompoundKey> &correctness_model,
                ScanAll scan_all) {
-  query::v2::ExecutionState<msgs::ScanVerticesRequest> request{.label = "test_label"};
-
-  auto results = request_router.Request(request);
+  auto results = request_router.ScanVertices("test_label");
 
   RC_ASSERT(results.size() == correctness_model.size());
 
diff --git a/tests/unit/high_density_shard_create_scan.cpp b/tests/unit/high_density_shard_create_scan.cpp
index 362e3525e..982f3e69a 100644
--- a/tests/unit/high_density_shard_create_scan.cpp
+++ b/tests/unit/high_density_shard_create_scan.cpp
@@ -182,7 +182,7 @@ void ExecuteOp(query::v2::RequestRouter<LocalTransport> &request_router, std::se
   std::vector<msgs::NewVertex> new_vertices;
   new_vertices.push_back(std::move(nv));
 
-  auto result = request_router.Request(std::move(new_vertices));
+  auto result = request_router.CreateVertices(std::move(new_vertices));
 
   MG_ASSERT(result.size() == 1);
   MG_ASSERT(!result[0].error.has_value());
@@ -194,7 +194,7 @@ void ExecuteOp(query::v2::RequestRouter<LocalTransport> &request_router, std::se
                ScanAll scan_all) {
   query::v2::ExecutionState<msgs::ScanVerticesRequest> request{.label = "test_label"};
 
-  auto results = request_router.Request(request);
+  auto results = request_router.ScanVertices("test_label");
 
   MG_ASSERT(results.size() == correctness_model.size());
 
diff --git a/tests/unit/machine_manager.cpp b/tests/unit/machine_manager.cpp
index 0b081e5a1..748233737 100644
--- a/tests/unit/machine_manager.cpp
+++ b/tests/unit/machine_manager.cpp
@@ -111,15 +111,12 @@ ShardMap TestShardMap() {
 
 template <typename RequestRouter>
 void TestScanAll(RequestRouter &request_router) {
-  query::v2::ExecutionState<msgs::ScanVerticesRequest> state{.label = kLabelName};
-
-  auto result = request_router.Request(state);
+  auto result = request_router.ScanVertices(kLabelName);
   EXPECT_EQ(result.size(), 2);
 }
 
 void TestCreateVertices(query::v2::RequestRouterInterface &request_router) {
   using PropVal = msgs::Value;
-  query::v2::ExecutionState<msgs::CreateVerticesRequest> state;
   std::vector<msgs::NewVertex> new_vertices;
   auto label_id = request_router.NameToLabel(kLabelName);
   msgs::NewVertex a1{.primary_key = {PropVal(int64_t(0)), PropVal(int64_t(0))}};
@@ -129,14 +126,13 @@ void TestCreateVertices(query::v2::RequestRouterInterface &request_router) {
   new_vertices.push_back(std::move(a1));
   new_vertices.push_back(std::move(a2));
 
-  auto result = request_router.Request(state, std::move(new_vertices));
+  auto result = request_router.CreateVertices(std::move(new_vertices));
   EXPECT_EQ(result.size(), 1);
   EXPECT_FALSE(result[0].error.has_value()) << result[0].error->message;
 }
 
 void TestCreateExpand(query::v2::RequestRouterInterface &request_router) {
   using PropVal = msgs::Value;
-  query::v2::ExecutionState<msgs::CreateExpandRequest> state;
   std::vector<msgs::NewExpand> new_expands;
 
   const auto edge_type_id = request_router.NameToEdgeType("edge_type");
@@ -150,20 +146,19 @@ void TestCreateExpand(query::v2::RequestRouterInterface &request_router) {
   new_expands.push_back(std::move(expand_1));
   new_expands.push_back(std::move(expand_2));
 
-  auto responses = request_router.Request(state, std::move(new_expands));
+  auto responses = request_router.CreateExpand(std::move(new_expands));
   MG_ASSERT(responses.size() == 1);
   MG_ASSERT(!responses[0].error.has_value());
 }
 
 void TestExpandOne(query::v2::RequestRouterInterface &request_router) {
-  query::v2::ExecutionState<msgs::ExpandOneRequest> state{};
   msgs::ExpandOneRequest request;
   const auto edge_type_id = request_router.NameToEdgeType("edge_type");
   const auto label = msgs::Label{request_router.NameToLabel("test_label")};
   request.src_vertices.push_back(msgs::VertexId{label, {msgs::Value(int64_t(0)), msgs::Value(int64_t(0))}});
   request.edge_types.push_back(msgs::EdgeType{edge_type_id});
   request.direction = msgs::EdgeDirection::BOTH;
-  auto result_rows = request_router.Request(state, std::move(request));
+  auto result_rows = request_router.ExpandOne(std::move(request));
   MG_ASSERT(result_rows.size() == 1);
   MG_ASSERT(result_rows[0].in_edges_with_all_properties.size() == 1);
   MG_ASSERT(result_rows[0].out_edges_with_all_properties.size() == 1);
diff --git a/tests/unit/query_v2_expression_evaluator.cpp b/tests/unit/query_v2_expression_evaluator.cpp
index 112ecd29e..5f77ed4e7 100644
--- a/tests/unit/query_v2_expression_evaluator.cpp
+++ b/tests/unit/query_v2_expression_evaluator.cpp
@@ -82,23 +82,15 @@ class MockedRequestRouter : public RequestRouterInterface {
   }
   void StartTransaction() override {}
   void Commit() override {}
-  std::vector<VertexAccessor> Request(ExecutionState<memgraph::msgs::ScanVerticesRequest> &state) override {
+  std::vector<VertexAccessor> ScanVertices(std::optional<std::string> /* label */) override { return {}; }
+
+  std::vector<CreateVerticesResponse> CreateVertices(std::vector<memgraph::msgs::NewVertex> new_vertices) override {
     return {};
   }
 
-  std::vector<CreateVerticesResponse> Request(ExecutionState<CreateVerticesRequest> &state,
-                                              std::vector<memgraph::msgs::NewVertex> new_vertices) override {
-    return {};
-  }
+  std::vector<ExpandOneResultRow> ExpandOne(ExpandOneRequest request) override { return {}; }
 
-  std::vector<ExpandOneResultRow> Request(ExecutionState<ExpandOneRequest> &state, ExpandOneRequest request) override {
-    return {};
-  }
-
-  std::vector<CreateExpandResponse> Request(ExecutionState<CreateExpandRequest> &state,
-                                            std::vector<NewExpand> new_edges) override {
-    return {};
-  }
+  std::vector<CreateExpandResponse> CreateExpand(std::vector<NewExpand> new_edges) override { return {}; }
 
   const std::string &PropertyToName(memgraph::storage::v3::PropertyId id) const override {
     return properties_.IdToName(id.AsUint());

From f8215306e833110729ed113178e438673166ec60 Mon Sep 17 00:00:00 2001
From: Tyler Neely <t@jujit.su>
Date: Tue, 29 Nov 2022 15:06:01 +0000
Subject: [PATCH 23/26] A variety of small code clean-ups, remove overloaded
 methods

---
 src/query/v2/request_router.hpp | 119 +++++++++++++++-----------------
 1 file changed, 56 insertions(+), 63 deletions(-)

diff --git a/src/query/v2/request_router.hpp b/src/query/v2/request_router.hpp
index 05ce6eb2c..58caa95c0 100644
--- a/src/query/v2/request_router.hpp
+++ b/src/query/v2/request_router.hpp
@@ -240,42 +240,70 @@ class RequestRouter : public RequestRouterInterface {
   std::vector<VertexAccessor> ScanVertices(std::optional<std::string> label) override {
     ExecutionState<msgs::ScanVerticesRequest> state = {};
     state.label = label;
+
+    // create requests
     InitializeExecutionState(state);
+
+    // begin all requests in parallel
+    for (auto &request : state.requests) {
+      auto &storage_client = GetStorageClientForShard(request.shard);
+      msgs::ReadRequests req = request.request;
+
+      request.async_request_token = storage_client.SendAsyncReadRequest(request.request);
+    }
+
+    // drive requests to completion
     std::vector<msgs::ScanVerticesResponse> responses;
-
-    SendAllRequests(state);
-
     do {
       DriveReadResponses(state, responses);
     } while (!state.requests.empty());
 
-    // TODO(kostasrim) Before returning start prefetching the batch (this shall be done once we get MgFuture as return
-    // result of storage_client.SendReadRequest()).
-    return PostProcess(std::move(responses));
+    // convert responses into VertexAccessor objects to return
+    std::vector<VertexAccessor> accessors;
+    for (auto &response : responses) {
+      for (auto &result_row : response.results) {
+        accessors.emplace_back(VertexAccessor(std::move(result_row.vertex), std::move(result_row.props), this));
+      }
+    }
+
+    return accessors;
   }
 
   std::vector<msgs::CreateVerticesResponse> CreateVertices(std::vector<msgs::NewVertex> new_vertices) override {
     ExecutionState<msgs::CreateVerticesRequest> state = {};
     MG_ASSERT(!new_vertices.empty());
+
+    // create requests
     InitializeExecutionState(state, new_vertices);
+
+    // begin all requests in parallel
+    for (auto &request : state.requests) {
+      auto req_deep_copy = request.request;
+
+      for (auto &new_vertex : req_deep_copy.new_vertices) {
+        new_vertex.label_ids.erase(new_vertex.label_ids.begin());
+      }
+
+      auto &storage_client = GetStorageClientForShard(request.shard);
+
+      msgs::WriteRequests req = req_deep_copy;
+      request.async_request_token = storage_client.SendAsyncWriteRequest(req);
+    }
+
+    // drive requests to completion
     std::vector<msgs::CreateVerticesResponse> responses;
-
-    // 1. Send the requests.
-    SendAllRequests(state);
-
-    // 2. Block untill all the futures are exhausted
     do {
       DriveWriteResponses(state, responses);
     } while (!state.requests.empty());
 
-    // TODO(kostasrim) Before returning start prefetching the batch (this shall be done once we get MgFuture as return
-    // result of storage_client.SendReadRequest()).
     return responses;
   }
 
   std::vector<msgs::CreateExpandResponse> CreateExpand(std::vector<msgs::NewExpand> new_edges) override {
     ExecutionState<msgs::CreateExpandRequest> state = {};
     MG_ASSERT(!new_edges.empty());
+
+    // create requests
     InitializeExecutionState(state, new_edges);
     std::vector<msgs::CreateExpandResponse> responses;
     for (auto &request : state.requests) {
@@ -305,16 +333,24 @@ class RequestRouter : public RequestRouterInterface {
     // 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
     // must be fetched again with an ExpandOne(Edges.dst)
+
+    // create requests
     InitializeExecutionState(state, std::move(request));
+
+    // begin all requests in parallel
+    for (auto &request : state.requests) {
+      auto &storage_client = GetStorageClientForShard(request.shard);
+      msgs::ReadRequests req = request.request;
+      request.async_request_token = storage_client.SendAsyncReadRequest(req);
+    }
+
+    // drive requests to completion
     std::vector<msgs::ExpandOneResponse> responses;
-
-    // 1. Send the requests.
-    SendAllRequests(state);
-
-    // 2. Block untill all the futures are exhausted
     do {
       DriveReadResponses(state, responses);
     } while (!state.requests.empty());
+
+    // post-process responses
     std::vector<msgs::ExpandOneResultRow> result_rows;
     const auto total_row_count = std::accumulate(responses.begin(), responses.end(), 0,
                                                  [](const int64_t partial_count, const msgs::ExpandOneResponse &resp) {
@@ -326,6 +362,7 @@ class RequestRouter : public RequestRouterInterface {
       result_rows.insert(result_rows.end(), std::make_move_iterator(response.result.begin()),
                          std::make_move_iterator(response.result.end()));
     }
+
     return result_rows;
   }
 
@@ -342,16 +379,6 @@ class RequestRouter : public RequestRouterInterface {
   }
 
  private:
-  std::vector<VertexAccessor> PostProcess(std::vector<msgs::ScanVerticesResponse> &&responses) const {
-    std::vector<VertexAccessor> accessors;
-    for (auto &response : responses) {
-      for (auto &result_row : response.results) {
-        accessors.emplace_back(VertexAccessor(std::move(result_row.vertex), std::move(result_row.props), this));
-      }
-    }
-    return accessors;
-  }
-
   void InitializeExecutionState(ExecutionState<msgs::CreateVerticesRequest> &state,
                                 std::vector<msgs::NewVertex> new_vertices) {
     state.transaction_id = transaction_id_;
@@ -359,7 +386,7 @@ class RequestRouter : public RequestRouterInterface {
     std::map<Shard, msgs::CreateVerticesRequest> per_shard_request_table;
 
     for (auto &new_vertex : new_vertices) {
-      MG_ASSERT(!new_vertex.label_ids.empty(), "This is error!");
+      MG_ASSERT(!new_vertex.label_ids.empty(), "No label_ids provided for new vertex in RequestRouter::CreateVertices");
       auto shard = shards_map_.GetShardForKey(new_vertex.label_ids[0].id,
                                               storage::conversions::ConvertPropertyVector(new_vertex.primary_key));
       if (!per_shard_request_table.contains(shard)) {
@@ -499,40 +526,6 @@ class RequestRouter : public RequestRouterInterface {
     storage_cli_manager_.AddClient(target_shard, std::move(cli));
   }
 
-  void SendAllRequests(ExecutionState<msgs::ScanVerticesRequest> &state) {
-    for (auto &request : state.requests) {
-      const auto &current_shard = request.shard;
-
-      auto &storage_client = GetStorageClientForShard(current_shard);
-      msgs::ReadRequests req = request.request;
-
-      request.async_request_token = storage_client.SendAsyncReadRequest(request.request);
-    }
-  }
-
-  void SendAllRequests(ExecutionState<msgs::CreateVerticesRequest> &state) {
-    for (auto &request : state.requests) {
-      auto req_deep_copy = request.request;
-
-      for (auto &new_vertex : req_deep_copy.new_vertices) {
-        new_vertex.label_ids.erase(new_vertex.label_ids.begin());
-      }
-
-      auto &storage_client = GetStorageClientForShard(request.shard);
-
-      msgs::WriteRequests req = req_deep_copy;
-      request.async_request_token = storage_client.SendAsyncWriteRequest(req);
-    }
-  }
-
-  void SendAllRequests(ExecutionState<msgs::ExpandOneRequest> &state) {
-    for (auto &request : state.requests) {
-      auto &storage_client = GetStorageClientForShard(request.shard);
-      msgs::ReadRequests req = request.request;
-      request.async_request_token = storage_client.SendAsyncReadRequest(req);
-    }
-  }
-
   template <typename RequestT, typename ResponseT>
   void DriveReadResponses(ExecutionState<RequestT> &state, std::vector<ResponseT> &responses) {
     for (auto &request : state.requests) {

From 7df3a743b997f0e9d91a3af83e355a7cafb577a9 Mon Sep 17 00:00:00 2001
From: Tyler Neely <t@jujit.su>
Date: Tue, 29 Nov 2022 15:07:59 +0000
Subject: [PATCH 24/26] Simplify and parallelize CreateExpand

---
 src/query/v2/request_router.hpp | 26 +++++++++++---------------
 1 file changed, 11 insertions(+), 15 deletions(-)

diff --git a/src/query/v2/request_router.hpp b/src/query/v2/request_router.hpp
index 58caa95c0..7a0fb9d8d 100644
--- a/src/query/v2/request_router.hpp
+++ b/src/query/v2/request_router.hpp
@@ -305,24 +305,20 @@ class RequestRouter : public RequestRouterInterface {
 
     // create requests
     InitializeExecutionState(state, new_edges);
-    std::vector<msgs::CreateExpandResponse> responses;
+
+    // begin all requests in parallel
     for (auto &request : state.requests) {
       auto &storage_client = GetStorageClientForShard(request.shard);
-      msgs::WriteRequests req = request.request;
-      auto write_response_result = storage_client.SendWriteRequest(std::move(req));
-      if (write_response_result.HasError()) {
-        throw std::runtime_error("CreateVertices request timedout");
-      }
-      msgs::WriteResponses response_variant = write_response_result.GetValue();
-      msgs::CreateExpandResponse mapped_response = std::get<msgs::CreateExpandResponse>(response_variant);
-
-      if (mapped_response.error) {
-        throw std::runtime_error("CreateExpand request did not succeed");
-      }
-      responses.push_back(mapped_response);
+      msgs::ReadRequests req = request.request;
+      request.async_request_token = storage_client.SendAsyncReadRequest(req);
     }
-    // We are done with this state
-    state.requests.clear();
+
+    // drive requests to completion
+    std::vector<msgs::ExpandOneResponse> responses;
+    do {
+      DriveReadResponses(state, responses);
+    } while (!state.requests.empty());
+
     return responses;
   }
 

From b3605c9ab19331d18bab146ee892966c30280d02 Mon Sep 17 00:00:00 2001
From: Tyler Neely <t@jujit.su>
Date: Tue, 29 Nov 2022 15:11:35 +0000
Subject: [PATCH 25/26] Fix typo in new simplified RequestRouter::CreateExpand
 method

---
 src/query/v2/request_router.hpp | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/src/query/v2/request_router.hpp b/src/query/v2/request_router.hpp
index 7a0fb9d8d..ffb075da0 100644
--- a/src/query/v2/request_router.hpp
+++ b/src/query/v2/request_router.hpp
@@ -309,14 +309,14 @@ class RequestRouter : public RequestRouterInterface {
     // begin all requests in parallel
     for (auto &request : state.requests) {
       auto &storage_client = GetStorageClientForShard(request.shard);
-      msgs::ReadRequests req = request.request;
-      request.async_request_token = storage_client.SendAsyncReadRequest(req);
+      msgs::WriteRequests req = request.request;
+      request.async_request_token = storage_client.SendAsyncWriteRequest(req);
     }
 
     // drive requests to completion
-    std::vector<msgs::ExpandOneResponse> responses;
+    std::vector<msgs::CreateExpandResponse> responses;
     do {
-      DriveReadResponses(state, responses);
+      DriveWriteResponses(state, responses);
     } while (!state.requests.empty());
 
     return responses;

From 04124a1e9b60ac04d4292c693ccfbf3d4448a352 Mon Sep 17 00:00:00 2001
From: Tyler Neely <t@jujit.su>
Date: Tue, 29 Nov 2022 15:50:35 +0000
Subject: [PATCH 26/26] Make AsyncRequestToken arguments const, reserve size in
 response vectors

---
 src/io/rsm/rsm_client.hpp                     | 12 ++++++------
 src/query/v2/request_router.hpp               |  5 +++++
 tests/unit/high_density_shard_create_scan.cpp |  2 --
 3 files changed, 11 insertions(+), 8 deletions(-)

diff --git a/src/io/rsm/rsm_client.hpp b/src/io/rsm/rsm_client.hpp
index 5eb4aee5f..920866c7a 100644
--- a/src/io/rsm/rsm_client.hpp
+++ b/src/io/rsm/rsm_client.hpp
@@ -135,7 +135,7 @@ class RsmClient {
     return AsyncRequestToken{token};
   }
 
-  void ResendAsyncReadRequest(AsyncRequestToken &token) {
+  void ResendAsyncReadRequest(const AsyncRequestToken &token) {
     auto &async_request = async_reads_.at(token.GetId());
 
     ReadRequest<ReadRequestT> read_req = {.operation = async_request.request};
@@ -144,7 +144,7 @@ class RsmClient {
         io_.template Request<ReadRequest<ReadRequestT>, ReadResponse<ReadResponseT>>(leader_, read_req);
   }
 
-  std::optional<BasicResult<TimedOut, ReadResponseT>> PollAsyncReadRequest(AsyncRequestToken &token) {
+  std::optional<BasicResult<TimedOut, ReadResponseT>> PollAsyncReadRequest(const AsyncRequestToken &token) {
     auto &async_request = async_reads_.at(token.GetId());
 
     if (!async_request.future.IsReady()) {
@@ -154,7 +154,7 @@ class RsmClient {
     return AwaitAsyncReadRequest();
   }
 
-  std::optional<BasicResult<TimedOut, ReadResponseT>> AwaitAsyncReadRequest(AsyncRequestToken &token) {
+  std::optional<BasicResult<TimedOut, ReadResponseT>> AwaitAsyncReadRequest(const AsyncRequestToken &token) {
     auto &async_request = async_reads_.at(token.GetId());
     ResponseResult<ReadResponse<ReadResponseT>> get_response_result = std::move(async_request.future).Wait();
 
@@ -206,7 +206,7 @@ class RsmClient {
     return AsyncRequestToken{token};
   }
 
-  void ResendAsyncWriteRequest(AsyncRequestToken &token) {
+  void ResendAsyncWriteRequest(const AsyncRequestToken &token) {
     auto &async_request = async_writes_.at(token.GetId());
 
     WriteRequest<WriteRequestT> write_req = {.operation = async_request.request};
@@ -215,7 +215,7 @@ class RsmClient {
         io_.template Request<WriteRequest<WriteRequestT>, WriteResponse<WriteResponseT>>(leader_, write_req);
   }
 
-  std::optional<BasicResult<TimedOut, WriteResponseT>> PollAsyncWriteRequest(AsyncRequestToken &token) {
+  std::optional<BasicResult<TimedOut, WriteResponseT>> PollAsyncWriteRequest(const AsyncRequestToken &token) {
     auto &async_request = async_writes_.at(token.GetId());
 
     if (!async_request.future.IsReady()) {
@@ -225,7 +225,7 @@ class RsmClient {
     return AwaitAsyncWriteRequest();
   }
 
-  std::optional<BasicResult<TimedOut, WriteResponseT>> AwaitAsyncWriteRequest(AsyncRequestToken &token) {
+  std::optional<BasicResult<TimedOut, WriteResponseT>> AwaitAsyncWriteRequest(const AsyncRequestToken &token) {
     auto &async_request = async_writes_.at(token.GetId());
     ResponseResult<WriteResponse<WriteResponseT>> get_response_result = std::move(async_request.future).Wait();
 
diff --git a/src/query/v2/request_router.hpp b/src/query/v2/request_router.hpp
index ffb075da0..996272fdc 100644
--- a/src/query/v2/request_router.hpp
+++ b/src/query/v2/request_router.hpp
@@ -254,12 +254,14 @@ class RequestRouter : public RequestRouterInterface {
 
     // drive requests to completion
     std::vector<msgs::ScanVerticesResponse> responses;
+    responses.reserve(state.requests.size());
     do {
       DriveReadResponses(state, responses);
     } while (!state.requests.empty());
 
     // convert responses into VertexAccessor objects to return
     std::vector<VertexAccessor> accessors;
+    accessors.reserve(responses.size());
     for (auto &response : responses) {
       for (auto &result_row : response.results) {
         accessors.emplace_back(VertexAccessor(std::move(result_row.vertex), std::move(result_row.props), this));
@@ -292,6 +294,7 @@ class RequestRouter : public RequestRouterInterface {
 
     // drive requests to completion
     std::vector<msgs::CreateVerticesResponse> responses;
+    responses.reserve(state.requests.size());
     do {
       DriveWriteResponses(state, responses);
     } while (!state.requests.empty());
@@ -315,6 +318,7 @@ class RequestRouter : public RequestRouterInterface {
 
     // drive requests to completion
     std::vector<msgs::CreateExpandResponse> responses;
+    responses.reserve(state.requests.size());
     do {
       DriveWriteResponses(state, responses);
     } while (!state.requests.empty());
@@ -342,6 +346,7 @@ class RequestRouter : public RequestRouterInterface {
 
     // drive requests to completion
     std::vector<msgs::ExpandOneResponse> responses;
+    responses.reserve(state.requests.size());
     do {
       DriveReadResponses(state, responses);
     } while (!state.requests.empty());
diff --git a/tests/unit/high_density_shard_create_scan.cpp b/tests/unit/high_density_shard_create_scan.cpp
index 982f3e69a..2be48fc77 100644
--- a/tests/unit/high_density_shard_create_scan.cpp
+++ b/tests/unit/high_density_shard_create_scan.cpp
@@ -192,8 +192,6 @@ void ExecuteOp(query::v2::RequestRouter<LocalTransport> &request_router, std::se
 
 void ExecuteOp(query::v2::RequestRouter<LocalTransport> &request_router, std::set<CompoundKey> &correctness_model,
                ScanAll scan_all) {
-  query::v2::ExecutionState<msgs::ScanVerticesRequest> request{.label = "test_label"};
-
   auto results = request_router.ScanVertices("test_label");
 
   MG_ASSERT(results.size() == correctness_model.size());