Migrate tests to storage v2 part 2
Reviewers: teon.banek Reviewed By: teon.banek Subscribers: pullbot Differential Revision: https://phabricator.memgraph.io/D2559
This commit is contained in:
parent
9cc10e131d
commit
f61a8c3358
@ -52,7 +52,7 @@ add_unit_test(deferred_deleter.cpp)
|
||||
target_link_libraries(${test_prefix}deferred_deleter mg-single-node kvstore_dummy_lib)
|
||||
|
||||
add_unit_test(bfs_single_node.cpp)
|
||||
target_link_libraries(${test_prefix}bfs_single_node mg-single-node kvstore_dummy_lib)
|
||||
target_link_libraries(${test_prefix}bfs_single_node mg-single-node-v2 mg-auth kvstore_dummy_lib)
|
||||
|
||||
add_unit_test(durability.cpp)
|
||||
target_link_libraries(${test_prefix}durability mg-single-node kvstore_dummy_lib)
|
||||
@ -127,10 +127,10 @@ add_unit_test(query_plan_accumulate_aggregate.cpp)
|
||||
target_link_libraries(${test_prefix}query_plan_accumulate_aggregate mg-single-node kvstore_dummy_lib)
|
||||
|
||||
add_unit_test(query_plan_bag_semantics.cpp)
|
||||
target_link_libraries(${test_prefix}query_plan_bag_semantics mg-single-node kvstore_dummy_lib)
|
||||
target_link_libraries(${test_prefix}query_plan_bag_semantics mg-single-node-v2 mg-auth kvstore_dummy_lib)
|
||||
|
||||
add_unit_test(query_plan_create_set_remove_delete.cpp)
|
||||
target_link_libraries(${test_prefix}query_plan_create_set_remove_delete mg-single-node kvstore_dummy_lib)
|
||||
target_link_libraries(${test_prefix}query_plan_create_set_remove_delete mg-single-node-v2 mg-auth kvstore_dummy_lib)
|
||||
|
||||
# Storage V2 in query execution
|
||||
add_unit_test(query_plan_v2_create_set_remove_delete.cpp)
|
||||
@ -163,7 +163,7 @@ add_unit_test(query_semantic.cpp)
|
||||
target_link_libraries(${test_prefix}query_semantic mg-single-node-v2 mg-auth kvstore_dummy_lib)
|
||||
|
||||
add_unit_test(query_variable_start_planner.cpp)
|
||||
target_link_libraries(${test_prefix}query_variable_start_planner mg-single-node kvstore_dummy_lib)
|
||||
target_link_libraries(${test_prefix}query_variable_start_planner mg-single-node-v2 mg-auth kvstore_dummy_lib)
|
||||
|
||||
add_unit_test(queue.cpp)
|
||||
target_link_libraries(${test_prefix}queue mg-single-node kvstore_dummy_lib)
|
||||
|
@ -26,15 +26,6 @@ void PrintTo(const query::EdgeAtom::Direction &dir, std::ostream *os) {
|
||||
}
|
||||
} // namespace query
|
||||
|
||||
#ifdef MG_SINGLE_NODE
|
||||
using VertexAddress = mvcc::VersionList<Vertex> *;
|
||||
using EdgeAddress = mvcc::VersionList<Edge> *;
|
||||
#endif
|
||||
#ifdef MG_SINGLE_NODE_HA
|
||||
using VertexAddress = mvcc::VersionList<Vertex> *;
|
||||
using EdgeAddress = mvcc::VersionList<Edge> *;
|
||||
#endif
|
||||
|
||||
const auto kVertexCount = 6;
|
||||
// Maps vertices to workers
|
||||
const std::vector<int> kVertexLocations = {0, 1, 1, 0, 2, 2};
|
||||
@ -203,8 +194,7 @@ enum class FilterLambdaType { NONE, USE_FRAME, USE_FRAME_NULL, USE_CTX, ERROR };
|
||||
// Common interface for single-node and distributed Memgraph.
|
||||
class Database {
|
||||
public:
|
||||
virtual std::unique_ptr<database::GraphDbAccessor> Access() = 0;
|
||||
virtual void AdvanceCommand(tx::TransactionId tx_id) = 0;
|
||||
virtual storage::Storage::Accessor Access() = 0;
|
||||
virtual std::unique_ptr<query::plan::LogicalOperator> MakeBfsOperator(
|
||||
query::Symbol source_sym, query::Symbol sink_sym, query::Symbol edge_sym,
|
||||
query::EdgeAtom::Direction direction,
|
||||
@ -213,9 +203,9 @@ class Database {
|
||||
bool existing_node, query::Expression *lower_bound,
|
||||
query::Expression *upper_bound,
|
||||
const query::plan::ExpansionLambda &filter_lambda) = 0;
|
||||
virtual std::pair<std::vector<VertexAddress>, std::vector<EdgeAddress>>
|
||||
BuildGraph(database::GraphDbAccessor *dba,
|
||||
const std::vector<int> &vertex_locations,
|
||||
virtual std::pair<std::vector<query::VertexAccessor>,
|
||||
std::vector<query::EdgeAccessor>>
|
||||
BuildGraph(query::DbAccessor *dba, const std::vector<int> &vertex_locations,
|
||||
const std::vector<std::tuple<int, int, std::string>> &edges) = 0;
|
||||
|
||||
virtual ~Database() {}
|
||||
@ -224,14 +214,14 @@ class Database {
|
||||
// Returns an operator that yields vertices given by their address. We will also
|
||||
// include query::TypedValue() to account for the optional match case.
|
||||
std::unique_ptr<query::plan::LogicalOperator> YieldVertices(
|
||||
database::GraphDbAccessor *dba, std::vector<VertexAddress> vertices,
|
||||
query::DbAccessor *dba, std::vector<query::VertexAccessor> vertices,
|
||||
query::Symbol symbol,
|
||||
std::shared_ptr<query::plan::LogicalOperator> input_op) {
|
||||
std::vector<std::vector<query::TypedValue>> frames;
|
||||
frames.push_back(std::vector<query::TypedValue>{query::TypedValue()});
|
||||
for (const auto &vertex : vertices) {
|
||||
frames.emplace_back(std::vector<query::TypedValue>{query::TypedValue(
|
||||
query::VertexAccessor(VertexAccessor(vertex, *dba)))});
|
||||
frames.emplace_back(
|
||||
std::vector<query::TypedValue>{query::TypedValue(vertex)});
|
||||
}
|
||||
return std::make_unique<Yield>(input_op, std::vector<query::Symbol>{symbol},
|
||||
frames);
|
||||
@ -239,42 +229,31 @@ std::unique_ptr<query::plan::LogicalOperator> YieldVertices(
|
||||
|
||||
// Returns an operator that yields edges and vertices given by their address.
|
||||
std::unique_ptr<query::plan::LogicalOperator> YieldEntities(
|
||||
database::GraphDbAccessor *dba, std::vector<VertexAddress> vertices,
|
||||
std::vector<EdgeAddress> edges, query::Symbol symbol,
|
||||
query::DbAccessor *dba, std::vector<query::VertexAccessor> vertices,
|
||||
std::vector<query::EdgeAccessor> edges, query::Symbol symbol,
|
||||
std::shared_ptr<query::plan::LogicalOperator> input_op) {
|
||||
std::vector<std::vector<query::TypedValue>> frames;
|
||||
for (const auto &vertex : vertices) {
|
||||
frames.emplace_back(std::vector<query::TypedValue>{query::TypedValue(
|
||||
query::VertexAccessor(VertexAccessor(vertex, *dba)))});
|
||||
frames.emplace_back(
|
||||
std::vector<query::TypedValue>{query::TypedValue(vertex)});
|
||||
}
|
||||
for (const auto &edge : edges) {
|
||||
frames.emplace_back(std::vector<query::TypedValue>{
|
||||
query::TypedValue(query::EdgeAccessor(EdgeAccessor(edge, *dba)))});
|
||||
frames.emplace_back(
|
||||
std::vector<query::TypedValue>{query::TypedValue(edge)});
|
||||
}
|
||||
return std::make_unique<Yield>(input_op, std::vector<query::Symbol>{symbol},
|
||||
frames);
|
||||
}
|
||||
|
||||
template <class TRecord>
|
||||
auto GetProp(const RecordAccessor<TRecord> &rec, std::string prop,
|
||||
database::GraphDbAccessor *dba) {
|
||||
return rec.PropsAt(dba->Property(prop));
|
||||
}
|
||||
|
||||
inline auto GetProp(const query::VertexAccessor &rec, std::string prop,
|
||||
database::GraphDbAccessor *dba) {
|
||||
return GetProp(rec.impl_, prop, dba);
|
||||
}
|
||||
|
||||
inline auto GetProp(const query::EdgeAccessor &rec, std::string prop,
|
||||
database::GraphDbAccessor *dba) {
|
||||
return GetProp(rec.impl_, prop, dba);
|
||||
auto GetProp(const TRecord &rec, std::string prop, query::DbAccessor *dba) {
|
||||
return *rec.GetProperty(storage::View::OLD, dba->NameToProperty(prop));
|
||||
}
|
||||
|
||||
// Checks if the given path is actually a path from source to sink and if all
|
||||
// of its edges exist in the given edge list.
|
||||
template <class TPathAllocator>
|
||||
void CheckPath(database::GraphDbAccessor *dba, const query::VertexAccessor &source,
|
||||
void CheckPath(query::DbAccessor *dba, const query::VertexAccessor &source,
|
||||
const query::VertexAccessor &sink,
|
||||
const std::vector<query::TypedValue, TPathAllocator> &path,
|
||||
const std::vector<std::pair<int, int>> &edges) {
|
||||
@ -298,8 +277,7 @@ void CheckPath(database::GraphDbAccessor *dba, const query::VertexAccessor &sour
|
||||
// Given a list of BFS results of form (from, to, path, blocked entity),
|
||||
// checks if all paths are valid and returns the distance matrix.
|
||||
std::vector<std::vector<int>> CheckPathsAndExtractDistances(
|
||||
database::GraphDbAccessor *dba,
|
||||
const std::vector<std::pair<int, int>> edges,
|
||||
query::DbAccessor *dba, const std::vector<std::pair<int, int>> edges,
|
||||
const std::vector<std::vector<query::TypedValue>> &results) {
|
||||
std::vector<std::vector<int>> distances(kVertexCount,
|
||||
std::vector<int>(kVertexCount, -1));
|
||||
@ -320,11 +298,10 @@ void BfsTest(Database *db, int lower_bound, int upper_bound,
|
||||
query::EdgeAtom::Direction direction,
|
||||
std::vector<std::string> edge_types, bool known_sink,
|
||||
FilterLambdaType filter_lambda_type) {
|
||||
auto dba_ptr = db->Access();
|
||||
auto &dba = *dba_ptr;
|
||||
auto storage_dba = db->Access();
|
||||
query::DbAccessor dba(&storage_dba);
|
||||
query::AstStorage storage;
|
||||
query::DbAccessor execution_dba(&dba);
|
||||
query::ExecutionContext context{&execution_dba};
|
||||
query::ExecutionContext context{&dba};
|
||||
query::Symbol blocked_sym =
|
||||
context.symbol_table.CreateSymbol("blocked", true);
|
||||
query::Symbol source_sym = context.symbol_table.CreateSymbol("source", true);
|
||||
@ -338,13 +315,12 @@ void BfsTest(Database *db, int lower_bound, int upper_bound,
|
||||
query::Identifier *inner_node = IDENT("inner_node")->MapTo(inner_node_sym);
|
||||
query::Identifier *inner_edge = IDENT("inner_edge")->MapTo(inner_edge_sym);
|
||||
|
||||
std::vector<VertexAddress> vertices;
|
||||
std::vector<EdgeAddress> edges;
|
||||
std::vector<query::VertexAccessor> vertices;
|
||||
std::vector<query::EdgeAccessor> edges;
|
||||
|
||||
std::tie(vertices, edges) =
|
||||
db->BuildGraph(dba_ptr.get(), kVertexLocations, kEdges);
|
||||
std::tie(vertices, edges) = db->BuildGraph(&dba, kVertexLocations, kEdges);
|
||||
|
||||
db->AdvanceCommand(dba_ptr->transaction_id());
|
||||
dba.AdvanceCommand();
|
||||
|
||||
std::shared_ptr<query::plan::LogicalOperator> input_op;
|
||||
|
||||
@ -361,14 +337,12 @@ void BfsTest(Database *db, int lower_bound, int upper_bound,
|
||||
break;
|
||||
case FilterLambdaType::USE_FRAME:
|
||||
// We block each entity in the graph and run BFS.
|
||||
input_op =
|
||||
YieldEntities(dba_ptr.get(), vertices, edges, blocked_sym, nullptr);
|
||||
input_op = YieldEntities(&dba, vertices, edges, blocked_sym, nullptr);
|
||||
filter_expr = AND(NEQ(inner_node, blocked), NEQ(inner_edge, blocked));
|
||||
break;
|
||||
case FilterLambdaType::USE_FRAME_NULL:
|
||||
// We block each entity in the graph and run BFS.
|
||||
input_op =
|
||||
YieldEntities(dba_ptr.get(), vertices, edges, blocked_sym, nullptr);
|
||||
input_op = YieldEntities(&dba, vertices, edges, blocked_sym, nullptr);
|
||||
filter_expr = IF(AND(NEQ(inner_node, blocked), NEQ(inner_edge, blocked)),
|
||||
LITERAL(true), LITERAL(PropertyValue()));
|
||||
break;
|
||||
@ -376,8 +350,8 @@ void BfsTest(Database *db, int lower_bound, int upper_bound,
|
||||
// We only block vertex #5 and run BFS.
|
||||
input_op = std::make_shared<Yield>(
|
||||
nullptr, std::vector<query::Symbol>{blocked_sym},
|
||||
std::vector<std::vector<query::TypedValue>>{{query::TypedValue(
|
||||
query::VertexAccessor(VertexAccessor(vertices[5], *dba_ptr)))}});
|
||||
std::vector<std::vector<query::TypedValue>>{
|
||||
{query::TypedValue(vertices[5])}});
|
||||
filter_expr = NEQ(PROPERTY_LOOKUP(inner_node, PROPERTY_PAIR("id")),
|
||||
PARAMETER_LOOKUP(0));
|
||||
context.evaluation_context.parameters.Add(0, PropertyValue(5));
|
||||
@ -390,17 +364,17 @@ void BfsTest(Database *db, int lower_bound, int upper_bound,
|
||||
}
|
||||
|
||||
// We run BFS once from each vertex for each blocked entity.
|
||||
input_op = YieldVertices(dba_ptr.get(), vertices, source_sym, input_op);
|
||||
input_op = YieldVertices(&dba, vertices, source_sym, input_op);
|
||||
|
||||
// If the sink is known, we run BFS for all posible combinations of source,
|
||||
// sink and blocked entity.
|
||||
if (known_sink) {
|
||||
input_op = YieldVertices(dba_ptr.get(), vertices, sink_sym, input_op);
|
||||
input_op = YieldVertices(&dba, vertices, sink_sym, input_op);
|
||||
}
|
||||
|
||||
std::vector<storage::EdgeType> storage_edge_types;
|
||||
for (const auto &t : edge_types) {
|
||||
storage_edge_types.push_back(dba_ptr->EdgeType(t));
|
||||
storage_edge_types.push_back(dba.NameToEdgeType(t));
|
||||
}
|
||||
|
||||
input_op = db->MakeBfsOperator(
|
||||
@ -411,9 +385,9 @@ void BfsTest(Database *db, int lower_bound, int upper_bound,
|
||||
filter_expr});
|
||||
|
||||
context.evaluation_context.properties =
|
||||
query::NamesToProperties(storage.properties_, &execution_dba);
|
||||
query::NamesToProperties(storage.properties_, &dba);
|
||||
context.evaluation_context.labels =
|
||||
query::NamesToLabels(storage.labels_, &execution_dba);
|
||||
query::NamesToLabels(storage.labels_, &dba);
|
||||
std::vector<std::vector<query::TypedValue>> results;
|
||||
|
||||
// An exception should be thrown on one of the pulls.
|
||||
@ -438,17 +412,14 @@ void BfsTest(Database *db, int lower_bound, int upper_bound,
|
||||
query::TypedValue::BoolEqual{}(results[j][3], blocked))
|
||||
++j;
|
||||
|
||||
SCOPED_TRACE(
|
||||
fmt::format("blocked entity = {}", ToString(blocked, execution_dba)));
|
||||
SCOPED_TRACE(fmt::format("blocked entity = {}", ToString(blocked, dba)));
|
||||
|
||||
// When an edge is blocked, it is blocked in both directions so we remove
|
||||
// it before modifying edge list to account for direction and edge types;
|
||||
auto edges = kEdges;
|
||||
if (blocked.IsEdge()) {
|
||||
int from =
|
||||
GetProp(blocked.ValueEdge(), "from", dba_ptr.get()).ValueInt();
|
||||
int to =
|
||||
GetProp(blocked.ValueEdge(), "to", dba_ptr.get()).ValueInt();
|
||||
int from = GetProp(blocked.ValueEdge(), "from", &dba).ValueInt();
|
||||
int to = GetProp(blocked.ValueEdge(), "to", &dba).ValueInt();
|
||||
edges.erase(std::remove_if(edges.begin(), edges.end(),
|
||||
[from, to](const auto &e) {
|
||||
return std::get<0>(e) == from &&
|
||||
@ -462,8 +433,7 @@ void BfsTest(Database *db, int lower_bound, int upper_bound,
|
||||
|
||||
// When a vertex is blocked, we remove all edges that lead into it.
|
||||
if (blocked.IsVertex()) {
|
||||
int id =
|
||||
GetProp(blocked.ValueVertex(), "id", dba_ptr.get()).ValueInt();
|
||||
int id = GetProp(blocked.ValueVertex(), "id", &dba).ValueInt();
|
||||
edges_blocked.erase(
|
||||
std::remove_if(edges_blocked.begin(), edges_blocked.end(),
|
||||
[id](const auto &e) { return e.second == id; }),
|
||||
@ -494,7 +464,7 @@ void BfsTest(Database *db, int lower_bound, int upper_bound,
|
||||
EXPECT_EQ(j - i, num_results);
|
||||
|
||||
auto distances = CheckPathsAndExtractDistances(
|
||||
dba_ptr.get(), edges_blocked,
|
||||
&dba, edges_blocked,
|
||||
std::vector<std::vector<query::TypedValue>>(results.begin() + i,
|
||||
results.begin() + j));
|
||||
|
||||
@ -504,5 +474,5 @@ void BfsTest(Database *db, int lower_bound, int upper_bound,
|
||||
i = j;
|
||||
}
|
||||
|
||||
dba_ptr->Abort();
|
||||
dba.Abort();
|
||||
}
|
||||
|
@ -7,16 +7,7 @@ class SingleNodeDb : public Database {
|
||||
public:
|
||||
SingleNodeDb() : db_() {}
|
||||
|
||||
std::unique_ptr<database::GraphDbAccessor> Access() override {
|
||||
std::unique_ptr<database::GraphDbAccessor> dba =
|
||||
std::make_unique<database::GraphDbAccessor>(db_.Access());
|
||||
return dba;
|
||||
}
|
||||
|
||||
void AdvanceCommand(tx::TransactionId tx_id) override {
|
||||
auto dba = db_.Access(tx_id);
|
||||
dba.AdvanceCommand();
|
||||
}
|
||||
storage::Storage::Accessor Access() override { return db_.Access(); }
|
||||
|
||||
std::unique_ptr<LogicalOperator> MakeBfsOperator(
|
||||
Symbol source_sym, Symbol sink_sym, Symbol edge_sym,
|
||||
@ -31,36 +22,42 @@ class SingleNodeDb : public Database {
|
||||
filter_lambda, std::nullopt, std::nullopt);
|
||||
}
|
||||
|
||||
std::pair<std::vector<VertexAddress>, std::vector<EdgeAddress>> BuildGraph(
|
||||
database::GraphDbAccessor *dba, const std::vector<int> &vertex_locations,
|
||||
std::pair<std::vector<query::VertexAccessor>,
|
||||
std::vector<query::EdgeAccessor>>
|
||||
BuildGraph(
|
||||
query::DbAccessor *dba, const std::vector<int> &vertex_locations,
|
||||
const std::vector<std::tuple<int, int, std::string>> &edges) override {
|
||||
std::vector<VertexAddress> vertex_addr;
|
||||
std::vector<EdgeAddress> edge_addr;
|
||||
std::vector<query::VertexAccessor> vertex_addr;
|
||||
std::vector<query::EdgeAccessor> edge_addr;
|
||||
|
||||
for (size_t id = 0; id < vertex_locations.size(); ++id) {
|
||||
auto vertex = dba->InsertVertex();
|
||||
vertex.PropsSet(dba->Property("id"),
|
||||
PropertyValue(static_cast<int64_t>(id)));
|
||||
vertex_addr.push_back(vertex.address());
|
||||
CHECK(vertex
|
||||
.SetProperty(dba->NameToProperty("id"),
|
||||
PropertyValue(static_cast<int64_t>(id)))
|
||||
.HasValue());
|
||||
vertex_addr.push_back(vertex);
|
||||
}
|
||||
|
||||
for (auto e : edges) {
|
||||
int u, v;
|
||||
std::string type;
|
||||
std::tie(u, v, type) = e;
|
||||
::VertexAccessor from(vertex_addr[u], *dba);
|
||||
::VertexAccessor to(vertex_addr[v], *dba);
|
||||
auto edge = dba->InsertEdge(from, to, dba->EdgeType(type));
|
||||
edge.PropsSet(dba->Property("from"), PropertyValue(u));
|
||||
edge.PropsSet(dba->Property("to"), PropertyValue(v));
|
||||
edge_addr.push_back(edge.address());
|
||||
auto &from = vertex_addr[u];
|
||||
auto &to = vertex_addr[v];
|
||||
auto edge = dba->InsertEdge(&from, &to, dba->NameToEdgeType(type));
|
||||
CHECK(edge->SetProperty(dba->NameToProperty("from"), PropertyValue(u))
|
||||
.HasValue());
|
||||
CHECK(edge->SetProperty(dba->NameToProperty("to"), PropertyValue(v))
|
||||
.HasValue());
|
||||
edge_addr.push_back(*edge);
|
||||
}
|
||||
|
||||
return std::make_pair(vertex_addr, edge_addr);
|
||||
}
|
||||
|
||||
protected:
|
||||
database::GraphDb db_;
|
||||
storage::Storage db_;
|
||||
};
|
||||
|
||||
class SingleNodeBfsTest
|
||||
|
@ -21,8 +21,9 @@ using namespace query;
|
||||
using namespace query::plan;
|
||||
|
||||
TEST(QueryPlan, Skip) {
|
||||
database::GraphDb db;
|
||||
auto dba = db.Access();
|
||||
storage::Storage db;
|
||||
auto storage_dba = db.Access();
|
||||
query::DbAccessor dba(&storage_dba);
|
||||
|
||||
AstStorage storage;
|
||||
SymbolTable symbol_table;
|
||||
@ -30,8 +31,7 @@ TEST(QueryPlan, Skip) {
|
||||
auto n = MakeScanAll(storage, symbol_table, "n1");
|
||||
auto skip = std::make_shared<plan::Skip>(n.op_, LITERAL(2));
|
||||
|
||||
query::DbAccessor execution_dba(&dba);
|
||||
auto context = MakeContext(storage, symbol_table, &execution_dba);
|
||||
auto context = MakeContext(storage, symbol_table, &dba);
|
||||
EXPECT_EQ(0, PullAll(*skip, &context));
|
||||
|
||||
dba.InsertVertex();
|
||||
@ -52,8 +52,9 @@ TEST(QueryPlan, Skip) {
|
||||
}
|
||||
|
||||
TEST(QueryPlan, Limit) {
|
||||
database::GraphDb db;
|
||||
auto dba = db.Access();
|
||||
storage::Storage db;
|
||||
auto storage_dba = db.Access();
|
||||
query::DbAccessor dba(&storage_dba);
|
||||
|
||||
AstStorage storage;
|
||||
SymbolTable symbol_table;
|
||||
@ -61,8 +62,7 @@ TEST(QueryPlan, Limit) {
|
||||
auto n = MakeScanAll(storage, symbol_table, "n1");
|
||||
auto skip = std::make_shared<plan::Limit>(n.op_, LITERAL(2));
|
||||
|
||||
query::DbAccessor execution_dba(&dba);
|
||||
auto context = MakeContext(storage, symbol_table, &execution_dba);
|
||||
auto context = MakeContext(storage, symbol_table, &dba);
|
||||
EXPECT_EQ(0, PullAll(*skip, &context));
|
||||
|
||||
dba.InsertVertex();
|
||||
@ -86,8 +86,9 @@ TEST(QueryPlan, CreateLimit) {
|
||||
// CREATE (n), (m)
|
||||
// MATCH (n) CREATE (m) LIMIT 1
|
||||
// in the end we need to have 3 vertices in the db
|
||||
database::GraphDb db;
|
||||
auto dba = db.Access();
|
||||
storage::Storage db;
|
||||
auto storage_dba = db.Access();
|
||||
query::DbAccessor dba(&storage_dba);
|
||||
dba.InsertVertex();
|
||||
dba.InsertVertex();
|
||||
dba.AdvanceCommand();
|
||||
@ -101,19 +102,19 @@ TEST(QueryPlan, CreateLimit) {
|
||||
auto c = std::make_shared<CreateNode>(n.op_, m);
|
||||
auto skip = std::make_shared<plan::Limit>(c, LITERAL(1));
|
||||
|
||||
query::DbAccessor execution_dba(&dba);
|
||||
auto context = MakeContext(storage, symbol_table, &execution_dba);
|
||||
auto context = MakeContext(storage, symbol_table, &dba);
|
||||
EXPECT_EQ(1, PullAll(*skip, &context));
|
||||
dba.AdvanceCommand();
|
||||
EXPECT_EQ(3, CountIterable(dba.Vertices(false)));
|
||||
EXPECT_EQ(3, CountIterable(dba.Vertices(storage::View::OLD)));
|
||||
}
|
||||
|
||||
TEST(QueryPlan, OrderBy) {
|
||||
database::GraphDb db;
|
||||
auto dba = db.Access();
|
||||
storage::Storage db;
|
||||
auto storage_dba = db.Access();
|
||||
query::DbAccessor dba(&storage_dba);
|
||||
AstStorage storage;
|
||||
SymbolTable symbol_table;
|
||||
auto prop = dba.Property("prop");
|
||||
auto prop = dba.NameToProperty("prop");
|
||||
|
||||
// contains a series of tests
|
||||
// each test defines the ordering a vector of values in the desired order
|
||||
@ -142,9 +143,10 @@ TEST(QueryPlan, OrderBy) {
|
||||
values.reserve(order_value_pair.second.size());
|
||||
for (const auto &v : order_value_pair.second) values.emplace_back(v);
|
||||
// empty database
|
||||
for (auto &vertex : dba.Vertices(false)) dba.DetachRemoveVertex(vertex);
|
||||
for (auto vertex : dba.Vertices(storage::View::OLD))
|
||||
dba.DetachRemoveVertex(&vertex);
|
||||
dba.AdvanceCommand();
|
||||
ASSERT_EQ(0, CountIterable(dba.Vertices(false)));
|
||||
ASSERT_EQ(0, CountIterable(dba.Vertices(storage::View::OLD)));
|
||||
|
||||
// take some effort to shuffle the values
|
||||
// because we are testing that something not ordered gets ordered
|
||||
@ -161,7 +163,9 @@ TEST(QueryPlan, OrderBy) {
|
||||
|
||||
// create the vertices
|
||||
for (const auto &value : shuffled)
|
||||
dba.InsertVertex().PropsSet(prop, PropertyValue(value));
|
||||
ASSERT_TRUE(dba.InsertVertex()
|
||||
.SetProperty(prop, PropertyValue(value))
|
||||
.HasValue());
|
||||
dba.AdvanceCommand();
|
||||
|
||||
// order by and collect results
|
||||
@ -173,8 +177,7 @@ TEST(QueryPlan, OrderBy) {
|
||||
auto n_p_ne =
|
||||
NEXPR("n.p", n_p)->MapTo(symbol_table.CreateSymbol("n.p", true));
|
||||
auto produce = MakeProduce(order_by, n_p_ne);
|
||||
query::DbAccessor execution_dba(&dba);
|
||||
auto context = MakeContext(storage, symbol_table, &execution_dba);
|
||||
auto context = MakeContext(storage, symbol_table, &dba);
|
||||
auto results = CollectProduce(*produce, &context);
|
||||
ASSERT_EQ(values.size(), results.size());
|
||||
for (int j = 0; j < results.size(); ++j)
|
||||
@ -183,13 +186,14 @@ TEST(QueryPlan, OrderBy) {
|
||||
}
|
||||
|
||||
TEST(QueryPlan, OrderByMultiple) {
|
||||
database::GraphDb db;
|
||||
auto dba = db.Access();
|
||||
storage::Storage db;
|
||||
auto storage_dba = db.Access();
|
||||
query::DbAccessor dba(&storage_dba);
|
||||
AstStorage storage;
|
||||
SymbolTable symbol_table;
|
||||
|
||||
auto p1 = dba.Property("p1");
|
||||
auto p2 = dba.Property("p2");
|
||||
auto p1 = dba.NameToProperty("p1");
|
||||
auto p2 = dba.NameToProperty("p2");
|
||||
|
||||
// create a bunch of vertices that in two properties
|
||||
// have all the variations (with repetition) of N values.
|
||||
@ -201,8 +205,8 @@ TEST(QueryPlan, OrderByMultiple) {
|
||||
std::random_shuffle(prop_values.begin(), prop_values.end());
|
||||
for (const auto &pair : prop_values) {
|
||||
auto v = dba.InsertVertex();
|
||||
v.PropsSet(p1, PropertyValue(pair.first));
|
||||
v.PropsSet(p2, PropertyValue(pair.second));
|
||||
ASSERT_TRUE(v.SetProperty(p1, PropertyValue(pair.first)).HasValue());
|
||||
ASSERT_TRUE(v.SetProperty(p2, PropertyValue(pair.second)).HasValue());
|
||||
}
|
||||
dba.AdvanceCommand();
|
||||
|
||||
@ -226,8 +230,7 @@ TEST(QueryPlan, OrderByMultiple) {
|
||||
auto n_p2_ne =
|
||||
NEXPR("n.p2", n_p2)->MapTo(symbol_table.CreateSymbol("n.p2", true));
|
||||
auto produce = MakeProduce(order_by, n_p1_ne, n_p2_ne);
|
||||
query::DbAccessor execution_dba(&dba);
|
||||
auto context = MakeContext(storage, symbol_table, &execution_dba);
|
||||
auto context = MakeContext(storage, symbol_table, &dba);
|
||||
auto results = CollectProduce(*produce, &context);
|
||||
ASSERT_EQ(N * N, results.size());
|
||||
for (int j = 0; j < N * N; ++j) {
|
||||
@ -239,11 +242,12 @@ TEST(QueryPlan, OrderByMultiple) {
|
||||
}
|
||||
|
||||
TEST(QueryPlan, OrderByExceptions) {
|
||||
database::GraphDb db;
|
||||
auto dba = db.Access();
|
||||
storage::Storage db;
|
||||
auto storage_dba = db.Access();
|
||||
query::DbAccessor dba(&storage_dba);
|
||||
AstStorage storage;
|
||||
SymbolTable symbol_table;
|
||||
auto prop = dba.Property("prop");
|
||||
auto prop = dba.NameToProperty("prop");
|
||||
|
||||
// a vector of pairs of typed values that should result
|
||||
// in an exception when trying to order on them
|
||||
@ -263,17 +267,19 @@ TEST(QueryPlan, OrderByExceptions) {
|
||||
|
||||
for (const auto &pair : exception_pairs) {
|
||||
// empty database
|
||||
for (auto &vertex : dba.Vertices(false)) dba.DetachRemoveVertex(vertex);
|
||||
for (auto vertex : dba.Vertices(storage::View::OLD))
|
||||
dba.DetachRemoveVertex(&vertex);
|
||||
dba.AdvanceCommand();
|
||||
ASSERT_EQ(0, CountIterable(dba.Vertices(false)));
|
||||
ASSERT_EQ(0, CountIterable(dba.Vertices(storage::View::OLD)));
|
||||
|
||||
// make two vertices, and set values
|
||||
dba.InsertVertex().PropsSet(prop, pair.first);
|
||||
dba.InsertVertex().PropsSet(prop, pair.second);
|
||||
ASSERT_TRUE(dba.InsertVertex().SetProperty(prop, pair.first).HasValue());
|
||||
ASSERT_TRUE(dba.InsertVertex().SetProperty(prop, pair.second).HasValue());
|
||||
dba.AdvanceCommand();
|
||||
ASSERT_EQ(2, CountIterable(dba.Vertices(false)));
|
||||
for (const auto &va : dba.Vertices(false))
|
||||
ASSERT_NE(va.PropsAt(prop).type(), PropertyValue::Type::Null);
|
||||
ASSERT_EQ(2, CountIterable(dba.Vertices(storage::View::OLD)));
|
||||
for (const auto &va : dba.Vertices(storage::View::OLD))
|
||||
ASSERT_NE(va.GetProperty(storage::View::OLD, prop).GetValue().type(),
|
||||
PropertyValue::Type::Null);
|
||||
|
||||
// order by and expect an exception
|
||||
auto n = MakeScanAll(storage, symbol_table, "n");
|
||||
@ -281,8 +287,7 @@ TEST(QueryPlan, OrderByExceptions) {
|
||||
auto order_by = std::make_shared<plan::OrderBy>(
|
||||
n.op_, std::vector<SortItem>{{Ordering::ASC, n_p}},
|
||||
std::vector<Symbol>{});
|
||||
query::DbAccessor execution_dba(&dba);
|
||||
auto context = MakeContext(storage, symbol_table, &execution_dba);
|
||||
auto context = MakeContext(storage, symbol_table, &dba);
|
||||
EXPECT_THROW(PullAll(*order_by, &context), QueryRuntimeException);
|
||||
}
|
||||
}
|
||||
|
@ -10,6 +10,12 @@
|
||||
#include "query/interpret/frame.hpp"
|
||||
#include "query/plan/operator.hpp"
|
||||
|
||||
// TODO (mferencevic): Remove once all cpp tests are migrated to v2.
|
||||
#ifdef MG_SINGLE_NODE_V2
|
||||
#include "query/db_accessor.hpp"
|
||||
#include "storage/v2/storage.hpp"
|
||||
#endif
|
||||
|
||||
#include "query_common.hpp"
|
||||
|
||||
using namespace query;
|
||||
@ -196,7 +202,28 @@ UnwindTuple MakeUnwind(SymbolTable &symbol_table,
|
||||
return UnwindTuple{sym, op};
|
||||
}
|
||||
|
||||
#ifdef MG_SINGLE_NODE_V2
|
||||
template <typename TIterable>
|
||||
auto CountIterable(TIterable &&iterable) {
|
||||
uint64_t count = 0;
|
||||
for (auto it = iterable.begin(); it != iterable.end(); ++it) {
|
||||
++count;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
inline uint64_t CountEdges(query::DbAccessor *dba, storage::View view) {
|
||||
uint64_t count = 0;
|
||||
for (auto vertex : dba->Vertices(view)) {
|
||||
auto maybe_edges = vertex.OutEdges(view);
|
||||
CHECK(maybe_edges.HasValue());
|
||||
count += CountIterable(*maybe_edges);
|
||||
}
|
||||
return count;
|
||||
}
|
||||
#else
|
||||
template <typename TIterable>
|
||||
auto CountIterable(TIterable iterable) {
|
||||
return std::distance(iterable.begin(), iterable.end());
|
||||
}
|
||||
#endif
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -86,12 +86,13 @@ void CheckPlansProduce(
|
||||
}
|
||||
|
||||
TEST(TestVariableStartPlanner, MatchReturn) {
|
||||
database::GraphDb db;
|
||||
auto dba = db.Access();
|
||||
storage::Storage db;
|
||||
auto storage_dba = db.Access();
|
||||
query::DbAccessor dba(&storage_dba);
|
||||
// Make a graph (v1) -[:r]-> (v2)
|
||||
auto v1 = dba.InsertVertex();
|
||||
auto v2 = dba.InsertVertex();
|
||||
dba.InsertEdge(v1, v2, dba.EdgeType("r"));
|
||||
ASSERT_TRUE(dba.InsertEdge(&v1, &v2, dba.NameToEdgeType("r")).HasValue());
|
||||
dba.AdvanceCommand();
|
||||
// Test MATCH (n) -[r]-> (m) RETURN n
|
||||
AstStorage storage;
|
||||
@ -99,24 +100,22 @@ TEST(TestVariableStartPlanner, MatchReturn) {
|
||||
MATCH(PATTERN(NODE("n"), EDGE("r", Direction::OUT), NODE("m"))),
|
||||
RETURN("n")));
|
||||
// We have 2 nodes `n` and `m` from which we could start, so expect 2 plans.
|
||||
query::DbAccessor execution_dba(&dba);
|
||||
CheckPlansProduce(
|
||||
2, query, storage, &execution_dba, [&](const auto &results) {
|
||||
// We expect to produce only a single (v1) node.
|
||||
AssertRows(results, {{TypedValue(query::VertexAccessor(v1))}},
|
||||
execution_dba);
|
||||
});
|
||||
CheckPlansProduce(2, query, storage, &dba, [&](const auto &results) {
|
||||
// We expect to produce only a single (v1) node.
|
||||
AssertRows(results, {{TypedValue(query::VertexAccessor(v1))}}, dba);
|
||||
});
|
||||
}
|
||||
|
||||
TEST(TestVariableStartPlanner, MatchTripletPatternReturn) {
|
||||
database::GraphDb db;
|
||||
auto dba = db.Access();
|
||||
storage::Storage db;
|
||||
auto storage_dba = db.Access();
|
||||
query::DbAccessor dba(&storage_dba);
|
||||
// Make a graph (v1) -[:r]-> (v2) -[:r]-> (v3)
|
||||
auto v1 = dba.InsertVertex();
|
||||
auto v2 = dba.InsertVertex();
|
||||
auto v3 = dba.InsertVertex();
|
||||
dba.InsertEdge(v1, v2, dba.EdgeType("r"));
|
||||
dba.InsertEdge(v2, v3, dba.EdgeType("r"));
|
||||
ASSERT_TRUE(dba.InsertEdge(&v1, &v2, dba.NameToEdgeType("r")).HasValue());
|
||||
ASSERT_TRUE(dba.InsertEdge(&v2, &v3, dba.NameToEdgeType("r")).HasValue());
|
||||
dba.AdvanceCommand();
|
||||
{
|
||||
// Test `MATCH (n) -[r]-> (m) -[e]-> (l) RETURN n`
|
||||
@ -126,13 +125,10 @@ TEST(TestVariableStartPlanner, MatchTripletPatternReturn) {
|
||||
EDGE("e", Direction::OUT), NODE("l"))),
|
||||
RETURN("n")));
|
||||
// We have 3 nodes: `n`, `m` and `l` from which we could start.
|
||||
query::DbAccessor execution_dba(&dba);
|
||||
CheckPlansProduce(
|
||||
3, query, storage, &execution_dba, [&](const auto &results) {
|
||||
// We expect to produce only a single (v1) node.
|
||||
AssertRows(results, {{TypedValue(query::VertexAccessor(v1))}},
|
||||
execution_dba);
|
||||
});
|
||||
CheckPlansProduce(3, query, storage, &dba, [&](const auto &results) {
|
||||
// We expect to produce only a single (v1) node.
|
||||
AssertRows(results, {{TypedValue(query::VertexAccessor(v1))}}, dba);
|
||||
});
|
||||
}
|
||||
{
|
||||
// Equivalent to `MATCH (n) -[r]-> (m), (m) -[e]-> (l) RETURN n`.
|
||||
@ -141,24 +137,22 @@ TEST(TestVariableStartPlanner, MatchTripletPatternReturn) {
|
||||
MATCH(PATTERN(NODE("n"), EDGE("r", Direction::OUT), NODE("m")),
|
||||
PATTERN(NODE("m"), EDGE("e", Direction::OUT), NODE("l"))),
|
||||
RETURN("n")));
|
||||
query::DbAccessor execution_dba(&dba);
|
||||
CheckPlansProduce(
|
||||
3, query, storage, &execution_dba, [&](const auto &results) {
|
||||
AssertRows(results, {{TypedValue(query::VertexAccessor(v1))}},
|
||||
execution_dba);
|
||||
});
|
||||
CheckPlansProduce(3, query, storage, &dba, [&](const auto &results) {
|
||||
AssertRows(results, {{TypedValue(query::VertexAccessor(v1))}}, dba);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
TEST(TestVariableStartPlanner, MatchOptionalMatchReturn) {
|
||||
database::GraphDb db;
|
||||
auto dba = db.Access();
|
||||
storage::Storage db;
|
||||
auto storage_dba = db.Access();
|
||||
query::DbAccessor dba(&storage_dba);
|
||||
// Make a graph (v1) -[:r]-> (v2) -[:r]-> (v3)
|
||||
auto v1 = dba.InsertVertex();
|
||||
auto v2 = dba.InsertVertex();
|
||||
auto v3 = dba.InsertVertex();
|
||||
dba.InsertEdge(v1, v2, dba.EdgeType("r"));
|
||||
dba.InsertEdge(v2, v3, dba.EdgeType("r"));
|
||||
ASSERT_TRUE(dba.InsertEdge(&v1, &v2, dba.NameToEdgeType("r")).HasValue());
|
||||
ASSERT_TRUE(dba.InsertEdge(&v2, &v3, dba.NameToEdgeType("r")).HasValue());
|
||||
dba.AdvanceCommand();
|
||||
// Test MATCH (n) -[r]-> (m) OPTIONAL MATCH (m) -[e]-> (l) RETURN n, l
|
||||
AstStorage storage;
|
||||
@ -168,29 +162,28 @@ TEST(TestVariableStartPlanner, MatchOptionalMatchReturn) {
|
||||
RETURN("n", "l")));
|
||||
// We have 2 nodes `n` and `m` from which we could start the MATCH, and 2
|
||||
// nodes for OPTIONAL MATCH. This should produce 2 * 2 plans.
|
||||
query::DbAccessor execution_dba(&dba);
|
||||
CheckPlansProduce(
|
||||
4, query, storage, &execution_dba, [&](const auto &results) {
|
||||
// We expect to produce 2 rows:
|
||||
// * (v1), (v3)
|
||||
// * (v2), null
|
||||
AssertRows(results,
|
||||
{{TypedValue(query::VertexAccessor(v1)),
|
||||
TypedValue(query::VertexAccessor(v3))},
|
||||
{TypedValue(query::VertexAccessor(v2)), TypedValue()}},
|
||||
execution_dba);
|
||||
});
|
||||
CheckPlansProduce(4, query, storage, &dba, [&](const auto &results) {
|
||||
// We expect to produce 2 rows:
|
||||
// * (v1), (v3)
|
||||
// * (v2), null
|
||||
AssertRows(results,
|
||||
{{TypedValue(query::VertexAccessor(v1)),
|
||||
TypedValue(query::VertexAccessor(v3))},
|
||||
{TypedValue(query::VertexAccessor(v2)), TypedValue()}},
|
||||
dba);
|
||||
});
|
||||
}
|
||||
|
||||
TEST(TestVariableStartPlanner, MatchOptionalMatchMergeReturn) {
|
||||
database::GraphDb db;
|
||||
auto dba = db.Access();
|
||||
storage::Storage db;
|
||||
auto storage_dba = db.Access();
|
||||
query::DbAccessor dba(&storage_dba);
|
||||
// Graph (v1) -[:r]-> (v2)
|
||||
query::VertexAccessor v1(dba.InsertVertex());
|
||||
query::VertexAccessor v2(dba.InsertVertex());
|
||||
auto r_type_name = "r";
|
||||
auto r_type = dba.EdgeType(r_type_name);
|
||||
dba.InsertEdge(v1.impl_, v2.impl_, r_type);
|
||||
auto r_type = dba.NameToEdgeType(r_type_name);
|
||||
ASSERT_TRUE(dba.InsertEdge(&v1, &v2, r_type).HasValue());
|
||||
dba.AdvanceCommand();
|
||||
// Test MATCH (n) -[r]-> (m) OPTIONAL MATCH (m) -[e]-> (l)
|
||||
// MERGE (u) -[q:r]-> (v) RETURN n, m, l, u, v
|
||||
@ -203,24 +196,23 @@ TEST(TestVariableStartPlanner, MatchOptionalMatchMergeReturn) {
|
||||
RETURN("n", "m", "l", "u", "v")));
|
||||
// Since MATCH, OPTIONAL MATCH and MERGE each have 2 nodes from which we can
|
||||
// start, we generate 2 * 2 * 2 plans.
|
||||
query::DbAccessor execution_dba(&dba);
|
||||
CheckPlansProduce(8, query, storage, &execution_dba,
|
||||
[&](const auto &results) {
|
||||
// We expect to produce a single row: (v1), (v2), null, (v1), (v2)
|
||||
AssertRows(results,
|
||||
{{TypedValue(v1), TypedValue(v2), TypedValue(),
|
||||
TypedValue(v1), TypedValue(v2)}},
|
||||
execution_dba);
|
||||
});
|
||||
CheckPlansProduce(8, query, storage, &dba, [&](const auto &results) {
|
||||
// We expect to produce a single row: (v1), (v2), null, (v1), (v2)
|
||||
AssertRows(results,
|
||||
{{TypedValue(v1), TypedValue(v2), TypedValue(), TypedValue(v1),
|
||||
TypedValue(v2)}},
|
||||
dba);
|
||||
});
|
||||
}
|
||||
|
||||
TEST(TestVariableStartPlanner, MatchWithMatchReturn) {
|
||||
database::GraphDb db;
|
||||
auto dba = db.Access();
|
||||
storage::Storage db;
|
||||
auto storage_dba = db.Access();
|
||||
query::DbAccessor dba(&storage_dba);
|
||||
// Graph (v1) -[:r]-> (v2)
|
||||
query::VertexAccessor v1(dba.InsertVertex());
|
||||
query::VertexAccessor v2(dba.InsertVertex());
|
||||
dba.InsertEdge(v1.impl_, v2.impl_, dba.EdgeType("r"));
|
||||
ASSERT_TRUE(dba.InsertEdge(&v1, &v2, dba.NameToEdgeType("r")).HasValue());
|
||||
dba.AdvanceCommand();
|
||||
// Test MATCH (n) -[r]-> (m) WITH n MATCH (m) -[r]-> (l) RETURN n, m, l
|
||||
AstStorage storage;
|
||||
@ -231,24 +223,23 @@ TEST(TestVariableStartPlanner, MatchWithMatchReturn) {
|
||||
RETURN("n", "m", "l")));
|
||||
// We can start from 2 nodes in each match. Since WITH separates query parts,
|
||||
// we expect to get 2 plans for each, which totals 2 * 2.
|
||||
query::DbAccessor execution_dba(&dba);
|
||||
CheckPlansProduce(
|
||||
4, query, storage, &execution_dba, [&](const auto &results) {
|
||||
// We expect to produce a single row: (v1), (v1), (v2)
|
||||
AssertRows(results, {{TypedValue(v1), TypedValue(v1), TypedValue(v2)}},
|
||||
execution_dba);
|
||||
});
|
||||
CheckPlansProduce(4, query, storage, &dba, [&](const auto &results) {
|
||||
// We expect to produce a single row: (v1), (v1), (v2)
|
||||
AssertRows(results, {{TypedValue(v1), TypedValue(v1), TypedValue(v2)}},
|
||||
dba);
|
||||
});
|
||||
}
|
||||
|
||||
TEST(TestVariableStartPlanner, MatchVariableExpand) {
|
||||
database::GraphDb db;
|
||||
auto dba = db.Access();
|
||||
storage::Storage db;
|
||||
auto storage_dba = db.Access();
|
||||
query::DbAccessor dba(&storage_dba);
|
||||
// Graph (v1) -[:r1]-> (v2) -[:r2]-> (v3)
|
||||
auto v1 = dba.InsertVertex();
|
||||
auto v2 = dba.InsertVertex();
|
||||
auto v3 = dba.InsertVertex();
|
||||
query::EdgeAccessor r1(dba.InsertEdge(v1, v2, dba.EdgeType("r1")));
|
||||
query::EdgeAccessor r2(dba.InsertEdge(v2, v3, dba.EdgeType("r2")));
|
||||
auto r1 = *dba.InsertEdge(&v1, &v2, dba.NameToEdgeType("r1"));
|
||||
auto r2 = *dba.InsertEdge(&v2, &v3, dba.NameToEdgeType("r2"));
|
||||
dba.AdvanceCommand();
|
||||
// Test MATCH (n) -[r*]-> (m) RETURN r
|
||||
AstStorage storage;
|
||||
@ -261,27 +252,25 @@ TEST(TestVariableStartPlanner, MatchVariableExpand) {
|
||||
// [r1, r2]
|
||||
TypedValue r1_r2_list(
|
||||
std::vector<TypedValue>{TypedValue(r1), TypedValue(r2)});
|
||||
query::DbAccessor execution_dba(&dba);
|
||||
CheckPlansProduce(2, query, storage, &execution_dba,
|
||||
[&](const auto &results) {
|
||||
AssertRows(results, {{r1_list}, {r2_list}, {r1_r2_list}},
|
||||
execution_dba);
|
||||
});
|
||||
CheckPlansProduce(2, query, storage, &dba, [&](const auto &results) {
|
||||
AssertRows(results, {{r1_list}, {r2_list}, {r1_r2_list}}, dba);
|
||||
});
|
||||
}
|
||||
|
||||
TEST(TestVariableStartPlanner, MatchVariableExpandReferenceNode) {
|
||||
database::GraphDb db;
|
||||
auto dba = db.Access();
|
||||
auto id = dba.Property("id");
|
||||
storage::Storage db;
|
||||
auto storage_dba = db.Access();
|
||||
query::DbAccessor dba(&storage_dba);
|
||||
auto id = dba.NameToProperty("id");
|
||||
// Graph (v1 {id:1}) -[:r1]-> (v2 {id: 2}) -[:r2]-> (v3 {id: 3})
|
||||
auto v1 = dba.InsertVertex();
|
||||
v1.PropsSet(id, PropertyValue(1));
|
||||
ASSERT_TRUE(v1.SetProperty(id, PropertyValue(1)).HasValue());
|
||||
auto v2 = dba.InsertVertex();
|
||||
v2.PropsSet(id, PropertyValue(2));
|
||||
ASSERT_TRUE(v2.SetProperty(id, PropertyValue(2)).HasValue());
|
||||
auto v3 = dba.InsertVertex();
|
||||
v3.PropsSet(id, PropertyValue(3));
|
||||
query::EdgeAccessor r1(dba.InsertEdge(v1, v2, dba.EdgeType("r1")));
|
||||
query::EdgeAccessor r2(dba.InsertEdge(v2, v3, dba.EdgeType("r2")));
|
||||
ASSERT_TRUE(v3.SetProperty(id, PropertyValue(3)).HasValue());
|
||||
auto r1 = *dba.InsertEdge(&v1, &v2, dba.NameToEdgeType("r1"));
|
||||
auto r2 = *dba.InsertEdge(&v2, &v3, dba.NameToEdgeType("r2"));
|
||||
dba.AdvanceCommand();
|
||||
// Test MATCH (n) -[r*..n.id]-> (m) RETURN r
|
||||
AstStorage storage;
|
||||
@ -294,24 +283,23 @@ TEST(TestVariableStartPlanner, MatchVariableExpandReferenceNode) {
|
||||
TypedValue r1_list(std::vector<TypedValue>{TypedValue(r1)});
|
||||
// [r2] (v2 -[*..2]-> v3)
|
||||
TypedValue r2_list(std::vector<TypedValue>{TypedValue(r2)});
|
||||
query::DbAccessor execution_dba(&dba);
|
||||
CheckPlansProduce(
|
||||
2, query, storage, &execution_dba, [&](const auto &results) {
|
||||
AssertRows(results, {{r1_list}, {r2_list}}, execution_dba);
|
||||
});
|
||||
CheckPlansProduce(2, query, storage, &dba, [&](const auto &results) {
|
||||
AssertRows(results, {{r1_list}, {r2_list}}, dba);
|
||||
});
|
||||
}
|
||||
|
||||
TEST(TestVariableStartPlanner, MatchVariableExpandBoth) {
|
||||
database::GraphDb db;
|
||||
auto dba = db.Access();
|
||||
auto id = dba.Property("id");
|
||||
storage::Storage db;
|
||||
auto storage_dba = db.Access();
|
||||
query::DbAccessor dba(&storage_dba);
|
||||
auto id = dba.NameToProperty("id");
|
||||
// Graph (v1 {id:1}) -[:r1]-> (v2) -[:r2]-> (v3)
|
||||
auto v1 = dba.InsertVertex();
|
||||
v1.PropsSet(id, PropertyValue(1));
|
||||
ASSERT_TRUE(v1.SetProperty(id, PropertyValue(1)).HasValue());
|
||||
auto v2 = dba.InsertVertex();
|
||||
auto v3 = dba.InsertVertex();
|
||||
query::EdgeAccessor r1(dba.InsertEdge(v1, v2, dba.EdgeType("r1")));
|
||||
query::EdgeAccessor r2(dba.InsertEdge(v2, v3, dba.EdgeType("r2")));
|
||||
auto r1 = *dba.InsertEdge(&v1, &v2, dba.NameToEdgeType("r1"));
|
||||
auto r2 = *dba.InsertEdge(&v2, &v3, dba.NameToEdgeType("r2"));
|
||||
dba.AdvanceCommand();
|
||||
// Test MATCH (n {id:1}) -[r*]- (m) RETURN r
|
||||
AstStorage storage;
|
||||
@ -325,26 +313,25 @@ TEST(TestVariableStartPlanner, MatchVariableExpandBoth) {
|
||||
// [r1, r2]
|
||||
TypedValue r1_r2_list(
|
||||
std::vector<TypedValue>{TypedValue(r1), TypedValue(r2)});
|
||||
query::DbAccessor execution_dba(&dba);
|
||||
CheckPlansProduce(
|
||||
2, query, storage, &execution_dba, [&](const auto &results) {
|
||||
AssertRows(results, {{r1_list}, {r1_r2_list}}, execution_dba);
|
||||
});
|
||||
CheckPlansProduce(2, query, storage, &dba, [&](const auto &results) {
|
||||
AssertRows(results, {{r1_list}, {r1_r2_list}}, dba);
|
||||
});
|
||||
}
|
||||
|
||||
TEST(TestVariableStartPlanner, MatchBfs) {
|
||||
database::GraphDb db;
|
||||
auto dba = db.Access();
|
||||
auto id = dba.Property("id");
|
||||
storage::Storage db;
|
||||
auto storage_dba = db.Access();
|
||||
query::DbAccessor dba(&storage_dba);
|
||||
auto id = dba.NameToProperty("id");
|
||||
// Graph (v1 {id:1}) -[:r1]-> (v2 {id: 2}) -[:r2]-> (v3 {id: 3})
|
||||
auto v1 = dba.InsertVertex();
|
||||
v1.PropsSet(id, PropertyValue(1));
|
||||
ASSERT_TRUE(v1.SetProperty(id, PropertyValue(1)).HasValue());
|
||||
auto v2 = dba.InsertVertex();
|
||||
v2.PropsSet(id, PropertyValue(2));
|
||||
ASSERT_TRUE(v2.SetProperty(id, PropertyValue(2)).HasValue());
|
||||
auto v3 = dba.InsertVertex();
|
||||
v3.PropsSet(id, PropertyValue(3));
|
||||
query::EdgeAccessor r1(dba.InsertEdge(v1, v2, dba.EdgeType("r1")));
|
||||
dba.InsertEdge(v2, v3, dba.EdgeType("r2"));
|
||||
ASSERT_TRUE(v3.SetProperty(id, PropertyValue(3)).HasValue());
|
||||
auto r1 = *dba.InsertEdge(&v1, &v2, dba.NameToEdgeType("r1"));
|
||||
ASSERT_TRUE(dba.InsertEdge(&v2, &v3, dba.NameToEdgeType("r2")).HasValue());
|
||||
dba.AdvanceCommand();
|
||||
// Test MATCH (n) -[r *bfs..10](r, n | n.id <> 3)]-> (m) RETURN r
|
||||
AstStorage storage;
|
||||
@ -359,11 +346,9 @@ TEST(TestVariableStartPlanner, MatchBfs) {
|
||||
SINGLE_QUERY(MATCH(PATTERN(NODE("n"), bfs, NODE("m"))), RETURN("r")));
|
||||
// We expect to get a single column with the following rows:
|
||||
TypedValue r1_list(std::vector<TypedValue>{TypedValue(r1)}); // [r1]
|
||||
query::DbAccessor execution_dba(&dba);
|
||||
CheckPlansProduce(2, query, storage, &execution_dba,
|
||||
[&](const auto &results) {
|
||||
AssertRows(results, {{r1_list}}, execution_dba);
|
||||
});
|
||||
CheckPlansProduce(2, query, storage, &dba, [&](const auto &results) {
|
||||
AssertRows(results, {{r1_list}}, dba);
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
Loading…
Reference in New Issue
Block a user