Merge branch 'project-pineapples' of github.com:memgraph/memgraph into tyler_rename_ShardRequestManager_to_RequestRouter
This commit is contained in:
commit
9f10c3ea06
2
.github/workflows/diff.yaml
vendored
2
.github/workflows/diff.yaml
vendored
@ -99,7 +99,7 @@ jobs:
|
||||
echo ${file}
|
||||
if [[ ${file} == *.py ]]; then
|
||||
python3 -m black --check --diff ${file}
|
||||
python3 -m isort --check-only --diff ${file}
|
||||
python3 -m isort --check-only --profile "black" --diff ${file}
|
||||
fi
|
||||
done
|
||||
|
||||
|
@ -14,6 +14,7 @@ repos:
|
||||
hooks:
|
||||
- id: isort
|
||||
name: isort (python)
|
||||
args: ["--profile", "black"]
|
||||
- repo: https://github.com/pre-commit/mirrors-clang-format
|
||||
rev: v13.0.0
|
||||
hooks:
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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 {
|
||||
@ -427,8 +428,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 {
|
||||
@ -491,7 +491,7 @@ class ExpressionEvaluator : public ExpressionVisitor<TypedValue> {
|
||||
}
|
||||
|
||||
TypedValue Visit(Function &function) override {
|
||||
FunctionContext function_ctx{dba_, ctx_->memory, ctx_->timestamp, &ctx_->counters, view_};
|
||||
functions::FunctionContext<DbAccessor> function_ctx{dba_, ctx_->memory, ctx_->timestamp, &ctx_->counters, view_};
|
||||
// Stack allocate evaluated arguments when there's a small number of them.
|
||||
if (function.arguments_.size() <= 8) {
|
||||
TypedValue arguments[8] = {TypedValue(ctx_->memory), TypedValue(ctx_->memory), TypedValue(ctx_->memory),
|
||||
|
1
src/functions/CMakeLists.txt
Normal file
1
src/functions/CMakeLists.txt
Normal file
@ -0,0 +1 @@
|
||||
add_library(mg-functions INTERFACE)
|
1423
src/functions/awesome_memgraph_functions.hpp
Normal file
1423
src/functions/awesome_memgraph_functions.hpp
Normal file
File diff suppressed because it is too large
Load Diff
@ -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}")
|
||||
|
@ -23,11 +23,12 @@ EdgeTypeId EdgeAccessor::EdgeType() const { return edge.type.id; }
|
||||
const std::vector<std::pair<PropertyId, Value>> &EdgeAccessor::Properties() const { return edge.properties; }
|
||||
|
||||
Value EdgeAccessor::GetProperty(const std::string &prop_name) const {
|
||||
auto prop_id = request_router_->NameToProperty(prop_name);
|
||||
auto it = std::find_if(edge.properties.begin(), edge.properties.end(), [&](auto &pr) { return prop_id == pr.first; });
|
||||
if (it == edge.properties.end()) {
|
||||
auto maybe_prop = request_router_->MaybeNameToProperty(prop_name);
|
||||
if (!maybe_prop) {
|
||||
return {};
|
||||
}
|
||||
const auto prop_id = *maybe_prop;
|
||||
auto it = std::find_if(edge.properties.begin(), edge.properties.end(), [&](auto &pr) { return prop_id == pr.first; });
|
||||
return it->second;
|
||||
}
|
||||
|
||||
@ -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>>{}, request_router_);
|
||||
}
|
||||
@ -88,7 +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 {
|
||||
return GetProperty(request_router_->NameToProperty(prop_name));
|
||||
auto maybe_prop = request_router_->MaybeNameToProperty(prop_name);
|
||||
if (!maybe_prop) {
|
||||
return {};
|
||||
}
|
||||
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,48 +93,11 @@ class VertexAccessor final {
|
||||
|
||||
[[nodiscard]] msgs::Vertex GetVertex() const;
|
||||
|
||||
// Dummy function
|
||||
// NOLINTNEXTLINE(readability-convert-member-functions-to-static)
|
||||
[[nodiscard]] size_t CypherId() const { return 10; }
|
||||
[[nodiscard]] size_t InDegree() const { throw utils::NotYetImplemented("InDegree() not yet implemented"); }
|
||||
|
||||
// auto InEdges(storage::View view, const std::vector<storage::EdgeTypeId> &edge_types) const
|
||||
// -> 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));
|
||||
// }
|
||||
|
||||
// storage::Result<size_t> InDegree(storage::View view) const { return impl_.InDegree(view); }
|
||||
//
|
||||
// storage::Result<size_t> OutDegree(storage::View view) const { return impl_.OutDegree(view); }
|
||||
//
|
||||
// NOLINTNEXTLINE(readability-convert-member-functions-to-static)
|
||||
[[nodiscard]] size_t OutDegree() const { throw utils::NotYetImplemented("OutDegree() not yet implemented"); }
|
||||
|
||||
friend bool operator==(const VertexAccessor &lhs, const VertexAccessor &rhs) {
|
||||
return lhs.vertex == rhs.vertex && lhs.properties == rhs.properties;
|
||||
@ -153,10 +111,6 @@ class VertexAccessor final {
|
||||
const RequestRouterInterface *request_router_;
|
||||
};
|
||||
|
||||
// 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 +151,14 @@ class Path {
|
||||
friend bool operator==(const Path & /*lhs*/, const Path & /*rhs*/) { return true; };
|
||||
utils::MemoryResource *GetMemoryResource() { return mem; }
|
||||
|
||||
auto &vertices() { return vertices_; }
|
||||
auto &edges() { return edges_; }
|
||||
const auto &vertices() const { return vertices_; }
|
||||
const auto &edges() const { return edges_; }
|
||||
|
||||
private:
|
||||
std::vector<VertexAccessor> vertices_;
|
||||
std::vector<EdgeAccessor> edges_;
|
||||
utils::MemoryResource *mem = utils::NewDeleteResource();
|
||||
};
|
||||
} // namespace memgraph::query::v2::accessors
|
||||
|
@ -28,7 +28,6 @@ namespace memgraph::query::v2 {
|
||||
|
||||
class RequestRouterInterface;
|
||||
|
||||
inline const auto lam = [](const auto &val) { return ValueToTypedValue(val); };
|
||||
namespace detail {
|
||||
class Callable {
|
||||
public:
|
||||
|
@ -56,6 +56,10 @@ inline TypedValue ValueToTypedValue(const msgs::Value &value, RequestRouterInter
|
||||
throw std::runtime_error("Incorrect type in conversion");
|
||||
}
|
||||
|
||||
inline const auto ValueToTypedValueFunctor = [](const msgs::Value &value, RequestRouterInterface *request_router) {
|
||||
return ValueToTypedValue(value, request_router);
|
||||
};
|
||||
|
||||
inline msgs::Value TypedValueToValue(const TypedValue &value) {
|
||||
using Value = msgs::Value;
|
||||
switch (value.type()) {
|
||||
|
@ -20,11 +20,13 @@
|
||||
#include "query/v2/bindings/ast_visitor.hpp"
|
||||
#include "common/types.hpp"
|
||||
#include "query/v2/bindings/symbol.hpp"
|
||||
#include "query/v2/interpret/awesome_memgraph_functions.hpp"
|
||||
#include "functions/awesome_memgraph_functions.hpp"
|
||||
#include "query/v2/bindings/typed_value.hpp"
|
||||
#include "query/v2/db_accessor.hpp"
|
||||
#include "query/v2/path.hpp"
|
||||
#include "query/v2/shard_request_manager.hpp"
|
||||
#include "utils/typeinfo.hpp"
|
||||
#include "query/v2/conversions.hpp"
|
||||
|
||||
cpp<#
|
||||
|
||||
@ -836,13 +838,15 @@ cpp<#
|
||||
:slk-load (slk-load-ast-vector "Expression"))
|
||||
(function-name "std::string" :scope :public)
|
||||
(function "std::function<TypedValue(const TypedValue *, int64_t,
|
||||
const FunctionContext &)>"
|
||||
const functions::FunctionContext<ShardRequestManagerInterface> &)>"
|
||||
:scope :public
|
||||
:dont-save t
|
||||
:clone :copy
|
||||
:slk-load (lambda (member)
|
||||
#>cpp
|
||||
self->${member} = query::v2::NameToFunction(self->function_name_);
|
||||
self->${member} = functions::NameToFunction<TypedValue,
|
||||
functions::FunctionContext<ShardRequestManagerInterface>,
|
||||
functions::QueryEngineTag, decltype(ValueToTypedValueFunctor)>(self->function_name_);
|
||||
cpp<#)))
|
||||
(:public
|
||||
#>cpp
|
||||
@ -865,7 +869,8 @@ cpp<#
|
||||
const std::vector<Expression *> &arguments)
|
||||
: arguments_(arguments),
|
||||
function_name_(function_name),
|
||||
function_(NameToFunction(function_name_)) {
|
||||
function_(functions::NameToFunction<TypedValue, functions::FunctionContext<ShardRequestManagerInterface>,
|
||||
functions::QueryEngineTag, decltype(ValueToTypedValueFunctor)>(function_name_)) {
|
||||
if (!function_) {
|
||||
throw SemanticException("Function '{}' doesn't exist.", function_name);
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -398,7 +398,7 @@ void Filters::AnalyzeAndStoreFilter(Expression *expr, const SymbolTable &symbol_
|
||||
auto add_id_equal = [&](auto *maybe_id_fun, auto *val_expr) -> bool {
|
||||
auto *id_fun = utils::Downcast<Function>(maybe_id_fun);
|
||||
if (!id_fun) return false;
|
||||
if (id_fun->function_name_ != kId) return false;
|
||||
if (id_fun->function_name_ != functions::kId) return false;
|
||||
if (id_fun->arguments_.size() != 1U) return false;
|
||||
auto *ident = utils::Downcast<Identifier>(id_fun->arguments_.front());
|
||||
if (!ident) return false;
|
||||
|
@ -125,9 +125,12 @@ class RequestRouterInterface {
|
||||
virtual storage::v3::EdgeTypeId NameToEdgeType(const std::string &name) const = 0;
|
||||
virtual storage::v3::PropertyId NameToProperty(const std::string &name) const = 0;
|
||||
virtual storage::v3::LabelId NameToLabel(const std::string &name) const = 0;
|
||||
virtual const std::string &PropertyToName(storage::v3::PropertyId prop) const = 0;
|
||||
virtual const std::string &LabelToName(storage::v3::LabelId label) const = 0;
|
||||
virtual const std::string &EdgeTypeToName(storage::v3::EdgeTypeId type) const = 0;
|
||||
virtual 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 std::optional<storage::v3::PropertyId> MaybeNameToProperty(const std::string &name) const = 0;
|
||||
virtual std::optional<storage::v3::EdgeTypeId> MaybeNameToEdgeType(const std::string &name) const = 0;
|
||||
virtual std::optional<storage::v3::LabelId> MaybeNameToLabel(const std::string &name) const = 0;
|
||||
virtual bool IsPrimaryLabel(storage::v3::LabelId label) const = 0;
|
||||
virtual bool IsPrimaryKey(storage::v3::LabelId primary_label, storage::v3::PropertyId property) const = 0;
|
||||
};
|
||||
@ -351,6 +354,18 @@ class RequestRouter : public RequestRouterInterface {
|
||||
return result_rows;
|
||||
}
|
||||
|
||||
std::optional<storage::v3::PropertyId> MaybeNameToProperty(const std::string &name) const override {
|
||||
return shards_map_.GetPropertyId(name);
|
||||
}
|
||||
|
||||
std::optional<storage::v3::EdgeTypeId> MaybeNameToEdgeType(const std::string &name) const override {
|
||||
return shards_map_.GetEdgeTypeId(name);
|
||||
}
|
||||
|
||||
std::optional<storage::v3::LabelId> MaybeNameToLabel(const std::string &name) const override {
|
||||
return shards_map_.GetLabelId(name);
|
||||
}
|
||||
|
||||
private:
|
||||
enum class PaginatedResponseState { Pending, PartiallyFinished };
|
||||
|
||||
|
@ -31,4 +31,4 @@ target_link_libraries(mg-storage-v3 Threads::Threads mg-utils gflags)
|
||||
target_include_directories(mg-storage-v3 PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/bindings)
|
||||
|
||||
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)
|
||||
|
@ -24,6 +24,8 @@
|
||||
#include "storage/v3/conversions.hpp"
|
||||
#include "storage/v3/path.hpp"
|
||||
#include "utils/typeinfo.hpp"
|
||||
#include "utils/exceptions.hpp"
|
||||
#include "functions/awesome_memgraph_functions.hpp"
|
||||
|
||||
cpp<#
|
||||
|
||||
@ -178,14 +180,6 @@ cpp<#
|
||||
(:serialize (:slk :load-args '((storage "storage::v3::AstStorage *")))))
|
||||
|
||||
#>cpp
|
||||
struct FunctionContext {
|
||||
DbAccessor *db_accessor;
|
||||
utils::MemoryResource *memory;
|
||||
int64_t timestamp;
|
||||
std::unordered_map<std::string, int64_t> *counters;
|
||||
View view;
|
||||
};
|
||||
|
||||
inline bool operator==(const LabelIx &a, const LabelIx &b) {
|
||||
return a.ix == b.ix && a.name == b.name;
|
||||
}
|
||||
@ -845,16 +839,24 @@ cpp<#
|
||||
:slk-load (slk-load-ast-vector "Expression"))
|
||||
(function-name "std::string" :scope :public)
|
||||
(function "std::function<TypedValue(const TypedValue *, int64_t,
|
||||
const FunctionContext &)>"
|
||||
const functions::FunctionContext<memgraph::storage::v3::DbAccessor> &)>"
|
||||
:scope :public
|
||||
:dont-save t
|
||||
:clone :copy
|
||||
:slk-load (lambda (member)
|
||||
#>cpp
|
||||
self->${member} = functions::NameToFunction<memgraph::storage::v3::TypedValue,
|
||||
functions::FunctionContext<memgraph::storage::v3::DbAccessor>,
|
||||
functions::StorageEngineTag, Conv>(self->function_name_);
|
||||
cpp<#)))
|
||||
(:public
|
||||
#>cpp
|
||||
Function() = default;
|
||||
using Conv = decltype(PropertyToTypedValueFunctor<TypedValue>);
|
||||
class SemanticException : public memgraph::utils::BasicException {
|
||||
using utils::BasicException::BasicException;
|
||||
};
|
||||
|
||||
|
||||
DEFVISITABLE(ExpressionVisitor<TypedValue>);
|
||||
DEFVISITABLE(ExpressionVisitor<void>);
|
||||
@ -872,7 +874,13 @@ cpp<#
|
||||
Function(const std::string &function_name,
|
||||
const std::vector<Expression *> &arguments)
|
||||
: arguments_(arguments),
|
||||
function_name_(function_name) {
|
||||
function_name_(function_name),
|
||||
function_(functions::NameToFunction<memgraph::storage::v3::TypedValue,
|
||||
functions::FunctionContext<memgraph::storage::v3::DbAccessor>,
|
||||
functions::StorageEngineTag, Conv>(function_name_)) {
|
||||
if (!function_) {
|
||||
throw SemanticException("Function '{}' doesn't exist.", function_name);
|
||||
}
|
||||
}
|
||||
cpp<#)
|
||||
(:private
|
||||
|
@ -88,7 +88,7 @@ class DbAccessor final {
|
||||
}
|
||||
|
||||
storage::v3::ShardResult<std::optional<EdgeAccessor>> RemoveEdge(EdgeAccessor *edge) {
|
||||
auto res = accessor_->DeleteEdge(edge->FromVertex(), edge->ToVertex(), edge->Gid());
|
||||
auto res = accessor_->DeleteEdge(edge->From(), edge->To(), edge->Gid());
|
||||
if (res.HasError()) {
|
||||
return res.GetError();
|
||||
}
|
||||
|
@ -69,6 +69,10 @@ TTypedValue PropertyToTypedValue(const PropertyValue &value) {
|
||||
LOG_FATAL("Unsupported type");
|
||||
}
|
||||
|
||||
template <typename TypedValueT>
|
||||
inline const auto PropertyToTypedValueFunctor =
|
||||
[](const PropertyValue &value) { return PropertyToTypedValue<TypedValueT>(value); };
|
||||
|
||||
template <typename TTypedValue>
|
||||
TTypedValue PropertyToTypedValue(const PropertyValue &value, utils::MemoryResource *mem) {
|
||||
switch (value.type()) {
|
||||
|
@ -51,9 +51,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_; }
|
||||
|
||||
ShardResult<PropertyValue> EdgeAccessor::SetProperty(PropertyId property, const PropertyValue &value) {
|
||||
utils::MemoryTracker::OutOfMemoryExceptionEnabler oom_exception;
|
||||
@ -180,4 +180,7 @@ ShardResult<std::map<PropertyId, PropertyValue>> EdgeAccessor::Properties(View v
|
||||
return std::move(properties);
|
||||
}
|
||||
|
||||
// NOLINTNEXTLINE(readability-convert-member-functions-to-static)
|
||||
size_t EdgeAccessor::CypherId() const { return Gid().AsUint(); }
|
||||
|
||||
} // namespace memgraph::storage::v3
|
||||
|
@ -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_;
|
||||
|
@ -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);
|
||||
|
||||
|
@ -257,7 +257,7 @@ EdgeUniquenessFunction InitializeEdgeUniquenessFunction(bool only_unique_neighbo
|
||||
case msgs::EdgeDirection::OUT: {
|
||||
is_edge_unique = [](std::set<const storage::v3::VertexId *, VertexIdCmpr> &other_vertex_set,
|
||||
const storage::v3::EdgeAccessor &edge_acc) {
|
||||
auto [it, insertion_happened] = other_vertex_set.insert(&edge_acc.ToVertex());
|
||||
auto [it, insertion_happened] = other_vertex_set.insert(&edge_acc.To());
|
||||
return insertion_happened;
|
||||
};
|
||||
break;
|
||||
@ -265,7 +265,7 @@ EdgeUniquenessFunction InitializeEdgeUniquenessFunction(bool only_unique_neighbo
|
||||
case msgs::EdgeDirection::IN: {
|
||||
is_edge_unique = [](std::set<const storage::v3::VertexId *, VertexIdCmpr> &other_vertex_set,
|
||||
const storage::v3::EdgeAccessor &edge_acc) {
|
||||
auto [it, insertion_happened] = other_vertex_set.insert(&edge_acc.FromVertex());
|
||||
auto [it, insertion_happened] = other_vertex_set.insert(&edge_acc.From());
|
||||
return insertion_happened;
|
||||
};
|
||||
break;
|
||||
@ -311,8 +311,8 @@ EdgeFiller InitializeEdgeFillerFunction(const msgs::ExpandOneRequest &req) {
|
||||
value_properties.insert(std::make_pair(prop_key, FromPropertyValueToValue(std::move(prop_val))));
|
||||
}
|
||||
using EdgeWithAllProperties = msgs::ExpandOneResultRow::EdgeWithAllProperties;
|
||||
EdgeWithAllProperties edges{ToMsgsVertexId(edge.FromVertex()), msgs::EdgeType{edge.EdgeType()},
|
||||
edge.Gid().AsUint(), std::move(value_properties)};
|
||||
EdgeWithAllProperties edges{ToMsgsVertexId(edge.From()), msgs::EdgeType{edge.EdgeType()}, edge.Gid().AsUint(),
|
||||
std::move(value_properties)};
|
||||
if (is_in_edge) {
|
||||
result_row.in_edges_with_all_properties.push_back(std::move(edges));
|
||||
} else {
|
||||
@ -336,7 +336,7 @@ EdgeFiller InitializeEdgeFillerFunction(const msgs::ExpandOneRequest &req) {
|
||||
value_properties.emplace_back(FromPropertyValueToValue(std::move(property_result.GetValue())));
|
||||
}
|
||||
using EdgeWithSpecificProperties = msgs::ExpandOneResultRow::EdgeWithSpecificProperties;
|
||||
EdgeWithSpecificProperties edges{ToMsgsVertexId(edge.FromVertex()), msgs::EdgeType{edge.EdgeType()},
|
||||
EdgeWithSpecificProperties edges{ToMsgsVertexId(edge.From()), msgs::EdgeType{edge.EdgeType()},
|
||||
edge.Gid().AsUint(), std::move(value_properties)};
|
||||
if (is_in_edge) {
|
||||
result_row.in_edges_with_specific_properties.push_back(std::move(edges));
|
||||
|
@ -442,7 +442,7 @@ ShardResult<std::optional<std::pair<VertexAccessor, std::vector<EdgeAccessor>>>>
|
||||
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() == common::ErrorCode::SERIALIZATION_ERROR, "Invalid database state!");
|
||||
return ret.GetError();
|
||||
@ -455,7 +455,7 @@ ShardResult<std::optional<std::pair<VertexAccessor, std::vector<EdgeAccessor>>>>
|
||||
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() == common::ErrorCode::SERIALIZATION_ERROR, "Invalid database state!");
|
||||
return ret.GetError();
|
||||
|
@ -9,3 +9,4 @@ distributed_queries_e2e_python_files(order_by_and_limit.py)
|
||||
distributed_queries_e2e_python_files(distinct.py)
|
||||
distributed_queries_e2e_python_files(optional_match.py)
|
||||
distributed_queries_e2e_python_files(common.py)
|
||||
distributed_queries_e2e_python_files(awesome_memgraph_functions.py)
|
||||
|
93
tests/e2e/distributed_queries/awesome_memgraph_functions.py
Normal file
93
tests/e2e/distributed_queries/awesome_memgraph_functions.py
Normal file
@ -0,0 +1,93 @@
|
||||
# Copyright 2022 Memgraph Ltd.
|
||||
#
|
||||
# Use of this software is governed by the Business Source License
|
||||
# included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
|
||||
# License, and you may not use this file except in compliance with the Business Source License.
|
||||
#
|
||||
# As of the Change Date specified in that file, in accordance with
|
||||
# the Business Source License, use of this software will be governed
|
||||
# by the Apache License, Version 2.0, included in the file
|
||||
# licenses/APL.txt.
|
||||
|
||||
import sys
|
||||
|
||||
import mgclient
|
||||
import pytest
|
||||
|
||||
from common import (
|
||||
connection,
|
||||
execute_and_fetch_all,
|
||||
has_n_result_row,
|
||||
wait_for_shard_manager_to_initialize,
|
||||
)
|
||||
|
||||
|
||||
def test_awesome_memgraph_functions(connection):
|
||||
wait_for_shard_manager_to_initialize()
|
||||
cursor = connection.cursor()
|
||||
|
||||
assert has_n_result_row(cursor, "CREATE (n :label {property:1})", 0)
|
||||
assert has_n_result_row(cursor, "CREATE (n :label {property:2})", 0)
|
||||
assert has_n_result_row(cursor, "CREATE (n :label {property:3})", 0)
|
||||
assert has_n_result_row(cursor, "CREATE (n :label {property:4})", 0)
|
||||
assert has_n_result_row(cursor, "CREATE (n :label {property:10})", 0)
|
||||
|
||||
results = execute_and_fetch_all(cursor, "MATCH (n) WITH COLLECT(n) as nn RETURN SIZE(nn)")
|
||||
assert len(results) == 1
|
||||
assert results[0][0] == 5
|
||||
|
||||
results = execute_and_fetch_all(cursor, "MATCH (n) WITH COLLECT(n.property) as nn RETURN ALL(i IN nn WHERE i > 0)")
|
||||
assert len(results) == 1
|
||||
assert results[0][0] == True
|
||||
|
||||
results = execute_and_fetch_all(cursor, """RETURN CONTAINS("Pineapple", "P")""")
|
||||
assert len(results) == 1
|
||||
assert results[0][0] == True
|
||||
|
||||
results = execute_and_fetch_all(cursor, """RETURN ENDSWITH("Pineapple", "e")""")
|
||||
assert len(results) == 1
|
||||
assert results[0][0] == True
|
||||
|
||||
results = execute_and_fetch_all(cursor, """RETURN LEFT("Pineapple", 1)""")
|
||||
assert len(results) == 1
|
||||
assert results[0][0] == "P"
|
||||
|
||||
results = execute_and_fetch_all(cursor, """RETURN RIGHT("Pineapple", 1)""")
|
||||
assert len(results) == 1
|
||||
assert results[0][0] == "e"
|
||||
|
||||
results = execute_and_fetch_all(cursor, """RETURN REVERSE("Apple")""")
|
||||
assert len(results) == 1
|
||||
assert results[0][0] == "elppA"
|
||||
|
||||
results = execute_and_fetch_all(cursor, """RETURN REPLACE("Apple", "A", "a")""")
|
||||
assert len(results) == 1
|
||||
assert results[0][0] == "apple"
|
||||
|
||||
results = execute_and_fetch_all(cursor, """RETURN TOLOWER("Apple")""")
|
||||
assert len(results) == 1
|
||||
assert results[0][0] == "apple"
|
||||
|
||||
results = execute_and_fetch_all(cursor, """RETURN TOUPPER("Apple")""")
|
||||
assert len(results) == 1
|
||||
assert results[0][0] == "APPLE"
|
||||
|
||||
results = execute_and_fetch_all(cursor, """RETURN TRIM(" Apple")""")
|
||||
assert len(results) == 1
|
||||
assert results[0][0] == "Apple"
|
||||
|
||||
results = execute_and_fetch_all(cursor, """RETURN SPLIT("Apple.Apple", ".")""")
|
||||
assert len(results) == 1
|
||||
assert results[0][0] == ["Apple", "Apple"]
|
||||
|
||||
results = execute_and_fetch_all(cursor, """RETURN LOG10(100)""")
|
||||
assert len(results) == 1
|
||||
assert results[0][0] == 2
|
||||
|
||||
results = execute_and_fetch_all(cursor, """RETURN SQRT(4)""")
|
||||
assert len(results) == 1
|
||||
assert results[0][0] == 2
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(pytest.main([__file__, "-rA"]))
|
@ -36,3 +36,8 @@ workloads:
|
||||
binary: "tests/e2e/pytest_runner.sh"
|
||||
args: ["distributed_queries/optional_match.py"]
|
||||
<<: *template_cluster
|
||||
|
||||
- name: "Awesome memgraph functions"
|
||||
binary: "tests/e2e/pytest_runner.sh"
|
||||
args: ["distributed_queries/awesome_memgraph_functions.py"]
|
||||
<<: *template_cluster
|
||||
|
@ -406,3 +406,7 @@ target_link_libraries(${test_prefix}coordinator_shard_map mg-coordinator)
|
||||
# Tests for many shards, many creates, scan
|
||||
add_unit_test(high_density_shard_create_scan.cpp)
|
||||
target_link_libraries(${test_prefix}high_density_shard_create_scan mg-io mg-coordinator mg-storage-v3 mg-query-v2)
|
||||
|
||||
# Tests for awesome_memgraph_functions
|
||||
add_unit_test(query_v2_expression_evaluator.cpp)
|
||||
target_link_libraries(${test_prefix}query_v2_expression_evaluator mg-query-v2)
|
||||
|
1728
tests/unit/query_v2_expression_evaluator.cpp
Normal file
1728
tests/unit/query_v2_expression_evaluator.cpp
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user