From 085bd2797617ccaf35a8cb89ec94ac98d8f68272 Mon Sep 17 00:00:00 2001 From: Aidar Samerkhanov Date: Thu, 7 Dec 2023 14:49:36 +0300 Subject: [PATCH] Add proper handling of deleted return values for query procedures and functions ran in analytical mode (#400) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Ante Pušić --- .github/workflows/test.yml | 4 +- .../betweenness_centrality_module.cpp | 6 ++- .../betweenness_centrality_online_module.cpp | 6 ++- .../biconnected_components_module.cpp | 9 +++- cpp/bridges_module/bridges_module.cpp | 9 +++- .../algorithm/collections.cpp | 36 ++++++++-------- cpp/collections_module/collections_module.cpp | 2 +- .../community_detection_module.cpp | 6 ++- .../community_detection_online_module.cpp | 43 +++++++++++-------- .../connectivity_module.cpp | 6 ++- cpp/create_module/algorithm/create.cpp | 20 ++++----- cpp/create_module/create_module.cpp | 2 +- .../algorithms/balanced_cut_clustering.cu | 12 +++++- .../algorithms/betweenness_centrality.cu | 12 +++++- cpp/cugraph_module/algorithms/hits.cu | 12 +++++- .../algorithms/katz_centrality.cu | 12 +++++- cpp/cugraph_module/algorithms/leiden.cu | 12 +++++- cpp/cugraph_module/algorithms/louvain.cu | 12 +++++- cpp/cugraph_module/algorithms/pagerank.cu | 12 +++++- .../algorithms/personalized_pagerank.cu | 12 +++++- .../algorithms/spectral_clustering.cu | 12 +++++- cpp/cycles_module/cycles_module.cpp | 6 ++- .../degree_centrality_module.cpp | 8 +++- .../distance_calculator.cpp | 6 +-- cpp/do_module/do_module.cpp | 6 +-- .../algorithms/ancestors.hpp | 2 +- .../algorithms/chain_nodes.hpp | 2 +- .../algorithms/connect_nodes.hpp | 2 +- .../algorithms/descendants.hpp | 2 +- .../algorithms/topological_sort.hpp | 2 +- cpp/graph_util_module/graph_util_module.cpp | 2 +- .../katz_centrality_module.cpp | 6 ++- .../katz_centrality_online_module.cpp | 38 ++++++++++++---- cpp/label_module/algorithm/label.cpp | 2 +- cpp/label_module/label_module.cpp | 2 +- cpp/map_module/algorithm/map.cpp | 18 ++++---- cpp/map_module/map_module.cpp | 2 +- cpp/memgraph | 2 +- cpp/mg_utility/data_structures/graph_view.hpp | 10 +++++ cpp/mg_utility/mg_graph.hpp | 32 +++++++++++++- cpp/mg_utility/mg_utils.hpp | 26 ++++++++++- cpp/neighbors_module/algorithm/neighbors.cpp | 4 +- cpp/neighbors_module/neighbors_module.cpp | 2 +- cpp/node_module/algorithm/node.cpp | 6 +-- cpp/node_module/node_module.cpp | 2 - .../node_similarity_module.cpp | 14 +++--- cpp/nodes_module/algorithm/nodes.cpp | 8 ++-- cpp/nodes_module/nodes_module.cpp | 2 +- cpp/pagerank_module/pagerank_module.cpp | 11 ++++- .../pagerank_online_module.cpp | 30 ++++++++++--- cpp/periodic_module/periodic_iterate.cpp | 4 +- cpp/refactor_module/algorithm/refactor.cpp | 11 ++++- cpp/text_module/text_module.cpp | 2 +- cpp/util_module/algorithm/util.cpp | 2 +- cpp/util_module/util_module.cpp | 2 +- rust/rsmgp-sys/mgp/mg_procedure.h | 6 +++ 56 files changed, 399 insertions(+), 140 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index c4967e553..4454d481d 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -7,7 +7,7 @@ env: MEMGRAPH_PORT: 7687 NEO4J_PORT: 7688 NEO4J_CONTAINER: "neo4j_test" - OFFICIAL: "true" + OFFICIAL: "false" on: [pull_request, workflow_dispatch] @@ -16,7 +16,7 @@ jobs: runs-on: ubuntu-latest continue-on-error: True env: - MEMGRAPH_VERSION: 2.12.1 + MEMGRAPH_VERSION: 2.13 strategy: matrix: architecture: ["amd64", "arm64"] diff --git a/cpp/betweenness_centrality_module/betweenness_centrality_module.cpp b/cpp/betweenness_centrality_module/betweenness_centrality_module.cpp index dddd7aebf..f188bf76e 100644 --- a/cpp/betweenness_centrality_module/betweenness_centrality_module.cpp +++ b/cpp/betweenness_centrality_module/betweenness_centrality_module.cpp @@ -17,9 +17,13 @@ constexpr char const *kArgumentThreads = "threads"; void InsertBCRecord(mgp_graph *graph, mgp_result *result, mgp_memory *memory, const double betweenness_centrality, const int node_id) { + auto *node = mg_utility::GetNodeForInsertion(node_id, graph, memory); + if (!node) return; + auto *record = mgp::result_new_record(result); + if (record == nullptr) throw mg_exception::NotEnoughMemoryException(); - mg_utility::InsertNodeValueResult(graph, record, kFieldNode, node_id, memory); + mg_utility::InsertNodeValueResult(record, kFieldNode, node, memory); mg_utility::InsertDoubleValueResult(record, kFieldBCScore, betweenness_centrality, memory); } diff --git a/cpp/betweenness_centrality_module/betweenness_centrality_online_module.cpp b/cpp/betweenness_centrality_module/betweenness_centrality_online_module.cpp index 7e18435f8..9ca23e654 100644 --- a/cpp/betweenness_centrality_module/betweenness_centrality_online_module.cpp +++ b/cpp/betweenness_centrality_module/betweenness_centrality_online_module.cpp @@ -35,9 +35,13 @@ bool ConnectedVia(std::uint64_t node_id, std::pair void InsertOnlineBCRecord(mgp_graph *graph, mgp_result *result, mgp_memory *memory, const std::uint64_t node_id, double bc_score) { + auto *node = mg_utility::GetNodeForInsertion(node_id, graph, memory); + if (!node) return; + auto *record = mgp::result_new_record(result); + if (record == nullptr) throw mg_exception::NotEnoughMemoryException(); - mg_utility::InsertNodeValueResult(graph, record, kFieldNode, node_id, memory); + mg_utility::InsertNodeValueResult(record, kFieldNode, node, memory); mg_utility::InsertDoubleValueResult(record, kFieldBCScore, bc_score, memory); } diff --git a/cpp/biconnected_components_module/biconnected_components_module.cpp b/cpp/biconnected_components_module/biconnected_components_module.cpp index 3b664e666..ca9ba6bb5 100644 --- a/cpp/biconnected_components_module/biconnected_components_module.cpp +++ b/cpp/biconnected_components_module/biconnected_components_module.cpp @@ -13,13 +13,18 @@ const char *fieldNodeTo = "node_to"; void InsertBiconnectedComponentRecord(mgp_graph *graph, mgp_result *result, mgp_memory *memory, const int bcc_id, const int edge_id, const int node_from_id, const int node_to_id) { + auto *node_from = mg_utility::GetNodeForInsertion(node_from_id, graph, memory); + auto *node_to = mg_utility::GetNodeForInsertion(node_to_id, graph, memory); + if (!node_from || !node_to) return; + auto *record = mgp::result_new_record(result); + if (record == nullptr) throw mg_exception::NotEnoughMemoryException(); mg_utility::InsertIntValueResult(record, fieldBiconnectedComponentID, bcc_id, memory); // TODO: Implement edge getting function // mg_utility::InsertIntValueResult(record, fieldEdgeID, edge_id, memory); - mg_utility::InsertNodeValueResult(graph, record, fieldNodeFrom, node_from_id, memory); - mg_utility::InsertNodeValueResult(graph, record, fieldNodeTo, node_to_id, memory); + mg_utility::InsertNodeValueResult(record, fieldNodeFrom, node_from, memory); + mg_utility::InsertNodeValueResult(record, fieldNodeTo, node_to, memory); } void GetBiconnectedComponents(mgp_list *args, mgp_graph *memgraph_graph, mgp_result *result, mgp_memory *memory) { diff --git a/cpp/bridges_module/bridges_module.cpp b/cpp/bridges_module/bridges_module.cpp index 7416e8c38..50c113c36 100644 --- a/cpp/bridges_module/bridges_module.cpp +++ b/cpp/bridges_module/bridges_module.cpp @@ -13,10 +13,15 @@ const char *k_field_node_to = "node_to"; void InsertBridgeRecord(mgp_graph *graph, mgp_result *result, mgp_memory *memory, const std::uint64_t node_from_id, const std::uint64_t node_to_id) { + auto *node_from = mg_utility::GetNodeForInsertion(node_from_id, graph, memory); + auto *node_to = mg_utility::GetNodeForInsertion(node_to_id, graph, memory); + if (!node_from || !node_to) return; + auto *record = mgp::result_new_record(result); + if (record == nullptr) throw mg_exception::NotEnoughMemoryException(); - mg_utility::InsertNodeValueResult(graph, record, k_field_node_from, node_from_id, memory); - mg_utility::InsertNodeValueResult(graph, record, k_field_node_to, node_to_id, memory); + mg_utility::InsertNodeValueResult(record, k_field_node_from, node_from, memory); + mg_utility::InsertNodeValueResult(record, k_field_node_to, node_to, memory); } void GetBridges(mgp_list *args, mgp_graph *memgraph_graph, mgp_result *result, mgp_memory *memory) { diff --git a/cpp/collections_module/algorithm/collections.cpp b/cpp/collections_module/algorithm/collections.cpp index f9088c859..6443c3160 100644 --- a/cpp/collections_module/algorithm/collections.cpp +++ b/cpp/collections_module/algorithm/collections.cpp @@ -42,7 +42,7 @@ void Collections::SetResult(mgp::Result &result, const mgp::Value &value) { } void Collections::SumLongs(mgp_list *args, mgp_func_context *ctx, mgp_func_result *res, mgp_memory *memory) { - mgp::MemoryDispatcherGuard guard{memory};; + mgp::MemoryDispatcherGuard guard{memory}; const auto arguments = mgp::List(args); auto result = mgp::Result(res); @@ -67,7 +67,7 @@ void Collections::SumLongs(mgp_list *args, mgp_func_context *ctx, mgp_func_resul } void Collections::Avg(mgp_list *args, mgp_func_context *ctx, mgp_func_result *res, mgp_memory *memory) { - mgp::MemoryDispatcherGuard guard{memory};; + mgp::MemoryDispatcherGuard guard{memory}; const auto arguments = mgp::List(args); auto result = mgp::Result(res); @@ -94,7 +94,7 @@ void Collections::Avg(mgp_list *args, mgp_func_context *ctx, mgp_func_result *re } void Collections::ContainsAll(mgp_list *args, mgp_func_context *ctx, mgp_func_result *res, mgp_memory *memory) { - mgp::MemoryDispatcherGuard guard{memory};; + mgp::MemoryDispatcherGuard guard{memory}; const auto arguments = mgp::List(args); auto result = mgp::Result(res); @@ -104,7 +104,7 @@ void Collections::ContainsAll(mgp_list *args, mgp_func_context *ctx, mgp_func_re const auto list2{arguments[1].ValueList()}; - std::unordered_set values(list2.begin(), list2.end());; + std::unordered_set values(list2.begin(), list2.end()); result.SetValue(std::all_of(values.begin(), values.end(), [&set](const auto &x) { return set.contains(x); })); @@ -115,7 +115,7 @@ void Collections::ContainsAll(mgp_list *args, mgp_func_context *ctx, mgp_func_re } void Collections::Intersection(mgp_list *args, mgp_func_context *ctx, mgp_func_result *res, mgp_memory *memory) { - mgp::MemoryDispatcherGuard guard{memory};; + mgp::MemoryDispatcherGuard guard{memory}; const auto arguments = mgp::List(args); auto result = mgp::Result(res); @@ -147,7 +147,7 @@ void Collections::Intersection(mgp_list *args, mgp_func_context *ctx, mgp_func_r } void Collections::RemoveAll(mgp_list *args, mgp_func_context *ctx, mgp_func_result *res, mgp_memory *memory) { - mgp::MemoryDispatcherGuard guard{memory};; + mgp::MemoryDispatcherGuard guard{memory}; const auto arguments = mgp::List(args); auto result = mgp::Result(res); @@ -181,7 +181,7 @@ void Collections::RemoveAll(mgp_list *args, mgp_func_context *ctx, mgp_func_resu } void Collections::Sum(mgp_list *args, mgp_func_context *ctx, mgp_func_result *res, mgp_memory *memory) { - mgp::MemoryDispatcherGuard guard{memory};; + mgp::MemoryDispatcherGuard guard{memory}; const auto arguments = mgp::List(args); auto result = mgp::Result(res); try { @@ -204,7 +204,7 @@ void Collections::Sum(mgp_list *args, mgp_func_context *ctx, mgp_func_result *re } void Collections::Union(mgp_list *args, mgp_func_context *ctx, mgp_func_result *res, mgp_memory *memory) { - mgp::MemoryDispatcherGuard guard{memory};; + mgp::MemoryDispatcherGuard guard{memory}; const auto arguments = mgp::List(args); auto result = mgp::Result(res); try { @@ -249,7 +249,7 @@ void Collections::Union(mgp_list *args, mgp_func_context *ctx, mgp_func_result * } void Collections::Sort(mgp_list *args, mgp_func_context *ctx, mgp_func_result *res, mgp_memory *memory) { - mgp::MemoryDispatcherGuard guard{memory};; + mgp::MemoryDispatcherGuard guard{memory}; const auto arguments = mgp::List(args); auto result = mgp::Result(res); try { @@ -271,7 +271,7 @@ void Collections::Sort(mgp_list *args, mgp_func_context *ctx, mgp_func_result *r } void Collections::ContainsSorted(mgp_list *args, mgp_func_context *ctx, mgp_func_result *res, mgp_memory *memory) { - mgp::MemoryDispatcherGuard guard{memory};; + mgp::MemoryDispatcherGuard guard{memory}; const auto arguments = mgp::List(args); auto result = mgp::Result(res); try { @@ -304,7 +304,7 @@ void Collections::ContainsSorted(mgp_list *args, mgp_func_context *ctx, mgp_func } void Collections::Max(mgp_list *args, mgp_func_context *ctx, mgp_func_result *res, mgp_memory *memory) { - mgp::MemoryDispatcherGuard guard{memory};; + mgp::MemoryDispatcherGuard guard{memory}; const auto arguments = mgp::List(args); auto result = mgp::Result(res); try { @@ -331,7 +331,7 @@ void Collections::Max(mgp_list *args, mgp_func_context *ctx, mgp_func_result *re } void Collections::Split(mgp_list *args, mgp_graph *memgraph_graph, mgp_result *result, mgp_memory *memory) { - mgp::MemoryDispatcherGuard guard{memory};; + mgp::MemoryDispatcherGuard guard{memory}; const auto arguments = mgp::List(args); const auto record_factory = mgp::RecordFactory(result); @@ -370,7 +370,7 @@ void Collections::Split(mgp_list *args, mgp_graph *memgraph_graph, mgp_result *r } void Collections::Pairs(mgp_list *args, mgp_func_context *ctx, mgp_func_result *res, mgp_memory *memory) { - mgp::MemoryDispatcherGuard guard{memory};; + mgp::MemoryDispatcherGuard guard{memory}; const auto arguments = mgp::List(args); auto result = mgp::Result(res); try { @@ -401,7 +401,7 @@ void Collections::Pairs(mgp_list *args, mgp_func_context *ctx, mgp_func_result * } void Collections::Contains(mgp_list *args, mgp_func_context *ctx, mgp_func_result *res, mgp_memory *memory) { - mgp::MemoryDispatcherGuard guard{memory};; + mgp::MemoryDispatcherGuard guard{memory}; const auto arguments = mgp::List(args); auto result = mgp::Result(res); try { @@ -429,7 +429,7 @@ void Collections::Contains(mgp_list *args, mgp_func_context *ctx, mgp_func_resul } void Collections::UnionAll(mgp_list *args, mgp_func_context *ctx, mgp_func_result *res, mgp_memory *memory) { - mgp::MemoryDispatcherGuard guard{memory};; + mgp::MemoryDispatcherGuard guard{memory}; auto arguments = mgp::List(args); auto result = mgp::Result(res); try { @@ -448,7 +448,7 @@ void Collections::UnionAll(mgp_list *args, mgp_func_context *ctx, mgp_func_resul } void Collections::Min(mgp_list *args, mgp_func_context *ctx, mgp_func_result *res, mgp_memory *memory) { - mgp::MemoryDispatcherGuard guard{memory};; + mgp::MemoryDispatcherGuard guard{memory}; const auto arguments = mgp::List(args); auto result = mgp::Result(res); try { @@ -486,7 +486,7 @@ void Collections::Min(mgp_list *args, mgp_func_context *ctx, mgp_func_result *re } void Collections::ToSet(mgp_list *args, mgp_func_context *ctx, mgp_func_result *res, mgp_memory *memory) { - mgp::MemoryDispatcherGuard guard{memory};; + mgp::MemoryDispatcherGuard guard{memory}; auto arguments = mgp::List(args); auto result = mgp::Result(res); try { @@ -506,7 +506,7 @@ void Collections::ToSet(mgp_list *args, mgp_func_context *ctx, mgp_func_result * } void Collections::Partition(mgp_list *args, mgp_graph *memgraph_graph, mgp_result *result, mgp_memory *memory) { - mgp::MemoryDispatcherGuard guard{memory};; + mgp::MemoryDispatcherGuard guard{memory}; auto arguments = mgp::List(args); const auto record_factory = mgp::RecordFactory(result); try { diff --git a/cpp/collections_module/collections_module.cpp b/cpp/collections_module/collections_module.cpp index 1b41c5017..e4b7dbb6f 100644 --- a/cpp/collections_module/collections_module.cpp +++ b/cpp/collections_module/collections_module.cpp @@ -4,7 +4,7 @@ extern "C" int mgp_init_module(struct mgp_module *module, struct mgp_memory *memory) { try { - mgp::MemoryDispatcherGuard guard{memory};; + mgp::MemoryDispatcherGuard guard{memory}; mgp::AddFunction(Collections::SumLongs, Collections::kProcedureSumLongs, {mgp::Parameter(Collections::kSumLongsArg1, {mgp::Type::List, mgp::Type::Any})}, module, memory); diff --git a/cpp/community_detection_module/community_detection_module.cpp b/cpp/community_detection_module/community_detection_module.cpp index 3710ba6e4..ffb5d5875 100644 --- a/cpp/community_detection_module/community_detection_module.cpp +++ b/cpp/community_detection_module/community_detection_module.cpp @@ -1,3 +1,4 @@ +#include #include #include @@ -24,10 +25,13 @@ const double kDefaultWeight = 1.0; void InsertLouvainRecord(mgp_graph *graph, mgp_result *result, mgp_memory *memory, const std::uint64_t node_id, const std::uint64_t community) { + auto *vertex = mg_utility::GetNodeForInsertion(node_id, graph, memory); + if (!vertex) return; + mgp_result_record *record = mgp::result_new_record(result); if (record == nullptr) throw mg_exception::NotEnoughMemoryException(); - mg_utility::InsertNodeValueResult(graph, record, kFieldNode, node_id, memory); + mg_utility::InsertNodeValueResult(record, kFieldNode, vertex, memory); mg_utility::InsertIntValueResult(record, kFieldCommunity, community, memory); } diff --git a/cpp/community_detection_module/community_detection_online_module.cpp b/cpp/community_detection_module/community_detection_online_module.cpp index 782e231f2..3d35031ad 100644 --- a/cpp/community_detection_module/community_detection_online_module.cpp +++ b/cpp/community_detection_module/community_detection_online_module.cpp @@ -51,9 +51,24 @@ auto saved_directedness = kDefaultDirected; auto saved_weightedness = kDefaultWeighted; std::string saved_weight_property = kDefaultWeightProperty.data(); +void WriteResults(const std::uint64_t node_id, const std::int64_t label, const mgp::Graph &graph, + const mgp::RecordFactory &record_factory) { + // As IN_MEMORY_ANALYTICAL doesn’t offer ACID guarantees, check if the graph elements in the result exist + try { + // If so, throw an exception: + const auto node = graph.GetNodeById(mgp::Id::FromUint(node_id)); + + auto record = record_factory.NewRecord(); + record.Insert(kFieldNode.data(), node); + record.Insert(kFieldCommunityId.data(), label); + } catch (const std::exception &) { + // If no node has been found, it’s enough to not write the result + } +} + void Set(mgp_list *args, mgp_graph *memgraph_graph, mgp_result *result, mgp_memory *memory) { try { - mgp::MemoryDispatcherGuard guard{memory};; + mgp::MemoryDispatcherGuard guard{memory}; const auto graph = mgp::Graph(memgraph_graph); const auto arguments = mgp::List(args); @@ -78,9 +93,7 @@ void Set(mgp_list *args, mgp_graph *memgraph_graph, mgp_result *result, mgp_memo ::initialized = true; for (const auto [node_id, label] : labels) { - auto record = record_factory.NewRecord(); - record.Insert(kFieldNode.data(), graph.GetNodeById(mgp::Id::FromUint(node_id))); - record.Insert(kFieldCommunityId.data(), label); + WriteResults(node_id, label, graph, record_factory); } } catch (const std::exception &e) { return; @@ -90,7 +103,7 @@ void Set(mgp_list *args, mgp_graph *memgraph_graph, mgp_result *result, mgp_memo void Get(mgp_list *args, mgp_graph *memgraph_graph, mgp_result *result, mgp_memory *memory) { try { - mgp::MemoryDispatcherGuard guard{memory};; + mgp::MemoryDispatcherGuard guard{memory}; const auto graph = mgp::Graph(memgraph_graph); const auto record_factory = mgp::RecordFactory(result); @@ -101,11 +114,11 @@ void Get(mgp_list *args, mgp_graph *memgraph_graph, mgp_result *result, mgp_memo // Previously-computed communities may contain nodes since deleted try { // If so, throw an exception: - const auto maybe_node = graph.GetNodeById(mgp::Id::FromUint(node_id)); + const auto node = graph.GetNodeById(mgp::Id::FromUint(node_id)); // Otherwise: auto record = record_factory.NewRecord(); - record.Insert(kFieldNode.data(), graph.GetNodeById(mgp::Id::FromUint(node_id))); + record.Insert(kFieldNode.data(), node); record.Insert(kFieldCommunityId.data(), label); } catch (const std::exception &e) { continue; @@ -119,7 +132,7 @@ void Get(mgp_list *args, mgp_graph *memgraph_graph, mgp_result *result, mgp_memo void Update(mgp_list *args, mgp_graph *memgraph_graph, mgp_result *result, mgp_memory *memory) { try { - mgp::MemoryDispatcherGuard guard{memory};; + mgp::MemoryDispatcherGuard guard{memory}; const auto graph = mgp::Graph(memgraph_graph); const auto arguments = mgp::List(args); @@ -167,17 +180,13 @@ void Update(mgp_list *args, mgp_graph *memgraph_graph, mgp_result *result, mgp_m algorithm.UpdateLabels(graph, modified_nodes, modified_relationships, deleted_nodes, deleted_relationships); for (const auto [node_id, label] : labels) { - auto record = record_factory.NewRecord(); - record.Insert(kFieldNode.data(), graph.GetNodeById(mgp::Id::FromUint(node_id))); - record.Insert(kFieldCommunityId.data(), label); + WriteResults(node_id, label, graph, record_factory); } } else { const auto labels = algorithm.SetLabels(graph); for (const auto [node_id, label] : labels) { - auto record = record_factory.NewRecord(); - record.Insert(kFieldNode.data(), graph.GetNodeById(mgp::Id::FromUint(node_id))); - record.Insert(kFieldCommunityId.data(), label); + WriteResults(node_id, label, graph, record_factory); } } @@ -189,7 +198,7 @@ void Update(mgp_list *args, mgp_graph *memgraph_graph, mgp_result *result, mgp_m void Reset(mgp_list *args, mgp_graph *memgraph_graph, mgp_result *result, mgp_memory *memory) { try { - mgp::MemoryDispatcherGuard guard{memory};; + mgp::MemoryDispatcherGuard guard{memory}; const auto record_factory = mgp::RecordFactory(result); @@ -203,7 +212,7 @@ void Reset(mgp_list *args, mgp_graph *memgraph_graph, mgp_result *result, mgp_me auto record = record_factory.NewRecord(); record.Insert(kFieldMessage.data(), "The algorithm has been successfully reset!"); } catch (const std::exception &e) { - mgp::MemoryDispatcherGuard guard{memory};; + mgp::MemoryDispatcherGuard guard{memory}; const auto record_factory = mgp::RecordFactory(result); auto record = record_factory.NewRecord(); @@ -216,7 +225,7 @@ void Reset(mgp_list *args, mgp_graph *memgraph_graph, mgp_result *result, mgp_me extern "C" int mgp_init_module(struct mgp_module *module, struct mgp_memory *memory) { try { - mgp::MemoryDispatcherGuard guard{memory};; + mgp::MemoryDispatcherGuard guard{memory}; const auto node_list = std::make_pair(mgp::Type::List, mgp::Type::Node); const auto relationship_list = std::make_pair(mgp::Type::List, mgp::Type::Relationship); diff --git a/cpp/connectivity_module/connectivity_module.cpp b/cpp/connectivity_module/connectivity_module.cpp index 207284ae1..3c7ba608c 100644 --- a/cpp/connectivity_module/connectivity_module.cpp +++ b/cpp/connectivity_module/connectivity_module.cpp @@ -13,9 +13,13 @@ constexpr char const *kFieldComponentId = "component_id"; void InsertWeaklyComponentResult(mgp_graph *graph, mgp_result *result, mgp_memory *memory, const int component_id, const int vertex_id) { + auto *vertex = mg_utility::GetNodeForInsertion(vertex_id, graph, memory); + if (!vertex) return; + auto *record = mgp::result_new_record(result); + if (record == nullptr) throw mg_exception::NotEnoughMemoryException(); - mg_utility::InsertNodeValueResult(graph, record, kFieldVertex, vertex_id, memory); + mg_utility::InsertNodeValueResult(record, kFieldVertex, vertex, memory); mg_utility::InsertIntValueResult(record, kFieldComponentId, component_id, memory); } diff --git a/cpp/create_module/algorithm/create.cpp b/cpp/create_module/algorithm/create.cpp index 7b1369ea0..fb4b9add8 100644 --- a/cpp/create_module/algorithm/create.cpp +++ b/cpp/create_module/algorithm/create.cpp @@ -34,7 +34,7 @@ void ModifyAndOutput(mgp::Relationship &relationship, const mgp::List &keys, con } // namespace void Create::RemoveRelProperties(mgp_list *args, mgp_graph *memgraph_graph, mgp_result *result, mgp_memory *memory) { - mgp::MemoryDispatcherGuard guard{memory};; + mgp::MemoryDispatcherGuard guard{memory}; const auto arguments = mgp::List(args); const auto record_factory = mgp::RecordFactory(result); @@ -80,7 +80,7 @@ void Create::RemoveRelProperties(mgp_list *args, mgp_graph *memgraph_graph, mgp_ } void Create::SetRelProperties(mgp_list *args, mgp_graph *memgraph_graph, mgp_result *result, mgp_memory *memory) { - mgp::MemoryDispatcherGuard guard{memory};; + mgp::MemoryDispatcherGuard guard{memory}; const auto arguments = mgp::List(args); const auto record_factory = mgp::RecordFactory(result); @@ -131,7 +131,7 @@ void Create::SetRelProperties(mgp_list *args, mgp_graph *memgraph_graph, mgp_res } void Create::Relationship(mgp_list *args, mgp_graph *memgraph_graph, mgp_result *result, mgp_memory *memory) { - mgp::MemoryDispatcherGuard guard{memory};; + mgp::MemoryDispatcherGuard guard{memory}; const auto arguments = mgp::List(args); const auto record_factory = mgp::RecordFactory(result); @@ -181,7 +181,7 @@ void Create::ProcessElement(const mgp::Value &element, const mgp::Graph graph, c } void Create::SetRelProperty(mgp_list *args, mgp_graph *memgraph_graph, mgp_result *result, mgp_memory *memory) { - mgp::MemoryDispatcherGuard guard{memory};; + mgp::MemoryDispatcherGuard guard{memory}; const auto arguments = mgp::List(args); const auto graph = mgp::Graph(memgraph_graph); const auto record_factory = mgp::RecordFactory(result); @@ -256,7 +256,7 @@ void Create::ProcessElement(const mgp::Value &element, const mgp::Graph graph, c } void Create::RemoveLabels(mgp_list *args, mgp_graph *memgraph_graph, mgp_result *result, mgp_memory *memory) { - mgp::MemoryDispatcherGuard guard{memory};; + mgp::MemoryDispatcherGuard guard{memory}; const auto arguments = mgp::List(args); const auto graph = mgp::Graph(memgraph_graph); const auto record_factory = mgp::RecordFactory(result); @@ -278,7 +278,7 @@ void Create::RemoveLabels(mgp_list *args, mgp_graph *memgraph_graph, mgp_result } void Create::RemoveProperties(mgp_list *args, mgp_graph *memgraph_graph, mgp_result *result, mgp_memory *memory) { - mgp::MemoryDispatcherGuard guard{memory};; + mgp::MemoryDispatcherGuard guard{memory}; const auto arguments = mgp::List(args); const auto record_factory = mgp::RecordFactory(result); try { @@ -324,7 +324,7 @@ void Create::ProcessElement(const mgp::Value &element, const mgp::Graph graph, c } void Create::SetProperties(mgp_list *args, mgp_graph *memgraph_graph, mgp_result *result, mgp_memory *memory) { - mgp::MemoryDispatcherGuard guard{memory};; + mgp::MemoryDispatcherGuard guard{memory}; const auto arguments = mgp::List(args); const auto graph = mgp::Graph(memgraph_graph); const auto record_factory = mgp::RecordFactory(result); @@ -351,7 +351,7 @@ void Create::SetProperties(mgp_list *args, mgp_graph *memgraph_graph, mgp_result } void Create::Node(mgp_list *args, mgp_graph *memgraph_graph, mgp_result *result, mgp_memory *memory) { - mgp::MemoryDispatcherGuard guard{memory};; + mgp::MemoryDispatcherGuard guard{memory}; const auto arguments = mgp::List(args); auto graph = mgp::Graph(memgraph_graph); const auto record_factory = mgp::RecordFactory(result); @@ -379,7 +379,7 @@ void Create::Node(mgp_list *args, mgp_graph *memgraph_graph, mgp_result *result, } void Create::Nodes(mgp_list *args, mgp_graph *memgraph_graph, mgp_result *result, mgp_memory *memory) { - mgp::MemoryDispatcherGuard guard{memory};; + mgp::MemoryDispatcherGuard guard{memory}; const auto arguments = mgp::List(args); const auto record_factory = mgp::RecordFactory(result); try { @@ -407,7 +407,7 @@ void Create::Nodes(mgp_list *args, mgp_graph *memgraph_graph, mgp_result *result } void Create::SetProperty(mgp_list *args, mgp_graph *memgraph_graph, mgp_result *result, mgp_memory *memory) { - mgp::MemoryDispatcherGuard guard{memory};; + mgp::MemoryDispatcherGuard guard{memory}; const auto arguments = mgp::List(args); const auto record_factory = mgp::RecordFactory(result); try { diff --git a/cpp/create_module/create_module.cpp b/cpp/create_module/create_module.cpp index 07cd58777..91baa4c59 100644 --- a/cpp/create_module/create_module.cpp +++ b/cpp/create_module/create_module.cpp @@ -4,7 +4,7 @@ extern "C" int mgp_init_module(struct mgp_module *module, struct mgp_memory *memory) { try { - mgp::MemoryDispatcherGuard guard{memory};; + mgp::MemoryDispatcherGuard guard{memory}; AddProcedure(Create::SetRelProperty, Create::kProcedureSetRelProp, mgp::ProcedureType::Write, {mgp::Parameter(Create::kArgumentsRelationship, mgp::Type::Any), diff --git a/cpp/cugraph_module/algorithms/balanced_cut_clustering.cu b/cpp/cugraph_module/algorithms/balanced_cut_clustering.cu index e8096e04d..f9167b166 100644 --- a/cpp/cugraph_module/algorithms/balanced_cut_clustering.cu +++ b/cpp/cugraph_module/algorithms/balanced_cut_clustering.cu @@ -38,8 +38,18 @@ constexpr char const *kDefaultWeightProperty = "weight"; void InsertBalancedCutResult(mgp_graph *graph, mgp_result *result, mgp_memory *memory, const std::uint64_t node_id, std::int64_t cluster) { + auto *node = mgp::graph_get_vertex_by_id(graph, mgp_vertex_id{.as_int = static_cast(node_id)}, memory); + if (!node) { + if (mgp::graph_is_transactional(graph)) { + throw mg_exception::InvalidIDException(); + } + return; + } + auto *record = mgp::result_new_record(result); - mg_utility::InsertNodeValueResult(graph, record, kResultFieldNode, node_id, memory); + if (record == nullptr) throw mg_exception::NotEnoughMemoryException(); + + mg_utility::InsertNodeValueResult(record, kResultFieldNode, node, memory); mg_utility::InsertIntValueResult(record, kResultFieldCluster, cluster, memory); } diff --git a/cpp/cugraph_module/algorithms/betweenness_centrality.cu b/cpp/cugraph_module/algorithms/betweenness_centrality.cu index 42a54fb42..da66ca1e3 100644 --- a/cpp/cugraph_module/algorithms/betweenness_centrality.cu +++ b/cpp/cugraph_module/algorithms/betweenness_centrality.cu @@ -35,8 +35,18 @@ constexpr char const *kDefaultWeightProperty = "weight"; void InsertBetweennessRecord(mgp_graph *graph, mgp_result *result, mgp_memory *memory, const std::uint64_t node_id, double rank) { + auto *node = mgp::graph_get_vertex_by_id(graph, mgp_vertex_id{.as_int = static_cast(node_id)}, memory); + if (!node) { + if (mgp::graph_is_transactional(graph)) { + throw mg_exception::InvalidIDException(); + } + return; + } + auto *record = mgp::result_new_record(result); - mg_utility::InsertNodeValueResult(graph, record, kResultFieldNode, node_id, memory); + if (record == nullptr) throw mg_exception::NotEnoughMemoryException(); + + mg_utility::InsertNodeValueResult(record, kResultFieldNode, node, memory); mg_utility::InsertDoubleValueResult(record, kResultFieldBetweennessCentrality, rank, memory); } diff --git a/cpp/cugraph_module/algorithms/hits.cu b/cpp/cugraph_module/algorithms/hits.cu index a02863a01..0dfe1b7e5 100644 --- a/cpp/cugraph_module/algorithms/hits.cu +++ b/cpp/cugraph_module/algorithms/hits.cu @@ -33,8 +33,18 @@ constexpr char const *kResultFieldAuthoritiesScore = "authorities"; void InsertHITSRecord(mgp_graph *graph, mgp_result *result, mgp_memory *memory, const std::uint64_t node_id, double hubs, double authorities) { + auto *node = mgp::graph_get_vertex_by_id(graph, mgp_vertex_id{.as_int = static_cast(node_id)}, memory); + if (!node) { + if (mgp::graph_is_transactional(graph)) { + throw mg_exception::InvalidIDException(); + } + return; + } + auto *record = mgp::result_new_record(result); - mg_utility::InsertNodeValueResult(graph, record, kResultFieldNode, node_id, memory); + if (record == nullptr) throw mg_exception::NotEnoughMemoryException(); + + mg_utility::InsertNodeValueResult(record, kResultFieldNode, node, memory); mg_utility::InsertDoubleValueResult(record, kResultFieldHubScore, hubs, memory); mg_utility::InsertDoubleValueResult(record, kResultFieldAuthoritiesScore, authorities, memory); } diff --git a/cpp/cugraph_module/algorithms/katz_centrality.cu b/cpp/cugraph_module/algorithms/katz_centrality.cu index b319693bb..6ca143069 100644 --- a/cpp/cugraph_module/algorithms/katz_centrality.cu +++ b/cpp/cugraph_module/algorithms/katz_centrality.cu @@ -34,8 +34,18 @@ constexpr char const *kResultFieldKatzCentrality = "katz_centrality"; void InsertKatzCentralityRecord(mgp_graph *graph, mgp_result *result, mgp_memory *memory, const std::uint64_t node_id, double rank) { + auto *node = mgp::graph_get_vertex_by_id(graph, mgp_vertex_id{.as_int = static_cast(node_id)}, memory); + if (!node) { + if (mgp::graph_is_transactional(graph)) { + throw mg_exception::InvalidIDException(); + } + return; + } + auto *record = mgp::result_new_record(result); - mg_utility::InsertNodeValueResult(graph, record, kResultFieldNode, node_id, memory); + if (record == nullptr) throw mg_exception::NotEnoughMemoryException(); + + mg_utility::InsertNodeValueResult(record, kResultFieldNode, node, memory); mg_utility::InsertDoubleValueResult(record, kResultFieldKatzCentrality, rank, memory); } diff --git a/cpp/cugraph_module/algorithms/leiden.cu b/cpp/cugraph_module/algorithms/leiden.cu index b49d38e99..dcca27875 100644 --- a/cpp/cugraph_module/algorithms/leiden.cu +++ b/cpp/cugraph_module/algorithms/leiden.cu @@ -30,8 +30,18 @@ constexpr char const *kResultFieldPartition = "partition"; void InsertLeidenRecord(mgp_graph *graph, mgp_result *result, mgp_memory *memory, const std::uint64_t node_id, std::int64_t partition) { + auto *node = mgp::graph_get_vertex_by_id(graph, mgp_vertex_id{.as_int = static_cast(node_id)}, memory); + if (!node) { + if (mgp::graph_is_transactional(graph)) { + throw mg_exception::InvalidIDException(); + } + return; + } + auto *record = mgp::result_new_record(result); - mg_utility::InsertNodeValueResult(graph, record, kResultFieldNode, node_id, memory); + if (record == nullptr) throw mg_exception::NotEnoughMemoryException(); + + mg_utility::InsertNodeValueResult(record, kResultFieldNode, node, memory); mg_utility::InsertIntValueResult(record, kResultFieldPartition, partition, memory); } diff --git a/cpp/cugraph_module/algorithms/louvain.cu b/cpp/cugraph_module/algorithms/louvain.cu index df67d9751..d55575263 100644 --- a/cpp/cugraph_module/algorithms/louvain.cu +++ b/cpp/cugraph_module/algorithms/louvain.cu @@ -30,8 +30,18 @@ constexpr char const *kResultFieldPartition = "partition"; void InsertLouvainRecord(mgp_graph *graph, mgp_result *result, mgp_memory *memory, const std::uint64_t node_id, std::int64_t partition) { + auto *node = mgp::graph_get_vertex_by_id(graph, mgp_vertex_id{.as_int = static_cast(node_id)}, memory); + if (!node) { + if (mgp::graph_is_transactional(graph)) { + throw mg_exception::InvalidIDException(); + } + return; + } + auto *record = mgp::result_new_record(result); - mg_utility::InsertNodeValueResult(graph, record, kResultFieldNode, node_id, memory); + if (record == nullptr) throw mg_exception::NotEnoughMemoryException(); + + mg_utility::InsertNodeValueResult(record, kResultFieldNode, node, memory); mg_utility::InsertIntValueResult(record, kResultFieldPartition, partition, memory); } diff --git a/cpp/cugraph_module/algorithms/pagerank.cu b/cpp/cugraph_module/algorithms/pagerank.cu index 5f5106514..42686c34e 100644 --- a/cpp/cugraph_module/algorithms/pagerank.cu +++ b/cpp/cugraph_module/algorithms/pagerank.cu @@ -35,8 +35,18 @@ constexpr char const *kDefaultWeightProperty = "weight"; void InsertPagerankRecord(mgp_graph *graph, mgp_result *result, mgp_memory *memory, const std::uint64_t node_id, double rank) { + auto *node = mgp::graph_get_vertex_by_id(graph, mgp_vertex_id{.as_int = static_cast(node_id)}, memory); + if (!node) { + if (mgp::graph_is_transactional(graph)) { + throw mg_exception::InvalidIDException(); + } + return; + } + auto *record = mgp::result_new_record(result); - mg_utility::InsertNodeValueResult(graph, record, kResultFieldNode, node_id, memory); + if (record == nullptr) throw mg_exception::NotEnoughMemoryException(); + + mg_utility::InsertNodeValueResult(record, kResultFieldNode, node, memory); mg_utility::InsertDoubleValueResult(record, kResultFieldPageRank, rank, memory); } diff --git a/cpp/cugraph_module/algorithms/personalized_pagerank.cu b/cpp/cugraph_module/algorithms/personalized_pagerank.cu index 1102d947b..021690da8 100644 --- a/cpp/cugraph_module/algorithms/personalized_pagerank.cu +++ b/cpp/cugraph_module/algorithms/personalized_pagerank.cu @@ -37,8 +37,18 @@ constexpr char const *kDefaultWeightProperty = "weight"; void InsertPersonalizedPagerankRecord(mgp_graph *graph, mgp_result *result, mgp_memory *memory, const std::uint64_t node_id, double rank) { + auto *node = mgp::graph_get_vertex_by_id(graph, mgp_vertex_id{.as_int = static_cast(node_id)}, memory); + if (!node) { + if (mgp::graph_is_transactional(graph)) { + throw mg_exception::InvalidIDException(); + } + return; + } + auto *record = mgp::result_new_record(result); - mg_utility::InsertNodeValueResult(graph, record, kResultFieldNode, node_id, memory); + if (record == nullptr) throw mg_exception::NotEnoughMemoryException(); + + mg_utility::InsertNodeValueResult(record, kResultFieldNode, node, memory); mg_utility::InsertDoubleValueResult(record, kResultFieldPageRank, rank, memory); } diff --git a/cpp/cugraph_module/algorithms/spectral_clustering.cu b/cpp/cugraph_module/algorithms/spectral_clustering.cu index 5a6613daa..5caa35ca4 100644 --- a/cpp/cugraph_module/algorithms/spectral_clustering.cu +++ b/cpp/cugraph_module/algorithms/spectral_clustering.cu @@ -38,8 +38,18 @@ constexpr char const *kDefaultWeightProperty = "weight"; void InsertSpectralClusteringResult(mgp_graph *graph, mgp_result *result, mgp_memory *memory, const std::uint64_t node_id, std::int64_t cluster) { + auto *node = mgp::graph_get_vertex_by_id(graph, mgp_vertex_id{.as_int = static_cast(node_id)}, memory); + if (!node) { + if (mgp::graph_is_transactional(graph)) { + throw mg_exception::InvalidIDException(); + } + return; + } + auto *record = mgp::result_new_record(result); - mg_utility::InsertNodeValueResult(graph, record, kResultFieldNode, node_id, memory); + if (record == nullptr) throw mg_exception::NotEnoughMemoryException(); + + mg_utility::InsertNodeValueResult(record, kResultFieldNode, node, memory); mg_utility::InsertIntValueResult(record, kResultFieldCluster, cluster, memory); } diff --git a/cpp/cycles_module/cycles_module.cpp b/cpp/cycles_module/cycles_module.cpp index 458d203e2..b50e9cd5c 100644 --- a/cpp/cycles_module/cycles_module.cpp +++ b/cpp/cycles_module/cycles_module.cpp @@ -11,10 +11,14 @@ constexpr char const *kFieldNode = "node"; void InsertCycleRecord(mgp_graph *graph, mgp_result *result, mgp_memory *memory, const int cycle_id, const int node_id) { + auto *node = mg_utility::GetNodeForInsertion(node_id, graph, memory); + if (!node) return; + auto *record = mgp::result_new_record(result); + if (record == nullptr) throw mg_exception::NotEnoughMemoryException(); mg_utility::InsertIntValueResult(record, kFieldCycleId, cycle_id, memory); - mg_utility::InsertNodeValueResult(graph, record, kFieldNode, node_id, memory); + mg_utility::InsertNodeValueResult(record, kFieldNode, node, memory); } void GetCycles(mgp_list *args, mgp_graph *memgraph_graph, mgp_result *result, mgp_memory *memory) { diff --git a/cpp/degree_centrality_module/degree_centrality_module.cpp b/cpp/degree_centrality_module/degree_centrality_module.cpp index ef5189499..a10f75be4 100644 --- a/cpp/degree_centrality_module/degree_centrality_module.cpp +++ b/cpp/degree_centrality_module/degree_centrality_module.cpp @@ -19,11 +19,15 @@ const char *kAlgorithmUndirected = "undirected"; const char *kAlgorithmOut = "out"; const char *kAlgorithmIn = "in"; -void InsertDegreeCentralityRecord(mgp_graph *graph, mgp_result *result, mgp_memory *memory, std::uint64_t node, +void InsertDegreeCentralityRecord(mgp_graph *graph, mgp_result *result, mgp_memory *memory, std::uint64_t node_id, double degree) { + auto *node = mg_utility::GetNodeForInsertion(node_id, graph, memory); + if (!node) return; + auto *record = mgp::result_new_record(result); + if (record == nullptr) throw mg_exception::NotEnoughMemoryException(); - mg_utility::InsertNodeValueResult(graph, record, kFieldNode, node, memory); + mg_utility::InsertNodeValueResult(record, kFieldNode, node, memory); mg_utility::InsertDoubleValueResult(record, kFieldDegree, degree, memory); } diff --git a/cpp/distance_calculator/distance_calculator.cpp b/cpp/distance_calculator/distance_calculator.cpp index fdcc6da5d..a229a2541 100644 --- a/cpp/distance_calculator/distance_calculator.cpp +++ b/cpp/distance_calculator/distance_calculator.cpp @@ -49,7 +49,7 @@ double distance_calc(const mgp::Node &node1, const mgp::Node &node2, bool use_km } void Single(mgp_list *args, mgp_graph *memgraph_graph, mgp_result *result, mgp_memory *memory) { - mgp::MemoryDispatcherGuard guard{memory};; + mgp::MemoryDispatcherGuard guard{memory}; const auto record_factory = mgp::RecordFactory(result); try { @@ -69,7 +69,7 @@ void Single(mgp_list *args, mgp_graph *memgraph_graph, mgp_result *result, mgp_m } void Multiple(mgp_list *args, mgp_graph *memgraph_graph, mgp_result *result, mgp_memory *memory) { - mgp::MemoryDispatcherGuard guard{memory};; + mgp::MemoryDispatcherGuard guard{memory}; const auto record_factory = mgp::RecordFactory(result); try { @@ -102,7 +102,7 @@ void Multiple(mgp_list *args, mgp_graph *memgraph_graph, mgp_result *result, mgp extern "C" int mgp_init_module(struct mgp_module *module, struct mgp_memory *memory) { try { - mgp::MemoryDispatcherGuard guard{memory};; + mgp::MemoryDispatcherGuard guard{memory}; AddProcedure( Single, kProcedureSingle, mgp::ProcedureType::Read, diff --git a/cpp/do_module/do_module.cpp b/cpp/do_module/do_module.cpp index f70483ba0..7a2a30b00 100644 --- a/cpp/do_module/do_module.cpp +++ b/cpp/do_module/do_module.cpp @@ -309,7 +309,7 @@ bool IsGlobalOperation(std::string_view query) { } void When(mgp_list *args, mgp_graph *memgraph_graph, mgp_result *result, mgp_memory *memory) { - mgp::MemoryDispatcherGuard guard{memory};; + mgp::MemoryDispatcherGuard guard{memory}; const auto arguments = mgp::List(args); const auto condition = arguments[0].ValueBool(); @@ -335,7 +335,7 @@ void When(mgp_list *args, mgp_graph *memgraph_graph, mgp_result *result, mgp_mem } void Case(mgp_list *args, mgp_graph *memgraph_graph, mgp_result *result, mgp_memory *memory) { - mgp::MemoryDispatcherGuard guard{memory};; + mgp::MemoryDispatcherGuard guard{memory}; const auto arguments = mgp::List(args); const auto conditionals = arguments[0].ValueList(); @@ -391,7 +391,7 @@ void Case(mgp_list *args, mgp_graph *memgraph_graph, mgp_result *result, mgp_mem extern "C" int mgp_init_module(struct mgp_module *module, struct mgp_memory *memory) { try { - mgp::MemoryDispatcherGuard guard{memory};; + mgp::MemoryDispatcherGuard guard{memory}; mgp::AddProcedure(Case, kProcedureCase, mgp::ProcedureType::Read, {mgp::Parameter(kArgumentConditionals, {mgp::Type::List, mgp::Type::Any}), diff --git a/cpp/graph_util_module/algorithms/ancestors.hpp b/cpp/graph_util_module/algorithms/ancestors.hpp index a79b4d78b..885965073 100644 --- a/cpp/graph_util_module/algorithms/ancestors.hpp +++ b/cpp/graph_util_module/algorithms/ancestors.hpp @@ -5,7 +5,7 @@ const char *kResultAncestors = "ancestors"; void Ancestors(mgp_list *args, mgp_graph *memgraph_graph, mgp_result *result, mgp_memory *memory) { - mgp::MemoryDispatcherGuard guard{memory};; + mgp::MemoryDispatcherGuard guard{memory}; const auto arguments = mgp::List(args); const auto record_factory = mgp::RecordFactory(result); try { diff --git a/cpp/graph_util_module/algorithms/chain_nodes.hpp b/cpp/graph_util_module/algorithms/chain_nodes.hpp index f0c440080..24b5b5c18 100644 --- a/cpp/graph_util_module/algorithms/chain_nodes.hpp +++ b/cpp/graph_util_module/algorithms/chain_nodes.hpp @@ -4,7 +4,7 @@ const char *kResultChainNodes = "connections"; void ChainNodes(mgp_list *args, mgp_graph *memgraph_graph, mgp_result *result, mgp_memory *memory) { try { - mgp::MemoryDispatcherGuard guard{memory};; + mgp::MemoryDispatcherGuard guard{memory}; const auto arguments = mgp::List(args); auto graph = mgp::Graph(memgraph_graph); auto factory = mgp::RecordFactory(result); diff --git a/cpp/graph_util_module/algorithms/connect_nodes.hpp b/cpp/graph_util_module/algorithms/connect_nodes.hpp index 1b345f57f..07c5673b6 100644 --- a/cpp/graph_util_module/algorithms/connect_nodes.hpp +++ b/cpp/graph_util_module/algorithms/connect_nodes.hpp @@ -3,7 +3,7 @@ const char *kResultConnections = "connections"; void ConnectNodes(mgp_list *args, mgp_graph *memgraph_graph, mgp_result *result, mgp_memory *memory) { - mgp::MemoryDispatcherGuard guard{memory};; + mgp::MemoryDispatcherGuard guard{memory}; const auto arguments = mgp::List(args); const auto record_factory = mgp::RecordFactory(result); try { diff --git a/cpp/graph_util_module/algorithms/descendants.hpp b/cpp/graph_util_module/algorithms/descendants.hpp index 1e2bf96ea..459a62c9e 100644 --- a/cpp/graph_util_module/algorithms/descendants.hpp +++ b/cpp/graph_util_module/algorithms/descendants.hpp @@ -5,7 +5,7 @@ const char *kResultDescendants = "descendants"; void Descendants(mgp_list *args, mgp_graph *memgraph_graph, mgp_result *result, mgp_memory *memory) { - mgp::MemoryDispatcherGuard guard{memory};; + mgp::MemoryDispatcherGuard guard{memory}; const auto arguments = mgp::List(args); const auto record_factory = mgp::RecordFactory(result); try { diff --git a/cpp/graph_util_module/algorithms/topological_sort.hpp b/cpp/graph_util_module/algorithms/topological_sort.hpp index 9a73c40f8..cf3cea353 100644 --- a/cpp/graph_util_module/algorithms/topological_sort.hpp +++ b/cpp/graph_util_module/algorithms/topological_sort.hpp @@ -5,7 +5,7 @@ const char *kResultSortedNodes = "sorted_nodes"; void TopologicalSort(mgp_list *args, mgp_graph *memgraph_graph, mgp_result *result, mgp_memory *memory) { - mgp::MemoryDispatcherGuard guard{memory};; + mgp::MemoryDispatcherGuard guard{memory}; const auto record_factory = mgp::RecordFactory(result); const auto graph = mgp::Graph(memgraph_graph); mgp::List topological_ordering = mgp::List(); diff --git a/cpp/graph_util_module/graph_util_module.cpp b/cpp/graph_util_module/graph_util_module.cpp index c0ac56956..b8cf4cc1c 100644 --- a/cpp/graph_util_module/graph_util_module.cpp +++ b/cpp/graph_util_module/graph_util_module.cpp @@ -23,7 +23,7 @@ const char *kArgumentNodes = "nodes"; extern "C" int mgp_init_module(struct mgp_module *module, struct mgp_memory *memory) { try { - mgp::MemoryDispatcherGuard guard{memory};; + mgp::MemoryDispatcherGuard guard{memory}; // Register ancestors procedure const auto ancestors_return = std::make_pair(mgp::Type::List, mgp::Type::Node); diff --git a/cpp/katz_centrality_module/katz_centrality_module.cpp b/cpp/katz_centrality_module/katz_centrality_module.cpp index 763352bf2..732e130b7 100644 --- a/cpp/katz_centrality_module/katz_centrality_module.cpp +++ b/cpp/katz_centrality_module/katz_centrality_module.cpp @@ -14,9 +14,13 @@ constexpr char const *kFieldRank = "rank"; void InsertKatzRecord(mgp_graph *graph, mgp_result *result, mgp_memory *memory, const double katz_centrality, const int node_id) { + auto *node = mg_utility::GetNodeForInsertion(node_id, graph, memory); + if (!node) return; + auto *record = mgp::result_new_record(result); + if (record == nullptr) throw mg_exception::NotEnoughMemoryException(); - mg_utility::InsertNodeValueResult(graph, record, kFieldNode, node_id, memory); + mg_utility::InsertNodeValueResult(record, kFieldNode, node, memory); mg_utility::InsertDoubleValueResult(record, kFieldRank, katz_centrality, memory); } diff --git a/cpp/katz_centrality_module/katz_centrality_online_module.cpp b/cpp/katz_centrality_module/katz_centrality_online_module.cpp index b6c50d9c4..51b69e168 100644 --- a/cpp/katz_centrality_module/katz_centrality_online_module.cpp +++ b/cpp/katz_centrality_module/katz_centrality_online_module.cpp @@ -22,9 +22,13 @@ constexpr char const *kArgumentDeletedEdges = "deleted_edges"; void InsertKatzRecord(mgp_graph *graph, mgp_result *result, mgp_memory *memory, const double katz_centrality, const int node_id) { + auto *node = mg_utility::GetNodeForInsertion(node_id, graph, memory); + if (!node) return; + auto *record = mgp::result_new_record(result); + if (record == nullptr) throw mg_exception::NotEnoughMemoryException(); - mg_utility::InsertNodeValueResult(graph, record, kFieldNode, node_id, memory); + mg_utility::InsertNodeValueResult(record, kFieldNode, node, memory); mg_utility::InsertDoubleValueResult(record, kFieldRank, katz_centrality, memory); } @@ -67,7 +71,7 @@ void SetKatzCentrality(mgp_list *args, mgp_graph *memgraph_graph, mgp_result *re void UpdateKatzCentrality(mgp_list *args, mgp_graph *memgraph_graph, mgp_result *result, mgp_memory *memory) { try { - mgp::MemoryDispatcherGuard guard{memory};; + mgp::MemoryDispatcherGuard guard{memory}; const auto record_factory = mgp::RecordFactory(result); const auto graph = mgp::Graph(memgraph_graph); @@ -80,9 +84,18 @@ void UpdateKatzCentrality(mgp_list *args, mgp_graph *memgraph_graph, mgp_result katz_centralities = katz_alg::SetKatz(*legacy_graph); for (auto &[node_id, centrality] : katz_centralities) { - auto record = record_factory.NewRecord(); - record.Insert(kFieldNode, graph.GetNodeById(mgp::Id::FromUint(node_id))); - record.Insert(kFieldRank, centrality); + // As IN_MEMORY_ANALYTICAL doesn’t offer ACID guarantees, check if the graph elements in the result exist + try { + // If so, throw an exception: + const auto node = graph.GetNodeById(mgp::Id::FromUint(node_id)); + + // Otherwise: + auto record = record_factory.NewRecord(); + record.Insert(kFieldNode, node); + record.Insert(kFieldRank, centrality); + } catch (const std::exception &e) { + continue; + } } return; @@ -124,9 +137,18 @@ void UpdateKatzCentrality(mgp_list *args, mgp_graph *memgraph_graph, mgp_result deleted_nodes, deleted_relationships); for (auto &[node_id, centrality] : katz_centralities) { - auto record = record_factory.NewRecord(); - record.Insert(kFieldNode, graph.GetNodeById(mgp::Id::FromUint(node_id))); - record.Insert(kFieldRank, centrality); + // As IN_MEMORY_ANALYTICAL doesn’t offer ACID guarantees, check if the graph elements in the result exist + try { + // If so, throw an exception: + const auto node = graph.GetNodeById(mgp::Id::FromUint(node_id)); + + // Otherwise: + auto record = record_factory.NewRecord(); + record.Insert(kFieldNode, node); + record.Insert(kFieldRank, centrality); + } catch (const std::exception &e) { + continue; + } } } catch (const std::exception &e) { mgp::result_set_error_msg(result, e.what()); diff --git a/cpp/label_module/algorithm/label.cpp b/cpp/label_module/algorithm/label.cpp index 4415691c6..64e197fee 100644 --- a/cpp/label_module/algorithm/label.cpp +++ b/cpp/label_module/algorithm/label.cpp @@ -1,7 +1,7 @@ #include "label.hpp" void Label::Exists(mgp_list *args, mgp_func_context *ctx, mgp_func_result *res, mgp_memory *memory) { - mgp::MemoryDispatcherGuard guard{memory};; + mgp::MemoryDispatcherGuard guard{memory}; const auto arguments = mgp::List(args); auto result = mgp::Result(res); try { diff --git a/cpp/label_module/label_module.cpp b/cpp/label_module/label_module.cpp index c0886dafb..bd4a29474 100644 --- a/cpp/label_module/label_module.cpp +++ b/cpp/label_module/label_module.cpp @@ -4,7 +4,7 @@ extern "C" int mgp_init_module(struct mgp_module *module, struct mgp_memory *memory) { try { - mgp::MemoryDispatcherGuard guard{memory};; + mgp::MemoryDispatcherGuard guard{memory}; mgp::AddFunction(Label::Exists, Label::kFunctionExists, {mgp::Parameter(Label::kArgumentsNode, mgp::Type::Any), diff --git a/cpp/map_module/algorithm/map.cpp b/cpp/map_module/algorithm/map.cpp index f232b10ca..c6a7609cf 100644 --- a/cpp/map_module/algorithm/map.cpp +++ b/cpp/map_module/algorithm/map.cpp @@ -9,7 +9,7 @@ const auto number_of_elements_in_pair = 2; /*NOTE: FromNodes isn't 1:1 for graphQL, because first, we need to extend C and CPP API to iterate vertices using ctx object, since the `FromNodes` procedure (function if we want to change API) needs to iterate over all graph nodes*/ void Map::FromNodes(mgp_list *args, mgp_graph *memgraph_graph, mgp_result *result, mgp_memory *memory) { - mgp::MemoryDispatcherGuard guard{memory};; + mgp::MemoryDispatcherGuard guard{memory}; const auto arguments = mgp::List(args); const auto record_factory = mgp::RecordFactory(result); @@ -55,7 +55,7 @@ void Map::FromNodes(mgp_list *args, mgp_graph *memgraph_graph, mgp_result *resul } void Map::FromValues(mgp_list *args, mgp_func_context *ctx, mgp_func_result *res, mgp_memory *memory) { - mgp::MemoryDispatcherGuard guard{memory};; + mgp::MemoryDispatcherGuard guard{memory}; const auto arguments = mgp::List(args); auto result = mgp::Result(res); @@ -87,7 +87,7 @@ void Map::FromValues(mgp_list *args, mgp_func_context *ctx, mgp_func_result *res } void Map::SetKey(mgp_list *args, mgp_func_context *ctx, mgp_func_result *res, mgp_memory *memory) { - mgp::MemoryDispatcherGuard guard{memory};; + mgp::MemoryDispatcherGuard guard{memory}; const auto arguments = mgp::List(args); auto result = mgp::Result(res); @@ -124,7 +124,7 @@ void Map::RemoveRecursion(mgp::Map &result, bool recursive, std::string_view key } void Map::RemoveKey(mgp_list *args, mgp_func_context *ctx, mgp_func_result *res, mgp_memory *memory) { - mgp::MemoryDispatcherGuard guard{memory};; + mgp::MemoryDispatcherGuard guard{memory}; const auto arguments = mgp::List(args); auto result = mgp::Result(res); try { @@ -145,7 +145,7 @@ void Map::RemoveKey(mgp_list *args, mgp_func_context *ctx, mgp_func_result *res, } void Map::FromPairs(mgp_list *args, mgp_func_context *ctx, mgp_func_result *res, mgp_memory *memory) { - mgp::MemoryDispatcherGuard guard{memory};; + mgp::MemoryDispatcherGuard guard{memory}; const auto arguments = mgp::List(args); auto result = mgp::Result(res); try { @@ -173,7 +173,7 @@ void Map::FromPairs(mgp_list *args, mgp_func_context *ctx, mgp_func_result *res, } void Map::Merge(mgp_list *args, mgp_func_context *ctx, mgp_func_result *res, mgp_memory *memory) { - mgp::MemoryDispatcherGuard guard{memory};; + mgp::MemoryDispatcherGuard guard{memory}; const auto arguments = mgp::List(args); auto result = mgp::Result(res); try { @@ -208,7 +208,7 @@ void Map::FlattenRecursion(mgp::Map &result, const mgp::Map &input, const std::s } void Map::Flatten(mgp_list *args, mgp_func_context *ctx, mgp_func_result *res, mgp_memory *memory) { - mgp::MemoryDispatcherGuard guard{memory};; + mgp::MemoryDispatcherGuard guard{memory}; const auto arguments = mgp::List(args); auto result = mgp::Result(res); try { @@ -225,7 +225,7 @@ void Map::Flatten(mgp_list *args, mgp_func_context *ctx, mgp_func_result *res, m } void Map::FromLists(mgp_list *args, mgp_func_context *ctx, mgp_func_result *res, mgp_memory *memory) { - mgp::MemoryDispatcherGuard guard{memory};; + mgp::MemoryDispatcherGuard guard{memory}; auto arguments = mgp::List(args); auto result_object = mgp::Result(res); try { @@ -271,7 +271,7 @@ void Map::RemoveRecursionSet(mgp::Map &result, bool recursive, std::unordered_se } void Map::RemoveKeys(mgp_list *args, mgp_func_context *ctx, mgp_func_result *res, mgp_memory *memory) { - mgp::MemoryDispatcherGuard guard{memory};; + mgp::MemoryDispatcherGuard guard{memory}; auto arguments = mgp::List(args); auto result = mgp::Result(res); try { diff --git a/cpp/map_module/map_module.cpp b/cpp/map_module/map_module.cpp index 9245c485b..5c1ec44af 100644 --- a/cpp/map_module/map_module.cpp +++ b/cpp/map_module/map_module.cpp @@ -4,7 +4,7 @@ extern "C" int mgp_init_module(struct mgp_module *module, struct mgp_memory *memory) { try { - mgp::MemoryDispatcherGuard guard{memory};; + mgp::MemoryDispatcherGuard guard{memory}; mgp::AddFunction(Map::Flatten, std::string(Map::kProcedureFlatten).c_str(), {mgp::Parameter(std::string(Map::kArgumentMapFlatten).c_str(), {mgp::Type::Map, mgp::Type::Any}), diff --git a/cpp/memgraph b/cpp/memgraph index da9d6dd8e..eceed274d 160000 --- a/cpp/memgraph +++ b/cpp/memgraph @@ -1 +1 @@ -Subproject commit da9d6dd8e13db91e1c6657270da0a612c4befab4 +Subproject commit eceed274d983d6f135189d945c407b30b6e506a6 diff --git a/cpp/mg_utility/data_structures/graph_view.hpp b/cpp/mg_utility/data_structures/graph_view.hpp index 8f5157efc..9af3ba253 100644 --- a/cpp/mg_utility/data_structures/graph_view.hpp +++ b/cpp/mg_utility/data_structures/graph_view.hpp @@ -1,6 +1,7 @@ #pragma once #include +#include #include #include "graph_data.hpp" @@ -97,9 +98,18 @@ class GraphView { /// ///@param memgraph_id Memgraph's internal ID ///@return TSize + ///@throws mg_exception::InvalidIDException if vertex does not exist /// virtual TSize GetInnerNodeId(std::uint64_t memgraph_id) const = 0; + /// + ///@brief Get the Inner Node ID from Memgraph ID + /// + ///@param memgraph_id Memgraph's internal ID + ///@return std::optional, which is null if vertex does not exist + /// + virtual std::optional GetInnerNodeIdOpt(std::uint64_t memgraph_id) const = 0; + /// ///@brief Get the Memgraph Edge Id from the inner renumbered node ID /// diff --git a/cpp/mg_utility/mg_graph.hpp b/cpp/mg_utility/mg_graph.hpp index d2679fdb3..64e1686ec 100644 --- a/cpp/mg_utility/mg_graph.hpp +++ b/cpp/mg_utility/mg_graph.hpp @@ -199,8 +199,14 @@ class Graph : public GraphView { return std::nullopt; } - auto from = GetInnerNodeId(memgraph_id_from); - auto to = GetInnerNodeId(memgraph_id_to); + auto fromOpt = GetInnerNodeIdOpt(memgraph_id_from); + auto toOpt = GetInnerNodeIdOpt(memgraph_id_to); + if (!fromOpt || !toOpt) { + return std::nullopt; + } + + auto from = *fromOpt; + auto to = *toOpt; auto id = edges_.size(); inner_to_memgraph_edge_id_.emplace(id, edge_id); @@ -314,6 +320,22 @@ class Graph : public GraphView { return memgraph_to_inner_id_.at(memgraph_id); } + /// + /// Returns the GraphView ID from Memgraph's internal ID + /// + /// @param node_id Memgraphs's inner ID + /// + std::optional GetInnerNodeIdOpt(std::uint64_t memgraph_id) const override { + auto it = memgraph_to_inner_id_.find(memgraph_id); + if (it != memgraph_to_inner_id_.end()) { + return it->second; + } + if (IsTransactional()) { + throw mg_exception::InvalidIDException(); + } + return std::nullopt; + } + /// /// Returns the Memgraph database ID from graph view /// @@ -381,6 +403,10 @@ class Graph : public GraphView { nodes_to_edge_.clear(); } + void SetIsTransactional(bool is_transactional) { is_transactional_ = is_transactional; } + + bool IsTransactional() const { return is_transactional_; } + private: // Constant is used for marking deleted edges. // If edge id is equal to constant, edge is deleted. @@ -402,5 +428,7 @@ class Graph : public GraphView { std::unordered_map memgraph_to_inner_edge_id_; std::multimap, TSize> nodes_to_edge_; + + bool is_transactional_; }; } // namespace mg_graph diff --git a/cpp/mg_utility/mg_utils.hpp b/cpp/mg_utility/mg_utils.hpp index 41630a31b..7f81e2cc8 100644 --- a/cpp/mg_utility/mg_utils.hpp +++ b/cpp/mg_utility/mg_utils.hpp @@ -9,9 +9,9 @@ #include #include +#include "_mgp.hpp" #include "mg_graph.hpp" #include "mgp.hpp" -#include "_mgp.hpp" namespace mg_graph { @@ -119,6 +119,7 @@ std::unique_ptr> GetGraphView(mgp_graph *memgraph_graph, const char *weight_property = nullptr, double default_weight = 1.0) { auto graph = std::make_unique>(); + graph->SetIsTransactional(mgp::graph_is_transactional(memgraph_graph)); /// /// Mapping Memgraph in-memory vertices into the graph view @@ -279,12 +280,33 @@ void InsertNodeValueResult(mgp_result_record *record, const char *field_name, mg InsertRecord(record, field_name, value); } +/// @brief Retrieves a node with the given ID to be fed into InsertNodeValueResult. If no node is found, the behavior’s +/// up to the storage mode: +/// * In transactional (ACID-compliant) storage modes one can expect vertices to not be erased -> InvalidIDException +/// * In IN_MEMORY_ANALYTICAL mode, vertices might be erased by parallel transactions -> nullptr +/// @param node_id +/// @param graph +/// @param memory +/// @return +mgp_vertex *GetNodeForInsertion(const int node_id, mgp_graph *graph, mgp_memory *memory) { + auto *vertex = mgp::graph_get_vertex_by_id(graph, mgp_vertex_id{.as_int = static_cast(node_id)}, memory); + if (!vertex && mgp::graph_is_transactional(graph)) { + throw mg_exception::InvalidIDException(); + } + return vertex; +} + /// Inserts a node with its ID node_id to create a vertex and insert /// the node to the field field_name of the record mgp_result_record record. -void InsertNodeValueResult(mgp_graph *graph, mgp_result_record *record, const char *field_name, const int node_id, +/// Returns true is insert is successful, false otherwise +bool InsertNodeValueResult(mgp_graph *graph, mgp_result_record *record, const char *field_name, const int node_id, mgp_memory *memory) { auto *vertex = mgp::graph_get_vertex_by_id(graph, mgp_vertex_id{.as_int = node_id}, memory); + if (!vertex) { + return false; + } InsertNodeValueResult(record, field_name, vertex, memory); + return true; } /// Inserts a relationship of value edge_value to the field field_name of diff --git a/cpp/neighbors_module/algorithm/neighbors.cpp b/cpp/neighbors_module/algorithm/neighbors.cpp index 8a645c6ce..db4323aca 100644 --- a/cpp/neighbors_module/algorithm/neighbors.cpp +++ b/cpp/neighbors_module/algorithm/neighbors.cpp @@ -38,7 +38,7 @@ void DetermineDirection(mgp::List &rel_types, std::unordered_set types, mgp::Rel } void Node::RelationshipExists(mgp_list *args, mgp_graph *memgraph_graph, mgp_result *result, mgp_memory *memory) { - mgp::MemoryDispatcherGuard guard{memory};; + mgp::MemoryDispatcherGuard guard{memory}; const auto arguments = mgp::List(args); const auto record_factory = mgp::RecordFactory(result); try { @@ -165,7 +165,7 @@ void Node::RelationshipExists(mgp_list *args, mgp_graph *memgraph_graph, mgp_res } void Node::RelationshipTypes(mgp_list *args, mgp_graph *memgraph_graph, mgp_result *result, mgp_memory *memory) { - mgp::MemoryDispatcherGuard guard{memory};; + mgp::MemoryDispatcherGuard guard{memory}; const auto arguments = mgp::List(args); const auto record_factory = mgp::RecordFactory(result); try { diff --git a/cpp/node_module/node_module.cpp b/cpp/node_module/node_module.cpp index 3ca023707..df7c70467 100644 --- a/cpp/node_module/node_module.cpp +++ b/cpp/node_module/node_module.cpp @@ -4,9 +4,7 @@ extern "C" int mgp_init_module(struct mgp_module *module, struct mgp_memory *memory) { try { - mgp::MemoryDispatcherGuard guard{memory}; - AddProcedure(Node::RelationshipsExist, std::string(Node::kProcedureRelationshipsExist).c_str(), mgp::ProcedureType::Read, {mgp::Parameter(std::string(Node::kArgumentNodesRelationshipsExist).c_str(), mgp::Type::Node), diff --git a/cpp/node_similarity_module/node_similarity_module.cpp b/cpp/node_similarity_module/node_similarity_module.cpp index dd2182c46..a57892386 100644 --- a/cpp/node_similarity_module/node_similarity_module.cpp +++ b/cpp/node_similarity_module/node_similarity_module.cpp @@ -38,7 +38,7 @@ void insert_results(const std::vector> Calculates Jaccard similarity between given pairs of nodes. */ void JaccardPairwise(mgp_list *args, mgp_graph *memgraph_graph, mgp_result *result, mgp_memory *memory) { - mgp::MemoryDispatcherGuard guard{memory};; + mgp::MemoryDispatcherGuard guard{memory}; const auto record_factory = mgp::RecordFactory(result); const auto &arguments = mgp::List(args); try { @@ -52,7 +52,7 @@ void JaccardPairwise(mgp_list *args, mgp_graph *memgraph_graph, mgp_result *resu Calculates overlap similarity between given pairs of nodes. */ void OverlapPairwise(mgp_list *args, mgp_graph *memgraph_graph, mgp_result *result, mgp_memory *memory) { - mgp::MemoryDispatcherGuard guard{memory};; + mgp::MemoryDispatcherGuard guard{memory}; const auto &arguments = mgp::List(args); const auto record_factory = mgp::RecordFactory(result); try { @@ -67,7 +67,7 @@ Calculates Jaccard similarity between all pairs of nodes. Jacc. similarity of two nodes can be calculated as len(intersection(neighbours(node1), neighbours(node2))) / len(union(neighbours(node1), neighbours(node2))) */ void Jaccard(mgp_list *args, mgp_graph *memgraph_graph, mgp_result *result, mgp_memory *memory) { - mgp::MemoryDispatcherGuard guard{memory};; + mgp::MemoryDispatcherGuard guard{memory}; const auto record_factory = mgp::RecordFactory(result); try { insert_results(node_similarity_algs::CalculateSimilarityCartesian(mgp::Graph(memgraph_graph), node_similarity_util::Similarity::jaccard), record_factory); @@ -81,7 +81,7 @@ Calculates overlap similarity between all pairs of nodes. Overlap similarity of two nodes can be calculated as len(intersection(neighbours(node1), neighbours(node2))) / min(len(neighbours(node1), len(node2))) */ void Overlap(mgp_list *args, mgp_graph *memgraph_graph, mgp_result *result, mgp_memory *memory) { - mgp::MemoryDispatcherGuard guard{memory};; + mgp::MemoryDispatcherGuard guard{memory}; const auto record_factory = mgp::RecordFactory(result); try { insert_results(node_similarity_algs::CalculateSimilarityCartesian(mgp::Graph(memgraph_graph), node_similarity_util::Similarity::overlap), record_factory); @@ -95,7 +95,7 @@ void Overlap(mgp_list *args, mgp_graph *memgraph_graph, mgp_result *result, mgp_ Calculates cosine similarity between all pairs of nodes. */ void Cosine(mgp_list *args, mgp_graph *memgraph_graph, mgp_result *result, mgp_memory *memory) { - mgp::MemoryDispatcherGuard guard{memory};; + mgp::MemoryDispatcherGuard guard{memory}; const auto record_factory = mgp::RecordFactory(result); const auto &arguments = mgp::List(args); try { @@ -109,7 +109,7 @@ void Cosine(mgp_list *args, mgp_graph *memgraph_graph, mgp_result *result, mgp_m Calculates overlap similarity between given pairs of nodes. */ void CosinePairwise(mgp_list *args, mgp_graph *memgraph_graph, mgp_result *result, mgp_memory *memory) { - mgp::MemoryDispatcherGuard guard{memory};; + mgp::MemoryDispatcherGuard guard{memory}; const auto record_factory = mgp::RecordFactory(result); const auto &arguments = mgp::List(args); try { @@ -121,7 +121,7 @@ void CosinePairwise(mgp_list *args, mgp_graph *memgraph_graph, mgp_result *resul extern "C" int mgp_init_module(struct mgp_module *module, struct mgp_memory *memory) { try { - mgp::MemoryDispatcherGuard guard{memory};; + mgp::MemoryDispatcherGuard guard{memory}; // method objects std::vector returns = { mgp::Return(node1_name, mgp::Type::Node), diff --git a/cpp/nodes_module/algorithm/nodes.cpp b/cpp/nodes_module/algorithm/nodes.cpp index ddac2b326..117649690 100644 --- a/cpp/nodes_module/algorithm/nodes.cpp +++ b/cpp/nodes_module/algorithm/nodes.cpp @@ -27,7 +27,7 @@ bool Nodes::RelationshipExist(const mgp::Node &node, std::string &rel_type) { } void Nodes::RelationshipsExist(mgp_list *args, mgp_graph *memgraph_graph, mgp_result *result, mgp_memory *memory) { - mgp::MemoryDispatcherGuard guard{memory};; + mgp::MemoryDispatcherGuard guard{memory}; const auto arguments = mgp::List(args); const auto record_factory = mgp::RecordFactory(result); try { @@ -167,7 +167,7 @@ void DetachDeleteNode(const mgp::Value &node, mgp::Graph &graph) { } // namespace void Nodes::RelationshipTypes(mgp_list *args, mgp_graph *memgraph_graph, mgp_result *result, mgp_memory *memory) { - mgp::MemoryDispatcherGuard guard{memory};; + mgp::MemoryDispatcherGuard guard{memory}; const auto arguments = mgp::List(args); const auto record_factory = mgp::RecordFactory(result); try { @@ -182,7 +182,7 @@ void Nodes::RelationshipTypes(mgp_list *args, mgp_graph *memgraph_graph, mgp_res } void Nodes::Delete(mgp_list *args, mgp_graph *memgraph_graph, mgp_result *result, mgp_memory *memory) { - mgp::MemoryDispatcherGuard guard{memory};; + mgp::MemoryDispatcherGuard guard{memory}; const auto arguments = mgp::List(args); const auto record_factory = mgp::RecordFactory(result); try { @@ -206,7 +206,7 @@ void Nodes::Delete(mgp_list *args, mgp_graph *memgraph_graph, mgp_result *result void Nodes::Link(mgp_list *args, mgp_graph *memgraph_graph, mgp_result *result, mgp_memory *memory) { - mgp::MemoryDispatcherGuard guard{memory};; + mgp::MemoryDispatcherGuard guard{memory}; const auto arguments = mgp::List(args); const auto record_factory = mgp::RecordFactory(result); try { diff --git a/cpp/nodes_module/nodes_module.cpp b/cpp/nodes_module/nodes_module.cpp index aa381e0fc..53eb2c0db 100644 --- a/cpp/nodes_module/nodes_module.cpp +++ b/cpp/nodes_module/nodes_module.cpp @@ -5,7 +5,7 @@ extern "C" int mgp_init_module(struct mgp_module *module, struct mgp_memory *memory) { try { - mgp::MemoryDispatcherGuard guard{memory};; + mgp::MemoryDispatcherGuard guard{memory}; AddProcedure(Nodes::Link, std::string(Nodes::kProcedureLink).c_str(), mgp::ProcedureType::Write, {mgp::Parameter(std::string(Nodes::kArgumentNodesLink).c_str(), {mgp::Type::List, mgp::Type::Node}), diff --git a/cpp/pagerank_module/pagerank_module.cpp b/cpp/pagerank_module/pagerank_module.cpp index a07694062..6a58f8e10 100644 --- a/cpp/pagerank_module/pagerank_module.cpp +++ b/cpp/pagerank_module/pagerank_module.cpp @@ -14,9 +14,18 @@ constexpr char const *kArgumentStopEpsilon = "stop_epsilon"; void InsertPagerankRecord(mgp_graph *graph, mgp_result *result, mgp_memory *memory, const std::uint64_t node_id, double rank) { + auto *vertex = mgp::graph_get_vertex_by_id(graph, mgp_vertex_id{.as_int = static_cast(node_id)}, memory); + if (!vertex) { + if (mgp::graph_is_transactional(graph)) { + throw mg_exception::InvalidIDException(); + } + return; + } + auto *record = mgp::result_new_record(result); + if (record == nullptr) throw mg_exception::NotEnoughMemoryException(); - mg_utility::InsertNodeValueResult(graph, record, kFieldNode, node_id, memory); + mg_utility::InsertNodeValueResult(record, kFieldNode, vertex, memory); mg_utility::InsertDoubleValueResult(record, kFieldRank, rank, memory); } diff --git a/cpp/pagerank_module/pagerank_online_module.cpp b/cpp/pagerank_module/pagerank_online_module.cpp index a904bf3ad..1e96d5497 100644 --- a/cpp/pagerank_module/pagerank_online_module.cpp +++ b/cpp/pagerank_module/pagerank_online_module.cpp @@ -21,9 +21,18 @@ constexpr char const *kArgumentDeletedEdges = "deleted_edges"; void InsertPageRankRecord(mgp_graph *graph, mgp_result *result, mgp_memory *memory, const std::uint64_t node_id, const double rank) { - auto *record = mgp::result_new_record(result); + auto *node = mgp::graph_get_vertex_by_id(graph, mgp_vertex_id{.as_int = static_cast(node_id)}, memory); + if (!node) { + if (mgp::graph_is_transactional(graph)) { + throw mg_exception::InvalidIDException(); + } + return; + } - mg_utility::InsertNodeValueResult(graph, record, kFieldNode, node_id, memory); + auto *record = mgp::result_new_record(result); + if (record == nullptr) throw mg_exception::NotEnoughMemoryException(); + + mg_utility::InsertNodeValueResult(record, kFieldNode, node, memory); mg_utility::InsertDoubleValueResult(record, kFieldRank, rank, memory); } @@ -69,7 +78,7 @@ void OnlinePageRankSet(mgp_list *args, mgp_graph *memgraph_graph, mgp_result *re void OnlinePageRankUpdate(mgp_list *args, mgp_graph *memgraph_graph, mgp_result *result, mgp_memory *memory) { try { - mgp::MemoryDispatcherGuard guard{memory};; + mgp::MemoryDispatcherGuard guard{memory}; const auto graph = mgp::Graph(memgraph_graph); const auto arguments = mgp::List(args); @@ -111,9 +120,18 @@ void OnlinePageRankUpdate(mgp_list *args, mgp_graph *memgraph_graph, mgp_result } for (auto const &[node_id, rank] : pageranks) { - auto record = record_factory.NewRecord(); - record.Insert(kFieldNode, graph.GetNodeById(mgp::Id::FromUint(node_id))); - record.Insert(kFieldRank, rank); + // As IN_MEMORY_ANALYTICAL doesn’t offer ACID guarantees, check if the graph elements in the result exist + try { + // If so, throw an exception: + const auto node = graph.GetNodeById(mgp::Id::FromUint(node_id)); + + // Otherwise: + auto record = record_factory.NewRecord(); + record.Insert(kFieldNode, node); + record.Insert(kFieldRank, rank); + } catch (const std::exception &e) { + continue; + } } } catch (const std::exception &e) { mgp::result_set_error_msg(result, e.what()); diff --git a/cpp/periodic_module/periodic_iterate.cpp b/cpp/periodic_module/periodic_iterate.cpp index 69de092d8..4ddeccc0e 100644 --- a/cpp/periodic_module/periodic_iterate.cpp +++ b/cpp/periodic_module/periodic_iterate.cpp @@ -226,7 +226,7 @@ mg::Client::Params GetClientParams() { } void PeriodicIterate(mgp_list *args, mgp_graph *memgraph_graph, mgp_result *result, mgp_memory *memory) { - mgp::MemoryDispatcherGuard guard{memory};; + mgp::MemoryDispatcherGuard guard{memory}; const auto arguments = mgp::List(args); auto num_of_executed_batches = 0; @@ -296,7 +296,7 @@ void PeriodicIterate(mgp_list *args, mgp_graph *memgraph_graph, mgp_result *resu extern "C" int mgp_init_module(struct mgp_module *module, struct mgp_memory *memory) { try { - mgp::MemoryDispatcherGuard guard{memory};; + mgp::MemoryDispatcherGuard guard{memory}; mgp::AddProcedure( PeriodicIterate, kProcedurePeriodic, mgp::ProcedureType::Read, {mgp::Parameter(kArgumentInputQuery, mgp::Type::String), diff --git a/cpp/refactor_module/algorithm/refactor.cpp b/cpp/refactor_module/algorithm/refactor.cpp index c7600a6b9..762717800 100644 --- a/cpp/refactor_module/algorithm/refactor.cpp +++ b/cpp/refactor_module/algorithm/refactor.cpp @@ -115,10 +115,19 @@ void Refactor::RenameNodeProperty(mgp_list *args, mgp_graph *memgraph_graph, mgp void Refactor::InsertCloneNodesRecord(mgp_graph *graph, mgp_result *result, mgp_memory *memory, const int cycle_id, const int node_id) { + auto *node = mgp::graph_get_vertex_by_id(graph, mgp_vertex_id{.as_int = static_cast(node_id)}, memory); + if (!node) { + if (mgp::graph_is_transactional(graph)) { + throw mg_exception::InvalidIDException(); + } + return; + } + auto *record = mgp::result_new_record(result); + if (record == nullptr) throw mg_exception::NotEnoughMemoryException(); mg_utility::InsertIntValueResult(record, std::string(kResultClonedNodeId).c_str(), cycle_id, memory); - mg_utility::InsertNodeValueResult(graph, record, std::string(kResultNewNode).c_str(), node_id, memory); + mg_utility::InsertNodeValueResult(record, std::string(kResultNewNode).c_str(), node, memory); mg_utility::InsertStringValueResult(record, std::string(kResultCloneNodeError).c_str(), "", memory); } diff --git a/cpp/text_module/text_module.cpp b/cpp/text_module/text_module.cpp index fc2fc9078..84958a967 100644 --- a/cpp/text_module/text_module.cpp +++ b/cpp/text_module/text_module.cpp @@ -4,7 +4,7 @@ extern "C" int mgp_init_module(struct mgp_module *module, struct mgp_memory *memory) { try { - mgp::MemoryDispatcherGuard guard{memory};; + mgp::MemoryDispatcherGuard guard{memory}; AddProcedure(Text::Join, Text::kProcedureJoin, mgp::ProcedureType::Read, {mgp::Parameter(Text::kJoinArg1, {mgp::Type::List, mgp::Type::String}), diff --git a/cpp/util_module/algorithm/util.cpp b/cpp/util_module/algorithm/util.cpp index 50b480de6..612111c8d 100644 --- a/cpp/util_module/algorithm/util.cpp +++ b/cpp/util_module/algorithm/util.cpp @@ -2,7 +2,7 @@ #include "md5.hpp" void Util::Md5(mgp_list *args, mgp_graph *memgraph_graph, mgp_result *result, mgp_memory *memory) { - mgp::MemoryDispatcherGuard guard{memory};; + mgp::MemoryDispatcherGuard guard{memory}; const auto arguments = mgp::List(args); const auto record_factory = mgp::RecordFactory(result); try { diff --git a/cpp/util_module/util_module.cpp b/cpp/util_module/util_module.cpp index b7a028849..4f9ec3706 100644 --- a/cpp/util_module/util_module.cpp +++ b/cpp/util_module/util_module.cpp @@ -4,7 +4,7 @@ extern "C" int mgp_init_module(struct mgp_module *module, struct mgp_memory *memory) { try { - mgp::MemoryDispatcherGuard guard{memory};; + mgp::MemoryDispatcherGuard guard{memory}; AddProcedure(Util::Md5, std::string(Util::kProcedureMd5).c_str(), mgp::ProcedureType::Write, {mgp::Parameter(std::string(Util::kArgumentValuesMd5).c_str(), {mgp::Type::List, mgp::Type::Any})}, {mgp::Return(std::string(Util::kArgumentResultMd5).c_str(), mgp::Type::String)}, module, memory); diff --git a/rust/rsmgp-sys/mgp/mg_procedure.h b/rust/rsmgp-sys/mgp/mg_procedure.h index ca24b737d..b1d4e323a 100644 --- a/rust/rsmgp-sys/mgp/mg_procedure.h +++ b/rust/rsmgp-sys/mgp/mg_procedure.h @@ -814,6 +814,12 @@ enum mgp_error mgp_graph_get_vertex_by_id(struct mgp_graph *g, struct mgp_vertex /// Current implementation always returns without errors. enum mgp_error mgp_graph_is_mutable(struct mgp_graph *graph, int *result); +/// Result is non-zero if the graph is in transactional storage mode. +/// If a graph is not in transactional mode (i.e. analytical mode), then vertices and edges can be missing +/// because changes from other transactions are visible. +/// Current implementation always returns without errors. +enum mgp_error mgp_graph_is_transactional(struct mgp_graph *graph, int *result); + /// Add a new vertex to the graph. /// Resulting vertex must be freed using mgp_vertex_destroy. /// Return MGP_ERROR_IMMUTABLE_OBJECT if `graph` is immutable.