From 281cebd38681d791f2207d0b48216e3e482ad194 Mon Sep 17 00:00:00 2001 From: gvolfing <107616712+gvolfing@users.noreply.github.com> Date: Thu, 20 Oct 2022 17:51:44 +0200 Subject: [PATCH] Add filtering capabilities to ExpandOne request (#581) --- src/query/v2/requests.hpp | 9 +- src/storage/v3/shard_rsm.cpp | 200 ++++++++++++++++++++++++--------- src/storage/v3/vertex_id.hpp | 7 ++ tests/simulation/shard_rsm.cpp | 180 ++++++++++++++++++++++++++--- 4 files changed, 319 insertions(+), 77 deletions(-) diff --git a/src/query/v2/requests.hpp b/src/query/v2/requests.hpp index d8a8ed287..12fa2ea95 100644 --- a/src/query/v2/requests.hpp +++ b/src/query/v2/requests.hpp @@ -399,13 +399,14 @@ struct ExpandOneRequest { std::optional<std::vector<PropertyId>> src_vertex_properties; // The empty optional means return all of the properties, while an empty list means do not return any properties std::optional<std::vector<PropertyId>> edge_properties; - // QUESTION(antaljanosbenjamin): Maybe also add possibility to expressions evaluated on the source vertex? - // List of expressions evaluated on edges - std::vector<Expression> expressions; + + std::vector<std::string> vertex_expressions; + std::vector<std::string> edge_expressions; + std::optional<std::vector<OrderBy>> order_by; // Limit the edges or the vertices? std::optional<size_t> limit; - std::optional<Filter> filter; + std::vector<std::string> filters; }; struct ExpandOneResultRow { diff --git a/src/storage/v3/shard_rsm.cpp b/src/storage/v3/shard_rsm.cpp index 1e5609b23..f598c6c54 100644 --- a/src/storage/v3/shard_rsm.cpp +++ b/src/storage/v3/shard_rsm.cpp @@ -12,6 +12,7 @@ #include <algorithm> #include <functional> #include <iterator> +#include <unordered_set> #include <utility> #include "parser/opencypher/parser.hpp" @@ -50,6 +51,24 @@ using conversions::ToPropertyValue; namespace { namespace msgs = msgs; +using AllEdgePropertyDataSructure = std::map<PropertyId, msgs::Value>; +using SpecificEdgePropertyDataSructure = std::vector<msgs::Value>; + +using AllEdgeProperties = std::tuple<msgs::VertexId, msgs::Gid, AllEdgePropertyDataSructure>; +using SpecificEdgeProperties = std::tuple<msgs::VertexId, msgs::Gid, SpecificEdgePropertyDataSructure>; + +using SpecificEdgePropertiesVector = std::vector<SpecificEdgeProperties>; +using AllEdgePropertiesVector = std::vector<AllEdgeProperties>; + +using EdgeAccessors = std::vector<memgraph::storage::v3::EdgeAccessor>; + +using EdgeFiller = std::function<bool(const EdgeAccessor &edge, bool is_in_edge, msgs::ExpandOneResultRow &result_row)>; +using EdgeUniqunessFunction = std::function<EdgeAccessors(EdgeAccessors &&, memgraph::msgs::EdgeDirection)>; + +struct VertexIdCmpr { + bool operator()(const storage::v3::VertexId *lhs, const storage::v3::VertexId *rhs) const { return *lhs < *rhs; } +}; + std::vector<std::pair<PropertyId, PropertyValue>> ConvertPropertyMap( std::vector<std::pair<PropertyId, Value>> &&properties) { std::vector<std::pair<PropertyId, PropertyValue>> ret; @@ -392,7 +411,8 @@ std::optional<std::map<PropertyId, Value>> FillUpSourceVertexProperties(const st } std::optional<std::array<std::vector<EdgeAccessor>, 2>> FillUpConnectingEdges( - const std::optional<VertexAccessor> &v_acc, const msgs::ExpandOneRequest &req) { + const std::optional<VertexAccessor> &v_acc, const msgs::ExpandOneRequest &req, + const EdgeUniqunessFunction &maybe_filter_based_on_edge_uniquness) { std::vector<EdgeAccessor> in_edges; std::vector<EdgeAccessor> out_edges; @@ -404,7 +424,8 @@ std::optional<std::array<std::vector<EdgeAccessor>, 2>> FillUpConnectingEdges( req.transaction_id.logical_id); return std::nullopt; } - out_edges = std::move(out_edges_result.GetValue()); + out_edges = + maybe_filter_based_on_edge_uniquness(std::move(out_edges_result.GetValue()), msgs::EdgeDirection::OUT); break; } case msgs::EdgeDirection::IN: { @@ -415,7 +436,7 @@ std::optional<std::array<std::vector<EdgeAccessor>, 2>> FillUpConnectingEdges( .logical_id]); return std::nullopt; } - in_edges = std::move(in_edges_result.GetValue()); + in_edges = maybe_filter_based_on_edge_uniquness(std::move(in_edges_result.GetValue()), msgs::EdgeDirection::IN); break; } case msgs::EdgeDirection::BOTH: { @@ -425,7 +446,7 @@ std::optional<std::array<std::vector<EdgeAccessor>, 2>> FillUpConnectingEdges( req.transaction_id.logical_id); return std::nullopt; } - in_edges = std::move(in_edges_result.GetValue()); + in_edges = maybe_filter_based_on_edge_uniquness(std::move(in_edges_result.GetValue()), msgs::EdgeDirection::IN); auto out_edges_result = v_acc->OutEdges(View::NEW); if (out_edges_result.HasError()) { @@ -433,24 +454,14 @@ std::optional<std::array<std::vector<EdgeAccessor>, 2>> FillUpConnectingEdges( req.transaction_id.logical_id); return std::nullopt; } - out_edges = std::move(out_edges_result.GetValue()); + out_edges = + maybe_filter_based_on_edge_uniquness(std::move(out_edges_result.GetValue()), msgs::EdgeDirection::OUT); break; } } return std::array<std::vector<EdgeAccessor>, 2>{in_edges, out_edges}; } -using AllEdgePropertyDataSructure = std::map<PropertyId, msgs::Value>; -using SpecificEdgePropertyDataSructure = std::vector<msgs::Value>; - -using AllEdgeProperties = std::tuple<msgs::VertexId, msgs::Gid, AllEdgePropertyDataSructure>; -using SpecificEdgeProperties = std::tuple<msgs::VertexId, msgs::Gid, SpecificEdgePropertyDataSructure>; - -using SpecificEdgePropertiesVector = std::vector<SpecificEdgeProperties>; -using AllEdgePropertiesVector = std::vector<AllEdgeProperties>; - -using EdgeFiller = std::function<bool(const EdgeAccessor &edge, bool is_in_edge, msgs::ExpandOneResultRow &result_row)>; - template <bool are_in_edges> bool FillEdges(const std::vector<EdgeAccessor> &edges, const msgs::ExpandOneRequest &req, msgs::ExpandOneResultRow &row, const EdgeFiller &edge_filler) { @@ -467,8 +478,101 @@ bool FillEdges(const std::vector<EdgeAccessor> &edges, const msgs::ExpandOneRequ return true; } -std::optional<msgs::ExpandOneResultRow> GetExpandOneResult(Shard::Accessor &acc, msgs::VertexId src_vertex, - const msgs::ExpandOneRequest &req) { +std::optional<msgs::ExpandOneResultRow> GetExpandOneResult( + Shard::Accessor &acc, msgs::VertexId src_vertex, const msgs::ExpandOneRequest &req, + const EdgeUniqunessFunction &maybe_filter_based_on_edge_uniquness, const EdgeFiller &edge_filler) { + /// Fill up source vertex + const auto primary_key = ConvertPropertyVector(std::move(src_vertex.second)); + auto v_acc = acc.FindVertex(primary_key, View::NEW); + + auto source_vertex = FillUpSourceVertex(v_acc, req, src_vertex); + if (!source_vertex) { + return std::nullopt; + } + + /// Fill up source vertex properties + auto src_vertex_properties = FillUpSourceVertexProperties(v_acc, req); + if (!src_vertex_properties) { + return std::nullopt; + } + + /// Fill up connecting edges + auto fill_up_connecting_edges = FillUpConnectingEdges(v_acc, req, maybe_filter_based_on_edge_uniquness); + if (!fill_up_connecting_edges) { + return std::nullopt; + } + + auto [in_edges, out_edges] = fill_up_connecting_edges.value(); + + msgs::ExpandOneResultRow result_row; + result_row.src_vertex = std::move(*source_vertex); + result_row.src_vertex_properties = std::move(*src_vertex_properties); + static constexpr bool kInEdges = true; + static constexpr bool kOutEdges = false; + if (!in_edges.empty() && !FillEdges<kInEdges>(in_edges, req, result_row, edge_filler)) { + return std::nullopt; + } + if (!out_edges.empty() && !FillEdges<kOutEdges>(out_edges, req, result_row, edge_filler)) { + return std::nullopt; + } + + return result_row; +} + +EdgeUniqunessFunction InitializeEdgeUniqunessFunction(bool only_unique_neighbor_rows) { + // Functions to select connecting edges based on uniquness + EdgeUniqunessFunction maybe_filter_based_on_edge_uniquness; + + if (only_unique_neighbor_rows) { + maybe_filter_based_on_edge_uniquness = [](EdgeAccessors &&edges, + memgraph::msgs::EdgeDirection edge_direction) -> EdgeAccessors { + std::function<bool(std::set<const storage::v3::VertexId *, VertexIdCmpr> &, + const memgraph::storage::v3::EdgeAccessor &)> + is_edge_unique; + switch (edge_direction) { + case memgraph::msgs::EdgeDirection::OUT: { + is_edge_unique = [](std::set<const storage::v3::VertexId *, VertexIdCmpr> &other_vertex_set, + const memgraph::storage::v3::EdgeAccessor &edge_acc) { + auto [it, insertion_happened] = other_vertex_set.insert(&edge_acc.ToVertex()); + return insertion_happened; + }; + break; + } + case memgraph::msgs::EdgeDirection::IN: { + is_edge_unique = [](std::set<const storage::v3::VertexId *, VertexIdCmpr> &other_vertex_set, + const memgraph::storage::v3::EdgeAccessor &edge_acc) { + auto [it, insertion_happened] = other_vertex_set.insert(&edge_acc.FromVertex()); + return insertion_happened; + }; + break; + } + case memgraph::msgs::EdgeDirection::BOTH: + MG_ASSERT(false, + "This is should never happen, memgraph::msgs::EdgeDirection::BOTH should not be passed here."); + } + + EdgeAccessors ret; + std::set<const storage::v3::VertexId *, VertexIdCmpr> other_vertex_set; + + for (const auto &edge : edges) { + if (is_edge_unique(other_vertex_set, edge)) { + ret.emplace_back(edge); + } + } + + return ret; + }; + } else { + maybe_filter_based_on_edge_uniquness = [](EdgeAccessors &&edges, + memgraph::msgs::EdgeDirection /*edge_direction*/) -> EdgeAccessors { + return std::move(edges); + }; + } + + return maybe_filter_based_on_edge_uniquness; +} + +EdgeFiller InitializeEdgeFillerFunction(const msgs::ExpandOneRequest &req) { EdgeFiller edge_filler; if (!req.edge_properties) { @@ -521,43 +625,9 @@ std::optional<msgs::ExpandOneResultRow> GetExpandOneResult(Shard::Accessor &acc, }; } - /// Fill up source vertex - const auto primary_key = ConvertPropertyVector(std::move(src_vertex.second)); - auto v_acc = acc.FindVertex(primary_key, View::NEW); - - auto source_vertex = FillUpSourceVertex(v_acc, req, src_vertex); - if (!source_vertex) { - return std::nullopt; - } - - /// Fill up source vertex properties - auto src_vertex_properties = FillUpSourceVertexProperties(v_acc, req); - if (!src_vertex_properties) { - return std::nullopt; - } - - /// Fill up connecting edges - auto fill_up_connecting_edges = FillUpConnectingEdges(v_acc, req); - if (!fill_up_connecting_edges) { - return std::nullopt; - } - - auto [in_edges, out_edges] = fill_up_connecting_edges.value(); - - msgs::ExpandOneResultRow result_row; - result_row.src_vertex = std::move(*source_vertex); - result_row.src_vertex_properties = std::move(*src_vertex_properties); - static constexpr bool kInEdges = true; - static constexpr bool kOutEdges = false; - if (!in_edges.empty() && !FillEdges<kInEdges>(in_edges, req, result_row, edge_filler)) { - return std::nullopt; - } - if (!out_edges.empty() && !FillEdges<kOutEdges>(out_edges, req, result_row, edge_filler)) { - return std::nullopt; - } - - return result_row; + return edge_filler; } + }; // namespace msgs::WriteResponses ShardRsm::ApplyWrite(msgs::CreateVerticesRequest &&req) { auto acc = shard_->Access(req.transaction_id); @@ -939,8 +1009,28 @@ msgs::ReadResponses ShardRsm::HandleRead(msgs::ExpandOneRequest &&req) { std::vector<msgs::ExpandOneResultRow> results; + auto maybe_filter_based_on_edge_uniquness = InitializeEdgeUniqunessFunction(req.only_unique_neighbor_rows); + auto edge_filler = InitializeEdgeFillerFunction(req); + for (auto &src_vertex : req.src_vertices) { - auto result = GetExpandOneResult(acc, src_vertex, req); + // Get Vertex acc + auto src_vertex_acc_opt = acc.FindVertex(ConvertPropertyVector((src_vertex.second)), View::NEW); + if (!src_vertex_acc_opt) { + action_successful = false; + spdlog::debug("Encountered an error while trying to obtain VertexAccessor. Transaction id: {}", + req.transaction_id.logical_id); + break; + } + + if (!req.filters.empty()) { + // NOTE - DbAccessor might get removed in the future. + auto dba = DbAccessor{&acc}; + const bool eval = FilterOnVertex(dba, src_vertex_acc_opt.value(), req.filters, expr::identifier_node_symbol); + if (!eval) { + continue; + } + } + auto result = GetExpandOneResult(acc, src_vertex, req, maybe_filter_based_on_edge_uniquness, edge_filler); if (!result) { action_successful = false; diff --git a/src/storage/v3/vertex_id.hpp b/src/storage/v3/vertex_id.hpp index 70dc85ec8..7c136f662 100644 --- a/src/storage/v3/vertex_id.hpp +++ b/src/storage/v3/vertex_id.hpp @@ -11,6 +11,8 @@ #pragma once +#include <tuple> + #include "storage/v3/id_types.hpp" #include "storage/v3/key_store.hpp" @@ -29,4 +31,9 @@ struct VertexId { inline bool operator==(const VertexId &lhs, const VertexId &rhs) { return lhs.primary_label == rhs.primary_label && lhs.primary_key == rhs.primary_key; } + +inline bool operator<(const VertexId &lhs, const VertexId &rhs) { + return std::tie(lhs.primary_label, lhs.primary_key) < std::tie(rhs.primary_label, rhs.primary_key); +} + } // namespace memgraph::storage::v3 diff --git a/tests/simulation/shard_rsm.cpp b/tests/simulation/shard_rsm.cpp index 953e0579a..aec26f6c1 100644 --- a/tests/simulation/shard_rsm.cpp +++ b/tests/simulation/shard_rsm.cpp @@ -463,18 +463,18 @@ void AttemptToExpandOneWithWrongEdgeType(ShardClient &client, uint64_t src_verte // Edge properties to look for std::optional<std::vector<PropertyId>> edge_properties = {}; - std::vector<msgs::Expression> expressions; + std::vector<std::string> expressions; std::optional<std::vector<msgs::OrderBy>> order_by = {}; std::optional<size_t> limit = {}; - std::optional<msgs::Filter> filter = {}; + std::vector<std::string> filter = {}; msgs::ExpandOneRequest expand_one_req{}; expand_one_req.direction = edge_direction; expand_one_req.edge_properties = edge_properties; expand_one_req.edge_types = {edge_type}; - expand_one_req.expressions = expressions; - expand_one_req.filter = filter; + expand_one_req.vertex_expressions = expressions; + expand_one_req.filters = filter; expand_one_req.limit = limit; expand_one_req.order_by = order_by; expand_one_req.src_vertex_properties = src_vertex_properties; @@ -518,18 +518,18 @@ void AttemptToExpandOneSimple(ShardClient &client, uint64_t src_vertex_val, Edge // Edge properties to look for std::optional<std::vector<PropertyId>> edge_properties = {}; - std::vector<msgs::Expression> expressions; + std::vector<std::string> expressions; std::optional<std::vector<msgs::OrderBy>> order_by = {}; std::optional<size_t> limit = {}; - std::optional<msgs::Filter> filter = {}; + std::vector<std::string> filter = {}; msgs::ExpandOneRequest expand_one_req{}; expand_one_req.direction = edge_direction; expand_one_req.edge_properties = edge_properties; expand_one_req.edge_types = {edge_type}; - expand_one_req.expressions = expressions; - expand_one_req.filter = filter; + expand_one_req.vertex_expressions = expressions; + expand_one_req.filters = filter; expand_one_req.limit = limit; expand_one_req.order_by = order_by; expand_one_req.src_vertex_properties = src_vertex_properties; @@ -556,6 +556,63 @@ void AttemptToExpandOneSimple(ShardClient &client, uint64_t src_vertex_val, Edge } } +void AttemptToExpandOneWithUniqueEdges(ShardClient &client, uint64_t src_vertex_val, EdgeTypeId edge_type_id) { + // Source vertex + msgs::Label label = {.id = get_primary_label()}; + auto src_vertex = std::make_pair(label, GetPrimaryKey(src_vertex_val)); + + // Edge type + auto edge_type = msgs::EdgeType{}; + edge_type.id = edge_type_id; + + // Edge direction + auto edge_direction = msgs::EdgeDirection::OUT; + + // Source Vertex properties to look for + std::optional<std::vector<PropertyId>> src_vertex_properties = {}; + + // Edge properties to look for + std::optional<std::vector<PropertyId>> edge_properties = {}; + + std::vector<std::string> expressions; + std::optional<std::vector<msgs::OrderBy>> order_by = {}; + std::optional<size_t> limit = {}; + std::vector<std::string> filter = {}; + + msgs::ExpandOneRequest expand_one_req{}; + + expand_one_req.direction = edge_direction; + expand_one_req.edge_properties = edge_properties; + expand_one_req.edge_types = {edge_type}; + expand_one_req.vertex_expressions = expressions; + expand_one_req.filters = filter; + expand_one_req.limit = limit; + expand_one_req.order_by = order_by; + expand_one_req.src_vertex_properties = src_vertex_properties; + expand_one_req.src_vertices = {src_vertex}; + expand_one_req.only_unique_neighbor_rows = true; + expand_one_req.transaction_id.logical_id = GetTransactionId(); + + while (true) { + auto read_res = client.SendReadRequest(expand_one_req); + if (read_res.HasError()) { + continue; + } + + auto write_response_result = read_res.GetValue(); + auto write_response = std::get<msgs::ExpandOneResponse>(write_response_result); + MG_ASSERT(write_response.result.size() == 1); + MG_ASSERT(write_response.result[0].out_edges_with_all_properties.size() == 1); + MG_ASSERT(write_response.result[0].in_edges_with_all_properties.empty()); + MG_ASSERT(write_response.result[0].in_edges_with_specific_properties.empty()); + MG_ASSERT(write_response.result[0].out_edges_with_specific_properties.empty()); + const auto number_of_properties_on_edge = + (write_response.result[0].out_edges_with_all_properties[0]).properties.size(); + MG_ASSERT(number_of_properties_on_edge == 1); + break; + } +} + void AttemptToExpandOneWithSpecifiedSrcVertexProperties(ShardClient &client, uint64_t src_vertex_val, EdgeTypeId edge_type_id) { // Source vertex @@ -576,18 +633,18 @@ void AttemptToExpandOneWithSpecifiedSrcVertexProperties(ShardClient &client, uin // Edge properties to look for std::optional<std::vector<PropertyId>> edge_properties = {}; - std::vector<msgs::Expression> expressions; + std::vector<std::string> expressions; std::optional<std::vector<msgs::OrderBy>> order_by = {}; std::optional<size_t> limit = {}; - std::optional<msgs::Filter> filter = {}; + std::vector<std::string> filter = {}; msgs::ExpandOneRequest expand_one_req{}; expand_one_req.direction = edge_direction; expand_one_req.edge_properties = edge_properties; expand_one_req.edge_types = {edge_type}; - expand_one_req.expressions = expressions; - expand_one_req.filter = filter; + expand_one_req.vertex_expressions = expressions; + expand_one_req.filters = filter; expand_one_req.limit = limit; expand_one_req.order_by = order_by; expand_one_req.src_vertex_properties = src_vertex_properties; @@ -636,18 +693,18 @@ void AttemptToExpandOneWithSpecifiedEdgeProperties(ShardClient &client, uint64_t std::vector<PropertyId> specified_edge_prop{PropertyId::FromUint(edge_prop_id)}; std::optional<std::vector<PropertyId>> edge_properties = {specified_edge_prop}; - std::vector<msgs::Expression> expressions; + std::vector<std::string> expressions; std::optional<std::vector<msgs::OrderBy>> order_by = {}; std::optional<size_t> limit = {}; - std::optional<msgs::Filter> filter = {}; + std::vector<std::string> filter = {}; msgs::ExpandOneRequest expand_one_req{}; expand_one_req.direction = edge_direction; expand_one_req.edge_properties = edge_properties; expand_one_req.edge_types = {edge_type}; - expand_one_req.expressions = expressions; - expand_one_req.filter = filter; + expand_one_req.vertex_expressions = expressions; + expand_one_req.filters = filter; expand_one_req.limit = limit; expand_one_req.order_by = order_by; expand_one_req.src_vertex_properties = src_vertex_properties; @@ -674,6 +731,62 @@ void AttemptToExpandOneWithSpecifiedEdgeProperties(ShardClient &client, uint64_t } } +void AttemptToExpandOneWithFilters(ShardClient &client, uint64_t src_vertex_val, EdgeTypeId edge_type_id, + uint64_t edge_prop_id, uint64_t prop_val_to_check_against) { + std::string filter_expr1 = "MG_SYMBOL_NODE.property = " + std::to_string(prop_val_to_check_against); + + // Source vertex + msgs::Label label = {.id = get_primary_label()}; + auto src_vertex = std::make_pair(label, GetPrimaryKey(src_vertex_val)); + + // Edge type + auto edge_type = msgs::EdgeType{}; + edge_type.id = edge_type_id; + + // Edge direction + auto edge_direction = msgs::EdgeDirection::OUT; + + // Source Vertex properties to look for + std::optional<std::vector<PropertyId>> src_vertex_properties = {}; + + // Edge properties to look for + std::optional<std::vector<PropertyId>> edge_properties = {}; + + std::vector<std::string> expressions; + std::optional<std::vector<msgs::OrderBy>> order_by = {}; + std::optional<size_t> limit = {}; + std::vector<std::string> filter = {}; + + msgs::ExpandOneRequest expand_one_req{}; + + expand_one_req.direction = edge_direction; + expand_one_req.edge_properties = edge_properties; + expand_one_req.edge_types = {edge_type}; + expand_one_req.vertex_expressions = expressions; + expand_one_req.filters = {filter_expr1}; + expand_one_req.limit = limit; + expand_one_req.order_by = order_by; + expand_one_req.src_vertex_properties = src_vertex_properties; + expand_one_req.src_vertices = {src_vertex}; + expand_one_req.transaction_id.logical_id = GetTransactionId(); + + while (true) { + auto read_res = client.SendReadRequest(expand_one_req); + if (read_res.HasError()) { + continue; + } + + auto write_response_result = read_res.GetValue(); + auto write_response = std::get<msgs::ExpandOneResponse>(write_response_result); + MG_ASSERT(write_response.result.size() == 1); + MG_ASSERT(write_response.result[0].out_edges_with_specific_properties.empty()); + MG_ASSERT(write_response.result[0].in_edges_with_specific_properties.empty()); + MG_ASSERT(write_response.result[0].in_edges_with_all_properties.empty()); + MG_ASSERT(write_response.result[0].out_edges_with_all_properties.size() == 2); + break; + } +} + } // namespace // tests @@ -818,7 +931,7 @@ void TestScanAllWithSmallBatchSize(ShardClient &client) { MG_ASSERT(!next_id4); } -void TestExpandOne(ShardClient &client) { +void TestExpandOneGraphOne(ShardClient &client) { { // ExpandOneSimple auto unique_prop_val_1 = GetUniqueInteger(); @@ -849,6 +962,36 @@ void TestExpandOne(ShardClient &client) { AttemptToExpandOneWithWrongEdgeType(client, unique_prop_val_1, wrong_edge_type_id); AttemptToExpandOneWithSpecifiedSrcVertexProperties(client, unique_prop_val_1, edge_type_id); AttemptToExpandOneWithSpecifiedEdgeProperties(client, unique_prop_val_1, edge_type_id, edge_prop_id); + AttemptToExpandOneWithFilters(client, unique_prop_val_1, edge_type_id, edge_prop_id, unique_prop_val_1); + } +} + +void TestExpandOneGraphTwo(ShardClient &client) { + { + // ExpandOneSimple + auto unique_prop_val_1 = GetUniqueInteger(); + auto unique_prop_val_2 = GetUniqueInteger(); + + MG_ASSERT(AttemptToCreateVertex(client, unique_prop_val_1)); + MG_ASSERT(AttemptToCreateVertex(client, unique_prop_val_2)); + + auto edge_type_id = EdgeTypeId::FromUint(GetUniqueInteger()); + auto wrong_edge_type_id = EdgeTypeId::FromUint(GetUniqueInteger()); + + auto edge_gid_1 = GetUniqueInteger(); + auto edge_gid_2 = GetUniqueInteger(); + + auto edge_prop_id = GetUniqueInteger(); + auto edge_prop_val = GetUniqueInteger(); + + // (V1)-[edge_type_id]->(V2) + MG_ASSERT(AttemptToAddEdgeWithProperties(client, unique_prop_val_1, unique_prop_val_2, edge_gid_1, edge_prop_id, + edge_prop_val, {edge_type_id})); + // (V1)-[edge_type_id]->(V3) + MG_ASSERT(AttemptToAddEdgeWithProperties(client, unique_prop_val_1, unique_prop_val_2, edge_gid_2, edge_prop_id, + edge_prop_val, {edge_type_id})); + // AttemptToExpandOneSimple(client, unique_prop_val_1, edge_type_id); + AttemptToExpandOneWithUniqueEdges(client, unique_prop_val_1, edge_type_id); } } @@ -930,7 +1073,8 @@ int TestMessages() { TestScanAllWithSmallBatchSize(client); // ExpandOne tests - TestExpandOne(client); + TestExpandOneGraphOne(client); + TestExpandOneGraphTwo(client); simulator.ShutDown();