Address GH comments

This commit is contained in:
Kostas Kyrimis 2022-11-23 14:51:38 +02:00
parent 9e81fe791c
commit 6d544e4fc0
10 changed files with 76 additions and 4269 deletions

View File

@ -416,8 +416,7 @@ class ExpressionEvaluator : public ExpressionVisitor<TypedValue> {
typename TReturnType = std::enable_if_t<std::is_same_v<TTag, QueryEngineTag>, bool>>
TReturnType HasLabelImpl(const VertexAccessor &vertex, const LabelIx &label_ix, QueryEngineTag /*tag*/) {
auto label = typename VertexAccessor::Label{LabelId::FromUint(label_ix.ix)};
auto has_label = vertex.HasLabel(label);
return has_label;
return vertex.HasLabel(label);
}
TypedValue Visit(LabelsTest &labels_test) override {

View File

@ -1,2 +1 @@
add_library(mg-functions INTERFACE)
target_include_directories(mg-functions INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})

View File

@ -409,21 +409,13 @@ void FType(const char *name, const TypedValueT *args, int64_t nargs, int64_t pos
// TODO: Implement degrees, haversin, radians
// TODO: Implement spatial functions
template <typename TypedValueT, typename FunctionContextT, typename Tag>
template <typename TypedValueT, typename FunctionContextT>
TypedValueT EndNode(const TypedValueT *args, int64_t nargs, const FunctionContextT &ctx) {
FType<TypedValueT, Or<Null, Edge>>("endNode", args, nargs);
if (args[0].IsNull()) return TypedValueT(ctx.memory);
if constexpr (std::is_same_v<Tag, StorageEngineTag>) {
const auto to = args[0].ValueEdge().To();
auto pk = to.primary_key;
auto maybe_vertex_accessor = ctx.db_accessor->FindVertex(pk, ctx.view);
if (!maybe_vertex_accessor) {
throw functions::FunctionRuntimeException("Trying to get properties from a deleted object.");
}
return TypedValueT(*maybe_vertex_accessor, ctx.memory);
} else {
return TypedValueT(args[0].ValueEdge().To(), ctx.memory);
if (args[0].IsNull()) {
return TypedValueT(ctx.memory);
}
return TypedValueT(args[0].ValueEdge().To(), ctx.memory);
}
template <typename TypedValueT, typename FunctionContextT>
@ -450,6 +442,7 @@ TypedValueT Properties(const TypedValueT *args, int64_t nargs, const FunctionCon
auto *dba = ctx.db_accessor;
auto get_properties = [&](const auto &record_accessor) {
typename TypedValueT::TMap properties(ctx.memory);
Conv conv;
if constexpr (std::is_same_v<Tag, StorageEngineTag>) {
auto maybe_props = record_accessor.Properties(ctx.view);
if (maybe_props.HasError()) {
@ -466,11 +459,9 @@ TypedValueT Properties(const TypedValueT *args, int64_t nargs, const FunctionCon
}
}
for (const auto &property : *maybe_props) {
Conv conv;
properties.emplace(dba->PropertyToName(property.first), conv(property.second));
}
} else {
Conv conv;
for (const auto &property : record_accessor.Properties()) {
properties.emplace(utils::pmr::string(dba->PropertyToName(property.first), ctx.memory),
conv(property.second, dba));
@ -510,21 +501,13 @@ TypedValueT Size(const TypedValueT *args, int64_t nargs, const FunctionContextT
return TypedValueT(static_cast<int64_t>(value.ValuePath().edges().size()), ctx.memory);
}
template <typename TypedValueT, typename FunctionContextT, typename Tag, typename Conv>
template <typename TypedValueT, typename FunctionContextT, typename Conv>
TypedValueT StartNode(const TypedValueT *args, int64_t nargs, const FunctionContextT &ctx) {
FType<TypedValueT, Or<Null, Edge>>("startNode", args, nargs);
if (args[0].IsNull()) return TypedValueT(ctx.memory);
if constexpr (std::is_same_v<Tag, StorageEngineTag>) {
const auto to = args[0].ValueEdge().From();
auto pk = to.primary_key;
auto maybe_vertex_accessor = ctx.db_accessor->FindVertex(pk, ctx.view);
if (!maybe_vertex_accessor) {
throw functions::FunctionRuntimeException("Trying to get properties from a deleted object.");
}
return TypedValueT(*maybe_vertex_accessor, ctx.memory);
} else {
return TypedValueT(args[0].ValueEdge().From(), ctx.memory);
if (args[0].IsNull()) {
return TypedValueT(ctx.memory);
}
return TypedValueT(args[0].ValueEdge().From(), ctx.memory);
}
// This is needed because clang-tidy fails to identify the use of this function in the if-constexpr branch
@ -702,49 +685,6 @@ TypedValueT ValueType(const TypedValueT *args, int64_t nargs, const FunctionCont
}
}
// TODO: How is Keys different from Properties function?
template <typename TypedValueT, typename FunctionContextT, typename Tag>
TypedValueT Keys(const TypedValueT *args, int64_t nargs, const FunctionContextT &ctx) {
FType<TypedValueT, Or<Null, Vertex, Edge>>("keys", args, nargs);
auto *dba = ctx.db_accessor;
auto get_keys = [&](const auto &record_accessor) {
typename TypedValueT::TVector keys(ctx.memory);
if constexpr (std::same_as<Tag, StorageEngineTag>) {
auto maybe_props = record_accessor.Properties(ctx.view);
if (maybe_props.HasError()) {
switch (maybe_props.GetError()) {
case storage::v3::Error::DELETED_OBJECT:
throw functions::FunctionRuntimeException("Trying to get keys from a deleted object.");
case storage::v3::Error::NONEXISTENT_OBJECT:
throw functions::FunctionRuntimeException("Trying to get keys from an object that doesn't exist.");
case storage::v3::Error::SERIALIZATION_ERROR:
case storage::v3::Error::VERTEX_HAS_EDGES:
case storage::v3::Error::PROPERTIES_DISABLED:
case storage::v3::Error::VERTEX_ALREADY_INSERTED:
throw functions::FunctionRuntimeException("Unexpected error when getting keys.");
}
}
for (const auto &property : *maybe_props) {
keys.emplace_back(dba->PropertyToName(property.first));
}
} else {
for (const auto &property : record_accessor.Properties()) {
keys.emplace_back(dba->PropertyToName(property.first));
}
}
return TypedValueT(std::move(keys));
};
const auto &value = args[0];
if (value.IsNull()) {
return TypedValueT(ctx.memory);
}
if (value.IsVertex()) {
return get_keys(value.ValueVertex());
}
return get_keys(value.ValueEdge());
}
template <typename TypedValueT, typename FunctionContextT, typename Tag>
TypedValueT Labels(const TypedValueT *args, int64_t nargs, const FunctionContextT &ctx) {
FType<TypedValueT, Or<Null, Vertex>>("labels", args, nargs);
@ -1026,12 +966,9 @@ template <typename TypedValueT, typename FunctionContextT>
TypedValueT Id(const TypedValueT *args, int64_t nargs, const FunctionContextT &ctx) {
FType<TypedValueT, Or<Null, Vertex, Edge>>("id", args, nargs);
const auto &arg = args[0];
if (arg.IsNull()) {
if (arg.IsNull() || arg.IsVertex()) {
return TypedValueT(ctx.memory);
}
if (arg.IsVertex()) {
return TypedValueT(static_cast<int64_t>(arg.ValueVertex().CypherId()), ctx.memory);
}
return TypedValueT(static_cast<int64_t>(arg.ValueEdge().CypherId()), ctx.memory);
}
@ -1382,22 +1319,24 @@ NameToFunction(const std::string &function_name) {
if (function_name == "DEGREE") return functions::impl::Degree<TypedValueT, FunctionContextT, Tag>;
if (function_name == "INDEGREE") return functions::impl::InDegree<TypedValueT, FunctionContextT, Tag>;
if (function_name == "OUTDEGREE") return functions::impl::OutDegree<TypedValueT, FunctionContextT, Tag>;
if (function_name == "ENDNODE") return functions::impl::EndNode<TypedValueT, FunctionContextT, Tag>;
if (function_name == "HEAD") return functions::impl::Head<TypedValueT, FunctionContextT>;
if (function_name == kId) return functions::impl::Id<TypedValueT, FunctionContextT>;
if (function_name == "LAST") return functions::impl::Last<TypedValueT, FunctionContextT>;
if (function_name == "PROPERTIES") return functions::impl::Properties<TypedValueT, FunctionContextT, Tag, Conv>;
if (function_name == "SIZE") return functions::impl::Size<TypedValueT, FunctionContextT>;
if (function_name == "STARTNODE") return functions::impl::StartNode<TypedValueT, FunctionContextT, Tag, Conv>;
if (function_name == "TIMESTAMP") return functions::impl::Timestamp<TypedValueT, FunctionContextT>;
if (function_name == "TOBOOLEAN") return functions::impl::ToBoolean<TypedValueT, FunctionContextT>;
if (function_name == "TOFLOAT") return functions::impl::ToFloat<TypedValueT, FunctionContextT>;
if (function_name == "TOINTEGER") return functions::impl::ToInteger<TypedValueT, FunctionContextT>;
if (function_name == "TYPE") return functions::impl::Type<TypedValueT, FunctionContextT>;
if (function_name == "VALUETYPE") return functions::impl::ValueType<TypedValueT, FunctionContextT>;
// Only on QE
if constexpr (std::is_same_v<Tag, QueryEngineTag>) {
if (function_name == "STARTNODE") return functions::impl::StartNode<TypedValueT, FunctionContextT, Conv>;
if (function_name == "ENDNODE") return functions::impl::EndNode<TypedValueT, FunctionContextT>;
}
// List functions
if (function_name == "KEYS") return functions::impl::Keys<TypedValueT, FunctionContextT, Tag>;
if (function_name == "LABELS") return functions::impl::Labels<TypedValueT, FunctionContextT, Tag>;
if (function_name == "NODES") return functions::impl::Nodes<TypedValueT, FunctionContextT>;
if (function_name == "RANGE") return functions::impl::Range<TypedValueT, FunctionContextT>;
@ -1449,9 +1388,12 @@ NameToFunction(const std::string &function_name) {
// Memgraph specific functions
if (function_name == "ASSERT") return functions::impl::Assert<TypedValueT, FunctionContextT>;
if (function_name == "COUNTER") return functions::impl::Counter<TypedValueT, FunctionContextT>;
if (function_name == "TOBYTESTRING") return functions::impl::ToByteString<TypedValueT, FunctionContextT>;
if (function_name == "FROMBYTESTRING") return functions::impl::FromByteString<TypedValueT, FunctionContextT>;
// Only on QE
if constexpr (std::is_same_v<Tag, QueryEngineTag>) {
if (function_name == "COUNTER") return functions::impl::Counter<TypedValueT, FunctionContextT>;
}
// Functions for temporal types
if (function_name == "DATE") return functions::impl::Date<TypedValueT, FunctionContextT>;
@ -1459,6 +1401,13 @@ NameToFunction(const std::string &function_name) {
if (function_name == "LOCALDATETIME") return functions::impl::LocalDateTime<TypedValueT, FunctionContextT>;
if (function_name == "DURATION") return functions::impl::Duration<TypedValueT, FunctionContextT>;
// Only on QE
if constexpr (std::is_same_v<Tag, QueryEngineTag>) {
if (function_name == "COUNTER") return functions::impl::Counter<TypedValueT, FunctionContextT>;
if (function_name == "STARTNODE") return functions::impl::StartNode<TypedValueT, FunctionContextT, Conv>;
if (function_name == "ENDNODE") return functions::impl::EndNode<TypedValueT, FunctionContextT>;
}
return nullptr;
}

View File

@ -23,10 +23,11 @@ EdgeTypeId EdgeAccessor::EdgeType() const { return edge.type.id; }
const std::vector<std::pair<PropertyId, Value>> &EdgeAccessor::Properties() const { return edge.properties; }
Value EdgeAccessor::GetProperty(const std::string &prop_name) const {
if (!manager_->HasProperty(prop_name)) {
auto maybe_prop = manager_->MaybeNameToProperty(prop_name);
if (!maybe_prop) {
return {};
}
auto prop_id = manager_->NameToProperty(prop_name);
const auto prop_id = *maybe_prop;
auto it = std::find_if(edge.properties.begin(), edge.properties.end(), [&](auto &pr) { return prop_id == pr.first; });
return it->second;
}
@ -35,6 +36,8 @@ const Edge &EdgeAccessor::GetEdge() const { return edge; }
bool EdgeAccessor::IsCycle() const { return edge.src == edge.dst; };
size_t EdgeAccessor::CypherId() const { return edge.id.gid; }
VertexAccessor EdgeAccessor::To() const {
return VertexAccessor(Vertex{edge.dst}, std::vector<std::pair<PropertyId, msgs::Value>>{}, manager_);
}
@ -88,10 +91,11 @@ Value VertexAccessor::GetProperty(PropertyId prop_id) const {
// NOLINTNEXTLINE(readability-convert-member-functions-to-static)
Value VertexAccessor::GetProperty(const std::string &prop_name) const {
if (!manager_->HasProperty(prop_name)) {
auto maybe_prop = manager_->MaybeNameToProperty(prop_name);
if (!maybe_prop) {
return {};
}
return GetProperty(manager_->NameToProperty(prop_name));
return GetProperty(*maybe_prop);
}
msgs::Vertex VertexAccessor::GetVertex() const { return vertex; }

View File

@ -53,12 +53,7 @@ class EdgeAccessor final {
[[nodiscard]] bool IsCycle() const;
// Dummy function
// NOLINTNEXTLINE(readability-convert-member-functions-to-static)
[[nodiscard]] size_t CypherId() const { return 10; }
// bool HasSrcAccessor const { return src == nullptr; }
// bool HasDstAccessor const { return dst == nullptr; }
[[nodiscard]] size_t CypherId() const;
[[nodiscard]] VertexAccessor To() const;
[[nodiscard]] VertexAccessor From() const;
@ -98,44 +93,6 @@ class VertexAccessor final {
[[nodiscard]] msgs::Vertex GetVertex() const;
// Dummy function
// NOLINTNEXTLINE(readability-convert-member-functions-to-static)
[[nodiscard]] size_t CypherId() const { return 10; }
// auto InEdges(storage::View view, const std::vector<storage::EdgeTypeId> &edge_types) const
// -> storage::Result<decltype(iter::imap(MakeEdgeAccessor, *impl_.InEdges(view)))> {
// auto maybe_edges = impl_.InEdges(view, edge_types);
// if (maybe_edges.HasError()) return maybe_edges.GetError();
// return iter::imap(MakeEdgeAccessor, std::move(*maybe_edges));
// }
//
// auto InEdges(storage::View view) const { return InEdges(view, {}); }
//
// auto InEdges(storage::View view, const std::vector<storage::EdgeTypeId> &edge_types, const VertexAccessor &dest)
// const
// -> storage::Result<decltype(iter::imap(MakeEdgeAccessor, *impl_.InEdges(view)))> {
// auto maybe_edges = impl_.InEdges(view, edge_types, &dest.impl_);
// if (maybe_edges.HasError()) return maybe_edges.GetError();
// return iter::imap(MakeEdgeAccessor, std::move(*maybe_edges));
// }
//
// auto OutEdges(storage::View view, const std::vector<storage::EdgeTypeId> &edge_types) const
// -> storage::Result<decltype(iter::imap(MakeEdgeAccessor, *impl_.OutEdges(view)))> {
// auto maybe_edges = impl_.OutEdges(view, edge_types);
// if (maybe_edges.HasError()) return maybe_edges.GetError();
// return iter::imap(MakeEdgeAccessor, std::move(*maybe_edges));
// }
//
// auto OutEdges(storage::View view) const { return OutEdges(view, {}); }
//
// auto OutEdges(storage::View view, const std::vector<storage::EdgeTypeId> &edge_types,
// const VertexAccessor &dest) const
// -> storage::Result<decltype(iter::imap(MakeEdgeAccessor, *impl_.OutEdges(view)))> {
// auto maybe_edges = impl_.OutEdges(view, edge_types, &dest.impl_);
// if (maybe_edges.HasError()) return maybe_edges.GetError();
// return iter::imap(MakeEdgeAccessor, std::move(*maybe_edges));
// }
// NOLINTNEXTLINE(readability-convert-member-functions-to-static)
[[nodiscard]] size_t InDegree() const { return 0; }

View File

@ -25,11 +25,10 @@
namespace memgraph::msgs {
class ShardRequestManagerInterface;
} // namespace memgraph::msgs
} // namespace memgraph::msgs
namespace memgraph::query::v2 {
inline const auto lam = [](const auto &val) { return ValueToTypedValue(val); };
namespace detail {
class Callable {
public:

View File

@ -129,9 +129,9 @@ class ShardRequestManagerInterface {
virtual const std::string &PropertyToName(memgraph::storage::v3::PropertyId prop) const = 0;
virtual const std::string &LabelToName(memgraph::storage::v3::LabelId label) const = 0;
virtual const std::string &EdgeTypeToName(memgraph::storage::v3::EdgeTypeId type) const = 0;
virtual bool HasProperty(const std::string &name) const = 0;
virtual bool HasEdgeType(const std::string &name) const = 0;
virtual bool HasLabel(const std::string &name) const = 0;
virtual std::optional<storage::v3::PropertyId> MaybeNameToProperty(const std::string &name) const = 0;
virtual std::optional<storage::v3::EdgeTypeId> MaybeNameToEdge(const std::string &name) const = 0;
virtual std::optional<storage::v3::LabelId> MaybeNameToLabel(const std::string &name) const = 0;
virtual bool IsPrimaryLabel(LabelId label) const = 0;
virtual bool IsPrimaryKey(LabelId primary_label, PropertyId property) const = 0;
};
@ -356,11 +356,17 @@ class ShardRequestManager : public ShardRequestManagerInterface {
return result_rows;
}
bool HasProperty(const std::string &name) const override { return shards_map_.GetPropertyId(name).has_value(); }
std::optional<storage::v3::PropertyId> MaybeNameToProperty(const std::string &name) const override {
return shards_map_.GetPropertyId(name);
}
bool HasEdgeType(const std::string &name) const override { return shards_map_.GetEdgeTypeId(name).has_value(); }
std::optional<storage::v3::EdgeTypeId> MaybeNameToEdge(const std::string &name) const override {
return shards_map_.GetEdgeTypeId(name);
}
bool HasLabel(const std::string &name) const override { return shards_map_.GetLabelId(name).has_value(); }
std::optional<storage::v3::LabelId> MaybeNameToLabel(const std::string &name) const override {
return shards_map_.GetLabelId(name);
}
private:
enum class PaginatedResponseState { Pending, PartiallyFinished };

View File

@ -19,7 +19,7 @@ import pytest
from common import *
def test_vertex_creation_and_scanall(connection):
def test_awesome_memgraph_functions(connection):
wait_for_shard_manager_to_initialize()
cursor = connection.cursor()

View File

@ -30,15 +30,12 @@
#include "query/v2/frontend/ast/ast.hpp"
#include "query/v2/requests.hpp"
#include "query/v2/shard_request_manager.hpp"
#include "query_v2_query_common.hpp"
#include "storage/v3/property_value.hpp"
#include "storage/v3/storage.hpp"
#include "utils/exceptions.hpp"
#include "utils/string.hpp"
#include "query_v2_query_common.hpp"
//#include "utils/temporal.hpp"
using namespace memgraph::query::v2;
using memgraph::query::v2::test_common::ToIntList;
using testing::ElementsAre;
using testing::UnorderedElementsAre;
@ -67,11 +64,11 @@ using CompoundKey = memgraph::coordinator::PrimaryKey;
using memgraph::expr::ExpressionRuntimeException;
using memgraph::functions::FunctionRuntimeException;
namespace {
namespace memgraph::query::v2::tests {
class MockedShardRequestManager : public memgraph::msgs::ShardRequestManagerInterface {
public:
using VertexAccessor = memgraph::query::v2::accessors::VertexAccessor;
using VertexAccessor = accessors::VertexAccessor;
explicit MockedShardRequestManager(ShardMap shard_map) : shards_map_(std::move(shard_map)) { SetUpNameIdMappers(); }
memgraph::storage::v3::EdgeTypeId NameToEdgeType(const std::string &name) const override {
return shards_map_.GetEdgeTypeId(name).value();
@ -118,11 +115,17 @@ class MockedShardRequestManager : public memgraph::msgs::ShardRequestManagerInte
return edge_types_.IdToName(id.AsUint());
}
bool HasProperty(const std::string &name) const override { return shards_map_.GetPropertyId(name).has_value(); }
std::optional<storage::v3::PropertyId> MaybeNameToProperty(const std::string &name) const override {
return shards_map_.GetPropertyId(name);
}
bool HasEdgeType(const std::string &name) const override { return shards_map_.GetEdgeTypeId(name).has_value(); }
std::optional<storage::v3::EdgeTypeId> MaybeNameToEdge(const std::string &name) const override {
return shards_map_.GetEdgeTypeId(name);
}
bool HasLabel(const std::string &name) const override { return shards_map_.GetLabelId(name).has_value(); }
std::optional<storage::v3::LabelId> MaybeNameToLabel(const std::string &name) const override {
return shards_map_.GetLabelId(name);
}
bool IsPrimaryLabel(LabelId label) const override { return true; }
@ -211,7 +214,7 @@ class ExpressionEvaluatorTest : public ::testing::Test {
protected:
AstStorage storage;
memgraph::utils::MonotonicBufferResource mem{1024};
EvaluationContext ctx{.memory = &mem, .timestamp = memgraph::query::v2::QueryTimestamp()};
EvaluationContext ctx{.memory = &mem, .timestamp = QueryTimestamp()};
SymbolTable symbol_table;
Frame frame{128};
@ -542,20 +545,19 @@ using Value = memgraph::msgs::Value;
using VertexId = memgraph::msgs::VertexId;
using Label = memgraph::msgs::Label;
memgraph::query::v2::accessors::VertexAccessor CreateVertex(std::vector<std::pair<PropertyId, Value>> props,
const memgraph::msgs::ShardRequestManagerInterface *manager,
Label label = {}) {
static size_t id = 0;
return {Vertex{VertexId{label, id++}, {label}}, std::move(props), manager};
accessors::VertexAccessor CreateVertex(std::vector<std::pair<PropertyId, Value>> props,
const memgraph::msgs::ShardRequestManagerInterface *manager, Label label = {}) {
static int64_t id = 0;
return {Vertex{VertexId{label, {memgraph::msgs::Value(id++)}}, {label}}, std::move(props), manager};
}
memgraph::query::v2::accessors::EdgeAccessor CreateEdge(std::vector<std::pair<PropertyId, Value>> props,
const memgraph::msgs::ShardRequestManagerInterface *manager) {
auto edge = Edge{.src = VertexId{{}, 0},
.dst = VertexId{{}, 0},
accessors::EdgeAccessor CreateEdge(std::vector<std::pair<PropertyId, Value>> props,
const memgraph::msgs::ShardRequestManagerInterface *manager) {
auto edge = Edge{.src = VertexId{{}, {}},
.dst = VertexId{{}, {}},
.properties = std::move(props),
.type = EdgeType{manager->NameToEdgeType("edge_type")}};
return memgraph::query::v2::accessors::EdgeAccessor{std::move(edge), manager};
return accessors::EdgeAccessor{std::move(edge), manager};
}
TEST_F(ExpressionEvaluatorTest, VertexAndEdgeIndexing) {
@ -575,8 +577,6 @@ TEST_F(ExpressionEvaluatorTest, VertexAndEdgeIndexing) {
auto value2 = Eval(op2);
EXPECT_EQ(value2.ValueInt(), 43);
}
// TODO(kostasrim) Investigate
// Shall we return null on missing properties? Or shall we throw bad optional access as we do now?
{
// Legal indexing, non-existing key.
@ -1135,16 +1135,6 @@ class ExpressionEvaluatorPropertyLookup : public ExpressionEvaluatorTest {
}
};
// TODO(kostasrim) These will fail because of memory resource not propagating correctly. This should be done as part of
// polishing the allocators.
// TEST_F(ExpressionEvaluatorPropertyLookup, Vertex) {
// auto v1 = CreateVertex({{prop_age.second, memgraph::msgs::Value(static_cast<int64_t>(32))}}, shard_manager.get());
// frame[symbol] = TypedValue(v1);
// EXPECT_EQ(Value(prop_age).ValueInt(), 10);
// EXPECT_TRUE(Value(prop_height).IsNull());
// }
// TEST_F(ExpressionEvaluatorPropertyLookup, Edge) {}
TEST_F(ExpressionEvaluatorPropertyLookup, Null) {
frame[symbol] = TypedValue();
EXPECT_TRUE(Value(prop_age).IsNull());
@ -1266,17 +1256,6 @@ TEST_F(FunctionTest, Size) {
.ValueInt(),
3);
ASSERT_THROW(EvaluateFunction("SIZE", 5), FunctionRuntimeException);
// TODO(kostasrim) Add this when we enable paths on the accessors
// auto v0 = dba.InsertVertex();
// memgraph::query::Path path(v0);
// EXPECT_EQ(EvaluateFunction("SIZE", path).ValueInt(), 0);
// auto v1 = dba.InsertVertex();
// auto edge = dba.InsertEdge(&v0, &v1, dba.NameToEdgeType("type"));
// ASSERT_TRUE(edge.HasValue());
// path.Expand(*edge);
// path.Expand(v1);
// EXPECT_EQ(EvaluateFunction("SIZE", path).ValueInt(), 1);
}
TEST_F(FunctionTest, StartNode) {
@ -1290,11 +1269,6 @@ TEST_F(FunctionTest, StartNode) {
ASSERT_THROW(EvaluateFunction("STARTNODE", 2), FunctionRuntimeException);
}
// TODO(kostasrim) Enable this test once we add degree to the accessors
// TEST_F(FunctionTest, Degree) {}
// TEST_F(FunctionTest, InDegree) {}
// TEST_F(FunctionTest, OutDegree) {}
TEST_F(FunctionTest, ToBoolean) {
ASSERT_THROW(EvaluateFunction("TOBOOLEAN"), FunctionRuntimeException);
ASSERT_TRUE(EvaluateFunction("TOBOOLEAN", TypedValue()).IsNull());
@ -1368,9 +1342,9 @@ TEST_F(FunctionTest, Labels) {
Label label{shard_manager->NameToLabel("label1")};
auto v = CreateVertex({}, shard_manager.get(), std::move(label));
std::vector<std::string> labels;
auto _labels = EvaluateFunction("LABELS", v).ValueList();
labels.reserve(_labels.size());
for (auto label : _labels) {
auto evaluated_labels = EvaluateFunction("LABELS", v).ValueList();
labels.reserve(evaluated_labels.size());
for (auto label : evaluated_labels) {
labels.emplace_back(label.ValueString());
}
ASSERT_THAT(labels, UnorderedElementsAre("label1"));
@ -1396,27 +1370,6 @@ TEST_F(FunctionTest, Range) {
EXPECT_THAT(ToIntList(EvaluateFunction("RANGE", -2, 4, -1)), ElementsAre());
}
TEST_F(FunctionTest, Keys) {
ASSERT_THROW(EvaluateFunction("KEYS"), FunctionRuntimeException);
ASSERT_TRUE(EvaluateFunction("KEYS", TypedValue()).IsNull());
const auto height = shard_manager->NameToProperty("height");
const auto age = shard_manager->NameToProperty("age");
auto v1 = CreateVertex({{height, Value(static_cast<int64_t>(5))}, {age, Value(static_cast<int64_t>(10))}},
shard_manager.get());
auto edge = CreateEdge({{height, Value(static_cast<int64_t>(3))}, {age, Value(static_cast<int64_t>(15))}},
shard_manager.get());
auto prop_keys_to_string = [](TypedValue t) {
std::vector<std::string> keys;
for (auto property : t.ValueList()) {
keys.emplace_back(property.ValueString());
}
return keys;
};
ASSERT_THAT(prop_keys_to_string(EvaluateFunction("KEYS", v1)), UnorderedElementsAre("height", "age"));
ASSERT_THAT(prop_keys_to_string(EvaluateFunction("KEYS", edge)), UnorderedElementsAre("height", "age"));
ASSERT_THROW(EvaluateFunction("KEYS", 2), FunctionRuntimeException);
}
TEST_F(FunctionTest, Tail) {
ASSERT_THROW(EvaluateFunction("TAIL"), FunctionRuntimeException);
ASSERT_TRUE(EvaluateFunction("TAIL", TypedValue()).IsNull());
@ -1606,18 +1559,6 @@ TEST_F(FunctionTest, Counter) {
EXPECT_THROW(EvaluateFunction("COUNTER", "c6", 0, 0), FunctionRuntimeException);
}
// TODO(kostasrim) Add this once we fix accessors CypherId() functions
// TEST_F(FunctionTest, Id) {
// auto v = CreateVertex({}, shard_manager.get());
// auto e = CreateEdge({}, shard_manager.get());
// EXPECT_TRUE(EvaluateFunction("ID", TypedValue()).IsNull());
// EXPECT_EQ(EvaluateFunction("ID", v).ValueInt(), 0);
// EXPECT_EQ(EvaluateFunction("ID", e).ValueInt(), 0);
// EXPECT_THROW(EvaluateFunction("ID"), FunctionRuntimeException);
// EXPECT_THROW(EvaluateFunction("ID", 0), FunctionRuntimeException);
// EXPECT_THROW(EvaluateFunction("ID", v, e), FunctionRuntimeException);
//}
TEST_F(FunctionTest, ToStringNull) { EXPECT_TRUE(EvaluateFunction("TOSTRING", TypedValue()).IsNull()); }
TEST_F(FunctionTest, ToStringString) {
@ -1782,5 +1723,4 @@ TEST_F(FunctionTest, FromByteString) {
EXPECT_EQ(EvaluateFunction("FROMBYTESTRING", std::string("\x00\x42", 2)).ValueString(), "0x0042");
}
// TODO(kostasrim) Add temporal type tests.
} // namespace
} // namespace memgraph::query::v2::tests

File diff suppressed because it is too large Load Diff