diff --git a/.clang-format b/.clang-format index e59653ee5..da20b3084 100644 --- a/.clang-format +++ b/.clang-format @@ -5,4 +5,5 @@ Standard: "C++11" UseTab: Never DerivePointerAlignment: false PointerAlignment: Right +ColumnLimit : 80 ... diff --git a/experimental/distributed/tests/reactors_local_unit.cpp b/experimental/distributed/tests/reactors_local_unit.cpp index fee571a4e..639698afd 100644 --- a/experimental/distributed/tests/reactors_local_unit.cpp +++ b/experimental/distributed/tests/reactors_local_unit.cpp @@ -1,21 +1,19 @@ -#include "gtest/gtest.h" #include "reactors_local.hpp" +#include "gtest/gtest.h" #include #include #include +#include #include #include #include #include -#include TEST(SystemTest, ReturnWithoutThrowing) { struct Master : public Reactor { Master(std::string name) : Reactor(name) {} - virtual void Run() { - CloseChannel("main"); - } + virtual void Run() { CloseChannel("main"); } }; System &system = System::GetInstance(); @@ -23,7 +21,6 @@ TEST(SystemTest, ReturnWithoutThrowing) { ASSERT_NO_THROW(system.AwaitShutdown()); } - TEST(ChannelCreationTest, ThrowOnReusingChannelName) { struct Master : public Reactor { Master(std::string name) : Reactor(name) {} @@ -40,13 +37,13 @@ TEST(ChannelCreationTest, ThrowOnReusingChannelName) { system.AwaitShutdown(); } - TEST(ChannelSetUpTest, CheckMainChannelIsSet) { struct Master : public Reactor { Master(std::string name) : Reactor(name) {} virtual void Run() { std::shared_ptr channel_writer; - while (!(channel_writer = System::GetInstance().FindChannel("worker", "main"))) + while (!(channel_writer = + System::GetInstance().FindChannel("worker", "main"))) std::this_thread::sleep_for(std::chrono::milliseconds(300)); std::this_thread::sleep_for(std::chrono::milliseconds(300)); CloseChannel("main"); @@ -57,7 +54,8 @@ TEST(ChannelSetUpTest, CheckMainChannelIsSet) { Worker(std::string name) : Reactor(name) {} virtual void Run() { std::shared_ptr channel_writer; - while (!(channel_writer = System::GetInstance().FindChannel("master", "main"))) + while (!(channel_writer = + System::GetInstance().FindChannel("master", "main"))) std::this_thread::sleep_for(std::chrono::milliseconds(300)); std::this_thread::sleep_for(std::chrono::milliseconds(300)); CloseChannel("main"); @@ -80,7 +78,8 @@ TEST(SimpleSendTest, OneCallback) { Master(std::string name) : Reactor(name) {} virtual void Run() { std::shared_ptr channel_writer; - while (!(channel_writer = System::GetInstance().FindChannel("worker", "main"))) + while (!(channel_writer = + System::GetInstance().FindChannel("worker", "main"))) std::this_thread::sleep_for(std::chrono::milliseconds(300)); channel_writer->Send(888); CloseChannel("main"); @@ -90,12 +89,13 @@ TEST(SimpleSendTest, OneCallback) { struct Worker : public Reactor { Worker(std::string name) : Reactor(name) {} virtual void Run() { - EventStream* stream = main_.first; + EventStream *stream = main_.first; - stream->OnEvent([this](const MessageInt &msg, const Subscription&) { - ASSERT_EQ(msg.x, 888); - CloseChannel("main"); - }); + stream->OnEvent( + [this](const MessageInt &msg, const Subscription &) { + ASSERT_EQ(msg.x, 888); + CloseChannel("main"); + }); } }; @@ -105,7 +105,6 @@ TEST(SimpleSendTest, OneCallback) { system.AwaitShutdown(); } - TEST(SimpleSendTest, IgnoreAfterClose) { struct MessageInt : public Message { MessageInt(int xx) : x(xx) {} @@ -116,26 +115,29 @@ TEST(SimpleSendTest, IgnoreAfterClose) { Master(std::string name) : Reactor(name) {} virtual void Run() { std::shared_ptr channel_writer; - while (!(channel_writer = System::GetInstance().FindChannel("worker", "main"))) + while (!(channel_writer = + System::GetInstance().FindChannel("worker", "main"))) std::this_thread::sleep_for(std::chrono::milliseconds(300)); channel_writer->Send(101); - channel_writer->Send(102); // should be ignored + channel_writer->Send(102); // should be ignored std::this_thread::sleep_for(std::chrono::milliseconds(300)); - channel_writer->Send(103); // should be ignored - channel_writer->Send(104); // should be ignored - CloseChannel("main"); // Write-end doesn't need to be closed because it's in RAII. + channel_writer->Send(103); // should be ignored + channel_writer->Send(104); // should be ignored + CloseChannel( + "main"); // Write-end doesn't need to be closed because it's in RAII. } }; struct Worker : public Reactor { Worker(std::string name) : Reactor(name) {} virtual void Run() { - EventStream* stream = main_.first; + EventStream *stream = main_.first; - stream->OnEvent([this](const MessageInt& msg, const Subscription&) { - CloseChannel("main"); - ASSERT_EQ(msg.x, 101); - }); + stream->OnEvent( + [this](const MessageInt &msg, const Subscription &) { + CloseChannel("main"); + ASSERT_EQ(msg.x, 101); + }); } }; @@ -152,20 +154,21 @@ TEST(SimpleSendTest, DuringFirstEvent) { }; struct Master : public Reactor { - Master(std::string name, std::promise p) : Reactor(name), p_(std::move(p)) {} + Master(std::string name, std::promise p) + : Reactor(name), p_(std::move(p)) {} virtual void Run() { - EventStream* stream = main_.first; + EventStream *stream = main_.first; - stream->OnEvent([this](const Message &msg, const Subscription &subscription) { - const MessageInt &msgint = dynamic_cast(msg); - if (msgint.x == 101) - FindChannel("main")->Send(102); - if (msgint.x == 102) { - subscription.Unsubscribe(); - CloseChannel("main"); - p_.set_value(777); - } - }); + stream->OnEvent( + [this](const Message &msg, const Subscription &subscription) { + const MessageInt &msgint = dynamic_cast(msg); + if (msgint.x == 101) FindChannel("main")->Send(102); + if (msgint.x == 102) { + subscription.Unsubscribe(); + CloseChannel("main"); + p_.set_value(777); + } + }); std::shared_ptr channel_writer = FindChannel("main"); channel_writer->Send(101); @@ -182,7 +185,6 @@ TEST(SimpleSendTest, DuringFirstEvent) { system.AwaitShutdown(); } - TEST(MultipleSendTest, UnsubscribeService) { struct MessageInt : public Message { MessageInt(int xx) : x(xx) {} @@ -197,7 +199,8 @@ TEST(MultipleSendTest, UnsubscribeService) { Master(std::string name) : Reactor(name) {} virtual void Run() { std::shared_ptr channel_writer; - while (!(channel_writer = System::GetInstance().FindChannel("worker", "main"))) + while (!(channel_writer = + System::GetInstance().FindChannel("worker", "main"))) std::this_thread::sleep_for(std::chrono::milliseconds(300)); channel_writer->Send(55); channel_writer->Send(66); @@ -218,24 +221,26 @@ TEST(MultipleSendTest, UnsubscribeService) { int num_msgs_received = 0; virtual void Run() { - EventStream* stream = main_.first; + EventStream *stream = main_.first; - stream->OnEvent([this](const MessageInt &msgint, const Subscription &subscription) { - ASSERT_TRUE(msgint.x == 55 || msgint.x == 66); - ++num_msgs_received; - if (msgint.x == 66) { - subscription.Unsubscribe(); // receive only two of them - } - }); - stream->OnEvent([this](const MessageChar &msgchar, const Subscription &subscription) { - char c = msgchar.x; - ++num_msgs_received; - ASSERT_TRUE(c == 'a' || c == 'b' || c == 'c'); - if (num_msgs_received == 5) { - subscription.Unsubscribe(); - CloseChannel("main"); - } - }); + stream->OnEvent( + [this](const MessageInt &msgint, const Subscription &subscription) { + ASSERT_TRUE(msgint.x == 55 || msgint.x == 66); + ++num_msgs_received; + if (msgint.x == 66) { + subscription.Unsubscribe(); // receive only two of them + } + }); + stream->OnEvent( + [this](const MessageChar &msgchar, const Subscription &subscription) { + char c = msgchar.x; + ++num_msgs_received; + ASSERT_TRUE(c == 'a' || c == 'b' || c == 'c'); + if (num_msgs_received == 5) { + subscription.Unsubscribe(); + CloseChannel("main"); + } + }); } }; @@ -245,7 +250,6 @@ TEST(MultipleSendTest, UnsubscribeService) { system.AwaitShutdown(); } - TEST(MultipleSendTest, OnEvent) { struct MessageInt : public Message { MessageInt(int xx) : x(xx) {} @@ -260,7 +264,8 @@ TEST(MultipleSendTest, OnEvent) { Master(std::string name) : Reactor(name) {} virtual void Run() { std::shared_ptr channel_writer; - while (!(channel_writer = System::GetInstance().FindChannel("worker", "main"))) + while (!(channel_writer = + System::GetInstance().FindChannel("worker", "main"))) std::this_thread::sleep_for(std::chrono::milliseconds(300)); channel_writer->Send(101); @@ -278,27 +283,30 @@ TEST(MultipleSendTest, OnEvent) { int correct_vals = 0; virtual void Run() { - EventStream* stream = main_.first; + EventStream *stream = main_.first; correct_vals = 0; - stream->OnEvent([this](const MessageInt &msgint, const Subscription&) { - ASSERT_TRUE(msgint.x == 101 || msgint.x == 103); - ++correct_vals; - main_.second->Send(); - }); + stream->OnEvent( + [this](const MessageInt &msgint, const Subscription &) { + ASSERT_TRUE(msgint.x == 101 || msgint.x == 103); + ++correct_vals; + main_.second->Send(); + }); - stream->OnEvent([this](const MessageChar &msgchar, const Subscription&) { - ASSERT_TRUE(msgchar.x == 'a' || msgchar.x == 'b'); - ++correct_vals; - main_.second->Send(); - }); + stream->OnEvent( + [this](const MessageChar &msgchar, const Subscription &) { + ASSERT_TRUE(msgchar.x == 'a' || msgchar.x == 'b'); + ++correct_vals; + main_.second->Send(); + }); - stream->OnEvent([this](const EndMessage&, const Subscription&) { - ASSERT_LE(correct_vals, 4); - if (correct_vals == 4) { - CloseChannel("main"); - } - }); + stream->OnEvent( + [this](const EndMessage &, const Subscription &) { + ASSERT_LE(correct_vals, 4); + if (correct_vals == 4) { + CloseChannel("main"); + } + }); } }; @@ -318,7 +326,8 @@ TEST(MultipleSendTest, Chaining) { Master(std::string name) : Reactor(name) {} virtual void Run() { std::shared_ptr channel_writer; - while (!(channel_writer = System::GetInstance().FindChannel("worker", "main"))) + while (!(channel_writer = + System::GetInstance().FindChannel("worker", "main"))) std::this_thread::sleep_for(std::chrono::milliseconds(300)); channel_writer->Send(55); channel_writer->Send(66); @@ -331,19 +340,22 @@ TEST(MultipleSendTest, Chaining) { Worker(std::string name) : Reactor(name) {} virtual void Run() { - EventStream* stream = main_.first; + EventStream *stream = main_.first; stream->OnEventOnce() - .ChainOnce([this](const MessageInt &msg, const Subscription&) { - ASSERT_EQ(msg.x, 55); - }) - .ChainOnce([](const MessageInt &msg, const Subscription&) { - ASSERT_EQ(msg.x, 66); - }) - .ChainOnce([this](const MessageInt &msg, const Subscription&) { - ASSERT_EQ(msg.x, 77); - CloseChannel("main"); - }); + .ChainOnce( + [this](const MessageInt &msg, const Subscription &) { + ASSERT_EQ(msg.x, 55); + }) + .ChainOnce( + [](const MessageInt &msg, const Subscription &) { + ASSERT_EQ(msg.x, 66); + }) + .ChainOnce( + [this](const MessageInt &msg, const Subscription &) { + ASSERT_EQ(msg.x, 77); + CloseChannel("main"); + }); } }; @@ -353,7 +365,6 @@ TEST(MultipleSendTest, Chaining) { system.AwaitShutdown(); } - TEST(MultipleSendTest, ChainingInRightOrder) { struct MessageInt : public Message { MessageInt(int xx) : x(xx) {} @@ -369,7 +380,8 @@ TEST(MultipleSendTest, ChainingInRightOrder) { Master(std::string name) : Reactor(name) {} virtual void Run() { std::shared_ptr channel_writer; - while (!(channel_writer = System::GetInstance().FindChannel("worker", "main"))) + while (!(channel_writer = + System::GetInstance().FindChannel("worker", "main"))) std::this_thread::sleep_for(std::chrono::milliseconds(300)); channel_writer->Send('a'); channel_writer->Send(55); @@ -383,19 +395,22 @@ TEST(MultipleSendTest, ChainingInRightOrder) { Worker(std::string name) : Reactor(name) {} virtual void Run() { - EventStream* stream = main_.first; + EventStream *stream = main_.first; stream->OnEventOnce() - .ChainOnce([this](const MessageInt &msg, const Subscription&) { - ASSERT_EQ(msg.x, 55); - }) - .ChainOnce([](const MessageChar &msg, const Subscription&) { - ASSERT_EQ(msg.x, 'b'); - }) - .ChainOnce([this](const MessageInt &msg, const Subscription&) { - ASSERT_EQ(msg.x, 77); - CloseChannel("main"); - }); + .ChainOnce( + [this](const MessageInt &msg, const Subscription &) { + ASSERT_EQ(msg.x, 55); + }) + .ChainOnce( + [](const MessageChar &msg, const Subscription &) { + ASSERT_EQ(msg.x, 'b'); + }) + .ChainOnce( + [this](const MessageInt &msg, const Subscription &) { + ASSERT_EQ(msg.x, 77); + CloseChannel("main"); + }); } }; @@ -405,7 +420,6 @@ TEST(MultipleSendTest, ChainingInRightOrder) { system.AwaitShutdown(); } - TEST(MultipleSendTest, ProcessManyMessages) { const static int num_tests = 100; @@ -418,7 +432,8 @@ TEST(MultipleSendTest, ProcessManyMessages) { Master(std::string name) : Reactor(name) {} virtual void Run() { std::shared_ptr channel_writer; - while (!(channel_writer = System::GetInstance().FindChannel("worker", "main"))) + while (!(channel_writer = + System::GetInstance().FindChannel("worker", "main"))) std::this_thread::sleep_for(std::chrono::milliseconds(300)); std::this_thread::sleep_for(std::chrono::milliseconds(rand() % 100)); @@ -437,20 +452,22 @@ TEST(MultipleSendTest, ProcessManyMessages) { int vals = 0; virtual void Run() { - EventStream* stream = main_.first; + EventStream *stream = main_.first; vals = 0; - stream->OnEvent([this](const Message&, const Subscription&) { - ++vals; - main_.second->Send(); - }); + stream->OnEvent( + [this](const Message &, const Subscription &) { + ++vals; + main_.second->Send(); + }); - stream->OnEvent([this](const Message&, const Subscription&) { - ASSERT_LE(vals, num_tests); - if (vals == num_tests) { - CloseChannel("main"); - } - }); + stream->OnEvent( + [this](const Message &, const Subscription &) { + ASSERT_LE(vals, num_tests); + if (vals == num_tests) { + CloseChannel("main"); + } + }); } }; @@ -460,10 +477,6 @@ TEST(MultipleSendTest, ProcessManyMessages) { system.AwaitShutdown(); } - - - - int main(int argc, char **argv) { ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); diff --git a/src/communication/bolt/v1/decoder/decoded_value.cpp b/src/communication/bolt/v1/decoder/decoded_value.cpp index 8bfdcc3dd..e2b2ddc2f 100644 --- a/src/communication/bolt/v1/decoder/decoded_value.cpp +++ b/src/communication/bolt/v1/decoder/decoded_value.cpp @@ -192,31 +192,33 @@ DecodedValue::operator query::TypedValue() const { std::ostream &operator<<(std::ostream &os, const DecodedVertex &vertex) { os << "V("; - PrintIterable(os, vertex.labels, ":", - [&](auto &stream, auto label) { stream << label; }); + utils::PrintIterable(os, vertex.labels, ":", + [&](auto &stream, auto label) { stream << label; }); os << " {"; - PrintIterable(os, vertex.properties, ", ", - [&](auto &stream, const auto &pair) { - stream << pair.first << ": " << pair.second; - }); + utils::PrintIterable(os, vertex.properties, ", ", + [&](auto &stream, const auto &pair) { + stream << pair.first << ": " << pair.second; + }); return os << "})"; } std::ostream &operator<<(std::ostream &os, const DecodedEdge &edge) { os << "E[" << edge.type; os << " {"; - PrintIterable(os, edge.properties, ", ", [&](auto &stream, const auto &pair) { - stream << pair.first << ": " << pair.second; - }); + utils::PrintIterable(os, edge.properties, ", ", + [&](auto &stream, const auto &pair) { + stream << pair.first << ": " << pair.second; + }); return os << "}]"; } std::ostream &operator<<(std::ostream &os, const DecodedUnboundedEdge &edge) { os << "E[" << edge.type; os << " {"; - PrintIterable(os, edge.properties, ", ", [&](auto &stream, const auto &pair) { - stream << pair.first << ": " << pair.second; - }); + utils::PrintIterable(os, edge.properties, ", ", + [&](auto &stream, const auto &pair) { + stream << pair.first << ": " << pair.second; + }); return os << "}]"; } @@ -256,14 +258,14 @@ std::ostream &operator<<(std::ostream &os, const DecodedValue &value) { return os << value.ValueString(); case DecodedValue::Type::List: os << "["; - PrintIterable(os, value.ValueList()); + utils::PrintIterable(os, value.ValueList()); return os << "]"; case DecodedValue::Type::Map: os << "{"; - PrintIterable(os, value.ValueMap(), ", ", - [](auto &stream, const auto &pair) { - stream << pair.first << ": " << pair.second; - }); + utils::PrintIterable(os, value.ValueMap(), ", ", + [](auto &stream, const auto &pair) { + stream << pair.first << ": " << pair.second; + }); return os << "}"; case DecodedValue::Type::Vertex: return os << value.ValueVertex(); diff --git a/src/query/console.cpp b/src/query/console.cpp index 20d40168f..2e42513f2 100644 --- a/src/query/console.cpp +++ b/src/query/console.cpp @@ -116,10 +116,10 @@ void PrintResults(ResultStreamFaker results) { // output the summary std::cout << "Query summary: {"; - PrintIterable(std::cout, results.GetSummary(), ", ", - [&](auto &stream, const auto &kv) { - stream << kv.first << ": " << kv.second; - }); + utils::PrintIterable(std::cout, results.GetSummary(), ", ", + [&](auto &stream, const auto &kv) { + stream << kv.first << ": " << kv.second; + }); std::cout << "}" << std::endl; } diff --git a/src/query/interpreter.hpp b/src/query/interpreter.hpp index c5595c960..ef7696f88 100644 --- a/src/query/interpreter.hpp +++ b/src/query/interpreter.hpp @@ -170,8 +170,8 @@ class Interpreter { // When the symbol is aliased or expanded from '*' (inside RETURN or // WITH), then there is no token position, so use symbol name. // Otherwise, find the name from stripped query. - header.push_back(FindOr(stripped.named_expressions(), - symbol.token_position(), symbol.name()) + header.push_back(utils::FindOr(stripped.named_expressions(), + symbol.token_position(), symbol.name()) .first); } stream.Header(header); diff --git a/src/query/plan/operator.cpp b/src/query/plan/operator.cpp index d9117e127..4ef2d5f8f 100644 --- a/src/query/plan/operator.cpp +++ b/src/query/plan/operator.cpp @@ -302,10 +302,10 @@ std::unique_ptr ScanAllByLabelPropertyRange::MakeCursor( context.symbol_table_, db, graph_view_); auto convert = [&evaluator](const auto &bound) -> std::experimental::optional> { - if (!bound) return std::experimental::nullopt; - return std::experimental::make_optional(utils::Bound( - bound.value().value()->Accept(evaluator), bound.value().type())); - }; + if (!bound) return std::experimental::nullopt; + return std::experimental::make_optional(utils::Bound( + bound.value().value()->Accept(evaluator), bound.value().type())); + }; return db.Vertices(label_, property_, convert(lower_bound()), convert(upper_bound()), graph_view_ == GraphView::NEW); }; @@ -380,16 +380,15 @@ std::unique_ptr ScanAllByLabelPropertyValue::MakeCursor( return std::make_unique(*this, db); } -ExpandCommon::ExpandCommon(Symbol node_symbol, Symbol edge_symbol, - EdgeAtom::Direction direction, - const GraphDbTypes::EdgeType &edge_type, - const std::shared_ptr &input, - Symbol input_symbol, bool existing_node, - bool existing_edge, GraphView graph_view) +ExpandCommon::ExpandCommon( + Symbol node_symbol, Symbol edge_symbol, EdgeAtom::Direction direction, + const std::vector &edge_types, + const std::shared_ptr &input, Symbol input_symbol, + bool existing_node, bool existing_edge, GraphView graph_view) : node_symbol_(node_symbol), edge_symbol_(edge_symbol), direction_(direction), - edge_type_(edge_type), + edge_types_(edge_types), input_(input ? input : std::make_shared()), input_symbol_(input_symbol), existing_node_(existing_node), @@ -539,10 +538,8 @@ bool Expand::ExpandCursor::InitEdges(Frame &frame, Context &context) { in_edges_.emplace( vertex.in_with_destination(existing_node.ValueVertex())); } - } else if (self_.edge_type_) { - in_edges_.emplace(vertex.in_with_type(self_.edge_type_)); } else { - in_edges_.emplace(vertex.in()); + in_edges_.emplace(vertex.in_with_types(&self_.edge_types())); } in_edges_it_.emplace(in_edges_->begin()); } @@ -558,10 +555,8 @@ bool Expand::ExpandCursor::InitEdges(Frame &frame, Context &context) { out_edges_.emplace( vertex.out_with_destination(existing_node.ValueVertex())); } - } else if (self_.edge_type_) { - out_edges_.emplace(vertex.out_with_type(self_.edge_type_)); } else { - out_edges_.emplace(vertex.out()); + out_edges_.emplace(vertex.out_with_types(&self_.edge_types())); } out_edges_it_.emplace(out_edges_->begin()); } @@ -570,16 +565,14 @@ bool Expand::ExpandCursor::InitEdges(Frame &frame, Context &context) { } } -ExpandVariable::ExpandVariable(Symbol node_symbol, Symbol edge_symbol, - EdgeAtom::Direction direction, - const GraphDbTypes::EdgeType &edge_type, - bool is_reverse, Expression *lower_bound, - Expression *upper_bound, - const std::shared_ptr &input, - Symbol input_symbol, bool existing_node, - bool existing_edge, GraphView graph_view, - Expression *filter) - : ExpandCommon(node_symbol, edge_symbol, direction, edge_type, input, +ExpandVariable::ExpandVariable( + Symbol node_symbol, Symbol edge_symbol, EdgeAtom::Direction direction, + const std::vector &edge_types, bool is_reverse, + Expression *lower_bound, Expression *upper_bound, + const std::shared_ptr &input, Symbol input_symbol, + bool existing_node, bool existing_edge, GraphView graph_view, + Expression *filter) + : ExpandCommon(node_symbol, edge_symbol, direction, edge_types, input, input_symbol, existing_node, existing_edge, graph_view), lower_bound_(lower_bound), upper_bound_(upper_bound), @@ -601,7 +594,7 @@ namespace { */ auto ExpandFromVertex(const VertexAccessor &vertex, EdgeAtom::Direction direction, - const GraphDbTypes::EdgeType &edge_type) { + const std::vector &edge_types) { // wraps an EdgeAccessor into a pair auto wrapper = [](EdgeAtom::Direction direction, auto &&vertices) { return iter::imap( @@ -615,27 +608,17 @@ auto ExpandFromVertex(const VertexAccessor &vertex, std::vector chain_elements; if (direction != EdgeAtom::Direction::OUT && vertex.in_degree() > 0) { - if (edge_type) { - auto edges = vertex.in_with_type(edge_type); - if (edges.begin() != edges.end()) { - chain_elements.emplace_back( - wrapper(EdgeAtom::Direction::IN, std::move(edges))); - } - } else { + auto edges = vertex.in_with_types(&edge_types); + if (edges.begin() != edges.end()) { chain_elements.emplace_back( - wrapper(EdgeAtom::Direction::IN, vertex.in())); + wrapper(EdgeAtom::Direction::IN, std::move(edges))); } } if (direction != EdgeAtom::Direction::IN && vertex.out_degree() > 0) { - if (edge_type) { - auto edges = vertex.out_with_type(edge_type); - if (edges.begin() != edges.end()) { - chain_elements.emplace_back( - wrapper(EdgeAtom::Direction::OUT, std::move(edges))); - } - } else { + auto edges = vertex.out_with_types(&edge_types); + if (edges.begin() != edges.end()) { chain_elements.emplace_back( - wrapper(EdgeAtom::Direction::OUT, vertex.out())); + wrapper(EdgeAtom::Direction::OUT, std::move(edges))); } } @@ -718,7 +701,7 @@ class ExpandVariableCursor : public Cursor { // the expansion currently being Pulled std::vector(), EdgeAtom::Direction::IN, - self_.edge_type_))> + self_.edge_types_))> edges_; // an iterator indicating the possition in the corresponding edges_ element @@ -763,7 +746,7 @@ class ExpandVariableCursor : public Cursor { if (upper_bound_ > 0) { SwitchAccessor(vertex, self_.graph_view_); edges_.emplace_back( - ExpandFromVertex(vertex, self_.direction_, self_.edge_type_)); + ExpandFromVertex(vertex, self_.direction_, self_.edge_types_)); edges_it_.emplace_back(edges_.back().begin()); } @@ -933,7 +916,7 @@ class ExpandVariableCursor : public Cursor { if (upper_bound_ > static_cast(edges_.size())) { SwitchAccessor(current_vertex, self_.graph_view_); edges_.emplace_back(ExpandFromVertex(current_vertex, self_.direction_, - self_.edge_type_)); + self_.edge_types_)); edges_it_.emplace_back(edges_.back().begin()); } @@ -955,14 +938,14 @@ std::unique_ptr ExpandVariable::MakeCursor(GraphDbAccessor &db) const { ExpandBreadthFirst::ExpandBreadthFirst( Symbol node_symbol, Symbol edge_list_symbol, EdgeAtom::Direction direction, - const GraphDbTypes::EdgeType &edge_type, Expression *max_depth, - Symbol inner_node_symbol, Symbol inner_edge_symbol, Expression *where, - const std::shared_ptr &input, Symbol input_symbol, - bool existing_node, GraphView graph_view) + const std::vector &edge_types, + Expression *max_depth, Symbol inner_node_symbol, Symbol inner_edge_symbol, + Expression *where, const std::shared_ptr &input, + Symbol input_symbol, bool existing_node, GraphView graph_view) : node_symbol_(node_symbol), edge_list_symbol_(edge_list_symbol), direction_(direction), - edge_type_(edge_type), + edge_types_(edge_types), max_depth_(max_depth), inner_node_symbol_(inner_node_symbol), inner_edge_symbol_(inner_edge_symbol), @@ -1023,22 +1006,12 @@ bool ExpandBreadthFirst::Cursor::Pull(Frame &frame, Context &context) { // the "where" condition. auto expand_from_vertex = [this, &expand_pair](VertexAccessor &vertex) { if (self_.direction_ != EdgeAtom::Direction::IN) { - if (self_.edge_type_) { - for (const EdgeAccessor &edge : vertex.out_with_type(self_.edge_type_)) - expand_pair(edge, edge.to()); - } else { - for (const EdgeAccessor &edge : vertex.out()) - expand_pair(edge, edge.to()); - } + for (const EdgeAccessor &edge : vertex.out_with_types(&self_.edge_types_)) + expand_pair(edge, edge.to()); } if (self_.direction_ != EdgeAtom::Direction::OUT) { - if (self_.edge_type_) { - for (const EdgeAccessor &edge : vertex.in_with_type(self_.edge_type_)) - expand_pair(edge, edge.from()); - } else { - for (const EdgeAccessor &edge : vertex.in()) - expand_pair(edge, edge.from()); - } + for (const EdgeAccessor &edge : vertex.in_with_types(&self_.edge_types_)) + expand_pair(edge, edge.from()); } }; diff --git a/src/query/plan/operator.hpp b/src/query/plan/operator.hpp index cef02651e..4e6ffcf8d 100644 --- a/src/query/plan/operator.hpp +++ b/src/query/plan/operator.hpp @@ -476,8 +476,9 @@ class ExpandCommon { * @param direction EdgeAtom::Direction determining the direction of edge * expansion. The direction is relative to the starting vertex for each * expansion. - * @param edge_type Optional GraphDbTypes::EdgeType specifying which edges we - * want to expand. + * @param edge_types GraphDbTypes::EdgeType specifying which edges we + * want to expand. If empty, all edges are valid. If not empty, only edges + * with one of the given types are valid. * @param input Optional LogicalOperator that preceeds this one. * @param input_symbol Symbol that points to a VertexAccessor in the Frame * that expansion should emanate from. @@ -487,7 +488,7 @@ class ExpandCommon { */ ExpandCommon(Symbol node_symbol, Symbol edge_symbol, EdgeAtom::Direction direction, - const GraphDbTypes::EdgeType &edge_type, + const std::vector &edge_types, const std::shared_ptr &input, Symbol input_symbol, bool existing_node, bool existing_edge, GraphView graph_view = GraphView::AS_IS); @@ -496,14 +497,14 @@ class ExpandCommon { const auto &node_symbol() const { return node_symbol_; } const auto &edge_symbol() const { return edge_symbol_; } const auto &direction() const { return direction_; } - const auto &edge_type() const { return edge_type_; } + const auto &edge_types() const { return edge_types_; } protected: // info on what's getting expanded const Symbol node_symbol_; const Symbol edge_symbol_; const EdgeAtom::Direction direction_; - const GraphDbTypes::EdgeType edge_type_ = nullptr; + const std::vector edge_types_; // the input op and the symbol under which the op's result // can be found in the frame @@ -620,8 +621,9 @@ class ExpandVariable : public LogicalOperator, public ExpandCommon { */ ExpandVariable(Symbol node_symbol, Symbol edge_symbol, EdgeAtom::Direction direction, - const GraphDbTypes::EdgeType &edge_type, bool is_reverse, - Expression *lower_bound, Expression *upper_bound, + const std::vector &edge_types, + bool is_reverse, Expression *lower_bound, + Expression *upper_bound, const std::shared_ptr &input, Symbol input_symbol, bool existing_node, bool existing_edge, GraphView graph_view = GraphView::AS_IS, @@ -669,7 +671,7 @@ class ExpandBreadthFirst : public LogicalOperator { public: ExpandBreadthFirst(Symbol node_symbol, Symbol edge_list_symbol, EdgeAtom::Direction direction, - const GraphDbTypes::EdgeType &edge_type, + const std::vector &edge_types, Expression *max_depth, Symbol inner_node_symbol, Symbol inner_edge_symbol, Expression *where, const std::shared_ptr &input, @@ -711,7 +713,7 @@ class ExpandBreadthFirst : public LogicalOperator { const Symbol edge_list_symbol_; const EdgeAtom::Direction direction_; - const GraphDbTypes::EdgeType edge_type_ = nullptr; + const std::vector edge_types_; Expression *max_depth_; // symbols for a single node and edge that are currently getting expanded diff --git a/src/query/plan/rule_based_planner.hpp b/src/query/plan/rule_based_planner.hpp index a9805a4c9..33e4738cc 100644 --- a/src/query/plan/rule_based_planner.hpp +++ b/src/query/plan/rule_based_planner.hpp @@ -428,17 +428,18 @@ class RuleBasedPlanner { const std::experimental::optional &max_vertex_count = std::experimental::nullopt) { const auto labels = - FindOr(match_ctx.matching.filters.label_filters(), node_symbol, - std::unordered_set()) + utils::FindOr(match_ctx.matching.filters.label_filters(), node_symbol, + std::unordered_set()) .first; if (labels.empty()) { // Without labels, we cannot generated any indexed ScanAll. return nullptr; } const auto properties = - FindOr(match_ctx.matching.filters.property_filters(), node_symbol, - std::unordered_map>()) + utils::FindOr( + match_ctx.matching.filters.property_filters(), node_symbol, + std::unordered_map>()) .first; // First, try to see if we can use label+property index. If not, use just // the label index (which ought to exist). @@ -532,16 +533,12 @@ class RuleBasedPlanner { } else { match_context.new_symbols.emplace_back(edge_symbol); } - GraphDbTypes::EdgeType edge_type = nullptr; - const auto &edge_types = - FindOr(matching.filters.edge_type_filters(), edge_symbol, - std::unordered_set()) + const auto edge_types_set = + utils::FindOr(matching.filters.edge_type_filters(), edge_symbol, + std::unordered_set()) .first; - if (edge_types.size() == 1U) { - // With exactly one edge type filter, we can generate a more efficient - // expand. - edge_type = First(edge_types); - } + const std::vector edge_types( + edge_types_set.begin(), edge_types_set.end()); if (auto *bf_atom = dynamic_cast(expansion.edge)) { const auto &traversed_edge_symbol = symbol_table.at(*bf_atom->traversed_edge_identifier_); @@ -549,22 +546,22 @@ class RuleBasedPlanner { symbol_table.at(*bf_atom->next_node_identifier_); // Inline BFS edge filtering together with its filter expression. auto *filter_expr = impl::BoolJoin( - storage, - impl::ExtractMultiExpandFilter(bound_symbols, node_symbol, - all_filters, storage), + storage, impl::ExtractMultiExpandFilter( + bound_symbols, node_symbol, all_filters, storage), bf_atom->filter_expression_); last_op = new ExpandBreadthFirst( - node_symbol, edge_symbol, expansion.direction, edge_type, - bf_atom->max_depth_, next_node_symbol, traversed_edge_symbol, - filter_expr, std::shared_ptr(last_op), - node1_symbol, existing_node, match_context.graph_view); + node_symbol, edge_symbol, expansion.direction, + std::move(edge_types), bf_atom->max_depth_, next_node_symbol, + traversed_edge_symbol, filter_expr, + std::shared_ptr(last_op), node1_symbol, + existing_node, match_context.graph_view); } else if (expansion.edge->has_range_) { auto *filter_expr = impl::ExtractMultiExpandFilter( bound_symbols, node_symbol, all_filters, storage); last_op = new ExpandVariable( - node_symbol, edge_symbol, expansion.direction, edge_type, - expansion.is_flipped, expansion.edge->lower_bound_, - expansion.edge->upper_bound_, + node_symbol, edge_symbol, expansion.direction, + std::move(edge_types), expansion.is_flipped, + expansion.edge->lower_bound_, expansion.edge->upper_bound_, std::shared_ptr(last_op), node1_symbol, existing_node, existing_edge, match_context.graph_view, filter_expr); @@ -585,10 +582,11 @@ class RuleBasedPlanner { existing_node = true; } } - last_op = new Expand( - node_symbol, edge_symbol, expansion.direction, edge_type, - std::shared_ptr(last_op), node1_symbol, - existing_node, existing_edge, match_context.graph_view); + last_op = new Expand(node_symbol, edge_symbol, expansion.direction, + std::move(edge_types), + std::shared_ptr(last_op), + node1_symbol, existing_node, existing_edge, + match_context.graph_view); } if (!existing_edge) { // Ensure Cyphermorphism (different edge symbols always map to diff --git a/src/query/typed_value.cpp b/src/query/typed_value.cpp index 444c29294..f803125e5 100644 --- a/src/query/typed_value.cpp +++ b/src/query/typed_value.cpp @@ -203,14 +203,14 @@ std::ostream &operator<<(std::ostream &os, const TypedValue &value) { return os << value.Value(); case TypedValue::Type::List: os << "["; - PrintIterable(os, value.Value>()); + utils::PrintIterable(os, value.Value>()); return os << "]"; case TypedValue::Type::Map: os << "{"; - PrintIterable(os, value.Value>(), ", ", - [](auto &stream, const auto &pair) { - stream << pair.first << ": " << pair.second; - }); + utils::PrintIterable(os, value.Value>(), + ", ", [](auto &stream, const auto &pair) { + stream << pair.first << ": " << pair.second; + }); return os << "}"; case TypedValue::Type::Vertex: return os << value.Value(); diff --git a/src/storage/edge_accessor.cpp b/src/storage/edge_accessor.cpp index 86cf33a49..8edfda751 100644 --- a/src/storage/edge_accessor.cpp +++ b/src/storage/edge_accessor.cpp @@ -31,7 +31,8 @@ bool EdgeAccessor::is_cycle() const { std::ostream &operator<<(std::ostream &os, const EdgeAccessor &ea) { os << "E[" << ea.db_accessor().EdgeTypeName(ea.EdgeType()); os << " {"; - PrintIterable(os, ea.Properties(), ", ", [&](auto &stream, const auto &pair) { + utils::PrintIterable(os, ea.Properties(), ", ", [&](auto &stream, + const auto &pair) { stream << ea.db_accessor().PropertyName(pair.first) << ": " << pair.second; }); return os << "}]"; diff --git a/src/storage/edges.hpp b/src/storage/edges.hpp index a078b100b..fd58c5127 100644 --- a/src/storage/edges.hpp +++ b/src/storage/edges.hpp @@ -5,6 +5,7 @@ #include "database/graph_db_datatypes.hpp" #include "mvcc/version_list.hpp" +#include "utils/algorithm.hpp" // forward declare Vertex and Edge because they need this data structure class Edge; @@ -26,7 +27,7 @@ class Edges { }; /** Custom iterator that takes care of skipping edges when the destination - * vertex or edge type are known. */ + * vertex or edge types are known. */ class Iterator { public: /** Ctor that just sets the position. Used for normal iteration (that does @@ -38,7 +39,7 @@ class Edges { explicit Iterator(std::vector::const_iterator iterator) : position_(iterator) {} - /** Ctor used for creating the beginning iterator with known destionation + /** Ctor used for creating the beginning iterator with known destination * vertex. * * @param iterator - Iterator in the underlying storage. @@ -51,16 +52,17 @@ class Edges { update_position(); } - /** Ctor used for creating the beginning iterator with known edge type. + /** Ctor used for creating the beginning iterator with known edge types. * * @param iterator - Iterator in the underlying storage. * @param end - End iterator in the underlying storage. - * @param edge_type - The edge type that must be matched. + * @param edge_types - The edge types at least one of which must be matched. + * If nullptr all edges are valid. */ Iterator(std::vector::const_iterator position, std::vector::const_iterator end, - GraphDbTypes::EdgeType edge_type) - : position_(position), end_(end), edge_type_(edge_type) { + const std::vector *edge_types) + : position_(position), end_(end), edge_types_(edge_types) { update_position(); } @@ -86,7 +88,8 @@ class Edges { // Optional predicates. If set they define which edges are skipped by the // iterator. Only one can be not-null in the current implementation. vertex_ptr_t vertex_{nullptr}; - GraphDbTypes::EdgeType edge_type_{nullptr}; + // For edge types we use a vector pointer because it's optional. + const std::vector *edge_types_ = nullptr; /** Helper function that skips edges that don't satisfy the predicate * present in this iterator. */ @@ -95,11 +98,10 @@ class Edges { position_ = std::find_if( position_, end_, [v = this->vertex_](const Element &e) { return e.vertex == v; }); - else if (edge_type_) - position_ = std::find_if(position_, end_, - [et = this->edge_type_](const Element &e) { - return e.edge_type == et; - }); + else if (edge_types_) + position_ = std::find_if(position_, end_, [this](const Element &e) { + return utils::Contains(*edge_types_, e.edge_type); + }); } }; @@ -144,11 +146,15 @@ class Edges { /* * Creates a beginning iterator that will skip edges whose edge type is not - * equal to the given. Relies on the fact that edge types are immutable during - * the whole edge lifetime. + * among the given. If none are given, or the pointer is null, then all edges + * are valid. Relies on the fact that edge types are immutable during the + * whole edge lifetime. */ - auto begin(GraphDbTypes::EdgeType edge_type) const { - return Iterator(storage_.begin(), storage_.end(), edge_type); + auto begin(const std::vector *edge_types) const { + if (edge_types && !edge_types->empty()) + return Iterator(storage_.begin(), storage_.end(), edge_types); + else + return Iterator(storage_.begin()); } private: diff --git a/src/storage/vertex_accessor.cpp b/src/storage/vertex_accessor.cpp index 55a96172f..0d29f5c95 100644 --- a/src/storage/vertex_accessor.cpp +++ b/src/storage/vertex_accessor.cpp @@ -43,11 +43,12 @@ const std::vector &VertexAccessor::labels() const { std::ostream &operator<<(std::ostream &os, const VertexAccessor &va) { os << "V("; - PrintIterable(os, va.labels(), ":", [&](auto &stream, auto label) { + utils::PrintIterable(os, va.labels(), ":", [&](auto &stream, auto label) { stream << va.db_accessor().LabelName(label); }); os << " {"; - PrintIterable(os, va.Properties(), ", ", [&](auto &stream, const auto &pair) { + utils::PrintIterable(os, va.Properties(), ", ", [&](auto &stream, + const auto &pair) { stream << va.db_accessor().PropertyName(pair.first) << ": " << pair.second; }); return os << "})"; diff --git a/src/storage/vertex_accessor.hpp b/src/storage/vertex_accessor.hpp index d4acbee4e..1a032b7e1 100644 --- a/src/storage/vertex_accessor.hpp +++ b/src/storage/vertex_accessor.hpp @@ -82,12 +82,14 @@ class VertexAccessor : public RecordAccessor { } /** - * Returns EdgeAccessors for all incoming edges whose type is equal to the - * given. + * Returns EdgeAccessors for all incoming edges whose type is one of the + * given. If the given collection of types is nullptr or empty, all edge types + * are valid. */ - auto in_with_type(GraphDbTypes::EdgeType edge_type) const { + auto in_with_types( + const std::vector *edge_types) const { return MakeAccessorIterator( - current().in_.begin(edge_type), current().in_.end(), db_accessor()); + current().in_.begin(edge_types), current().in_.end(), db_accessor()); } /** @@ -108,12 +110,14 @@ class VertexAccessor : public RecordAccessor { } /** - * Returns EdgeAccessors for all outgoing edges whose type is equal to the - * given. + * Returns EdgeAccessors for all outgoing edges whose type is one of the + * given. If the given collection of types is nullptr or empty, all edge types + * are valid. */ - auto out_with_type(GraphDbTypes::EdgeType edge_type) const { + auto out_with_types( + const std::vector *edge_types) const { return MakeAccessorIterator( - current().out_.begin(edge_type), current().out_.end(), db_accessor()); + current().out_.begin(edge_types), current().out_.end(), db_accessor()); } }; diff --git a/src/transactions/snapshot.hpp b/src/transactions/snapshot.hpp index 46dce6ad5..d3b386d6f 100644 --- a/src/transactions/snapshot.hpp +++ b/src/transactions/snapshot.hpp @@ -81,7 +81,7 @@ class Snapshot { friend std::ostream &operator<<(std::ostream &stream, const Snapshot &snapshot) { stream << "Snapshot("; - PrintIterable(stream, snapshot.transaction_ids_); + utils::PrintIterable(stream, snapshot.transaction_ids_); stream << ")"; return stream; } diff --git a/src/utils/algorithm.hpp b/src/utils/algorithm.hpp index d8943d993..4208d393e 100644 --- a/src/utils/algorithm.hpp +++ b/src/utils/algorithm.hpp @@ -6,6 +6,8 @@ #include "utils/exceptions.hpp" +namespace utils { + /** * Outputs a collection of items to the given stream, separating them with the * given delimiter. @@ -17,8 +19,9 @@ * streams the item to the stream. */ template -void PrintIterable(TStream &stream, const TIterable &iterable, - const std::string &delim = ", ", TStreamer streamer = {}) { +inline void PrintIterable(TStream &stream, const TIterable &iterable, + const std::string &delim = ", ", + TStreamer streamer = {}) { bool first = true; for (const auto &item : iterable) { if (first) @@ -38,8 +41,8 @@ void PrintIterable(TStream &stream, const TIterable &iterable, * @param delim Delimiter that is put between items. */ template -void PrintIterable(TStream &stream, const TIterable &iterable, - const std::string &delim = ", ") { +inline void PrintIterable(TStream &stream, const TIterable &iterable, + const std::string &delim = ", ") { PrintIterable(stream, iterable, delim, [](auto &stream, const auto &item) { stream << item; }); } @@ -54,8 +57,8 @@ void PrintIterable(TStream &stream, const TIterable &iterable, * map. */ template -std::pair FindOr(const TMap &map, const TKey &key, - TVal &&or_value) { +inline std::pair FindOr(const TMap &map, const TKey &key, + TVal &&or_value) { auto it = map.find(key); if (it != map.end()) return {it->second, true}; return {std::forward(or_value), false}; @@ -69,7 +72,7 @@ std::pair FindOr(const TMap &map, const TKey &key, * @exception BasicException is thrown if the `iterable` is empty. */ template -auto First(TIterable &&iterable) { +inline auto First(TIterable &&iterable) { if (iterable.begin() != iterable.end()) return *iterable.begin(); throw utils::BasicException("Empty iterable"); } @@ -82,7 +85,22 @@ auto First(TIterable &&iterable) { * @return The first element of the `iterable` or the `empty_value`. */ template -TVal First(TIterable &&iterable, TVal &&empty_value) { +inline TVal First(TIterable &&iterable, TVal &&empty_value) { if (iterable.begin() != iterable.end()) return *iterable.begin(); return empty_value; } + +/** + * Returns `true` if the given iterable contains the given element. + * + * @param iterable An iterable collection of values. + * @param element The sought element. + * @return `true` if element is contained in iterable. + * @tparam TIiterable type of iterable. + * @tparam TElement type of element. + */ +template +inline bool Contains(const TIterable &iterable, const TElement &element) { + return std::find(iterable.begin(), iterable.end(), element) != iterable.end(); +} +} // namespace utils diff --git a/tests/macro_benchmark/clients/common.hpp b/tests/macro_benchmark/clients/common.hpp index 0729fdf59..4cc3878a9 100644 --- a/tests/macro_benchmark/clients/common.hpp +++ b/tests/macro_benchmark/clients/common.hpp @@ -31,20 +31,20 @@ void PrintJsonDecodedValue(std::ostream &os, break; case DecodedValue::Type::List: os << "["; - PrintIterable(os, value.ValueList(), ", ", - [](auto &stream, const auto &item) { - PrintJsonDecodedValue(stream, item); - }); + utils::PrintIterable(os, value.ValueList(), ", ", + [](auto &stream, const auto &item) { + PrintJsonDecodedValue(stream, item); + }); os << "]"; break; case DecodedValue::Type::Map: os << "{"; - PrintIterable(os, value.ValueMap(), ", ", - [](auto &stream, const auto &pair) { - PrintJsonDecodedValue(stream, {pair.first}); - stream << ": "; - PrintJsonDecodedValue(stream, pair.second); - }); + utils::PrintIterable(os, value.ValueMap(), ", ", + [](auto &stream, const auto &pair) { + PrintJsonDecodedValue(stream, {pair.first}); + stream << ": "; + PrintJsonDecodedValue(stream, pair.second); + }); os << "}"; break; default: diff --git a/tests/macro_benchmark/clients/long_running_client.cpp b/tests/macro_benchmark/clients/long_running_client.cpp index 4ecdeae21..3eb5bf0f2 100644 --- a/tests/macro_benchmark/clients/long_running_client.cpp +++ b/tests/macro_benchmark/clients/long_running_client.cpp @@ -102,16 +102,16 @@ class Session { auto CreateVertex(const DecodedVertex &vertex) { std::stringstream os; os << "CREATE (n :"; - PrintIterable(os, vertex.labels, ":"); + utils::PrintIterable(os, vertex.labels, ":"); os << " {"; - PrintIterable(os, vertex.properties, ", ", - [&](auto &stream, const auto &pair) { - if (pair.second.type() == DecodedValue::Type::String) { - stream << pair.first << ": \"" << pair.second << "\""; - } else { - stream << pair.first << ": " << pair.second; - } - }); + utils::PrintIterable( + os, vertex.properties, ", ", [&](auto &stream, const auto &pair) { + if (pair.second.type() == DecodedValue::Type::String) { + stream << pair.first << ": \"" << pair.second << "\""; + } else { + stream << pair.first << ": " << pair.second; + } + }); os << "})"; return Execute(os.str(), {}, "CREATE (n :labels... {...})"); } @@ -129,14 +129,14 @@ class Session { os << "-"; } os << "[:" << edge.type << " {"; - PrintIterable(os, edge.properties, ", ", - [&](auto &stream, const auto &pair) { - if (pair.second.type() == DecodedValue::Type::String) { - stream << pair.first << ": \"" << pair.second << "\""; - } else { - stream << pair.first << ": " << pair.second; - } - }); + utils::PrintIterable( + os, edge.properties, ", ", [&](auto &stream, const auto &pair) { + if (pair.second.type() == DecodedValue::Type::String) { + stream << pair.first << ": \"" << pair.second << "\""; + } else { + stream << pair.first << ": " << pair.second; + } + }); os << "}]"; if (edge.from == from.id) { os << "->"; @@ -418,7 +418,8 @@ int main(int argc, char **argv) { out << "{\"num_executed_queries\": " << executed_queries << ", " << "\"elapsed_time\": " << timer.Elapsed().count() << ", \"queries\": ["; - PrintIterable(out, aggregated_stats, ", ", [](auto &stream, const auto &x) { + utils::PrintIterable(out, aggregated_stats, ", ", [](auto &stream, + const auto &x) { stream << "{\"query\": " << nlohmann::json(x.first) << ", \"stats\": "; PrintJsonDecodedValue(stream, DecodedValue(x.second)); stream << "}"; diff --git a/tests/macro_benchmark/clients/query_client.cpp b/tests/macro_benchmark/clients/query_client.cpp index 74cf43f01..1dc21221e 100644 --- a/tests/macro_benchmark/clients/query_client.cpp +++ b/tests/macro_benchmark/clients/query_client.cpp @@ -34,7 +34,7 @@ void PrintJsonMetadata( std::ostream &os, const std::vector> &metadata) { os << "["; - PrintIterable(os, metadata, ", ", [](auto &stream, const auto &item) { + utils::PrintIterable(os, metadata, ", ", [](auto &stream, const auto &item) { PrintJsonDecodedValue(stream, item); }); os << "]"; diff --git a/tests/manual/query_planner.cpp b/tests/manual/query_planner.cpp index 7a82754be..a928a233e 100644 --- a/tests/manual/query_planner.cpp +++ b/tests/manual/query_planner.cpp @@ -420,8 +420,9 @@ class PlanPrinter : public query::plan::HierarchicalLogicalOperatorVisitor { bool PreVisit(query::plan::Produce &op) override { WithPrintLn([&](auto &out) { out << "* Produce {"; - PrintIterable(out, op.named_expressions(), ", ", - [](auto &out, const auto &nexpr) { out << nexpr->name_; }); + utils::PrintIterable( + out, op.named_expressions(), ", ", + [](auto &out, const auto &nexpr) { out << nexpr->name_; }); out << "}"; }); return true; diff --git a/tests/unit/query_cost_estimator.cpp b/tests/unit/query_cost_estimator.cpp index 3f2bc988a..377f4409e 100644 --- a/tests/unit/query_cost_estimator.cpp +++ b/tests/unit/query_cost_estimator.cpp @@ -163,22 +163,24 @@ TEST_F(QueryCostEstimator, ScanAllByLabelPropertyRangeConstExpr) { } TEST_F(QueryCostEstimator, Expand) { - MakeOp(NextSymbol(), NextSymbol(), EdgeAtom::Direction::IN, nullptr, - last_op_, NextSymbol(), false, false); + MakeOp(NextSymbol(), NextSymbol(), EdgeAtom::Direction::IN, + std::vector{}, last_op_, NextSymbol(), + false, false); EXPECT_COST(CardParam::kExpand * CostParam::kExpand); } TEST_F(QueryCostEstimator, ExpandVariable) { MakeOp(NextSymbol(), NextSymbol(), EdgeAtom::Direction::IN, - nullptr, false, nullptr, nullptr, last_op_, - NextSymbol(), false, false); + std::vector{}, false, nullptr, + nullptr, last_op_, NextSymbol(), false, false); EXPECT_COST(CardParam::kExpandVariable * CostParam::kExpandVariable); } TEST_F(QueryCostEstimator, ExpandBreadthFirst) { MakeOp( - NextSymbol(), NextSymbol(), EdgeAtom::Direction::IN, nullptr, Literal(3), - NextSymbol(), NextSymbol(), Literal(true), last_op_, NextSymbol(), false); + NextSymbol(), NextSymbol(), EdgeAtom::Direction::IN, + std::vector{}, Literal(3), NextSymbol(), + NextSymbol(), Literal(true), last_op_, NextSymbol(), false); EXPECT_COST(CardParam::kExpandBreadthFirst * CostParam::kExpandBreadthFirst); } @@ -204,12 +206,11 @@ TEST_F(QueryCostEstimator, ExpandUniquenessFilter) { } TEST_F(QueryCostEstimator, UnwindLiteral) { - TEST_OP( - MakeOp( - last_op_, - storage_.Create(std::vector(7, nullptr)), - NextSymbol()), - CostParam::kUnwind, 7); + TEST_OP(MakeOp( + last_op_, storage_.Create( + std::vector(7, nullptr)), + NextSymbol()), + CostParam::kUnwind, 7); } TEST_F(QueryCostEstimator, UnwindNoLiteral) { diff --git a/tests/unit/query_plan_accumulate_aggregate.cpp b/tests/unit/query_plan_accumulate_aggregate.cpp index c313dfc06..0afb4740b 100644 --- a/tests/unit/query_plan_accumulate_aggregate.cpp +++ b/tests/unit/query_plan_accumulate_aggregate.cpp @@ -48,9 +48,8 @@ TEST(QueryPlan, Accumulate) { SymbolTable symbol_table; auto n = MakeScanAll(storage, symbol_table, "n"); - auto r_m = - MakeExpand(storage, symbol_table, n.op_, n.sym_, "r", - EdgeAtom::Direction::BOTH, nullptr, false, "m", false); + auto r_m = MakeExpand(storage, symbol_table, n.op_, n.sym_, "r", + EdgeAtom::Direction::BOTH, {}, false, "m", false); auto one = LITERAL(1); auto n_p = PROPERTY_LOOKUP("n", prop); diff --git a/tests/unit/query_plan_common.hpp b/tests/unit/query_plan_common.hpp index e2f4d07b7..bb92a14eb 100644 --- a/tests/unit/query_plan_common.hpp +++ b/tests/unit/query_plan_common.hpp @@ -178,7 +178,7 @@ ExpandTuple MakeExpand(AstTreeStorage &storage, SymbolTable &symbol_table, std::shared_ptr input, Symbol input_symbol, const std::string &edge_identifier, EdgeAtom::Direction direction, - const GraphDbTypes::EdgeType &edge_type, + const std::vector &edge_types, bool existing_edge, const std::string &node_identifier, bool existing_node, GraphView graph_view = GraphView::AS_IS) { @@ -190,7 +190,7 @@ ExpandTuple MakeExpand(AstTreeStorage &storage, SymbolTable &symbol_table, auto node_sym = symbol_table.CreateSymbol(node_identifier, true); symbol_table[*node->identifier_] = node_sym; - auto op = std::make_shared(node_sym, edge_sym, direction, edge_type, + auto op = std::make_shared(node_sym, edge_sym, direction, edge_types, input, input_symbol, existing_node, existing_edge, graph_view); diff --git a/tests/unit/query_plan_create_set_remove_delete.cpp b/tests/unit/query_plan_create_set_remove_delete.cpp index 5a4d7d11d..b528072d6 100644 --- a/tests/unit/query_plan_create_set_remove_delete.cpp +++ b/tests/unit/query_plan_create_set_remove_delete.cpp @@ -302,7 +302,7 @@ TEST(QueryPlan, Delete) { { auto n = MakeScanAll(storage, symbol_table, "n"); auto r_m = MakeExpand(storage, symbol_table, n.op_, n.sym_, "r", - EdgeAtom::Direction::OUT, nullptr, false, "m", false); + EdgeAtom::Direction::OUT, {}, false, "m", false); auto r_get = storage.Create("r"); symbol_table[*r_get] = r_m.edge_sym_; auto delete_op = std::make_shared( @@ -354,9 +354,8 @@ TEST(QueryPlan, DeleteTwiceDeleteBlockingEdge) { SymbolTable symbol_table; auto n = MakeScanAll(storage, symbol_table, "n"); - auto r_m = - MakeExpand(storage, symbol_table, n.op_, n.sym_, "r", - EdgeAtom::Direction::BOTH, nullptr, false, "m", false); + auto r_m = MakeExpand(storage, symbol_table, n.op_, n.sym_, "r", + EdgeAtom::Direction::BOTH, {}, false, "m", false); // getter expressions for deletion auto n_get = storage.Create("n"); @@ -479,7 +478,7 @@ TEST(QueryPlan, SetProperty) { // scan (n)-[r]->(m) auto n = MakeScanAll(storage, symbol_table, "n"); auto r_m = MakeExpand(storage, symbol_table, n.op_, n.sym_, "r", - EdgeAtom::Direction::OUT, nullptr, false, "m", false); + EdgeAtom::Direction::OUT, {}, false, "m", false); // set prop1 to 42 on n and r auto prop1 = dba->Property("prop1"); @@ -530,7 +529,7 @@ TEST(QueryPlan, SetProperties) { // scan (n)-[r]->(m) auto n = MakeScanAll(storage, symbol_table, "n"); auto r_m = MakeExpand(storage, symbol_table, n.op_, n.sym_, "r", - EdgeAtom::Direction::OUT, nullptr, false, "m", false); + EdgeAtom::Direction::OUT, {}, false, "m", false); auto op = update ? plan::SetProperties::Op::UPDATE : plan::SetProperties::Op::REPLACE; @@ -633,7 +632,7 @@ TEST(QueryPlan, RemoveProperty) { // scan (n)-[r]->(m) auto n = MakeScanAll(storage, symbol_table, "n"); auto r_m = MakeExpand(storage, symbol_table, n.op_, n.sym_, "r", - EdgeAtom::Direction::OUT, nullptr, false, "m", false); + EdgeAtom::Direction::OUT, {}, false, "m", false); auto n_p = PROPERTY_LOOKUP("n", prop1); symbol_table[*n_p->expression_] = n.sym_; @@ -711,7 +710,7 @@ TEST(QueryPlan, NodeFilterSet) { scan_all.node_->properties_[prop] = LITERAL(42); auto expand = MakeExpand(storage, symbol_table, scan_all.op_, scan_all.sym_, "r", - EdgeAtom::Direction::BOTH, nullptr, false, "m", false); + EdgeAtom::Direction::BOTH, {}, false, "m", false); auto *filter_expr = EQ(storage.Create(scan_all.node_->identifier_, prop), LITERAL(42)); @@ -751,7 +750,7 @@ TEST(QueryPlan, FilterRemove) { scan_all.node_->properties_[prop] = LITERAL(42); auto expand = MakeExpand(storage, symbol_table, scan_all.op_, scan_all.sym_, "r", - EdgeAtom::Direction::BOTH, nullptr, false, "m", false); + EdgeAtom::Direction::BOTH, {}, false, "m", false); auto filter_prop = PROPERTY_LOOKUP("n", prop); symbol_table[*filter_prop->expression_] = scan_all.sym_; auto filter = @@ -813,9 +812,8 @@ TEST(QueryPlan, Merge) { auto n = MakeScanAll(storage, symbol_table, "n"); // merge_match branch - auto r_m = - MakeExpand(storage, symbol_table, std::make_shared(), n.sym_, "r", - EdgeAtom::Direction::BOTH, nullptr, false, "m", false); + auto r_m = MakeExpand(storage, symbol_table, std::make_shared(), n.sym_, + "r", EdgeAtom::Direction::BOTH, {}, false, "m", false); auto m_p = PROPERTY_LOOKUP("m", prop); symbol_table[*m_p->expression_] = r_m.node_sym_; auto m_set = std::make_shared(r_m.op_, m_p, LITERAL(1)); diff --git a/tests/unit/query_plan_match_filter_return.cpp b/tests/unit/query_plan_match_filter_return.cpp index cc59ec451..34883a5e3 100644 --- a/tests/unit/query_plan_match_filter_return.cpp +++ b/tests/unit/query_plan_match_filter_return.cpp @@ -278,7 +278,7 @@ TEST_F(ExpandFixture, Expand) { auto test_expand = [&](EdgeAtom::Direction direction, GraphView graph_view) { auto n = MakeScanAll(storage, symbol_table, "n"); auto r_m = MakeExpand(storage, symbol_table, n.op_, n.sym_, "r", direction, - nullptr, false, "m", false, graph_view); + {}, false, "m", false, graph_view); // make a named expression and a produce auto output = NEXPR("m", IDENT("m")); @@ -315,7 +315,7 @@ TEST_F(ExpandFixture, Expand) { TEST_F(ExpandFixture, ExpandPath) { auto n = MakeScanAll(storage, symbol_table, "n"); auto r_m = MakeExpand(storage, symbol_table, n.op_, n.sym_, "r", - EdgeAtom::Direction::OUT, nullptr, false, "m", false); + EdgeAtom::Direction::OUT, {}, false, "m", false); Symbol path_sym = symbol_table.CreateSymbol("path", true); auto path = std::make_shared( r_m.op_, path_sym, @@ -409,7 +409,7 @@ class QueryPlanExpandVariable : public testing::Test { std::shared_ptr AddMatch( std::shared_ptr input_op, const std::string &node_from, int layer, EdgeAtom::Direction direction, - const GraphDbTypes::EdgeType &edge_type, + const std::vector &edge_types, std::experimental::optional lower, std::experimental::optional upper, Symbol edge_sym, bool existing_edge, const std::string &node_to, @@ -430,11 +430,11 @@ class QueryPlanExpandVariable : public testing::Test { return bound ? LITERAL(static_cast(bound.value())) : nullptr; }; return std::make_shared( - n_to_sym, edge_sym, direction, edge_type, is_reverse, convert(lower), + n_to_sym, edge_sym, direction, edge_types, is_reverse, convert(lower), convert(upper), filter_op, n_from.sym_, false, existing_edge, graph_view); } else - return std::make_shared(n_to_sym, edge_sym, direction, edge_type, + return std::make_shared(n_to_sym, edge_sym, direction, edge_types, filter_op, n_from.sym_, false, existing_edge, graph_view); } @@ -494,7 +494,7 @@ TEST_F(QueryPlanExpandVariable, OneVariableExpansion) { bool reverse) { auto e = Edge("r", direction); return GetEdgeListSizes( - AddMatch(nullptr, "n", layer, direction, nullptr, lower, + AddMatch(nullptr, "n", layer, direction, {}, lower, upper, e, false, "m", GraphView::AS_IS, reverse), e); @@ -558,20 +558,20 @@ TEST_F(QueryPlanExpandVariable, EdgeUniquenessSingleAndVariableExpansion) { if (single_expansion_before) { symbols.push_back(Edge("r0", direction)); - last_op = AddMatch(last_op, "n0", layer, direction, nullptr, - lower, upper, symbols.back(), false, "m0"); + last_op = AddMatch(last_op, "n0", layer, direction, {}, lower, + upper, symbols.back(), false, "m0"); } auto var_length_sym = Edge("r1", direction); symbols.push_back(var_length_sym); last_op = - AddMatch(last_op, "n1", layer, direction, nullptr, - lower, upper, var_length_sym, false, "m1"); + AddMatch(last_op, "n1", layer, direction, {}, lower, + upper, var_length_sym, false, "m1"); if (!single_expansion_before) { symbols.push_back(Edge("r2", direction)); - last_op = AddMatch(last_op, "n2", layer, direction, nullptr, - lower, upper, symbols.back(), false, "m2"); + last_op = AddMatch(last_op, "n2", layer, direction, {}, lower, + upper, symbols.back(), false, "m2"); } if (add_uniqueness_check) { @@ -600,12 +600,11 @@ TEST_F(QueryPlanExpandVariable, EdgeUniquenessTwoVariableExpansions) { std::experimental::optional upper, bool add_uniqueness_check) { auto e1 = Edge("r1", direction); - auto first = - AddMatch(nullptr, "n1", layer, direction, nullptr, - lower, upper, e1, false, "m1"); + auto first = AddMatch(nullptr, "n1", layer, direction, {}, + lower, upper, e1, false, "m1"); auto e2 = Edge("r2", direction); - auto last_op = AddMatch( - first, "n2", layer, direction, nullptr, lower, upper, e2, false, "m2"); + auto last_op = AddMatch(first, "n2", layer, direction, {}, + lower, upper, e2, false, "m2"); if (add_uniqueness_check) { last_op = std::make_shared>( last_op, e2, std::vector{e1}); @@ -626,12 +625,11 @@ TEST_F(QueryPlanExpandVariable, ExistingEdges) { std::experimental::optional upper, bool same_edge_symbol) { auto e1 = Edge("r1", direction); - auto first = - AddMatch(nullptr, "n1", layer, direction, nullptr, - lower, upper, e1, false, "m1"); + auto first = AddMatch(nullptr, "n1", layer, direction, {}, + lower, upper, e1, false, "m1"); auto e2 = same_edge_symbol ? e1 : Edge("r2", direction); auto second = - AddMatch(first, "n2", layer, direction, nullptr, lower, + AddMatch(first, "n2", layer, direction, {}, lower, upper, e2, same_edge_symbol, "m2"); return GetEdgeListSizes(second, e2); }; @@ -658,11 +656,13 @@ TEST_F(QueryPlanExpandVariable, ExistingEdges) { } TEST_F(QueryPlanExpandVariable, GraphState) { - auto test_expand = [&](GraphView graph_view, const auto &edge_type) { + auto test_expand = [&]( + GraphView graph_view, + const std::vector &edge_types) { auto e = Edge("r", EdgeAtom::Direction::OUT); return GetEdgeListSizes( AddMatch(nullptr, "n", 0, EdgeAtom::Direction::OUT, - edge_type, 2, 2, e, false, "m", graph_view), + edge_types, 2, 2, e, false, "m", graph_view), e); }; @@ -676,23 +676,23 @@ TEST_F(QueryPlanExpandVariable, GraphState) { ASSERT_EQ(CountIterable(dba->Vertices(false)), 6); ASSERT_EQ(CountIterable(dba->Vertices(true)), 8); - EXPECT_EQ(test_expand(GraphView::OLD, nullptr), (map_int{{2, 8}})); - EXPECT_EQ(test_expand(GraphView::OLD, new_edge_type), (map_int{})); - EXPECT_EQ(test_expand(GraphView::NEW, nullptr), (map_int{{2, 12}})); - EXPECT_EQ(test_expand(GraphView::NEW, edge_type), (map_int{{2, 8}})); - EXPECT_EQ(test_expand(GraphView::NEW, new_edge_type), (map_int{})); + EXPECT_EQ(test_expand(GraphView::OLD, {}), (map_int{{2, 8}})); + EXPECT_EQ(test_expand(GraphView::OLD, {new_edge_type}), (map_int{})); + EXPECT_EQ(test_expand(GraphView::NEW, {}), (map_int{{2, 12}})); + EXPECT_EQ(test_expand(GraphView::NEW, {edge_type}), (map_int{{2, 8}})); + EXPECT_EQ(test_expand(GraphView::NEW, {new_edge_type}), (map_int{})); dba->AdvanceCommand(); for (const auto graph_view : {GraphView::OLD, GraphView::NEW}) { - EXPECT_EQ(test_expand(graph_view, nullptr), (map_int{{2, 12}})); - EXPECT_EQ(test_expand(graph_view, edge_type), (map_int{{2, 8}})); - EXPECT_EQ(test_expand(graph_view, new_edge_type), (map_int{})); + EXPECT_EQ(test_expand(graph_view, {}), (map_int{{2, 12}})); + EXPECT_EQ(test_expand(graph_view, {edge_type}), (map_int{{2, 8}})); + EXPECT_EQ(test_expand(graph_view, {new_edge_type}), (map_int{})); } } TEST_F(QueryPlanExpandVariable, NamedPath) { auto e = Edge("r", EdgeAtom::Direction::OUT); auto expand = AddMatch( - nullptr, "n", 0, EdgeAtom::Direction::OUT, nullptr, 2, 2, e, false, "m"); + nullptr, "n", 0, EdgeAtom::Direction::OUT, {}, 2, 2, e, false, "m"); auto find_symbol = [this](const std::string &name) { for (const auto &pos_sym : symbol_table.table()) if (pos_sym.second.name() == name) return pos_sym.second; @@ -803,9 +803,10 @@ class QueryPlanExpandBreadthFirst : public testing::Test { : symbol_table.CreateSymbol("node", true); auto edge_list_sym = symbol_table.CreateSymbol("edgelist_", true); last_op = std::make_shared( - node_sym, edge_list_sym, direction, nullptr, LITERAL(max_depth), - inner_node, inner_edge, where, last_op, n.sym_, - existing_node_input != nullptr, graph_view); + node_sym, edge_list_sym, direction, + std::vector{}, LITERAL(max_depth), inner_node, + inner_edge, where, last_op, n.sym_, existing_node_input != nullptr, + graph_view); Frame frame(symbol_table.max_position()); auto cursor = last_op->MakeCursor(*dba); @@ -974,7 +975,7 @@ TEST(QueryPlan, ExpandOptional) { // MATCH (n) OPTIONAL MATCH (n)-[r]->(m) auto n = MakeScanAll(storage, symbol_table, "n"); auto r_m = MakeExpand(storage, symbol_table, nullptr, n.sym_, "r", - EdgeAtom::Direction::OUT, nullptr, false, "m", false); + EdgeAtom::Direction::OUT, {}, false, "m", false); auto optional = std::make_shared( n.op_, r_m.op_, std::vector{r_m.edge_sym_, r_m.node_sym_}); @@ -1049,7 +1050,7 @@ TEST(QueryPlan, OptionalMatchEmptyDBExpandFromNode) { auto with = MakeProduce(optional, n_ne); // MATCH (n) -[r]-> (m) auto r_m = MakeExpand(storage, symbol_table, with, with_n_sym, "r", - EdgeAtom::Direction::OUT, nullptr, false, "m", false); + EdgeAtom::Direction::OUT, {}, false, "m", false); // RETURN m auto m_ne = NEXPR("m", IDENT("m")); symbol_table[*m_ne->expression_] = r_m.node_sym_; @@ -1096,9 +1097,9 @@ TEST(QueryPlan, OptionalMatchThenExpandToMissingNode) { symbol_table[*edge->identifier_] = edge_sym; auto node = NODE("n"); symbol_table[*node->identifier_] = with_n_sym; - auto expand = - std::make_shared(with_n_sym, edge_sym, edge_direction, - nullptr, m.op_, m.sym_, true, false); + auto expand = std::make_shared( + with_n_sym, edge_sym, edge_direction, + std::vector{}, m.op_, m.sym_, true, false); // RETURN m auto m_ne = NEXPR("m", IDENT("m")); symbol_table[*m_ne->expression_] = m.sym_; @@ -1129,7 +1130,7 @@ TEST(QueryPlan, OptionalMatchThenExpandToMissingEdge) { storage.Create(n.node_->identifier_, n.node_->labels_); auto node_filter = std::make_shared(n.op_, filter_expr); auto r_m = MakeExpand(storage, symbol_table, node_filter, n.sym_, "r", - EdgeAtom::Direction::BOTH, nullptr, false, "m", false); + EdgeAtom::Direction::BOTH, {}, false, "m", false); auto optional = std::make_shared( nullptr, r_m.op_, std::vector{n.sym_, r_m.edge_sym_, r_m.node_sym_}); @@ -1147,9 +1148,9 @@ TEST(QueryPlan, OptionalMatchThenExpandToMissingEdge) { auto node = NODE("n"); auto node_sym = symbol_table.CreateSymbol("b", true); symbol_table[*node->identifier_] = node_sym; - auto expand = - std::make_shared(node_sym, with_r_sym, edge_direction, - nullptr, a.op_, a.sym_, false, true); + auto expand = std::make_shared( + node_sym, with_r_sym, edge_direction, + std::vector{}, a.op_, a.sym_, false, true); // RETURN a auto a_ne = NEXPR("a", IDENT("a")); symbol_table[*a_ne->expression_] = a.sym_; @@ -1177,13 +1178,14 @@ TEST(QueryPlan, ExpandExistingNode) { auto test_existing = [&](bool with_existing, int expected_result_count) { auto n = MakeScanAll(storage, symbol_table, "n"); - auto r_n = MakeExpand(storage, symbol_table, n.op_, n.sym_, "r", - EdgeAtom::Direction::OUT, nullptr, false, "n", - with_existing); + auto r_n = + MakeExpand(storage, symbol_table, n.op_, n.sym_, "r", + EdgeAtom::Direction::OUT, {}, false, "n", with_existing); if (with_existing) - r_n.op_ = std::make_shared(n.sym_, r_n.edge_sym_, - r_n.edge_->direction_, nullptr, n.op_, - n.sym_, with_existing, false); + r_n.op_ = + std::make_shared(n.sym_, r_n.edge_sym_, r_n.edge_->direction_, + std::vector{}, n.op_, + n.sym_, with_existing, false); // make a named expression and a produce auto output = NEXPR("n", IDENT("n")); @@ -1221,16 +1223,16 @@ TEST(QueryPlan, ExpandExistingEdge) { auto test_existing = [&](bool with_existing, int expected_result_count) { auto i = MakeScanAll(storage, symbol_table, "i"); - auto r_j = - MakeExpand(storage, symbol_table, i.op_, i.sym_, "r", - EdgeAtom::Direction::BOTH, nullptr, false, "j", false); - auto r_k = MakeExpand(storage, symbol_table, r_j.op_, r_j.node_sym_, "r", - EdgeAtom::Direction::BOTH, nullptr, with_existing, - "k", false); + auto r_j = MakeExpand(storage, symbol_table, i.op_, i.sym_, "r", + EdgeAtom::Direction::BOTH, {}, false, "j", false); + auto r_k = + MakeExpand(storage, symbol_table, r_j.op_, r_j.node_sym_, "r", + EdgeAtom::Direction::BOTH, {}, with_existing, "k", false); if (with_existing) r_k.op_ = std::make_shared( - r_k.node_sym_, r_j.edge_sym_, r_k.edge_->direction_, nullptr, r_j.op_, - r_j.node_sym_, false, with_existing); + r_k.node_sym_, r_j.edge_sym_, r_k.edge_->direction_, + std::vector{}, r_j.op_, r_j.node_sym_, false, + with_existing); // make a named expression and a produce auto output = NEXPR("r", IDENT("r")); @@ -1263,7 +1265,7 @@ TEST(QueryPlan, ExpandBothCycleEdgeCase) { auto n = MakeScanAll(storage, symbol_table, "n"); auto r_ = MakeExpand(storage, symbol_table, n.op_, n.sym_, "r", - EdgeAtom::Direction::BOTH, nullptr, false, "_", false); + EdgeAtom::Direction::BOTH, {}, false, "_", false); EXPECT_EQ(1, PullAll(r_.op_, *dba, symbol_table)); } @@ -1311,7 +1313,7 @@ TEST(QueryPlan, EdgeFilter) { const auto &edge_type = edge_types[0]; auto r_m = MakeExpand(storage, symbol_table, n.op_, n.sym_, "r", - EdgeAtom::Direction::OUT, edge_type, false, "m", false); + EdgeAtom::Direction::OUT, {edge_type}, false, "m", false); r_m.edge_->edge_types_.push_back(edge_type); r_m.edge_->properties_[prop] = LITERAL(42); auto *filter_expr = @@ -1356,7 +1358,7 @@ TEST(QueryPlan, EdgeFilterMultipleTypes) { // make a scan all auto n = MakeScanAll(storage, symbol_table, "n"); auto r_m = MakeExpand(storage, symbol_table, n.op_, n.sym_, "r", - EdgeAtom::Direction::OUT, nullptr, false, "m", false); + EdgeAtom::Direction::OUT, {}, false, "m", false); // add an edge type filter r_m.edge_->edge_types_.push_back(type_1); r_m.edge_->edge_types_.push_back(type_2); @@ -1423,16 +1425,15 @@ TEST(QueryPlan, ExpandUniquenessFilter) { SymbolTable symbol_table; auto n1 = MakeScanAll(storage, symbol_table, "n1"); - auto r1_n2 = - MakeExpand(storage, symbol_table, n1.op_, n1.sym_, "r1", - EdgeAtom::Direction::OUT, nullptr, false, "n2", false); + auto r1_n2 = MakeExpand(storage, symbol_table, n1.op_, n1.sym_, "r1", + EdgeAtom::Direction::OUT, {}, false, "n2", false); std::shared_ptr last_op = r1_n2.op_; if (vertex_uniqueness) last_op = std::make_shared>( last_op, r1_n2.node_sym_, std::vector{n1.sym_}); auto r2_n3 = MakeExpand(storage, symbol_table, last_op, r1_n2.node_sym_, "r2", - EdgeAtom::Direction::OUT, nullptr, false, "n3", false); + EdgeAtom::Direction::OUT, {}, false, "n3", false); last_op = r2_n3.op_; if (edge_uniqueness) last_op = std::make_shared>( diff --git a/tests/unit/query_variable_start_planner.cpp b/tests/unit/query_variable_start_planner.cpp index 36e413bf9..ecbadecc0 100644 --- a/tests/unit/query_variable_start_planner.cpp +++ b/tests/unit/query_variable_start_planner.cpp @@ -19,12 +19,12 @@ namespace std { // Overloads for printing resulting rows from a query. std::ostream &operator<<(std::ostream &stream, const std::vector &row) { - PrintIterable(stream, row); + utils::PrintIterable(stream, row); return stream; } std::ostream &operator<<(std::ostream &stream, const std::vector> &rows) { - PrintIterable(stream, rows, "\n"); + utils::PrintIterable(stream, rows, "\n"); return stream; } diff --git a/tests/unit/record_edge_vertex_accessor.cpp b/tests/unit/record_edge_vertex_accessor.cpp index 0db0ecb3b..a9e890873 100644 --- a/tests/unit/record_edge_vertex_accessor.cpp +++ b/tests/unit/record_edge_vertex_accessor.cpp @@ -289,22 +289,28 @@ TEST(RecordAccessor, VertexEdgeConnectionsWithEdgeType) { auto v2 = dba->InsertVertex(); auto a = dba->EdgeType("a"); auto b = dba->EdgeType("b"); + auto c = dba->EdgeType("c"); auto ea = dba->InsertEdge(v1, v2, a); auto eb_1 = dba->InsertEdge(v2, v1, b); auto eb_2 = dba->InsertEdge(v2, v1, b); + auto ec = dba->InsertEdge(v1, v2, c); dba->AdvanceCommand(); TEST_EDGE_ITERABLE(v1.in(), {eb_1, eb_2}); - TEST_EDGE_ITERABLE(v2.in(), {ea}); + TEST_EDGE_ITERABLE(v2.in(), {ea, ec}); - TEST_EDGE_ITERABLE(v1.in_with_type(a)); - TEST_EDGE_ITERABLE(v1.in_with_type(b), {eb_1, eb_2}); - TEST_EDGE_ITERABLE(v1.out_with_type(a), {ea}); - TEST_EDGE_ITERABLE(v1.out_with_type(b)); - TEST_EDGE_ITERABLE(v2.in_with_type(a), {ea}); - TEST_EDGE_ITERABLE(v2.in_with_type(b)); - TEST_EDGE_ITERABLE(v2.out_with_type(a)); - TEST_EDGE_ITERABLE(v2.out_with_type(b), {eb_1, eb_2}); + std::vector edges_a{a}; + std::vector edges_b{b}; + std::vector edges_ac{a, c}; + TEST_EDGE_ITERABLE(v1.in_with_types(&edges_a)); + TEST_EDGE_ITERABLE(v1.in_with_types(&edges_b), {eb_1, eb_2}); + TEST_EDGE_ITERABLE(v1.out_with_types(&edges_a), {ea}); + TEST_EDGE_ITERABLE(v1.out_with_types(&edges_b)); + TEST_EDGE_ITERABLE(v1.out_with_types(&edges_ac), {ea, ec}); + TEST_EDGE_ITERABLE(v2.in_with_types(&edges_a), {ea}); + TEST_EDGE_ITERABLE(v2.in_with_types(&edges_b)); + TEST_EDGE_ITERABLE(v2.out_with_types(&edges_a)); + TEST_EDGE_ITERABLE(v2.out_with_types(&edges_b), {eb_1, eb_2}); } #undef TEST_EDGE_ITERABLE