From 02ef954e5134d79e0831d28796bec50c96721de8 Mon Sep 17 00:00:00 2001 From: Kostas Kyrimis Date: Mon, 7 Nov 2022 18:28:35 +0200 Subject: [PATCH] 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 Visit(Function &function) override { - FunctionContext function_ctx{dba_, ctx_->memory, ctx_->timestamp, &ctx_->counters, view_}; + functions::FunctionContext 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 +#include +#include +#include + +#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 +struct FunctionContext { + TAccessor *db_accessor; + utils::MemoryResource *memory; + int64_t timestamp; + std::unordered_map *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 +std::function +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` 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, 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` check. +// * Two arguments were supplied, the 1st one passes `Or` 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, NonNegativeInteger, +// Optional>("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 +bool ArgIsType(const TypedValueT &arg) { + if constexpr (std::is_same_v) { + return arg.IsNull(); + } else if constexpr (std::is_same_v) { + return arg.IsBool(); + } else if constexpr (std::is_same_v) { + return arg.IsInt(); + } else if constexpr (std::is_same_v) { + return arg.IsInt() && arg.ValueInt() > 0; + } else if constexpr (std::is_same_v) { + return arg.IsInt() && arg.ValueInt() != 0; + } else if constexpr (std::is_same_v) { + return arg.IsInt() && arg.ValueInt() >= 0; + } else if constexpr (std::is_same_v) { + return arg.IsDouble(); + } else if constexpr (std::is_same_v) { + return arg.IsNumeric(); + } else if constexpr (std::is_same_v) { + return arg.IsList(); + } else if constexpr (std::is_same_v) { + return arg.IsString(); + } else if constexpr (std::is_same_v) { + return arg.IsMap(); + } else if constexpr (std::is_same_v) { + return arg.IsVertex(); + } else if constexpr (std::is_same_v) { + return arg.IsEdge(); + } else if constexpr (std::is_same_v) { + return arg.IsPath(); + } else if constexpr (std::is_same_v) { + return arg.IsDate(); + } else if constexpr (std::is_same_v) { + return arg.IsLocalTime(); + } else if constexpr (std::is_same_v) { + return arg.IsLocalDateTime(); + } else if constexpr (std::is_same_v) { + return arg.IsDuration(); + } else if constexpr (std::is_same_v) { + return true; + } else { + static_assert(std::is_same_v, "Unknown ArgType"); + } + return false; +} + +template +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) { + return "null"; + } else if constexpr (std::is_same_v) { + return "boolean"; + } else if constexpr (std::is_same_v) { + return "integer"; + } else if constexpr (std::is_same_v) { + return "positive integer"; + } else if constexpr (std::is_same_v) { + return "non-zero integer"; + } else if constexpr (std::is_same_v) { + return "non-negative integer"; + } else if constexpr (std::is_same_v) { + return "float"; + } else if constexpr (std::is_same_v) { + return "number"; + } else if constexpr (std::is_same_v) { + return "list"; + } else if constexpr (std::is_same_v) { + return "string"; + } else if constexpr (std::is_same_v) { + return "map"; + } else if constexpr (std::is_same_v) { + return "node"; + } else if constexpr (std::is_same_v) { + return "relationship"; + } else if constexpr (std::is_same_v) { + return "path"; + } else if constexpr (std::is_same_v) { + return "void"; + } else if constexpr (std::is_same_v) { + return "Date"; + } else if constexpr (std::is_same_v) { + return "LocalTime"; + } else if constexpr (std::is_same_v) { + return "LocalDateTime"; + } else if constexpr (std::is_same_v) { + return "Duration"; + } else { + static_assert(std::is_same_v, "Unknown ArgType"); + } + return ""; +} + +template +struct Or; + +template +struct Or { + template + static bool Check(const TypedValueT &arg) { + return ArgIsType(arg); + } + + static std::string TypeNames() { return ArgTypeName(); } +}; + +template +struct Or { + template + static bool Check(const TypedValueT &arg) { + if (ArgIsType(arg)) return true; + return Or::Check(arg); + } + + static std::string TypeNames() { + if constexpr (sizeof...(ArgTypes) > 1) { + return fmt::format("'{}', {}", ArgTypeName(), Or::TypeNames()); + } else { + return fmt::format("'{}' or '{}'", ArgTypeName(), Or::TypeNames()); + } + } +}; + +template +struct IsOrType { + static constexpr bool value = false; +}; + +template +struct IsOrType> { + static constexpr bool value = true; +}; + +template +struct Optional; + +template +struct Optional { + static constexpr size_t size = 1; + + template + 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::value) { + if (!ArgType::Check(arg)) { + throw FunctionRuntimeException("Optional '{}' argument at position {} must be either {}.", name, pos, + ArgType::TypeNames()); + } + } else { + if (!ArgIsType(arg)) + throw FunctionRuntimeException("Optional '{}' argument at position {} must be '{}'.", name, pos, + ArgTypeName()); + } + } +}; + +template +struct Optional { + static constexpr size_t size = 1 + sizeof...(ArgTypes); + + template + static void Check(const char *name, const TypedValueT *args, int64_t nargs, int64_t pos) { + if (nargs == 0) return; + Optional::Check(name, args, nargs, pos); + Optional::Check(name, args + 1, nargs - 1, pos + 1); + } +}; + +template +struct IsOptional { + static constexpr bool value = false; +}; + +template +struct IsOptional> { + static constexpr bool value = true; +}; + +template +constexpr size_t FTypeRequiredArgs() { + if constexpr (IsOptional::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(); + } +} + +template +constexpr size_t FTypeOptionalArgs() { + if constexpr (IsOptional::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(); + } +} + +template +void FType(const char *name, const TypedValueT *args, int64_t nargs, int64_t pos = 1) { + if constexpr (std::is_same_v) { + if (nargs != 0) { + throw FunctionRuntimeException("'{}' requires no arguments.", name); + } + return; + } + static constexpr int64_t required_args = FTypeRequiredArgs(); + static constexpr int64_t optional_args = FTypeOptionalArgs(); + 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::value) { + if (!ArgType::Check(arg)) { + throw FunctionRuntimeException("'{}' argument at position {} must be either {}.", name, pos, + ArgType::TypeNames()); + } + } else if constexpr (IsOptional::value) { + static_assert(sizeof...(ArgTypes) == 0, "Optional arguments must be last!"); + ArgType::Check(name, args, nargs, pos); + } else { + if (!ArgIsType(arg)) { + throw FunctionRuntimeException("'{}' argument at position {} must be '{}'", name, pos, ArgTypeName()); + } + } + if constexpr (sizeof...(ArgTypes) > 0) { + FType(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 +TypedValueT EndNode(const TypedValueT *args, int64_t nargs, const FunctionContextT &ctx) { + FType>("endNode", args, nargs); + if (args[0].IsNull()) return TypedValueT(ctx.memory); + if constexpr (std::is_same_v) { + 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 +TypedValueT Head(const TypedValueT *args, int64_t nargs, const FunctionContextT &ctx) { + FType>("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 +TypedValueT Last(const TypedValueT *args, int64_t nargs, const FunctionContextT &ctx) { + FType>("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 +TypedValueT Properties(const TypedValueT *args, int64_t nargs, const FunctionContextT &ctx) { + FType>("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) { + 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 +TypedValueT Size(const TypedValueT *args, int64_t nargs, const FunctionContextT &ctx) { + FType>("size", args, nargs); + const auto &value = args[0]; + if (value.IsNull()) { + return TypedValueT(ctx.memory); + } else if (value.IsList()) { + return TypedValueT(static_cast(value.ValueList().size()), ctx.memory); + } else if (value.IsString()) { + return TypedValueT(static_cast(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(value.ValueMap().size()), ctx.memory); + } else { + return TypedValueT(static_cast(value.ValuePath().edges().size()), ctx.memory); + } +} + +template +TypedValueT StartNode(const TypedValueT *args, int64_t nargs, const FunctionContextT &ctx) { + FType>("startNode", args, nargs); + if (args[0].IsNull()) return TypedValueT(ctx.memory); + if constexpr (std::is_same_v) { + 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 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 +TypedValueT Degree(const TypedValueT *args, int64_t nargs, const FunctionContextT &ctx) { + FType>("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) { + 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(out_degree + in_degree), ctx.memory); +} + +template +TypedValueT InDegree(const TypedValueT *args, int64_t nargs, const FunctionContextT &ctx) { + FType>("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) { + in_degree = UnwrapDegreeResult(vertex.InDegree(ctx.view)); + } else { + in_degree = vertex.InDegree(); + } + return TypedValueT(static_cast(in_degree), ctx.memory); +} + +template +TypedValueT OutDegree(const TypedValueT *args, int64_t nargs, const FunctionContextT &ctx) { + FType>("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) { + out_degree = UnwrapDegreeResult(vertex.OutDegree(ctx.view)); + } else { + out_degree = vertex.OutDegree(); + } + return TypedValueT(static_cast(out_degree), ctx.memory); +} + +template +TypedValueT ToBoolean(const TypedValueT *args, int64_t nargs, const FunctionContextT &ctx) { + FType>("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 +TypedValueT ToFloat(const TypedValueT *args, int64_t nargs, const FunctionContextT &ctx) { + FType>("toFloat", args, nargs); + const auto &value = args[0]; + if (value.IsNull()) { + return TypedValueT(ctx.memory); + } else if (value.IsInt()) { + return TypedValueT(static_cast(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 +TypedValueT ToInteger(const TypedValueT *args, int64_t nargs, const FunctionContextT &ctx) { + FType>("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(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(utils::ParseDouble(utils::Trim(value.ValueString()))), ctx.memory); + } catch (const utils::BasicException &) { + return TypedValueT(ctx.memory); + } + } +} + +template +TypedValueT Type(const TypedValueT *args, int64_t nargs, const FunctionContextT &ctx) { + FType>("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 +TypedValueT ValueType(const TypedValueT *args, int64_t nargs, const FunctionContextT &ctx) { + FType>("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 +TypedValueT Keys(const TypedValueT *args, int64_t nargs, const FunctionContextT &ctx) { + FType>("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) { + 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 +TypedValueT Labels(const TypedValueT *args, int64_t nargs, const FunctionContextT &ctx) { + FType>("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) { + 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 +TypedValueT Nodes(const TypedValueT *args, int64_t nargs, const FunctionContextT &ctx) { + FType>("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 +TypedValueT Relationships(const TypedValueT *args, int64_t nargs, const FunctionContextT &ctx) { + FType>("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 +TypedValueT Range(const TypedValueT *args, int64_t nargs, const FunctionContextT &ctx) { + FType, Or, Optional>>("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 +TypedValueT Tail(const TypedValueT *args, int64_t nargs, const FunctionContextT &ctx) { + FType>("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 +TypedValueT UniformSample(const TypedValueT *args, int64_t nargs, const FunctionContextT &ctx) { + FType, Or>("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 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 +TypedValueT Abs(const TypedValueT *args, int64_t nargs, const FunctionContextT &ctx) { + FType>("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 \ + TypedValueT name(const TypedValueT *args, int64_t nargs, const FunctionContextT &ctx) { \ + FType>(#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 +TypedValueT Atan2(const TypedValueT *args, int64_t nargs, const FunctionContextT &ctx) { + FType, Or>("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 +TypedValueT Sign(const TypedValueT *args, int64_t nargs, const FunctionContextT &ctx) { + FType>("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 +TypedValueT E(const TypedValueT *args, int64_t nargs, const FunctionContextT &ctx) { + FType("e", args, nargs); + return TypedValueT(M_E, ctx.memory); +} + +template +TypedValueT Pi(const TypedValueT *args, int64_t nargs, const FunctionContextT &ctx) { + FType("pi", args, nargs); + return TypedValueT(M_PI, ctx.memory); +} + +template +TypedValueT Rand(const TypedValueT *args, int64_t nargs, const FunctionContextT &ctx) { + FType("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 +TypedValueT StringMatchOperator(const TypedValueT *args, int64_t nargs, const FunctionContextT &ctx) { + FType, Or>(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 +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 +inline auto StartsWith = StringMatchOperator, TypedValueT, FunctionContextT>; + +// Check if s1 ends with s2. +template +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 +inline auto EndsWith = StringMatchOperator, TypedValueT, FunctionContextT>; + +// Check if s1 contains s2. +template +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 +inline auto Contains = StringMatchOperator, TypedValueT, FunctionContextT>; + +template +TypedValueT Assert(const TypedValueT *args, int64_t nargs, const FunctionContextT &ctx) { + FType>("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 +TypedValueT Counter(const TypedValueT *args, int64_t nargs, const FunctionContextT &context) { + FType>("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 +TypedValueT Id(const TypedValueT *args, int64_t nargs, const FunctionContextT &ctx) { + FType>("id", args, nargs); + const auto &arg = args[0]; + if (arg.IsNull()) { + return TypedValueT(ctx.memory); + } else if (arg.IsVertex()) { + return TypedValueT(static_cast(arg.ValueVertex().CypherId()), ctx.memory); + } else { + return TypedValueT(static_cast(arg.ValueEdge().CypherId()), ctx.memory); + } +} + +template +TypedValueT ToString(const TypedValueT *args, int64_t nargs, const FunctionContextT &ctx) { + FType>("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 +TypedValueT Timestamp(const TypedValueT *args, int64_t nargs, const FunctionContextT &ctx) { + FType>>("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 +TypedValueT Left(const TypedValueT *args, int64_t nargs, const FunctionContextT &ctx) { + FType, Or>("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 +TypedValueT Right(const TypedValueT *args, int64_t nargs, const FunctionContextT &ctx) { + FType, Or>("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 +TypedValueT CallStringFunction( + const TypedValueT *args, int64_t nargs, utils::MemoryResource *memory, const char *name, + std::function fun) { + FType>(name, args, nargs); + if (args[0].IsNull()) return TypedValueT(memory); + return TypedValueT(fun(args[0].ValueString()), memory); +} + +template +TypedValueT LTrim(const TypedValueT *args, int64_t nargs, const FunctionContextT &ctx) { + return CallStringFunction(args, nargs, ctx.memory, "lTrim", [&](const auto &str) { + return typename TypedValueT::TString(utils::LTrim(str), ctx.memory); + }); +} + +template +TypedValueT RTrim(const TypedValueT *args, int64_t nargs, const FunctionContextT &ctx) { + return CallStringFunction(args, nargs, ctx.memory, "rTrim", [&](const auto &str) { + return typename TypedValueT::TString(utils::RTrim(str), ctx.memory); + }); +} + +template +TypedValueT Trim(const TypedValueT *args, int64_t nargs, const FunctionContextT &ctx) { + return CallStringFunction(args, nargs, ctx.memory, "trim", [&](const auto &str) { + return typename TypedValueT::TString(utils::Trim(str), ctx.memory); + }); +} + +template +TypedValueT Reverse(const TypedValueT *args, int64_t nargs, const FunctionContextT &ctx) { + return CallStringFunction( + args, nargs, ctx.memory, "reverse", [&](const auto &str) { return utils::Reversed(str, ctx.memory); }); +} + +template +TypedValueT ToLower(const TypedValueT *args, int64_t nargs, const FunctionContextT &ctx) { + return CallStringFunction(args, nargs, ctx.memory, "toLower", [&](const auto &str) { + typename TypedValueT::TString res(ctx.memory); + utils::ToLowerCase(&res, str); + return res; + }); +} + +template +TypedValueT ToUpper(const TypedValueT *args, int64_t nargs, const FunctionContextT &ctx) { + return CallStringFunction(args, nargs, ctx.memory, "toUpper", [&](const auto &str) { + typename TypedValueT::TString res(ctx.memory); + utils::ToUpperCase(&res, str); + return res; + }); +} + +template +TypedValueT Replace(const TypedValueT *args, int64_t nargs, const FunctionContextT &ctx) { + FType, Or, Or>("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 +TypedValueT Split(const TypedValueT *args, int64_t nargs, const FunctionContextT &ctx) { + FType, Or>("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 +TypedValueT Substring(const TypedValueT *args, int64_t nargs, const FunctionContextT &ctx) { + FType, NonNegativeInteger, Optional>("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 +TypedValueT ToByteString(const TypedValueT *args, int64_t nargs, const FunctionContextT &ctx) { + FType("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(byte)); + } + return TypedValueT(std::move(bytes)); +} + +template +TypedValueT FromByteString(const TypedValueT *args, int64_t nargs, const FunctionContextT &ctx) { + FType>("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(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('0') + val : static_cast('a') + val - 10U; + return utils::MemcpyCast(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 +concept IsNumberOrInteger = utils::SameAsAnyOf; + +template +void MapNumericParameters(auto ¶meter_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 && value.IsDouble()) { + *it->second = value.ValueDouble(); + } else { + std::string_view error = std::is_same_v ? "an integer." : "a numeric value."; + throw FunctionRuntimeException("Invalid value for key '{}'. Expected {}", key, error); + } + } else { + throw FunctionRuntimeException("Unknown key '{}'.", key); + } + } +} + +template +TypedValueT Date(const TypedValueT *args, int64_t nargs, const FunctionContextT &ctx) { + FType>>("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(parameter_mappings, args[0].ValueMap()); + return TypedValueT(utils::Date(date_parameters), ctx.memory); +} + +template +TypedValueT LocalTime(const TypedValueT *args, int64_t nargs, const FunctionContextT &ctx) { + FType>>("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(parameter_mappings, args[0].ValueMap()); + return TypedValueT(utils::LocalTime(local_time_parameters), ctx.memory); +} + +template +TypedValueT LocalDateTime(const TypedValueT *args, int64_t nargs, const FunctionContextT &ctx) { + FType>>("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(parameter_mappings, args[0].ValueMap()); + return TypedValueT(utils::LocalDateTime(date_parameters, local_time_parameters), ctx.memory); +} + +template +TypedValueT Duration(const TypedValueT *args, int64_t nargs, const FunctionContextT &ctx) { + FType>("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(parameter_mappings, args[0].ValueMap()); + return TypedValueT(utils::Duration(duration_parameters), ctx.memory); +} + +} // namespace memgraph::functions::impl + +namespace memgraph::functions { + +template +std::function +NameToFunction(const std::string &function_name) { + // Scalar functions + if (function_name == "DEGREE") return functions::impl::Degree; + if (function_name == "INDEGREE") return functions::impl::InDegree; + if (function_name == "OUTDEGREE") return functions::impl::OutDegree; + if (function_name == "ENDNODE") return functions::impl::EndNode; + if (function_name == "HEAD") return functions::impl::Head; + if (function_name == kId) return functions::impl::Id; + if (function_name == "LAST") return functions::impl::Last; + if (function_name == "PROPERTIES") return functions::impl::Properties; + if (function_name == "SIZE") return functions::impl::Size; + if (function_name == "STARTNODE") return functions::impl::StartNode; + if (function_name == "TIMESTAMP") return functions::impl::Timestamp; + if (function_name == "TOBOOLEAN") return functions::impl::ToBoolean; + if (function_name == "TOFLOAT") return functions::impl::ToFloat; + if (function_name == "TOINTEGER") return functions::impl::ToInteger; + if (function_name == "TYPE") return functions::impl::Type; + if (function_name == "VALUETYPE") return functions::impl::ValueType; + + // List functions + if (function_name == "KEYS") return functions::impl::Keys; + if (function_name == "LABELS") return functions::impl::Labels; + if (function_name == "NODES") return functions::impl::Nodes; + if (function_name == "RANGE") return functions::impl::Range; + if (function_name == "RELATIONSHIPS") return functions::impl::Relationships; + if (function_name == "TAIL") return functions::impl::Tail; + if (function_name == "UNIFORMSAMPLE") return functions::impl::UniformSample; + + // Mathematical functions - numeric + if (function_name == "ABS") return functions::impl::Abs; + if (function_name == "CEIL") return functions::impl::Ceil; + if (function_name == "FLOOR") return functions::impl::Floor; + if (function_name == "RAND") return functions::impl::Rand; + if (function_name == "ROUND") return functions::impl::Round; + if (function_name == "SIGN") return functions::impl::Sign; + + // Mathematical functions - logarithmic + if (function_name == "E") return functions::impl::E; + if (function_name == "EXP") return functions::impl::Exp; + if (function_name == "LOG") return functions::impl::Log; + if (function_name == "LOG10") return functions::impl::Log10; + if (function_name == "SQRT") return functions::impl::Sqrt; + + // Mathematical functions - trigonometric + if (function_name == "ACOS") return functions::impl::Acos; + if (function_name == "ASIN") return functions::impl::Asin; + if (function_name == "ATAN") return functions::impl::Atan; + if (function_name == "ATAN2") return functions::impl::Atan2; + if (function_name == "COS") return functions::impl::Cos; + if (function_name == "PI") return functions::impl::Pi; + if (function_name == "SIN") return functions::impl::Sin; + if (function_name == "TAN") return functions::impl::Tan; + + // String functions + if (function_name == kContains) return functions::impl::Contains; + if (function_name == kEndsWith) return functions::impl::EndsWith; + if (function_name == "LEFT") return functions::impl::Left; + if (function_name == "LTRIM") return functions::impl::LTrim; + if (function_name == "REPLACE") return functions::impl::Replace; + if (function_name == "REVERSE") return functions::impl::Reverse; + if (function_name == "RIGHT") return functions::impl::Right; + if (function_name == "RTRIM") return functions::impl::RTrim; + if (function_name == "SPLIT") return functions::impl::Split; + if (function_name == kStartsWith) return functions::impl::StartsWith; + if (function_name == "SUBSTRING") return functions::impl::Substring; + if (function_name == "TOLOWER") return functions::impl::ToLower; + if (function_name == "TOSTRING") return functions::impl::ToString; + if (function_name == "TOUPPER") return functions::impl::ToUpper; + if (function_name == "TRIM") return functions::impl::Trim; + + // Memgraph specific functions + if (function_name == "ASSERT") return functions::impl::Assert; + if (function_name == "COUNTER") return functions::impl::Counter; + if (function_name == "TOBYTESTRING") return functions::impl::ToByteString; + if (function_name == "FROMBYTESTRING") return functions::impl::FromByteString; + + // Functions for temporal types + if (function_name == "DATE") return functions::impl::Date; + if (function_name == "LOCALTIME") return functions::impl::LocalTime; + if (function_name == "LOCALDATETIME") return functions::impl::LocalDateTime; + if (function_name == "DURATION") return functions::impl::Duration; + + 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 InDegree(storage::View view) const { return impl_.InDegree(view); } - // - // storage::Result 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 vertices_; + std::vector 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" + const functions::FunctionContext &)>" :scope :public :dont-save t :clone :copy :slk-load (lambda (member) #>cpp - self->${member} = query::v2::NameToFunction(self->function_name_); + self->${member} = functions::NameToFunction, + functions::QueryEngineTag, decltype(ValueToTypedValueFunctor)>(self->function_name_); cpp<#))) (:public #>cpp @@ -865,7 +869,8 @@ cpp<# const std::vector &arguments) : arguments_(arguments), function_name_(function_name), - function_(NameToFunction(function_name_)) { + function_(functions::NameToFunction, + 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 -#include -#include -#include -#include -#include -#include -#include - -#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` 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, 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` check. -// * Two arguments were supplied, the 1st one passes `Or` 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, NonNegativeInteger, -// Optional>("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 -bool ArgIsType(const TypedValue &arg) { - if constexpr (std::is_same_v) { - return arg.IsNull(); - } else if constexpr (std::is_same_v) { - return arg.IsBool(); - } else if constexpr (std::is_same_v) { - return arg.IsInt(); - } else if constexpr (std::is_same_v) { - return arg.IsInt() && arg.ValueInt() > 0; - } else if constexpr (std::is_same_v) { - return arg.IsInt() && arg.ValueInt() != 0; - } else if constexpr (std::is_same_v) { - return arg.IsInt() && arg.ValueInt() >= 0; - } else if constexpr (std::is_same_v) { - return arg.IsDouble(); - } else if constexpr (std::is_same_v) { - return arg.IsNumeric(); - } else if constexpr (std::is_same_v) { - return arg.IsList(); - } else if constexpr (std::is_same_v) { - return arg.IsString(); - } else if constexpr (std::is_same_v) { - return arg.IsMap(); - } else if constexpr (std::is_same_v) { - return arg.IsVertex(); - } else if constexpr (std::is_same_v) { - return arg.IsEdge(); - } else if constexpr (std::is_same_v) { - return arg.IsPath(); - } else if constexpr (std::is_same_v) { - return arg.IsDate(); - } else if constexpr (std::is_same_v) { - return arg.IsLocalTime(); - } else if constexpr (std::is_same_v) { - return arg.IsLocalDateTime(); - } else if constexpr (std::is_same_v) { - return arg.IsDuration(); - } else if constexpr (std::is_same_v) { - return true; - } else { - static_assert(std::is_same_v, "Unknown ArgType"); - } - return false; -} - -template -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) { - return "null"; - } else if constexpr (std::is_same_v) { - return "boolean"; - } else if constexpr (std::is_same_v) { - return "integer"; - } else if constexpr (std::is_same_v) { - return "positive integer"; - } else if constexpr (std::is_same_v) { - return "non-zero integer"; - } else if constexpr (std::is_same_v) { - return "non-negative integer"; - } else if constexpr (std::is_same_v) { - return "float"; - } else if constexpr (std::is_same_v) { - return "number"; - } else if constexpr (std::is_same_v) { - return "list"; - } else if constexpr (std::is_same_v) { - return "string"; - } else if constexpr (std::is_same_v) { - return "map"; - } else if constexpr (std::is_same_v) { - return "node"; - } else if constexpr (std::is_same_v) { - return "relationship"; - } else if constexpr (std::is_same_v) { - return "path"; - } else if constexpr (std::is_same_v) { - return "void"; - } else if constexpr (std::is_same_v) { - return "Date"; - } else if constexpr (std::is_same_v) { - return "LocalTime"; - } else if constexpr (std::is_same_v) { - return "LocalDateTime"; - } else if constexpr (std::is_same_v) { - return "Duration"; - } else { - static_assert(std::is_same_v, "Unknown ArgType"); - } - return ""; -} - -template -struct Or; - -template -struct Or { - static bool Check(const TypedValue &arg) { return ArgIsType(arg); } - - static std::string TypeNames() { return ArgTypeName(); } -}; - -template -struct Or { - static bool Check(const TypedValue &arg) { - if (ArgIsType(arg)) return true; - return Or::Check(arg); - } - - static std::string TypeNames() { - if constexpr (sizeof...(ArgTypes) > 1) { - return fmt::format("'{}', {}", ArgTypeName(), Or::TypeNames()); - } else { - return fmt::format("'{}' or '{}'", ArgTypeName(), Or::TypeNames()); - } - } -}; - -template -struct IsOrType { - static constexpr bool value = false; -}; - -template -struct IsOrType> { - static constexpr bool value = true; -}; - -template -struct Optional; - -template -struct Optional { - 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::value) { - if (!ArgType::Check(arg)) { - throw QueryRuntimeException("Optional '{}' argument at position {} must be either {}.", name, pos, - ArgType::TypeNames()); - } - } else { - if (!ArgIsType(arg)) - throw QueryRuntimeException("Optional '{}' argument at position {} must be '{}'.", name, pos, - ArgTypeName()); - } - } -}; - -template -struct Optional { - 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::Check(name, args, nargs, pos); - Optional::Check(name, args + 1, nargs - 1, pos + 1); - } -}; - -template -struct IsOptional { - static constexpr bool value = false; -}; - -template -struct IsOptional> { - static constexpr bool value = true; -}; - -template -constexpr size_t FTypeRequiredArgs() { - if constexpr (IsOptional::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(); - } -} - -template -constexpr size_t FTypeOptionalArgs() { - if constexpr (IsOptional::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(); - } -} - -template -void FType(const char *name, const TypedValue *args, int64_t nargs, int64_t pos = 1) { - if constexpr (std::is_same_v) { - if (nargs != 0) { - throw QueryRuntimeException("'{}' requires no arguments.", name); - } - return; - } - static constexpr int64_t required_args = FTypeRequiredArgs(); - static constexpr int64_t optional_args = FTypeOptionalArgs(); - 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::value) { - if (!ArgType::Check(arg)) { - throw QueryRuntimeException("'{}' argument at position {} must be either {}.", name, pos, ArgType::TypeNames()); - } - } else if constexpr (IsOptional::value) { - static_assert(sizeof...(ArgTypes) == 0, "Optional arguments must be last!"); - ArgType::Check(name, args, nargs, pos); - } else { - if (!ArgIsType(arg)) { - throw QueryRuntimeException("'{}' argument at position {} must be '{}'", name, pos, ArgTypeName()); - } - } - if constexpr (sizeof...(ArgTypes) > 0) { - FType(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>("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>("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>("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>("size", args, nargs); - const auto &value = args[0]; - if (value.IsNull()) { - return TypedValue(ctx.memory); - } else if (value.IsList()) { - return TypedValue(static_cast(value.ValueList().size()), ctx.memory); - } else if (value.IsString()) { - return TypedValue(static_cast(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(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>("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>("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>("toFloat", args, nargs); - const auto &value = args[0]; - if (value.IsNull()) { - return TypedValue(ctx.memory); - } else if (value.IsInt()) { - return TypedValue(static_cast(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>("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(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(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>("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>("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, Optional>>("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>("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>("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 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>("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>(#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>("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>("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("e", args, nargs); - return TypedValue(M_E, ctx.memory); -} - -TypedValue Pi(const TypedValue *args, int64_t nargs, const FunctionContext &ctx) { - FType("pi", args, nargs); - return TypedValue(M_PI, ctx.memory); -} - -TypedValue Rand(const TypedValue *args, int64_t nargs, const FunctionContext &ctx) { - FType("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 -TypedValue StringMatchOperator(const TypedValue *args, int64_t nargs, const FunctionContext &ctx) { - FType, Or>(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; - -// 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; - -// 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; - -TypedValue Assert(const TypedValue *args, int64_t nargs, const FunctionContext &ctx) { - FType>("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>("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>("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>("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>>("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>("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>("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 fun) { - FType>(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, Or>("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>("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, NonNegativeInteger, Optional>("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("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(byte)); - } - return TypedValue(std::move(bytes)); -} - -TypedValue FromByteString(const TypedValue *args, int64_t nargs, const FunctionContext &ctx) { - FType>("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(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('0') + val : static_cast('a') + val - 10U; - return utils::MemcpyCast(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 -concept IsNumberOrInteger = utils::SameAsAnyOf; - -template -void MapNumericParameters(auto ¶meter_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 && value.IsDouble()) { - *it->second = value.ValueDouble(); - } else { - std::string_view error = std::is_same_v ? "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>>("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(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>>("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(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>>("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(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>("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(parameter_mappings, args[0].ValueMap()); - return TypedValue(utils::Duration(duration_parameters), ctx.memory); -} - -} // namespace - -std::function 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 -#include -#include - -#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 *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 -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(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(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 *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" + const functions::FunctionContext &)>" :scope :public :dont-save t :clone :copy :slk-load (lambda (member) #>cpp + self->${member} = functions::NameToFunction, + functions::StorageEngineTag, Conv>(self->function_name_); cpp<#))) (:public #>cpp Function() = default; + using Conv = decltype(PropertyToTypedValueFunctor); + class SemanticException : public memgraph::utils::BasicException { + using utils::BasicException::BasicException; + }; + DEFVISITABLE(ExpressionVisitor); DEFVISITABLE(ExpressionVisitor); @@ -872,7 +874,13 @@ cpp<# Function(const std::string &function_name, const std::vector &arguments) : arguments_(arguments), - function_name_(function_name) { + function_name_(function_name), + function_(functions::NameToFunction, + 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> 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 +inline const auto PropertyToTypedValueFunctor = + [](const PropertyValue &value) { return PropertyToTypedValue(value); }; + template 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 EdgeAccessor::SetProperty(PropertyId property, const PropertyValue &value) { utils::MemoryTracker::OutOfMemoryExceptionEnabler oom_exception; @@ -179,4 +179,7 @@ Result> 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>>> 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>>> 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 &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 &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 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()); // } // {