Address GH comments
This commit is contained in:
parent
9e81fe791c
commit
6d544e4fc0
@ -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 {
|
||||
|
@ -1,2 +1 @@
|
||||
add_library(mg-functions INTERFACE)
|
||||
target_include_directories(mg-functions INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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; }
|
||||
|
@ -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; }
|
||||
|
||||
|
@ -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:
|
||||
|
@ -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 };
|
||||
|
@ -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()
|
||||
|
||||
|
@ -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
Loading…
Reference in New Issue
Block a user