Remove Dbms

Summary:
Remove name from GraphDb.
Take GraphDb in query test macros instead of accessor.
Add is_accepting_transactions flag to GraphDb.

Reviewers: mislav.bradac, florijan, mferencevic

Reviewed By: mislav.bradac

Subscribers: mferencevic, pullbot

Differential Revision: https://phabricator.memgraph.io/D940
This commit is contained in:
Teon Banek 2017-10-30 10:43:25 +01:00
parent 7ab6da5f6a
commit 55456b4214
45 changed files with 1960 additions and 2206 deletions

View File

@ -190,7 +190,6 @@ set(memgraph_src_files
${src_dir}/communication/reactor/reactor_local.cpp
${src_dir}/communication/reactor/reactor_distributed.cpp
${src_dir}/data_structures/concurrent/skiplist_gc.cpp
${src_dir}/database/dbms.cpp
${src_dir}/database/graph_db.cpp
${src_dir}/database/graph_db_accessor.cpp
${src_dir}/durability/recovery.cpp

View File

@ -6,7 +6,6 @@
#include "io/network/socket.hpp"
#include "io/network/stream_buffer.hpp"
#include "database/dbms.hpp"
#include "query/interpreter.hpp"
#include "transactions/transaction.hpp"
@ -32,7 +31,7 @@ namespace communication::bolt {
* that are passed through the network server and worker to the session.
*/
struct SessionData {
Dbms dbms;
GraphDb db;
query::Interpreter interpreter;
};
@ -67,7 +66,7 @@ class Session {
Session(TSocket &&socket, SessionData &data)
: socket_(std::move(socket)),
dbms_(data.dbms),
db_(data.db),
interpreter_(data.interpreter) {}
~Session() {
@ -203,7 +202,7 @@ class Session {
// TODO: Rethink if there is a way to hide some members. At the momement all
// of them are public.
TSocket socket_;
Dbms &dbms_;
GraphDb &db_;
query::Interpreter &interpreter_;
TimeoutSocket timeout_socket_{*this};

View File

@ -72,17 +72,18 @@ State HandleRun(TSession &session, State state, Marker marker) {
// Transaction already exists.
in_explicit_transaction = true;
} else {
// Create new transaction.
session.db_accessor_ = session.dbms_.active();
if (!session.db_accessor_) {
// Dbms is shutting down and doesn't accept new transactions so we should
// TODO: Possible (but very unlikely) race condition, where we have alive
// session during shutdown, but is_accepting_transactions_ isn't yet false.
// We should probably create transactions under some locking mechanism.
if (!session.db_.is_accepting_transactions_) {
// Db is shutting down and doesn't accept new transactions so we should
// close this session.
return State::Close;
}
// Create new transaction.
session.db_accessor_ = std::make_unique<GraphDbAccessor>(session.db_);
}
DLOG(INFO) << fmt::format("[ActiveDB] '{}'", session.db_accessor_->name());
// If there was not explicitly started transaction before maybe we are
// starting one now.
if (!in_explicit_transaction && query.ValueString() == "BEGIN") {

View File

@ -1,30 +0,0 @@
#include "gflags/gflags.h"
#include "database/dbms.hpp"
DEFINE_string(snapshot_directory, "snapshots",
"Relative path to directory in which to save snapshots.");
DEFINE_bool(snapshot_recover_on_startup, false, "Recover database on startup.");
std::unique_ptr<GraphDbAccessor> Dbms::active() {
return std::make_unique<GraphDbAccessor>(
*active_db.load(std::memory_order_acquire));
}
std::unique_ptr<GraphDbAccessor> Dbms::active(const std::string &name,
const fs::path &snapshot_db_dir) {
if (!alive_) return nullptr;
auto acc = dbs.access();
// create db if it doesn't exist
auto it = acc.find(name);
if (it == acc.end()) {
it = acc.emplace(name, std::forward_as_tuple(name),
std::forward_as_tuple(name, snapshot_db_dir))
.first;
}
// set and return active db
auto &db = it->second;
active_db.store(&db);
return std::make_unique<GraphDbAccessor>(db);
}

View File

@ -1,105 +0,0 @@
#pragma once
#include <algorithm>
#include <memory>
#include <vector>
#include "gflags/gflags.h"
#include "data_structures/concurrent/concurrent_map.hpp"
#include "database/graph_db.hpp"
#include "database/graph_db_accessor.hpp"
#include "durability/recovery.hpp"
#include "utils/exceptions.hpp"
DECLARE_string(snapshot_directory);
DECLARE_bool(snapshot_recover_on_startup);
namespace fs = std::experimental::filesystem;
// Always be sure that Dbms object is destructed before main exits, i. e. Dbms
// object shouldn't be part of global/static variable, except if its destructor
// is explicitly called before main exits.
// Consider code:
//
// Dbms dbms; // KeyIndex is created as a part of dbms.
// int main() {
// auto dba = dbms.active();
// auto v = dba->InsertVertex();
// v.add_label(dba->Label(
// "Start")); // New SkipList is created in KeyIndex for LabelIndex.
// // That SkipList creates SkipListGc which
// // initialises static Executor object.
// return 0;
// }
//
// After main exits: 1. Executor is destructed, 2. KeyIndex is destructed.
// Destructor of KeyIndex calls delete on created SkipLists which destroy
// SkipListGc that tries to use Excutioner object that doesn't exist anymore.
// -> CRASH
class Dbms {
public:
Dbms() {
auto snapshot_root_dir = fs::path(FLAGS_snapshot_directory);
if (fs::exists(snapshot_root_dir) && !fs::is_directory(snapshot_root_dir)) {
throw utils::BasicException("Specified snapshot directory is a file!");
}
if (FLAGS_snapshot_recover_on_startup) {
if (fs::exists(snapshot_root_dir)) {
auto accessor = dbs.access();
for (auto &snapshot_db_dir :
fs::directory_iterator(FLAGS_snapshot_directory)) {
// The snapshot folder structure is:
// snapshot_root_dir/database_name/[timestamp]
if (fs::is_directory(snapshot_db_dir)) {
// Create db and set it active
active(snapshot_db_dir.path().filename(), snapshot_db_dir);
}
}
}
}
// create the default database and set is a active
active("default");
}
/**
* Aborts every transaction in every GraphDb.
*/
void Shutdown() {
alive_ = false;
for (auto &db : dbs.access()) {
db.second.tx_engine_.ForEachActiveTransaction(
[](tx::Transaction &t) { t.set_should_abort(); });
}
}
/**
* Returns an accessor to the active database. If dbms is shutting down
* (alive_ is false) it will reject new transactions and return nullptr.
*/
std::unique_ptr<GraphDbAccessor> active();
/**
* Set the database with the given name to be active.
* If there is no database with the given name,
* it's created. If snapshooting is true, snapshooter starts
* snapshooting on database creation.
*
* @return an accessor to the database with the given name.
*/
std::unique_ptr<GraphDbAccessor> active(
const std::string &name, const fs::path &snapshot_db_dir = fs::path());
// TODO: DELETE action
private:
// dbs container
ConcurrentMap<std::string, GraphDb> dbs;
// currently active database
std::atomic<GraphDb *> active_db{nullptr};
std::atomic<bool> alive_{true};
};

View File

@ -11,6 +11,15 @@
#include "storage/garbage_collector.hpp"
#include "utils/timer.hpp"
bool ValidateSnapshotDirectory(const char *flagname, const std::string &value) {
if (fs::exists(value) && !fs::is_directory(value)) {
std::cout << "The snapshot directory path '" << value
<< "' is not a directory!" << std::endl;
return false;
}
return true;
}
DEFINE_int32(gc_cycle_sec, 30,
"Amount of time between starts of two cleaning cycles in seconds. "
"-1 to turn off.");
@ -22,14 +31,14 @@ DEFINE_int32(snapshot_cycle_sec, -1,
DEFINE_int32(query_execution_time_sec, 180,
"Maximum allowed query execution time. Queries exceeding this "
"limit will be aborted. Value of -1 means no limit.");
DEFINE_bool(snapshot_on_exit, false, "Snapshot on exiting the database.");
DEFINE_string(snapshot_directory, "snapshots",
"Path to directory in which to save snapshots.");
DEFINE_validator(snapshot_directory, &ValidateSnapshotDirectory);
DEFINE_bool(snapshot_recover_on_startup, false, "Recover database on startup.");
DECLARE_string(snapshot_directory);
GraphDb::GraphDb(const std::string &name, const fs::path &snapshot_db_dir)
: name_(name),
gc_vertices_(vertices_, vertex_record_deleter_,
GraphDb::GraphDb()
: gc_vertices_(vertices_, vertex_record_deleter_,
vertex_version_list_deleter_),
gc_edges_(edges_, edge_record_deleter_, edge_version_list_deleter_) {
// Pause of -1 means we shouldn't run the GC.
@ -38,7 +47,9 @@ GraphDb::GraphDb(const std::string &name, const fs::path &snapshot_db_dir)
[this]() { CollectGarbage(); });
}
RecoverDatabase(snapshot_db_dir);
if (FLAGS_snapshot_recover_on_startup) {
RecoverDatabase(FLAGS_snapshot_directory);
}
StartSnapshooting();
if (FLAGS_query_execution_time_sec != -1) {
@ -57,12 +68,16 @@ GraphDb::GraphDb(const std::string &name, const fs::path &snapshot_db_dir)
}
}
void GraphDb::Shutdown() {
is_accepting_transactions_ = false;
tx_engine_.ForEachActiveTransaction([](auto &t) { t.set_should_abort(); });
}
void GraphDb::StartSnapshooting() {
if (FLAGS_snapshot_cycle_sec != -1) {
auto create_snapshot = [this]() -> void {
GraphDbAccessor db_accessor(*this);
snapshooter_.MakeSnapshot(db_accessor,
fs::path(FLAGS_snapshot_directory) / name_,
snapshooter_.MakeSnapshot(db_accessor, fs::path(FLAGS_snapshot_directory),
FLAGS_snapshot_max_retained);
};
snapshot_creator_.Run(std::chrono::seconds(FLAGS_snapshot_cycle_sec),
@ -162,7 +177,7 @@ GraphDb::~GraphDb() {
GraphDbAccessor db_accessor(*this);
LOG(INFO) << "Creating snapshot on shutdown..." << std::endl;
const bool status = snapshooter_.MakeSnapshot(
db_accessor, fs::path(FLAGS_snapshot_directory) / name_,
db_accessor, fs::path(FLAGS_snapshot_directory),
FLAGS_snapshot_max_retained);
if (status) {
std::cout << "Snapshot created successfully." << std::endl;

View File

@ -23,43 +23,55 @@
namespace fs = std::experimental::filesystem;
// TODO: Maybe split this in another layer between Db and Dbms. Where the new
// layer would hold SnapshotEngine and his kind of concept objects. Some
// guidelines would be: retain objects which are necessary to implement querys
// in Db, the rest can be moved to the new layer.
/**
* Main class which represents Database concept in code.
* This class is essentially a data structure. It exposes
* all the data publicly, and should therefore not be directly
* exposed to client functions. The GraphDbAccessor is used for that.
*
* Always be sure that GraphDb object is destructed before main exits, i. e.
* GraphDb object shouldn't be part of global/static variable, except if its
* destructor is explicitly called before main exits. Consider code:
*
* GraphDb db; // KeyIndex is created as a part of db.
* int main() {
* GraphDbAccessor dba(db);
* auto v = dba.InsertVertex();
* v.add_label(dba.Label(
* "Start")); // New SkipList is created in KeyIndex for LabelIndex.
* // That SkipList creates SkipListGc which
* // initialises static Executor object.
* return 0;
* }
*
* After main exits: 1. Executor is destructed, 2. KeyIndex is destructed.
* Destructor of KeyIndex calls delete on created SkipLists which destroy
* SkipListGc that tries to use Excutioner object that doesn't exist anymore.
* -> CRASH
*/
class GraphDb {
public:
/**
* Construct database with a custom name.
*
* @param name database name
* @param import_snapshot will in constructor import latest snapshot
* into the db.
*/
GraphDb(const std::string &name, const fs::path &snapshot_db_dir);
/**
* @brief - Destruct database object. Delete all vertices and edges and free
* all deferred deleters.
*/
GraphDb();
/** Delete all vertices and edges and free all deferred deleters. */
~GraphDb();
/**
* Database object can't be copied.
*/
/** Database object can't be copied. */
GraphDb(const GraphDb &db) = delete;
GraphDb(GraphDb &&other) = default;
GraphDb &operator=(const GraphDb &other) = default;
GraphDb &operator=(GraphDb &&other) = default;
/**
* Starts database snapshooting.
*/
/** Stop all transactions and set is_accepting_transactions_ to false. */
void Shutdown();
void CollectGarbage();
/** When this is false, no new transactions should be created. */
std::atomic<bool> is_accepting_transactions_{true};
private:
friend class GraphDbAccessor;
void StartSnapshooting();
/**
@ -68,17 +80,9 @@ class GraphDb {
*/
void RecoverDatabase(const fs::path &snapshot_db_path);
/**
* Collects garbage.
*/
void CollectGarbage();
/** transaction engine related to this database */
tx::Engine tx_engine_;
// database name
const std::string name_;
// main storage for the graph
SkipList<mvcc::VersionList<Vertex> *> vertices_;
SkipList<mvcc::VersionList<Edge> *> edges_;
@ -105,10 +109,12 @@ class GraphDb {
KeyIndex<GraphDbTypes::Label, Vertex> labels_index_;
LabelPropertyIndex label_property_index_;
// Flag indicating if index building is in progress. Memgraph does not support
// concurrent index builds on the same database (transaction engine), so we
// reject index builds if there is one in progress. See
// GraphDbAccessor::BuildIndex.
/**
* Flag indicating if index building is in progress. Memgraph does not support
* concurrent index builds on the same database (transaction engine), so we
* reject index builds if there is one in progress. See
* GraphDbAccessor::BuildIndex.
*/
std::atomic<bool> index_build_in_progress_{false};
// snapshooter
@ -121,6 +127,6 @@ class GraphDb {
// time to stop their execution.
Scheduler transaction_killer_;
// DB level global counters, used in the "counter" function
/** DB level global counters, used in the "counter" function. */
ConcurrentMap<std::string, std::atomic<int64_t>> counters_;
};

View File

@ -16,8 +16,6 @@ GraphDbAccessor::~GraphDbAccessor() {
}
}
const std::string &GraphDbAccessor::name() const { return db_.name_; }
void GraphDbAccessor::AdvanceCommand() {
DCHECK(!commited_ && !aborted_) << "Accessor committed or aborted";
transaction_->engine_.Advance(transaction_->id_);

View File

@ -65,11 +65,6 @@ class GraphDbAccessor {
GraphDbAccessor &operator=(const GraphDbAccessor &other) = delete;
GraphDbAccessor &operator=(GraphDbAccessor &&other) = delete;
/**
* Returns the name of the database of this accessor.
*/
const std::string &name() const;
/**
* Creates a new Vertex and returns an accessor to it.
*

View File

@ -19,9 +19,9 @@
#include "version.hpp"
namespace fs = std::experimental::filesystem;
using communication::bolt::SessionData;
using io::network::NetworkEndpoint;
using io::network::Socket;
using communication::bolt::SessionData;
using SessionT = communication::bolt::Session<Socket>;
using ResultStreamT = SessionT::ResultStreamT;
using ServerT = communication::Server<SessionT, SessionData>;
@ -70,7 +70,7 @@ int main(int argc, char **argv) {
<< stacktrace.dump() << std::endl;
});
// Initialize bolt session data (Dbms and Interpreter).
// Initialize bolt session data (GraphDb and Interpreter).
SessionData session_data;
// Initialize endpoint.
@ -85,18 +85,17 @@ int main(int argc, char **argv) {
// Initialize server.
ServerT server(endpoint, session_data);
auto shutdown = [&server, &session_data]() {
// Server needs to be shutdown first and then the database. This prevents a
// race condition when a transaction is accepted during server shutdown.
server.Shutdown();
session_data.db.Shutdown();
};
// register SIGTERM handler
SignalHandler::register_handler(Signal::Terminate,
[&server, &session_data]() {
server.Shutdown();
session_data.dbms.Shutdown();
});
SignalHandler::register_handler(Signal::Terminate, shutdown);
// register SIGINT handler
SignalHandler::register_handler(Signal::Interupt, [&server, &session_data]() {
server.Shutdown();
session_data.dbms.Shutdown();
});
SignalHandler::register_handler(Signal::Interupt, shutdown);
// Start memory warning logger.
Scheduler mem_log_scheduler;

View File

@ -123,7 +123,7 @@ void PrintResults(const ResultStreamFaker &results) {
std::cout << "}" << std::endl;
}
void query::Repl(Dbms &dbms) {
void query::Repl(GraphDb &db) {
std::cout
<< "Welcome to *Awesome* Memgraph Read Evaluate Print Loop (AM-REPL)"
<< std::endl;
@ -138,11 +138,11 @@ void query::Repl(Dbms &dbms) {
// regular cypher queries
try {
auto dba = dbms.active();
GraphDbAccessor dba(db);
ResultStreamFaker results;
interpeter.Interpret(command, *dba, results, {}, false);
interpeter.Interpret(command, dba, results, {}, false);
PrintResults(results);
dba->Commit();
dba.Commit();
} catch (const query::SyntaxException &e) {
std::cout << "SYNTAX EXCEPTION: " << e.what() << std::endl;
} catch (const query::LexingException &e) {

View File

@ -8,16 +8,14 @@
#include <list>
#include "communication/result_stream_faker.hpp"
#include "database/dbms.hpp"
namespace query {
/**
* Read Evaluate Print Loop,
* for interacting with a database
* (the active database in the given DBMS).
* Immediately starts the user-input loop
* and interprets the entered queries.
* Read Evaluate Print Loop, for interacting with a database (the database in
* the given GraphDb). Immediately starts the user-input loop and interprets the
* entered queries.
*/
void Repl(Dbms &dbms);
}
void Repl(GraphDb &);
} // namespace query

View File

@ -7,12 +7,12 @@
#include <algorithm>
#include <cstdlib>
#include <experimental/optional>
#include <functional>
#include <thread>
#include <vector>
#include "data_structures/concurrent/skiplist.hpp"
#include "database/dbms.hpp"
#include "database/graph_db_datatypes.hpp"
#include "mvcc/version_list.hpp"
#include "storage/property_value.hpp"
@ -37,7 +37,7 @@ auto RandomIntGenerator(int from, int to) {
*/
class RandomGraphGenerator {
public:
explicit RandomGraphGenerator(Dbms &dbms) : dbms_(dbms) {}
explicit RandomGraphGenerator(GraphDb &db) : db_(db) {}
/**
* Adds a progress listener that gets notified when
@ -65,10 +65,10 @@ class RandomGraphGenerator {
*/
void AddVertices(int count, const std::vector<std::string> &label_names,
int thread_count, int batch_size = 2000) {
auto dba = dbms_.active();
GraphDbAccessor dba(db_);
std::vector<GraphDbTypes::Label> labels;
for (const auto &label_name : label_names)
labels.push_back(dba->Label(label_name));
labels.push_back(dba.Label(label_name));
Map(
[&labels, this](GraphDbAccessor &dba) {
@ -83,7 +83,7 @@ class RandomGraphGenerator {
* Returns the number of vertices created by this generator,
* regardless of their labels.
*/
int64_t VertexCount() const { return dbms_.active()->VerticesCount(); }
int64_t VertexCount() const { return GraphDbAccessor(db_).VerticesCount(); }
/**
* Adds the given number of edges to the graph.
@ -106,12 +106,12 @@ class RandomGraphGenerator {
auto vertices_from = FilterVertices(from_filter);
auto vertices_to = FilterVertices(to_filter);
auto dba = dbms_.active();
auto edge_type = dba->EdgeType(edge_type_name);
GraphDbAccessor dba(db_);
auto edge_type = dba.EdgeType(edge_type_name);
// for small vertex counts reduce the batch size
batch_size =
std::min(batch_size, static_cast<int>(dba->VerticesCount() / 1000 + 1));
std::min(batch_size, static_cast<int>(dba.VerticesCount() / 1000 + 1));
Map(
[&vertices_from, &vertices_to, edge_type, this](GraphDbAccessor &dba) {
@ -130,7 +130,7 @@ class RandomGraphGenerator {
* Returns the number of edges created by this generator,
* regardless of their types and origin/destination labels.
*/
int64_t EdgeCount() const { return dbms_.active()->EdgesCount(); }
int64_t EdgeCount() const { return GraphDbAccessor(db_).EdgesCount(); }
/**
* Sets a generated property on a random vertex.
@ -146,15 +146,15 @@ class RandomGraphGenerator {
const std::string &prop_name, std::function<TValue()> value_generator,
std::function<bool(VertexAccessor &va)> predicate = {}) {
if (!predicate) predicate = [](VertexAccessor &) { return true; };
auto dba = dbms_.active();
auto property = dba->Property(prop_name);
for (VertexAccessor va : dba->Vertices(false))
GraphDbAccessor dba(db_);
auto property = dba.Property(prop_name);
for (VertexAccessor va : dba.Vertices(false))
if (predicate(va)) va.PropsSet(property, value_generator());
dba->Commit();
dba.Commit();
}
private:
Dbms &dbms_;
GraphDb &db_;
// progress listeners, they get notified about vertices and edges being
// created
@ -167,7 +167,7 @@ class RandomGraphGenerator {
*
*
* @param predicate A predicate. By default always true.
* @return A vector of vertex accessors. They belong to a GraphDbAccesor
* @return A vector of vertex accessors. They belong to a GraphDbAccessor
* that is dead when this function retuns, make sure to
* GraphDbAccessor::Transfer them.
*/
@ -175,8 +175,8 @@ class RandomGraphGenerator {
std::function<bool(VertexAccessor &item)> predicate = {}) {
if (!predicate) predicate = [](VertexAccessor &) { return true; };
std::vector<VertexAccessor> r_val;
auto dba = dbms_.active();
for (VertexAccessor &item : dba->Vertices(false))
GraphDbAccessor dba(db_);
for (VertexAccessor &item : dba.Vertices(false))
if (predicate(item)) r_val.emplace_back(item);
return r_val;
@ -204,7 +204,7 @@ class RandomGraphGenerator {
for (int thread_ind = 0; thread_ind < thread_count; thread_ind++) {
if (thread_ind == thread_count - 1) count_per_thread += count_remainder;
threads.emplace_back([count_per_thread, &f, this, elements_per_commit]() {
auto dba = dbms_.active();
std::experimental::optional<GraphDbAccessor> dba(db_);
for (int i = 0; i < count_per_thread; i++) {
try {
f(*dba);
@ -218,8 +218,8 @@ class RandomGraphGenerator {
if (i == (count_per_thread - 1) ||
(i >= 0 && i % elements_per_commit == 0)) {
dba->Commit();
auto dba2 = dbms_.active();
dba.swap(dba2);
dba = std::experimental::nullopt;
dba.emplace(db_);
}
}
});

View File

@ -3,47 +3,46 @@
#include <glog/logging.h>
#include "communication/result_stream_faker.hpp"
#include "database/dbms.hpp"
#include "query/interpreter.hpp"
#include "query/typed_value.hpp"
class ExpansionBenchFixture : public benchmark::Fixture {
protected:
// Dbms shouldn't be global constructed/destructed. See documentation in
// database/dbms.hpp for details.
std::experimental::optional<Dbms> dbms_;
// GraphDb shouldn't be global constructed/destructed. See documentation in
// database/graph_db.hpp for details.
std::experimental::optional<GraphDb> db_;
query::Interpreter interpeter_;
void SetUp(const benchmark::State &state) override {
dbms_.emplace();
auto dba = dbms_->active();
for (int i = 0; i < state.range(0); i++) dba->InsertVertex();
db_.emplace();
GraphDbAccessor dba(*db_);
for (int i = 0; i < state.range(0); i++) dba.InsertVertex();
// the fixed part is one vertex expanding to 1000 others
auto start = dba->InsertVertex();
start.add_label(dba->Label("Start"));
auto edge_type = dba->EdgeType("edge_type");
auto start = dba.InsertVertex();
start.add_label(dba.Label("Start"));
auto edge_type = dba.EdgeType("edge_type");
for (int i = 0; i < 1000; i++) {
auto dest = dba->InsertVertex();
dba->InsertEdge(start, dest, edge_type);
auto dest = dba.InsertVertex();
dba.InsertEdge(start, dest, edge_type);
}
dba->Commit();
dba.Commit();
}
void TearDown(const benchmark::State &) override {
auto dba = dbms_->active();
for (auto vertex : dba->Vertices(false)) dba->DetachRemoveVertex(vertex);
dba->Commit();
dbms_ = std::experimental::nullopt;
GraphDbAccessor dba(*db_);
for (auto vertex : dba.Vertices(false)) dba.DetachRemoveVertex(vertex);
dba.Commit();
db_ = std::experimental::nullopt;
}
};
BENCHMARK_DEFINE_F(ExpansionBenchFixture, Match)(benchmark::State &state) {
auto query = "MATCH (s:Start) return s";
auto dba = dbms_->active();
GraphDbAccessor dba(*db_);
while (state.KeepRunning()) {
ResultStreamFaker results;
interpeter_.Interpret(query, *dba, results, {}, false);
interpeter_.Interpret(query, dba, results, {}, false);
}
}
@ -54,10 +53,10 @@ BENCHMARK_REGISTER_F(ExpansionBenchFixture, Match)
BENCHMARK_DEFINE_F(ExpansionBenchFixture, Expand)(benchmark::State &state) {
auto query = "MATCH (s:Start) WITH s MATCH (s)--(d) RETURN count(d)";
auto dba = dbms_->active();
GraphDbAccessor dba(*db_);
while (state.KeepRunning()) {
ResultStreamFaker results;
interpeter_.Interpret(query, *dba, results, {}, false);
interpeter_.Interpret(query, dba, results, {}, false);
}
}

View File

@ -2,7 +2,6 @@
#include <benchmark/benchmark_api.h>
#include "database/dbms.hpp"
#include "query/frontend/semantic/symbol_generator.hpp"
#include "query/plan/cost_estimator.hpp"
#include "query/plan/planner.hpp"
@ -28,8 +27,8 @@ static void AddChainedMatches(int num_matches, query::AstTreeStorage &storage) {
}
static void BM_PlanChainedMatches(benchmark::State &state) {
Dbms dbms;
auto dba = dbms.active();
GraphDb db;
GraphDbAccessor dba(db);
while (state.KeepRunning()) {
state.PauseTiming();
query::AstTreeStorage storage;
@ -38,7 +37,7 @@ static void BM_PlanChainedMatches(benchmark::State &state) {
query::SymbolTable symbol_table;
query::SymbolGenerator symbol_generator(symbol_table);
storage.query()->Accept(symbol_generator);
auto ctx = query::plan::MakePlanningContext(storage, symbol_table, *dba);
auto ctx = query::plan::MakePlanningContext(storage, symbol_table, dba);
state.ResumeTiming();
query::plan::LogicalOperator *current_plan;
auto plans =
@ -75,32 +74,30 @@ static void AddIndexedMatches(
}
static auto CreateIndexedVertices(int index_count, int vertex_count,
Dbms &dbms) {
auto dba = dbms.active();
auto label = dba->Label("label");
auto prop = dba->Property("prop");
dba->BuildIndex(label, prop);
dba = dbms.active();
GraphDb &db) {
auto label = GraphDbAccessor(db).Label("label");
auto prop = GraphDbAccessor(db).Property("prop");
GraphDbAccessor(db).BuildIndex(label, prop);
GraphDbAccessor dba(db);
for (int vi = 0; vi < vertex_count; ++vi) {
for (int index = 0; index < index_count; ++index) {
auto vertex = dba->InsertVertex();
auto vertex = dba.InsertVertex();
vertex.add_label(label);
vertex.PropsSet(prop, index);
}
}
dba->Commit();
dba.Commit();
return std::make_pair(label, prop);
}
static void BM_PlanAndEstimateIndexedMatching(benchmark::State &state) {
Dbms dbms;
GraphDb db;
GraphDbTypes::Label label;
GraphDbTypes::Property prop;
int index_count = state.range(0);
int vertex_count = state.range(1);
std::tie(label, prop) =
CreateIndexedVertices(index_count, vertex_count, dbms);
auto dba = dbms.active();
std::tie(label, prop) = CreateIndexedVertices(index_count, vertex_count, db);
GraphDbAccessor dba(db);
Parameters parameters;
while (state.KeepRunning()) {
state.PauseTiming();
@ -111,26 +108,25 @@ static void BM_PlanAndEstimateIndexedMatching(benchmark::State &state) {
query::SymbolGenerator symbol_generator(symbol_table);
storage.query()->Accept(symbol_generator);
state.ResumeTiming();
auto ctx = query::plan::MakePlanningContext(storage, symbol_table, *dba);
auto ctx = query::plan::MakePlanningContext(storage, symbol_table, dba);
auto plans =
query::plan::MakeLogicalPlan<query::plan::VariableStartPlanner>(ctx);
for (auto plan : plans) {
query::plan::EstimatePlanCost(*dba, parameters, *plan);
query::plan::EstimatePlanCost(dba, parameters, *plan);
}
}
}
static void BM_PlanAndEstimateIndexedMatchingWithCachedCounts(
benchmark::State &state) {
Dbms dbms;
GraphDb db;
GraphDbTypes::Label label;
GraphDbTypes::Property prop;
int index_count = state.range(0);
int vertex_count = state.range(1);
std::tie(label, prop) =
CreateIndexedVertices(index_count, vertex_count, dbms);
auto dba = dbms.active();
auto vertex_counts = query::plan::MakeVertexCountCache(*dba);
std::tie(label, prop) = CreateIndexedVertices(index_count, vertex_count, db);
GraphDbAccessor dba(db);
auto vertex_counts = query::plan::MakeVertexCountCache(dba);
Parameters parameters;
while (state.KeepRunning()) {
state.PauseTiming();

View File

@ -5,7 +5,6 @@
#include <gflags/gflags.h>
#include <glog/logging.h>
#include "database/dbms.hpp"
#include "query/console.hpp"
#include "query/interpreter.hpp"
#include "utils/random_graph_generator.hpp"
@ -44,8 +43,8 @@ class ProgressReporter {
std::mutex mutex_{};
};
void random_generate(Dbms &dbms, int64_t node_count, int64_t edge_count) {
utils::RandomGraphGenerator generator(dbms);
void random_generate(GraphDb &db, int64_t node_count, int64_t edge_count) {
utils::RandomGraphGenerator generator(db);
ProgressReporter reporter(node_count, edge_count,
std::max(1l, (node_count + edge_count) / 100));
generator.AddProgressListener([&reporter](auto &rgg) { reporter(rgg); });
@ -70,10 +69,10 @@ int main(int argc, char *argv[]) {
// TODO switch to GFlags, once finally available
if (argc > 3) google::InitGoogleLogging(argv[0]);
Dbms dbms;
GraphDb db;
std::cout << "Generating graph..." << std::endl;
// fill_db(dbms);
random_generate(dbms, node_count, edge_count);
query::Repl(dbms);
// fill_db;
random_generate(db, node_count, edge_count);
query::Repl(db);
return 0;
}

View File

@ -10,7 +10,6 @@
#include "gflags/gflags.h"
#include "glog/logging.h"
#include "database/dbms.hpp"
#include "query/context.hpp"
#include "query/frontend/ast/ast.hpp"
#include "query/frontend/ast/cypher_main_visitor.hpp"
@ -646,7 +645,7 @@ int main(int argc, char *argv[]) {
std::cerr << "File '" << in_db_filename << "' does not exist!" << std::endl;
std::exit(EXIT_FAILURE);
}
Dbms dbms;
GraphDb db;
Timer planning_timer;
InteractiveDbAccessor interactive_db(
in_db_filename.empty() ? ReadInt("Vertices in DB: ") : 0, planning_timer);
@ -659,8 +658,8 @@ int main(int argc, char *argv[]) {
if (!line || *line == "quit") break;
if (line->empty()) continue;
try {
auto dba = dbms.active();
auto ast = MakeAst(*line, *dba);
GraphDbAccessor dba(db);
auto ast = MakeAst(*line, dba);
auto symbol_table = MakeSymbolTable(ast);
planning_timer.Start();
auto plans = MakeLogicalPlans(ast, symbol_table, interactive_db);

View File

@ -1,37 +1,41 @@
#include <rapidcheck.h>
#include <map>
#include <unordered_map>
#include <vector>
#include "database/dbms.hpp"
/**
* gtest/gtest.h must be included before rapidcheck/gtest.h!
*/
#include "gtest/gtest.h"
#include <gtest/gtest.h>
#include <rapidcheck.h>
#include <rapidcheck/gtest.h>
#include "database/graph_db.hpp"
#include "database/graph_db_accessor.hpp"
#include "storage/vertex_accessor.hpp"
/**
* It is possible to run test with custom seed with:
* RC_PARAMS="seed=1" ./random_graph
*/
RC_GTEST_PROP(RandomGraph, RandomGraph, (std::vector<std::string> vertex_labels,
std::vector<std::string> edge_types)) {
RC_GTEST_PROP(RandomGraph, RandomGraph,
(std::vector<std::string> vertex_labels,
std::vector<std::string> edge_types)) {
RC_PRE(!vertex_labels.empty());
RC_PRE(!edge_types.empty());
int vertices_num = vertex_labels.size();
int edges_num = edge_types.size();
Dbms dbms;
GraphDb db;
std::vector<VertexAccessor> vertices;
std::map<VertexAccessor, std::string> vertex_label_map;
std::map<EdgeAccessor, std::string> edge_type_map;
auto dba = dbms.active();
GraphDbAccessor dba(db);
for (auto label : vertex_labels) {
auto vertex_accessor = dba->InsertVertex();
vertex_accessor.add_label(dba->Label(label));
auto vertex_accessor = dba.InsertVertex();
vertex_accessor.add_label(dba.Label(label));
vertex_label_map.insert({vertex_accessor, label});
vertices.push_back(vertex_accessor);
}
@ -39,21 +43,21 @@ RC_GTEST_PROP(RandomGraph, RandomGraph, (std::vector<std::string> vertex_labels,
for (auto type : edge_types) {
auto from = vertices[*rc::gen::inRange(0, vertices_num)];
auto to = vertices[*rc::gen::inRange(0, vertices_num)];
auto edge_accessor = dba->InsertEdge(from, to, dba->EdgeType(type));
auto edge_accessor = dba.InsertEdge(from, to, dba.EdgeType(type));
edge_type_map.insert({edge_accessor, type});
}
dba->AdvanceCommand();
dba.AdvanceCommand();
int edges_num_check = 0;
int vertices_num_check = 0;
for (const auto &vertex : dba->Vertices(false)) {
for (const auto &vertex : dba.Vertices(false)) {
auto label = vertex_label_map.at(vertex);
RC_ASSERT(vertex.labels().size() == 1);
RC_ASSERT(*vertex.labels()[0] == label);
vertices_num_check++;
}
for (const auto &edge : dba->Edges(false)) {
for (const auto &edge : dba.Edges(false)) {
auto type = edge_type_map.at(edge);
RC_ASSERT(*edge.EdgeType() == type);
edges_num_check++;

View File

@ -2,7 +2,6 @@
#include "bolt_testdata.hpp"
#include "communication/bolt/v1/encoder/encoder.hpp"
#include "database/dbms.hpp"
#include "database/graph_db.hpp"
#include "database/graph_db_accessor.hpp"
#include "query/typed_value.hpp"
@ -165,10 +164,10 @@ TEST(BoltEncoder, VertexAndEdge) {
output.clear();
// create vertex
Dbms dbms;
auto db_accessor = dbms.active();
auto va1 = db_accessor->InsertVertex();
auto va2 = db_accessor->InsertVertex();
GraphDb db;
GraphDbAccessor db_accessor(db);
auto va1 = db_accessor.InsertVertex();
auto va2 = db_accessor.InsertVertex();
std::string l1("label1"), l2("label2");
va1.add_label(&l1);
va1.add_label(&l2);
@ -179,7 +178,7 @@ TEST(BoltEncoder, VertexAndEdge) {
// create edge
std::string et("edgetype");
auto ea = db_accessor->InsertEdge(va1, va2, &et);
auto ea = db_accessor.InsertEdge(va1, va2, &et);
std::string p3("prop3"), p4("prop4");
PropertyValue pv3(42), pv4(1234);
ea.PropsSet(&p3, pv3);

View File

@ -6,7 +6,6 @@
#include <vector>
#include "antlr4-runtime.h"
#include "database/dbms.hpp"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "query/context.hpp"
@ -21,21 +20,21 @@ namespace {
using namespace query;
using namespace query::frontend;
using query::TypedValue;
using testing::Pair;
using testing::ElementsAre;
using testing::Pair;
using testing::UnorderedElementsAre;
// Base class for all test types
class Base {
public:
Base(const std::string &query) : query_string_(query) {}
Dbms dbms_;
std::unique_ptr<GraphDbAccessor> db_accessor_ = dbms_.active();
Context context_{*db_accessor_};
GraphDb db_;
GraphDbAccessor db_accessor_{db_};
Context context_{db_accessor_};
std::string query_string_;
auto Prop(const std::string &prop_name) {
return db_accessor_->Property(prop_name);
return db_accessor_.Property(prop_name);
}
auto PropPair(const std::string &prop_name) {
@ -136,7 +135,7 @@ TYPED_TEST(CypherMainVisitorTest, PropertyLookup) {
ASSERT_TRUE(identifier);
ASSERT_EQ(identifier->name_, "n");
ASSERT_EQ(property_lookup->property_,
ast_generator.db_accessor_->Property("x"));
ast_generator.db_accessor_.Property("x"));
}
TYPED_TEST(CypherMainVisitorTest, LabelsTest) {
@ -151,8 +150,8 @@ TYPED_TEST(CypherMainVisitorTest, LabelsTest) {
ASSERT_TRUE(identifier);
ASSERT_EQ(identifier->name_, "n");
ASSERT_THAT(labels_test->labels_,
ElementsAre(ast_generator.db_accessor_->Label("x"),
ast_generator.db_accessor_->Label("y")));
ElementsAre(ast_generator.db_accessor_.Label("x"),
ast_generator.db_accessor_.Label("y")));
}
TYPED_TEST(CypherMainVisitorTest, EscapedLabel) {
@ -165,7 +164,7 @@ TYPED_TEST(CypherMainVisitorTest, EscapedLabel) {
auto identifier = dynamic_cast<Identifier *>(labels_test->expression_);
ASSERT_EQ(identifier->name_, "n");
ASSERT_THAT(labels_test->labels_,
ElementsAre(ast_generator.db_accessor_->Label("l-$\"'ab`e``l")));
ElementsAre(ast_generator.db_accessor_.Label("l-$\"'ab`e``l")));
}
TYPED_TEST(CypherMainVisitorTest, KeywordLabel) {
@ -182,7 +181,7 @@ TYPED_TEST(CypherMainVisitorTest, HexLetterLabel) {
auto identifier = dynamic_cast<Identifier *>(labels_test->expression_);
EXPECT_EQ(identifier->name_, "n");
ASSERT_THAT(labels_test->labels_,
ElementsAre(ast_generator.db_accessor_->Label("a")));
ElementsAre(ast_generator.db_accessor_.Label("a")));
}
TYPED_TEST(CypherMainVisitorTest, ReturnNoDistinctNoBagSemantics) {
@ -761,10 +760,10 @@ TYPED_TEST(CypherMainVisitorTest, NodePattern) {
EXPECT_EQ(node->identifier_->name_,
CypherMainVisitor::kAnonPrefix + std::to_string(1));
EXPECT_FALSE(node->identifier_->user_declared_);
EXPECT_THAT(node->labels_, UnorderedElementsAre(
ast_generator.db_accessor_->Label("label1"),
ast_generator.db_accessor_->Label("label2"),
ast_generator.db_accessor_->Label("label3")));
EXPECT_THAT(node->labels_,
UnorderedElementsAre(ast_generator.db_accessor_.Label("label1"),
ast_generator.db_accessor_.Label("label2"),
ast_generator.db_accessor_.Label("label3")));
std::map<std::pair<std::string, GraphDbTypes::Property>, int64_t> properties;
for (auto x : node->properties_) {
TypedValue value = LiteralValue(ast_generator.context_, x.second);
@ -855,8 +854,8 @@ TYPED_TEST(CypherMainVisitorTest, RelationshipPatternDetails) {
EXPECT_EQ(edge->direction_, EdgeAtom::Direction::IN);
EXPECT_THAT(
edge->edge_types_,
UnorderedElementsAre(ast_generator.db_accessor_->EdgeType("type1"),
ast_generator.db_accessor_->EdgeType("type2")));
UnorderedElementsAre(ast_generator.db_accessor_.EdgeType("type1"),
ast_generator.db_accessor_.EdgeType("type2")));
std::map<std::pair<std::string, GraphDbTypes::Property>, int64_t> properties;
for (auto x : edge->properties_) {
TypedValue value = LiteralValue(ast_generator.context_, x.second);
@ -994,7 +993,7 @@ TYPED_TEST(CypherMainVisitorTest,
CheckLiteral(ast_generator.context_,
edge->properties_[ast_generator.PropPair("prop")], 42);
ASSERT_EQ(edge->edge_types_.size(), 1U);
auto edge_type = ast_generator.db_accessor_->EdgeType("edge_type");
auto edge_type = ast_generator.db_accessor_.EdgeType("edge_type");
EXPECT_EQ(edge->edge_types_[0], edge_type);
}
@ -1116,7 +1115,7 @@ TYPED_TEST(CypherMainVisitorTest, Set) {
ASSERT_TRUE(identifier1);
ASSERT_EQ(identifier1->name_, "a");
ASSERT_EQ(set_property->property_lookup_->property_,
ast_generator.db_accessor_->Property("x"));
ast_generator.db_accessor_.Property("x"));
auto *identifier2 = dynamic_cast<Identifier *>(set_property->expression_);
ASSERT_EQ(identifier2->name_, "b");
}
@ -1151,8 +1150,8 @@ TYPED_TEST(CypherMainVisitorTest, Set) {
ASSERT_TRUE(set_labels->identifier_);
ASSERT_EQ(set_labels->identifier_->name_, "g");
ASSERT_THAT(set_labels->labels_,
UnorderedElementsAre(ast_generator.db_accessor_->Label("h"),
ast_generator.db_accessor_->Label("i")));
UnorderedElementsAre(ast_generator.db_accessor_.Label("h"),
ast_generator.db_accessor_.Label("i")));
}
}
@ -1170,7 +1169,7 @@ TYPED_TEST(CypherMainVisitorTest, Remove) {
ASSERT_TRUE(identifier1);
ASSERT_EQ(identifier1->name_, "a");
ASSERT_EQ(remove_property->property_lookup_->property_,
ast_generator.db_accessor_->Property("x"));
ast_generator.db_accessor_.Property("x"));
}
{
auto *remove_labels = dynamic_cast<RemoveLabels *>(query->clauses_[1]);
@ -1178,8 +1177,8 @@ TYPED_TEST(CypherMainVisitorTest, Remove) {
ASSERT_TRUE(remove_labels->identifier_);
ASSERT_EQ(remove_labels->identifier_->name_, "g");
ASSERT_THAT(remove_labels->labels_,
UnorderedElementsAre(ast_generator.db_accessor_->Label("h"),
ast_generator.db_accessor_->Label("i")));
UnorderedElementsAre(ast_generator.db_accessor_.Label("h"),
ast_generator.db_accessor_.Label("i")));
}
}
@ -1356,9 +1355,9 @@ TYPED_TEST(CypherMainVisitorTest, CreateIndex) {
ASSERT_EQ(query->clauses_.size(), 1U);
auto *create_index = dynamic_cast<CreateIndex *>(query->clauses_[0]);
ASSERT_TRUE(create_index);
ASSERT_EQ(create_index->label_, ast_generator.db_accessor_->Label("mirko"));
ASSERT_EQ(create_index->label_, ast_generator.db_accessor_.Label("mirko"));
ASSERT_EQ(create_index->property_,
ast_generator.db_accessor_->Property("slavko"));
ast_generator.db_accessor_.Property("slavko"));
}
TYPED_TEST(CypherMainVisitorTest, ReturnAll) {
@ -1392,8 +1391,8 @@ TYPED_TEST(CypherMainVisitorTest, MatchBfsReturn) {
EXPECT_EQ(bfs->direction_, EdgeAtom::Direction::OUT);
EXPECT_THAT(
bfs->edge_types_,
UnorderedElementsAre(ast_generator.db_accessor_->EdgeType("type1"),
ast_generator.db_accessor_->EdgeType("type2")));
UnorderedElementsAre(ast_generator.db_accessor_.EdgeType("type1"),
ast_generator.db_accessor_.EdgeType("type2")));
EXPECT_EQ(bfs->identifier_->name_, "r");
EXPECT_EQ(bfs->inner_edge_->name_, "e");
EXPECT_EQ(bfs->inner_node_->name_, "n");
@ -1401,4 +1400,4 @@ TYPED_TEST(CypherMainVisitorTest, MatchBfsReturn) {
auto *eq = dynamic_cast<EqualOperator *>(bfs->filter_expression_);
ASSERT_TRUE(eq);
}
}
} // namespace

View File

@ -1,7 +1,6 @@
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "database/dbms.hpp"
#include "database/graph_db_accessor.hpp"
#include "database/graph_db_datatypes.hpp"
#include "storage/vertex.hpp"
@ -13,36 +12,36 @@ using testing::UnorderedElementsAreArray;
// Test index does it insert everything uniquely
TEST(LabelsIndex, UniqueInsert) {
KeyIndex<GraphDbTypes::Label, Vertex> index;
Dbms dbms;
auto dba = dbms.active();
GraphDb db;
GraphDbAccessor dba(db);
tx::Engine engine;
auto t1 = engine.Begin();
mvcc::VersionList<Vertex> vlist(*t1);
t1->Commit();
auto t2 = engine.Begin();
vlist.find(*t2)->labels_.push_back(dba->Label("1"));
index.Update(dba->Label("1"), &vlist, vlist.find(*t2));
vlist.find(*t2)->labels_.push_back(dba.Label("1"));
index.Update(dba.Label("1"), &vlist, vlist.find(*t2));
// Try multiple inserts
index.Update(dba->Label("1"), &vlist, vlist.find(*t2));
index.Update(dba.Label("1"), &vlist, vlist.find(*t2));
vlist.find(*t2)->labels_.push_back(dba->Label("2"));
index.Update(dba->Label("2"), &vlist, vlist.find(*t2));
vlist.find(*t2)->labels_.push_back(dba.Label("2"));
index.Update(dba.Label("2"), &vlist, vlist.find(*t2));
vlist.find(*t2)->labels_.push_back(dba->Label("3"));
index.Update(dba->Label("3"), &vlist, vlist.find(*t2));
vlist.find(*t2)->labels_.push_back(dba.Label("3"));
index.Update(dba.Label("3"), &vlist, vlist.find(*t2));
t2->Commit();
EXPECT_EQ(index.Count(dba->Label("1")), 1);
EXPECT_EQ(index.Count(dba->Label("2")), 1);
EXPECT_EQ(index.Count(dba->Label("3")), 1);
EXPECT_EQ(index.Count(dba.Label("1")), 1);
EXPECT_EQ(index.Count(dba.Label("2")), 1);
EXPECT_EQ(index.Count(dba.Label("3")), 1);
}
// Check if index filters duplicates.
TEST(LabelsIndex, UniqueFilter) {
Dbms dbms;
GraphDb db;
KeyIndex<GraphDbTypes::Label, Vertex> index;
auto dba = dbms.active();
GraphDbAccessor dba(db);
tx::Engine engine;
auto t1 = engine.Begin();
@ -53,7 +52,7 @@ TEST(LabelsIndex, UniqueFilter) {
auto r1v2 = vlist2.find(*t1);
EXPECT_NE(vlist1.find(*t1), nullptr);
auto label1 = dba->Label("1");
auto label1 = dba.Label("1");
vlist1.find(*t1)->labels_.push_back(label1);
vlist2.find(*t1)->labels_.push_back(label1);
index.Update(label1, &vlist1, r1v1);
@ -81,8 +80,8 @@ TEST(LabelsIndex, UniqueFilter) {
// Delete not anymore relevant recods from index.
TEST(LabelsIndex, Refresh) {
KeyIndex<GraphDbTypes::Label, Vertex> index;
Dbms dbms;
auto access = dbms.active();
GraphDb db;
GraphDbAccessor access(db);
tx::Engine engine;
// add two vertices to database
@ -96,7 +95,7 @@ TEST(LabelsIndex, Refresh) {
EXPECT_NE(v1r1, nullptr);
EXPECT_NE(v2r1, nullptr);
auto label = access->Label("label");
auto label = access.Label("label");
v1r1->labels_.push_back(label);
v2r1->labels_.push_back(label);
index.Update(label, &vlist1, v1r1);
@ -120,11 +119,11 @@ TEST(LabelsIndex, Refresh) {
// Transaction hasn't ended and so the vertex is not visible.
TEST(LabelsIndexDb, AddGetZeroLabels) {
Dbms dbms;
auto dba = dbms.active();
auto vertex = dba->InsertVertex();
vertex.add_label(dba->Label("test"));
auto collection = dba->Vertices(dba->Label("test"), false);
GraphDb db;
GraphDbAccessor dba(db);
auto vertex = dba.InsertVertex();
vertex.add_label(dba.Label("test"));
auto collection = dba.Vertices(dba.Label("test"), false);
std::vector<VertexAccessor> collection_vector(collection.begin(),
collection.end());
EXPECT_EQ(collection_vector.size(), (size_t)0);
@ -133,63 +132,63 @@ TEST(LabelsIndexDb, AddGetZeroLabels) {
// Test label index by adding and removing one vertex, and removing label from
// another, while the third one with an irrelevant label exists.
TEST(LabelsIndexDb, AddGetRemoveLabel) {
Dbms dbms;
GraphDb db;
{
auto dba = dbms.active();
GraphDbAccessor dba(db);
auto vertex1 = dba->InsertVertex();
vertex1.add_label(dba->Label("test"));
auto vertex1 = dba.InsertVertex();
vertex1.add_label(dba.Label("test"));
auto vertex2 = dba->InsertVertex();
vertex2.add_label(dba->Label("test2"));
auto vertex2 = dba.InsertVertex();
vertex2.add_label(dba.Label("test2"));
auto vertex3 = dba->InsertVertex();
vertex3.add_label(dba->Label("test"));
auto vertex3 = dba.InsertVertex();
vertex3.add_label(dba.Label("test"));
dba->Commit();
dba.Commit();
} // Finish transaction.
{
auto dba = dbms.active();
GraphDbAccessor dba(db);
auto filtered = dba->Vertices(dba->Label("test"), false);
auto filtered = dba.Vertices(dba.Label("test"), false);
std::vector<VertexAccessor> collection(filtered.begin(), filtered.end());
auto vertices = dba->Vertices(false);
auto vertices = dba.Vertices(false);
std::vector<VertexAccessor> expected_collection;
for (auto vertex : vertices) {
if (vertex.has_label(dba->Label("test"))) {
if (vertex.has_label(dba.Label("test"))) {
expected_collection.push_back(vertex);
} else {
EXPECT_TRUE(vertex.has_label(dba->Label("test2")));
EXPECT_TRUE(vertex.has_label(dba.Label("test2")));
}
}
EXPECT_EQ(expected_collection.size(), collection.size());
EXPECT_TRUE(collection[0].has_label(dba->Label("test")));
EXPECT_TRUE(collection[1].has_label(dba->Label("test")));
EXPECT_FALSE(collection[0].has_label(dba->Label("test2")));
EXPECT_FALSE(collection[1].has_label(dba->Label("test2")));
dba->RemoveVertex(collection[0]); // Remove from database and test if
// index won't return it.
EXPECT_TRUE(collection[0].has_label(dba.Label("test")));
EXPECT_TRUE(collection[1].has_label(dba.Label("test")));
EXPECT_FALSE(collection[0].has_label(dba.Label("test2")));
EXPECT_FALSE(collection[1].has_label(dba.Label("test2")));
dba.RemoveVertex(collection[0]); // Remove from database and test if
// index won't return it.
// Remove label from the vertex and add new label.
collection[1].remove_label(dba->Label("test"));
collection[1].add_label(dba->Label("test2"));
dba->Commit();
collection[1].remove_label(dba.Label("test"));
collection[1].add_label(dba.Label("test2"));
dba.Commit();
}
{
auto dba = dbms.active();
GraphDbAccessor dba(db);
auto filtered = dba->Vertices(dba->Label("test"), false);
auto filtered = dba.Vertices(dba.Label("test"), false);
std::vector<VertexAccessor> collection(filtered.begin(), filtered.end());
auto vertices = dba->Vertices(false);
auto vertices = dba.Vertices(false);
std::vector<VertexAccessor> expected_collection;
for (auto vertex : vertices) {
if (vertex.has_label(dba->Label("test"))) {
if (vertex.has_label(dba.Label("test"))) {
expected_collection.push_back(vertex);
} else {
EXPECT_TRUE(vertex.has_label(dba->Label("test2")));
EXPECT_TRUE(vertex.has_label(dba.Label("test2")));
}
}

View File

@ -1,7 +1,7 @@
#include "gtest/gtest.h"
#include "database/dbms.hpp"
#include "database/graph_db.hpp"
#include "database/graph_db_accessor.hpp"
#include "database/graph_db_datatypes.hpp"
#include "database/indexes/label_property_index.hpp"
@ -10,12 +10,12 @@
class LabelPropertyIndexComplexTest : public ::testing::Test {
protected:
virtual void SetUp() {
auto accessor = dbms.active();
GraphDbAccessor accessor(db_);
label = accessor->Label("label");
property = accessor->Property("property");
label2 = accessor->Label("label2");
property2 = accessor->Property("property2");
label = accessor.Label("label");
property = accessor.Property("property");
label2 = accessor.Label("label2");
property2 = accessor.Property("property2");
key = new LabelPropertyIndex::Key(label, property);
EXPECT_EQ(index.CreateIndex(*key), true);
@ -39,7 +39,7 @@ class LabelPropertyIndexComplexTest : public ::testing::Test {
}
public:
Dbms dbms;
GraphDb db_;
LabelPropertyIndex index;
LabelPropertyIndex::Key *key;
@ -56,20 +56,20 @@ class LabelPropertyIndexComplexTest : public ::testing::Test {
};
TEST(LabelPropertyIndex, CreateIndex) {
Dbms dbms;
auto accessor = dbms.active();
LabelPropertyIndex::Key key(accessor->Label("test"),
accessor->Property("test2"));
GraphDb db;
GraphDbAccessor accessor(db);
LabelPropertyIndex::Key key(accessor.Label("test"),
accessor.Property("test2"));
LabelPropertyIndex index;
EXPECT_EQ(index.CreateIndex(key), true);
EXPECT_EQ(index.CreateIndex(key), false);
}
TEST(LabelPropertyIndex, IndexExistance) {
Dbms dbms;
auto accessor = dbms.active();
LabelPropertyIndex::Key key(accessor->Label("test"),
accessor->Property("test2"));
GraphDb db;
GraphDbAccessor accessor(db);
LabelPropertyIndex::Key key(accessor.Label("test"),
accessor.Property("test2"));
LabelPropertyIndex index;
EXPECT_EQ(index.CreateIndex(key), true);
// Index doesn't exist - and can't be used untill it's been notified as built.
@ -79,10 +79,10 @@ TEST(LabelPropertyIndex, IndexExistance) {
}
TEST(LabelPropertyIndex, Count) {
Dbms dbms;
auto accessor = dbms.active();
auto label = accessor->Label("label");
auto property = accessor->Property("property");
GraphDb db;
GraphDbAccessor accessor(db);
auto label = accessor.Label("label");
auto property = accessor.Property("property");
LabelPropertyIndex::Key key(label, property);
LabelPropertyIndex index;
::testing::FLAGS_gtest_death_test_style = "threadsafe";

View File

@ -1,6 +1,5 @@
#include <glog/logging.h>
#include "communication/result_stream_faker.hpp"
#include "database/dbms.hpp"
#include "query/exceptions.hpp"
#include "query/interpreter.hpp"
@ -10,25 +9,25 @@ DECLARE_int32(query_execution_time_sec);
TEST(TransactionTimeout, TransactionTimeout) {
FLAGS_query_execution_time_sec = 3;
Dbms dbms;
GraphDb db;
query::Interpreter interpreter;
{
ResultStreamFaker stream;
auto dba1 = dbms.active();
interpreter.Interpret("MATCH (n) RETURN n", *dba1, stream, {}, false);
GraphDbAccessor dba(db);
interpreter.Interpret("MATCH (n) RETURN n", dba, stream, {}, false);
}
{
ResultStreamFaker stream;
auto dba2 = dbms.active();
GraphDbAccessor dba(db);
std::this_thread::sleep_for(std::chrono::seconds(5));
ASSERT_THROW(
interpreter.Interpret("MATCH (n) RETURN n", *dba2, stream, {}, false),
interpreter.Interpret("MATCH (n) RETURN n", dba, stream, {}, false),
query::HintedAbortError);
}
{
ResultStreamFaker stream;
auto dba3 = dbms.active();
interpreter.Interpret("MATCH (n) RETURN n", *dba3, stream, {}, false);
GraphDbAccessor dba(db);
interpreter.Interpret("MATCH (n) RETURN n", dba, stream, {}, false);
}
}

View File

@ -1,101 +0,0 @@
#include <experimental/filesystem>
#include "gflags/gflags.h"
#include "gtest/gtest.h"
#include "database/dbms.hpp"
DECLARE_bool(recovery_on_startup);
DECLARE_string(snapshot_directory);
DECLARE_int32(snapshot_cycle_sec);
namespace fs = std::experimental::filesystem;
char tmp[] = "XXXXXX";
const fs::path SNAPSHOTS_DBMS_RECOVERY_ALL_DB = mkdtemp(tmp);
const fs::path SNAPSHOTS_DBMS_RECOVERY_DEFAULT_DB_DIR =
SNAPSHOTS_DBMS_RECOVERY_ALL_DB / "default";
std::vector<fs::path> GetFilesFromDir(
const std::string &snapshots_default_db_dir) {
std::vector<fs::path> files;
for (auto &file : fs::directory_iterator(snapshots_default_db_dir))
files.push_back(file.path());
return files;
}
void CleanDbDir() {
if (!fs::exists(SNAPSHOTS_DBMS_RECOVERY_DEFAULT_DB_DIR)) return;
std::vector<fs::path> files =
GetFilesFromDir(SNAPSHOTS_DBMS_RECOVERY_DEFAULT_DB_DIR);
for (auto file : files) fs::remove(file);
}
class DbmsRecoveryTest : public ::testing::Test {
protected:
virtual void TearDown() { CleanDbDir(); }
virtual void SetUp() {
CleanDbDir();
FLAGS_snapshot_directory = SNAPSHOTS_DBMS_RECOVERY_ALL_DB;
FLAGS_snapshot_cycle_sec = -1;
}
};
void CreateSnapshot() {
FLAGS_snapshot_recover_on_startup = false;
Dbms dbms;
auto dba = dbms.active();
// setup (v1) - [:likes] -> (v2) <- [:hates] - (v3)
auto va1 = dba->InsertVertex();
auto va2 = dba->InsertVertex();
dba->InsertEdge(va1, va2, dba->EdgeType("likes"));
auto va3 = dba->InsertVertex();
dba->InsertEdge(va3, va2, dba->EdgeType("hates"));
dba->AdvanceCommand();
Snapshooter snapshooter;
EXPECT_EQ(snapshooter.MakeSnapshot(*dba.get(),
SNAPSHOTS_DBMS_RECOVERY_DEFAULT_DB_DIR, 1),
true);
}
void RecoverDbms() {
FLAGS_snapshot_recover_on_startup = true;
Dbms dbms;
auto dba = dbms.active();
std::vector<VertexAccessor> vertices;
std::vector<EdgeAccessor> edges;
int vertex_count = 0;
for (auto const &vertex : dba->Vertices(false)) {
vertices.push_back(vertex);
vertex_count++;
}
EXPECT_EQ(vertex_count, 3);
int edge_count = 0;
for (auto const &edge : dba->Edges(false)) {
EXPECT_NE(vertices.end(),
std::find(vertices.begin(), vertices.end(), edge.to()));
EXPECT_NE(vertices.end(),
std::find(vertices.begin(), vertices.end(), edge.from()));
edges.push_back(edge);
edge_count++;
}
ASSERT_EQ(edge_count, 2);
EXPECT_EQ(edges[0].to() == edges[1].to(), true);
EXPECT_EQ(edges[0].from() == edges[1].from(), false);
}
TEST_F(DbmsRecoveryTest, TestDbmsRecovery) {
CreateSnapshot();
RecoverDbms();
}
int main(int argc, char **argv) {
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}

View File

@ -11,7 +11,7 @@ DECLARE_int32(gc_cycle_sec);
TEST(GraphDbTest, GarbageCollectIndices) {
FLAGS_gc_cycle_sec = -1;
GraphDb graph_db{"default", fs::path()};
GraphDb graph_db;
std::unique_ptr<GraphDbAccessor> dba =
std::make_unique<GraphDbAccessor>(graph_db);

View File

@ -1,7 +1,6 @@
#include <experimental/optional>
#include "gtest/gtest.h"
#include "database/dbms.hpp"
#include "database/graph_db.hpp"
#include "database/graph_db_accessor.hpp"
@ -13,90 +12,87 @@ auto Count(TIterable iterable) {
return std::distance(iterable.begin(), iterable.end());
}
TEST(GraphDbAccessorTest, DbmsCreateDefault) {
Dbms dbms;
auto accessor = dbms.active();
EXPECT_EQ(accessor->name(), "default");
}
TEST(GraphDbAccessorTest, InsertVertex) {
Dbms dbms;
auto accessor = dbms.active();
GraphDb db;
GraphDbAccessor accessor(db);
EXPECT_EQ(Count(accessor->Vertices(false)), 0);
EXPECT_EQ(Count(accessor.Vertices(false)), 0);
accessor->InsertVertex();
EXPECT_EQ(Count(accessor->Vertices(false)), 0);
EXPECT_EQ(Count(accessor->Vertices(true)), 1);
accessor->AdvanceCommand();
EXPECT_EQ(Count(accessor->Vertices(false)), 1);
accessor.InsertVertex();
EXPECT_EQ(Count(accessor.Vertices(false)), 0);
EXPECT_EQ(Count(accessor.Vertices(true)), 1);
accessor.AdvanceCommand();
EXPECT_EQ(Count(accessor.Vertices(false)), 1);
accessor->InsertVertex();
EXPECT_EQ(Count(accessor->Vertices(false)), 1);
EXPECT_EQ(Count(accessor->Vertices(true)), 2);
accessor->AdvanceCommand();
EXPECT_EQ(Count(accessor->Vertices(false)), 2);
accessor.InsertVertex();
EXPECT_EQ(Count(accessor.Vertices(false)), 1);
EXPECT_EQ(Count(accessor.Vertices(true)), 2);
accessor.AdvanceCommand();
EXPECT_EQ(Count(accessor.Vertices(false)), 2);
}
TEST(GraphDbAccessorTest, RemoveVertexSameTransaction) {
Dbms dbms;
auto accessor = dbms.active();
GraphDb db;
GraphDbAccessor accessor(db);
EXPECT_EQ(Count(accessor->Vertices(false)), 0);
EXPECT_EQ(Count(accessor.Vertices(false)), 0);
auto va1 = accessor->InsertVertex();
accessor->AdvanceCommand();
EXPECT_EQ(Count(accessor->Vertices(false)), 1);
auto va1 = accessor.InsertVertex();
accessor.AdvanceCommand();
EXPECT_EQ(Count(accessor.Vertices(false)), 1);
EXPECT_TRUE(accessor->RemoveVertex(va1));
EXPECT_EQ(Count(accessor->Vertices(false)), 1);
EXPECT_EQ(Count(accessor->Vertices(true)), 0);
accessor->AdvanceCommand();
EXPECT_EQ(Count(accessor->Vertices(false)), 0);
EXPECT_EQ(Count(accessor->Vertices(true)), 0);
EXPECT_TRUE(accessor.RemoveVertex(va1));
EXPECT_EQ(Count(accessor.Vertices(false)), 1);
EXPECT_EQ(Count(accessor.Vertices(true)), 0);
accessor.AdvanceCommand();
EXPECT_EQ(Count(accessor.Vertices(false)), 0);
EXPECT_EQ(Count(accessor.Vertices(true)), 0);
}
TEST(GraphDbAccessorTest, RemoveVertexDifferentTransaction) {
Dbms dbms;
GraphDb db;
// first transaction creates a vertex
auto accessor1 = dbms.active();
accessor1->InsertVertex();
accessor1->Commit();
{
GraphDbAccessor accessor(db);
accessor.InsertVertex();
accessor.Commit();
}
// second transaction checks that it sees it, and deletes it
auto accessor2 = dbms.active();
EXPECT_EQ(Count(accessor2->Vertices(false)), 1);
EXPECT_EQ(Count(accessor2->Vertices(true)), 1);
for (auto vertex_accessor : accessor2->Vertices(false))
accessor2->RemoveVertex(vertex_accessor);
accessor2->Commit();
{
GraphDbAccessor accessor(db);
EXPECT_EQ(Count(accessor.Vertices(false)), 1);
EXPECT_EQ(Count(accessor.Vertices(true)), 1);
for (auto vertex_accessor : accessor.Vertices(false))
accessor.RemoveVertex(vertex_accessor);
accessor.Commit();
}
// third transaction checks that it does not see the vertex
auto accessor3 = dbms.active();
EXPECT_EQ(Count(accessor3->Vertices(false)), 0);
EXPECT_EQ(Count(accessor3->Vertices(true)), 0);
{
GraphDbAccessor accessor(db);
EXPECT_EQ(Count(accessor.Vertices(false)), 0);
EXPECT_EQ(Count(accessor.Vertices(true)), 0);
}
}
TEST(GraphDbAccessorTest, InsertEdge) {
Dbms dbms;
auto dba = dbms.active();
GraphDb db;
GraphDbAccessor dba(db);
auto va1 = dba->InsertVertex();
auto va2 = dba->InsertVertex();
dba->AdvanceCommand();
auto va1 = dba.InsertVertex();
auto va2 = dba.InsertVertex();
dba.AdvanceCommand();
EXPECT_EQ(va1.in_degree(), 0);
EXPECT_EQ(va1.out_degree(), 0);
EXPECT_EQ(va2.in_degree(), 0);
EXPECT_EQ(va2.out_degree(), 0);
// setup (v1) - [:likes] -> (v2)
dba->InsertEdge(va1, va2, dba->EdgeType("likes"));
EXPECT_EQ(Count(dba->Edges(false)), 0);
EXPECT_EQ(Count(dba->Edges(true)), 1);
dba->AdvanceCommand();
EXPECT_EQ(Count(dba->Edges(false)), 1);
EXPECT_EQ(Count(dba->Edges(true)), 1);
dba.InsertEdge(va1, va2, dba.EdgeType("likes"));
EXPECT_EQ(Count(dba.Edges(false)), 0);
EXPECT_EQ(Count(dba.Edges(true)), 1);
dba.AdvanceCommand();
EXPECT_EQ(Count(dba.Edges(false)), 1);
EXPECT_EQ(Count(dba.Edges(true)), 1);
EXPECT_EQ(va1.out().begin()->to(), va2);
EXPECT_EQ(va2.in().begin()->from(), va1);
EXPECT_EQ(va1.in_degree(), 0);
@ -105,12 +101,12 @@ TEST(GraphDbAccessorTest, InsertEdge) {
EXPECT_EQ(va2.out_degree(), 0);
// setup (v1) - [:likes] -> (v2) <- [:hates] - (v3)
auto va3 = dba->InsertVertex();
dba->InsertEdge(va3, va2, dba->EdgeType("hates"));
EXPECT_EQ(Count(dba->Edges(false)), 1);
EXPECT_EQ(Count(dba->Edges(true)), 2);
dba->AdvanceCommand();
EXPECT_EQ(Count(dba->Edges(false)), 2);
auto va3 = dba.InsertVertex();
dba.InsertEdge(va3, va2, dba.EdgeType("hates"));
EXPECT_EQ(Count(dba.Edges(false)), 1);
EXPECT_EQ(Count(dba.Edges(true)), 2);
dba.AdvanceCommand();
EXPECT_EQ(Count(dba.Edges(false)), 2);
EXPECT_EQ(va3.out().begin()->to(), va2);
EXPECT_EQ(va1.in_degree(), 0);
EXPECT_EQ(va1.out_degree(), 1);
@ -121,38 +117,38 @@ TEST(GraphDbAccessorTest, InsertEdge) {
}
TEST(GraphDbAccessorTest, RemoveEdge) {
Dbms dbms;
auto dba = dbms.active();
GraphDb db;
GraphDbAccessor dba(db);
// setup (v1) - [:likes] -> (v2) <- [:hates] - (v3)
auto va1 = dba->InsertVertex();
auto va2 = dba->InsertVertex();
auto va3 = dba->InsertVertex();
dba->InsertEdge(va1, va2, dba->EdgeType("likes"));
dba->InsertEdge(va3, va2, dba->EdgeType("hates"));
dba->AdvanceCommand();
EXPECT_EQ(Count(dba->Edges(false)), 2);
EXPECT_EQ(Count(dba->Edges(true)), 2);
auto va1 = dba.InsertVertex();
auto va2 = dba.InsertVertex();
auto va3 = dba.InsertVertex();
dba.InsertEdge(va1, va2, dba.EdgeType("likes"));
dba.InsertEdge(va3, va2, dba.EdgeType("hates"));
dba.AdvanceCommand();
EXPECT_EQ(Count(dba.Edges(false)), 2);
EXPECT_EQ(Count(dba.Edges(true)), 2);
// remove all [:hates] edges
for (auto edge : dba->Edges(false))
if (edge.EdgeType() == dba->EdgeType("hates")) dba->RemoveEdge(edge);
EXPECT_EQ(Count(dba->Edges(false)), 2);
EXPECT_EQ(Count(dba->Edges(true)), 1);
for (auto edge : dba.Edges(false))
if (edge.EdgeType() == dba.EdgeType("hates")) dba.RemoveEdge(edge);
EXPECT_EQ(Count(dba.Edges(false)), 2);
EXPECT_EQ(Count(dba.Edges(true)), 1);
// current state: (v1) - [:likes] -> (v2), (v3)
dba->AdvanceCommand();
EXPECT_EQ(Count(dba->Edges(false)), 1);
EXPECT_EQ(Count(dba->Edges(true)), 1);
EXPECT_EQ(Count(dba->Vertices(false)), 3);
EXPECT_EQ(Count(dba->Vertices(true)), 3);
for (auto edge : dba->Edges(false)) {
EXPECT_EQ(edge.EdgeType(), dba->EdgeType("likes"));
dba.AdvanceCommand();
EXPECT_EQ(Count(dba.Edges(false)), 1);
EXPECT_EQ(Count(dba.Edges(true)), 1);
EXPECT_EQ(Count(dba.Vertices(false)), 3);
EXPECT_EQ(Count(dba.Vertices(true)), 3);
for (auto edge : dba.Edges(false)) {
EXPECT_EQ(edge.EdgeType(), dba.EdgeType("likes"));
auto v1 = edge.from();
auto v2 = edge.to();
// ensure correct connectivity for all the vertices
for (auto vertex : dba->Vertices(false)) {
for (auto vertex : dba.Vertices(false)) {
if (vertex == v1) {
EXPECT_EQ(vertex.in_degree(), 0);
EXPECT_EQ(vertex.out_degree(), 1);
@ -168,188 +164,188 @@ TEST(GraphDbAccessorTest, RemoveEdge) {
}
TEST(GraphDbAccessorTest, DetachRemoveVertex) {
Dbms dbms;
auto dba = dbms.active();
GraphDb db;
GraphDbAccessor dba(db);
// setup (v0)- []->(v1)<-[]-(v2)<-[]-(v3)
std::vector<VertexAccessor> vertices;
for (int i = 0; i < 4; ++i) vertices.emplace_back(dba->InsertVertex());
for (int i = 0; i < 4; ++i) vertices.emplace_back(dba.InsertVertex());
auto edge_type = dba->EdgeType("type");
dba->InsertEdge(vertices[0], vertices[1], edge_type);
dba->InsertEdge(vertices[2], vertices[1], edge_type);
dba->InsertEdge(vertices[3], vertices[2], edge_type);
auto edge_type = dba.EdgeType("type");
dba.InsertEdge(vertices[0], vertices[1], edge_type);
dba.InsertEdge(vertices[2], vertices[1], edge_type);
dba.InsertEdge(vertices[3], vertices[2], edge_type);
dba->AdvanceCommand();
dba.AdvanceCommand();
for (auto &vertex : vertices) vertex.Reconstruct();
// ensure that plain remove does NOT work
EXPECT_EQ(Count(dba->Vertices(false)), 4);
EXPECT_EQ(Count(dba->Edges(false)), 3);
EXPECT_FALSE(dba->RemoveVertex(vertices[0]));
EXPECT_FALSE(dba->RemoveVertex(vertices[1]));
EXPECT_FALSE(dba->RemoveVertex(vertices[2]));
EXPECT_EQ(Count(dba->Vertices(false)), 4);
EXPECT_EQ(Count(dba->Edges(false)), 3);
EXPECT_EQ(Count(dba.Vertices(false)), 4);
EXPECT_EQ(Count(dba.Edges(false)), 3);
EXPECT_FALSE(dba.RemoveVertex(vertices[0]));
EXPECT_FALSE(dba.RemoveVertex(vertices[1]));
EXPECT_FALSE(dba.RemoveVertex(vertices[2]));
EXPECT_EQ(Count(dba.Vertices(false)), 4);
EXPECT_EQ(Count(dba.Edges(false)), 3);
dba->DetachRemoveVertex(vertices[2]);
EXPECT_EQ(Count(dba->Vertices(false)), 4);
EXPECT_EQ(Count(dba->Vertices(true)), 3);
EXPECT_EQ(Count(dba->Edges(false)), 3);
EXPECT_EQ(Count(dba->Edges(true)), 1);
dba->AdvanceCommand();
dba.DetachRemoveVertex(vertices[2]);
EXPECT_EQ(Count(dba.Vertices(false)), 4);
EXPECT_EQ(Count(dba.Vertices(true)), 3);
EXPECT_EQ(Count(dba.Edges(false)), 3);
EXPECT_EQ(Count(dba.Edges(true)), 1);
dba.AdvanceCommand();
for (auto &vertex : vertices) vertex.Reconstruct();
EXPECT_EQ(Count(dba->Vertices(false)), 3);
EXPECT_EQ(Count(dba->Edges(false)), 1);
EXPECT_TRUE(dba->RemoveVertex(vertices[3]));
EXPECT_EQ(Count(dba->Vertices(true)), 2);
EXPECT_EQ(Count(dba->Vertices(false)), 3);
dba->AdvanceCommand();
EXPECT_EQ(Count(dba.Vertices(false)), 3);
EXPECT_EQ(Count(dba.Edges(false)), 1);
EXPECT_TRUE(dba.RemoveVertex(vertices[3]));
EXPECT_EQ(Count(dba.Vertices(true)), 2);
EXPECT_EQ(Count(dba.Vertices(false)), 3);
dba.AdvanceCommand();
for (auto &vertex : vertices) vertex.Reconstruct();
EXPECT_EQ(Count(dba->Vertices(false)), 2);
EXPECT_EQ(Count(dba->Edges(false)), 1);
for (auto va : dba->Vertices(false)) EXPECT_FALSE(dba->RemoveVertex(va));
dba->AdvanceCommand();
EXPECT_EQ(Count(dba.Vertices(false)), 2);
EXPECT_EQ(Count(dba.Edges(false)), 1);
for (auto va : dba.Vertices(false)) EXPECT_FALSE(dba.RemoveVertex(va));
dba.AdvanceCommand();
for (auto &vertex : vertices) vertex.Reconstruct();
EXPECT_EQ(Count(dba->Vertices(false)), 2);
EXPECT_EQ(Count(dba->Edges(false)), 1);
for (auto va : dba->Vertices(false)) {
EXPECT_FALSE(dba->RemoveVertex(va));
dba->DetachRemoveVertex(va);
EXPECT_EQ(Count(dba.Vertices(false)), 2);
EXPECT_EQ(Count(dba.Edges(false)), 1);
for (auto va : dba.Vertices(false)) {
EXPECT_FALSE(dba.RemoveVertex(va));
dba.DetachRemoveVertex(va);
break;
}
EXPECT_EQ(Count(dba->Vertices(true)), 1);
EXPECT_EQ(Count(dba->Vertices(false)), 2);
dba->AdvanceCommand();
EXPECT_EQ(Count(dba.Vertices(true)), 1);
EXPECT_EQ(Count(dba.Vertices(false)), 2);
dba.AdvanceCommand();
for (auto &vertex : vertices) vertex.Reconstruct();
EXPECT_EQ(Count(dba->Vertices(false)), 1);
EXPECT_EQ(Count(dba->Edges(false)), 0);
EXPECT_EQ(Count(dba.Vertices(false)), 1);
EXPECT_EQ(Count(dba.Edges(false)), 0);
// remove the last vertex, it has no connections
// so that should work
for (auto va : dba->Vertices(false)) EXPECT_TRUE(dba->RemoveVertex(va));
dba->AdvanceCommand();
for (auto va : dba.Vertices(false)) EXPECT_TRUE(dba.RemoveVertex(va));
dba.AdvanceCommand();
EXPECT_EQ(Count(dba->Vertices(false)), 0);
EXPECT_EQ(Count(dba->Edges(false)), 0);
EXPECT_EQ(Count(dba.Vertices(false)), 0);
EXPECT_EQ(Count(dba.Edges(false)), 0);
}
TEST(GraphDbAccessorTest, DetachRemoveVertexMultiple) {
// This test checks that we can detach remove the
// same vertex / edge multiple times
Dbms dbms;
auto dba = dbms.active();
GraphDb db;
GraphDbAccessor dba(db);
// setup: make a fully connected N graph
// with cycles too!
int N = 7;
std::vector<VertexAccessor> vertices;
auto edge_type = dba->EdgeType("edge");
for (int i = 0; i < N; ++i) vertices.emplace_back(dba->InsertVertex());
auto edge_type = dba.EdgeType("edge");
for (int i = 0; i < N; ++i) vertices.emplace_back(dba.InsertVertex());
for (int j = 0; j < N; ++j)
for (int k = 0; k < N; ++k)
dba->InsertEdge(vertices[j], vertices[k], edge_type);
dba.InsertEdge(vertices[j], vertices[k], edge_type);
dba->AdvanceCommand();
dba.AdvanceCommand();
for (auto &vertex : vertices) vertex.Reconstruct();
EXPECT_EQ(Count(dba->Vertices(false)), N);
EXPECT_EQ(Count(dba->Edges(false)), N * N);
EXPECT_EQ(Count(dba.Vertices(false)), N);
EXPECT_EQ(Count(dba.Edges(false)), N * N);
// detach delete one edge
dba->DetachRemoveVertex(vertices[0]);
dba->AdvanceCommand();
dba.DetachRemoveVertex(vertices[0]);
dba.AdvanceCommand();
for (auto &vertex : vertices) vertex.Reconstruct();
EXPECT_EQ(Count(dba->Vertices(false)), N - 1);
EXPECT_EQ(Count(dba->Edges(false)), (N - 1) * (N - 1));
EXPECT_EQ(Count(dba.Vertices(false)), N - 1);
EXPECT_EQ(Count(dba.Edges(false)), (N - 1) * (N - 1));
// detach delete two neighboring edges
dba->DetachRemoveVertex(vertices[1]);
dba->DetachRemoveVertex(vertices[2]);
dba->AdvanceCommand();
dba.DetachRemoveVertex(vertices[1]);
dba.DetachRemoveVertex(vertices[2]);
dba.AdvanceCommand();
for (auto &vertex : vertices) vertex.Reconstruct();
EXPECT_EQ(Count(dba->Vertices(false)), N - 3);
EXPECT_EQ(Count(dba->Edges(false)), (N - 3) * (N - 3));
EXPECT_EQ(Count(dba.Vertices(false)), N - 3);
EXPECT_EQ(Count(dba.Edges(false)), (N - 3) * (N - 3));
// detach delete everything, buwahahahaha
for (int l = 3; l < N; ++l) dba->DetachRemoveVertex(vertices[l]);
dba->AdvanceCommand();
for (int l = 3; l < N; ++l) dba.DetachRemoveVertex(vertices[l]);
dba.AdvanceCommand();
for (auto &vertex : vertices) vertex.Reconstruct();
EXPECT_EQ(Count(dba->Vertices(false)), 0);
EXPECT_EQ(Count(dba->Edges(false)), 0);
EXPECT_EQ(Count(dba.Vertices(false)), 0);
EXPECT_EQ(Count(dba.Edges(false)), 0);
}
TEST(GraphDbAccessorTest, Labels) {
Dbms dbms;
auto dba1 = dbms.active();
GraphDb db;
GraphDbAccessor dba(db);
GraphDbTypes::Label label_friend = dba1->Label("friend");
EXPECT_EQ(label_friend, dba1->Label("friend"));
EXPECT_NE(label_friend, dba1->Label("friend2"));
EXPECT_EQ(dba1->LabelName(label_friend), "friend");
GraphDbTypes::Label label_friend = dba.Label("friend");
EXPECT_EQ(label_friend, dba.Label("friend"));
EXPECT_NE(label_friend, dba.Label("friend2"));
EXPECT_EQ(dba.LabelName(label_friend), "friend");
// test that getting labels through a different accessor works
EXPECT_EQ(label_friend, dbms.active()->Label("friend"));
EXPECT_NE(label_friend, dbms.active()->Label("friend2"));
EXPECT_EQ(label_friend, GraphDbAccessor(db).Label("friend"));
EXPECT_NE(label_friend, GraphDbAccessor(db).Label("friend2"));
}
TEST(GraphDbAccessorTest, EdgeTypes) {
Dbms dbms;
auto dba1 = dbms.active();
GraphDb db;
GraphDbAccessor dba(db);
GraphDbTypes::EdgeType edge_type = dba1->EdgeType("likes");
EXPECT_EQ(edge_type, dba1->EdgeType("likes"));
EXPECT_NE(edge_type, dba1->EdgeType("hates"));
EXPECT_EQ(dba1->EdgeTypeName(edge_type), "likes");
GraphDbTypes::EdgeType edge_type = dba.EdgeType("likes");
EXPECT_EQ(edge_type, dba.EdgeType("likes"));
EXPECT_NE(edge_type, dba.EdgeType("hates"));
EXPECT_EQ(dba.EdgeTypeName(edge_type), "likes");
// test that getting labels through a different accessor works
EXPECT_EQ(edge_type, dbms.active()->EdgeType("likes"));
EXPECT_NE(edge_type, dbms.active()->EdgeType("hates"));
EXPECT_EQ(edge_type, GraphDbAccessor(db).EdgeType("likes"));
EXPECT_NE(edge_type, GraphDbAccessor(db).EdgeType("hates"));
}
TEST(GraphDbAccessorTest, Properties) {
Dbms dbms;
auto dba1 = dbms.active();
GraphDb db;
GraphDbAccessor dba(db);
GraphDbTypes::EdgeType prop = dba1->Property("name");
EXPECT_EQ(prop, dba1->Property("name"));
EXPECT_NE(prop, dba1->Property("surname"));
EXPECT_EQ(dba1->PropertyName(prop), "name");
GraphDbTypes::EdgeType prop = dba.Property("name");
EXPECT_EQ(prop, dba.Property("name"));
EXPECT_NE(prop, dba.Property("surname"));
EXPECT_EQ(dba.PropertyName(prop), "name");
// test that getting labels through a different accessor works
EXPECT_EQ(prop, dbms.active()->Property("name"));
EXPECT_NE(prop, dbms.active()->Property("surname"));
EXPECT_EQ(prop, GraphDbAccessor(db).Property("name"));
EXPECT_NE(prop, GraphDbAccessor(db).Property("surname"));
}
TEST(GraphDbAccessorTest, Transfer) {
Dbms dbms;
GraphDb db;
auto dba1 = dbms.active();
auto prop = dba1->Property("property");
VertexAccessor v1 = dba1->InsertVertex();
GraphDbAccessor dba1(db);
auto prop = dba1.Property("property");
VertexAccessor v1 = dba1.InsertVertex();
v1.PropsSet(prop, 1);
VertexAccessor v2 = dba1->InsertVertex();
VertexAccessor v2 = dba1.InsertVertex();
v2.PropsSet(prop, 2);
EdgeAccessor e12 = dba1->InsertEdge(v1, v2, dba1->EdgeType("et"));
EdgeAccessor e12 = dba1.InsertEdge(v1, v2, dba1.EdgeType("et"));
e12.PropsSet(prop, 12);
// make dba2 that has dba1 in it's snapshot, so data isn't visible
auto dba2 = dbms.active();
EXPECT_EQ(dba2->Transfer(v1), std::experimental::nullopt);
EXPECT_EQ(dba2->Transfer(e12), std::experimental::nullopt);
GraphDbAccessor dba2(db);
EXPECT_EQ(dba2.Transfer(v1), std::experimental::nullopt);
EXPECT_EQ(dba2.Transfer(e12), std::experimental::nullopt);
// make dba3 that does not have dba1 in it's snapshot
dba1->Commit();
auto dba3 = dbms.active();
dba1.Commit();
GraphDbAccessor dba3(db);
// we can transfer accessors even though the GraphDbAccessor they
// belong to is not alive anymore
EXPECT_EQ(dba3->Transfer(v1)->PropsAt(prop).Value<int64_t>(), 1);
EXPECT_EQ(dba3->Transfer(e12)->PropsAt(prop).Value<int64_t>(), 12);
EXPECT_EQ(dba3.Transfer(v1)->PropsAt(prop).Value<int64_t>(), 1);
EXPECT_EQ(dba3.Transfer(e12)->PropsAt(prop).Value<int64_t>(), 12);
}
int main(int argc, char **argv) {

View File

@ -5,7 +5,6 @@
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "database/dbms.hpp"
#include "database/graph_db_accessor.hpp"
#include "utils/bound.hpp"
@ -22,8 +21,8 @@ auto Count(TIterable iterable) {
*/
class GraphDbAccessorIndex : public testing::Test {
protected:
Dbms dbms;
std::unique_ptr<GraphDbAccessor> dba = dbms.active();
GraphDb db;
std::experimental::optional<GraphDbAccessor> dba{db};
GraphDbTypes::Property property = dba->Property("property");
GraphDbTypes::Label label = dba->Label("label");
GraphDbTypes::EdgeType edge_type = dba->EdgeType("edge_type");
@ -44,8 +43,7 @@ class GraphDbAccessorIndex : public testing::Test {
// commits the current dba, and replaces it with a new one
void Commit() {
dba->Commit();
auto dba2 = dbms.active();
dba.swap(dba2);
dba.emplace(db);
}
};
@ -134,20 +132,19 @@ TEST_F(GraphDbAccessorIndex, LabelPropertyIndexCount) {
}
TEST(GraphDbAccessorIndexApi, LabelPropertyBuildIndexConcurrent) {
Dbms dbms;
auto dba = dbms.active();
GraphDb db;
GraphDbAccessor dba(db);
// We need to build indices in other threads.
auto build_index_async = [&dbms](int &success, int index) {
std::thread([&dbms, &success, index]() {
auto dba = dbms.active();
auto build_index_async = [&db](int &success, int index) {
std::thread([&db, &success, index]() {
GraphDbAccessor dba(db);
try {
dba->BuildIndex(dba->Label("l" + std::to_string(index)),
dba->Property("p" + std::to_string(index)));
dba->Commit();
dba.BuildIndex(dba.Label("l" + std::to_string(index)),
dba.Property("p" + std::to_string(index)));
success = 1;
} catch (IndexBuildInProgressException &) {
dba->Abort();
dba.Abort();
success = 0;
}
}).detach();
@ -166,7 +163,7 @@ TEST(GraphDbAccessorIndexApi, LabelPropertyBuildIndexConcurrent) {
EXPECT_EQ(build_2_success, 0);
// End dba and expect that first build index finished successfully.
dba->Commit();
dba.Commit();
std::this_thread::sleep_for(std::chrono::milliseconds(30));
EXPECT_EQ(build_1_success, 1);
}

View File

@ -1,12 +1,10 @@
#include <cstdlib>
#include "communication/result_stream_faker.hpp"
#include "database/dbms.hpp"
#include "database/graph_db_accessor.hpp"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "query/exceptions.hpp"
#include "query/exceptions.hpp"
#include "query/interpreter.hpp"
#include "query/typed_value.hpp"
#include "query_common.hpp"
@ -20,11 +18,11 @@ namespace {
// ast is read from cache.
TEST(Interpreter, AstCache) {
query::Interpreter interpreter;
Dbms dbms;
GraphDb db;
{
ResultStreamFaker stream;
auto dba = dbms.active();
interpreter.Interpret("RETURN 2 + 3", *dba, stream, {}, false);
GraphDbAccessor dba(db);
interpreter.Interpret("RETURN 2 + 3", dba, stream, {}, false);
ASSERT_EQ(stream.GetHeader().size(), 1U);
EXPECT_EQ(stream.GetHeader()[0], "2 + 3");
ASSERT_EQ(stream.GetResults().size(), 1U);
@ -34,8 +32,8 @@ TEST(Interpreter, AstCache) {
{
// Cached ast, different literals.
ResultStreamFaker stream;
auto dba = dbms.active();
interpreter.Interpret("RETURN 5 + 4", *dba, stream, {}, false);
GraphDbAccessor dba(db);
interpreter.Interpret("RETURN 5 + 4", dba, stream, {}, false);
ASSERT_EQ(stream.GetResults().size(), 1U);
ASSERT_EQ(stream.GetResults()[0].size(), 1U);
ASSERT_EQ(stream.GetResults()[0][0].Value<int64_t>(), 9);
@ -43,8 +41,8 @@ TEST(Interpreter, AstCache) {
{
// Different ast (because of different types).
ResultStreamFaker stream;
auto dba = dbms.active();
interpreter.Interpret("RETURN 5.5 + 4", *dba, stream, {}, false);
GraphDbAccessor dba(db);
interpreter.Interpret("RETURN 5.5 + 4", dba, stream, {}, false);
ASSERT_EQ(stream.GetResults().size(), 1U);
ASSERT_EQ(stream.GetResults()[0].size(), 1U);
ASSERT_EQ(stream.GetResults()[0][0].Value<double>(), 9.5);
@ -52,8 +50,8 @@ TEST(Interpreter, AstCache) {
{
// Cached ast, same literals.
ResultStreamFaker stream;
auto dba = dbms.active();
interpreter.Interpret("RETURN 2 + 3", *dba, stream, {}, false);
GraphDbAccessor dba(db);
interpreter.Interpret("RETURN 2 + 3", dba, stream, {}, false);
ASSERT_EQ(stream.GetResults().size(), 1U);
ASSERT_EQ(stream.GetResults()[0].size(), 1U);
ASSERT_EQ(stream.GetResults()[0][0].Value<int64_t>(), 5);
@ -61,8 +59,8 @@ TEST(Interpreter, AstCache) {
{
// Cached ast, different literals.
ResultStreamFaker stream;
auto dba = dbms.active();
interpreter.Interpret("RETURN 10.5 + 1", *dba, stream, {}, false);
GraphDbAccessor dba(db);
interpreter.Interpret("RETURN 10.5 + 1", dba, stream, {}, false);
ASSERT_EQ(stream.GetResults().size(), 1U);
ASSERT_EQ(stream.GetResults()[0].size(), 1U);
ASSERT_EQ(stream.GetResults()[0][0].Value<double>(), 11.5);
@ -70,8 +68,8 @@ TEST(Interpreter, AstCache) {
{
// Cached ast, same literals, different whitespaces.
ResultStreamFaker stream;
auto dba = dbms.active();
interpreter.Interpret("RETURN 10.5 + 1", *dba, stream, {}, false);
GraphDbAccessor dba(db);
interpreter.Interpret("RETURN 10.5 + 1", dba, stream, {}, false);
ASSERT_EQ(stream.GetResults().size(), 1U);
ASSERT_EQ(stream.GetResults()[0].size(), 1U);
ASSERT_EQ(stream.GetResults()[0][0].Value<double>(), 11.5);
@ -79,8 +77,8 @@ TEST(Interpreter, AstCache) {
{
// Cached ast, same literals, different named header.
ResultStreamFaker stream;
auto dba = dbms.active();
interpreter.Interpret("RETURN 10.5+1", *dba, stream, {}, false);
GraphDbAccessor dba(db);
interpreter.Interpret("RETURN 10.5+1", dba, stream, {}, false);
ASSERT_EQ(stream.GetHeader().size(), 1U);
EXPECT_EQ(stream.GetHeader()[0], "10.5+1");
ASSERT_EQ(stream.GetResults().size(), 1U);
@ -92,11 +90,11 @@ TEST(Interpreter, AstCache) {
// Run query with same ast multiple times with different parameters.
TEST(Interpreter, Parameters) {
query::Interpreter interpreter;
Dbms dbms;
GraphDb db;
{
ResultStreamFaker stream;
auto dba = dbms.active();
interpreter.Interpret("RETURN $2 + $`a b`", *dba, stream,
GraphDbAccessor dba(db);
interpreter.Interpret("RETURN $2 + $`a b`", dba, stream,
{{"2", 10}, {"a b", 15}}, false);
ASSERT_EQ(stream.GetHeader().size(), 1U);
EXPECT_EQ(stream.GetHeader()[0], "$2 + $`a b`");
@ -107,8 +105,8 @@ TEST(Interpreter, Parameters) {
{
// Not needed parameter.
ResultStreamFaker stream;
auto dba = dbms.active();
interpreter.Interpret("RETURN $2 + $`a b`", *dba, stream,
GraphDbAccessor dba(db);
interpreter.Interpret("RETURN $2 + $`a b`", dba, stream,
{{"2", 10}, {"a b", 15}, {"c", 10}}, false);
ASSERT_EQ(stream.GetHeader().size(), 1U);
EXPECT_EQ(stream.GetHeader()[0], "$2 + $`a b`");
@ -119,8 +117,8 @@ TEST(Interpreter, Parameters) {
{
// Cached ast, different parameters.
ResultStreamFaker stream;
auto dba = dbms.active();
interpreter.Interpret("RETURN $2 + $`a b`", *dba, stream,
GraphDbAccessor dba(db);
interpreter.Interpret("RETURN $2 + $`a b`", dba, stream,
{{"2", "da"}, {"a b", "ne"}}, false);
ASSERT_EQ(stream.GetResults().size(), 1U);
ASSERT_EQ(stream.GetResults()[0].size(), 1U);
@ -129,8 +127,8 @@ TEST(Interpreter, Parameters) {
{
// Non-primitive literal.
ResultStreamFaker stream;
auto dba = dbms.active();
interpreter.Interpret("RETURN $2", *dba, stream,
GraphDbAccessor dba(db);
interpreter.Interpret("RETURN $2", dba, stream,
{{"2", std::vector<query::TypedValue>{5, 2, 3}}},
false);
ASSERT_EQ(stream.GetResults().size(), 1U);
@ -142,8 +140,8 @@ TEST(Interpreter, Parameters) {
{
// Cached ast, unprovided parameter.
ResultStreamFaker stream;
auto dba = dbms.active();
ASSERT_THROW(interpreter.Interpret("RETURN $2 + $`a b`", *dba, stream,
GraphDbAccessor dba(db);
ASSERT_THROW(interpreter.Interpret("RETURN $2 + $`a b`", dba, stream,
{{"2", "da"}, {"ab", "ne"}}, false),
query::UnprovidedParameterError);
}
@ -161,26 +159,26 @@ TEST(Interpreter, Bfs) {
const auto kId = "id";
query::Interpreter interpreter;
Dbms dbms;
GraphDb db;
ResultStreamFaker stream;
std::vector<std::vector<VertexAccessor>> levels(kNumLevels);
int id = 0;
// Set up.
{
auto dba = dbms.active();
GraphDbAccessor dba(db);
auto add_node = [&](int level, bool reachable) {
auto node = dba->InsertVertex();
node.PropsSet(dba->Property(kId), id++);
node.PropsSet(dba->Property(kReachable), reachable);
auto node = dba.InsertVertex();
node.PropsSet(dba.Property(kId), id++);
node.PropsSet(dba.Property(kReachable), reachable);
levels[level].push_back(node);
return node;
};
auto add_edge = [&](VertexAccessor &v1, VertexAccessor &v2,
bool reachable) {
auto edge = dba->InsertEdge(v1, v2, dba->EdgeType("edge"));
edge.PropsSet(dba->Property(kReachable), reachable);
auto edge = dba.InsertEdge(v1, v2, dba.EdgeType("edge"));
edge.PropsSet(dba.Property(kReachable), reachable);
};
// Add source node.
@ -218,15 +216,15 @@ TEST(Interpreter, Bfs) {
add_edge(node1, node2, false);
}
dba->Commit();
dba.Commit();
}
auto dba = dbms.active();
GraphDbAccessor dba(db);
interpreter.Interpret(
"MATCH (n {id: 0})-[r *bfs..5 (e, n | n.reachable and e.reachable)]->(m) "
"RETURN r",
*dba, stream, {}, false);
dba, stream, {}, false);
ASSERT_EQ(stream.GetHeader().size(), 1U);
EXPECT_EQ(stream.GetHeader()[0], "r");
@ -243,13 +241,13 @@ TEST(Interpreter, Bfs) {
// shorter to longer ones.
EXPECT_EQ(edges.size(), expected_level);
// Check that starting node is correct.
EXPECT_EQ(edges[0].from().PropsAt(dba->Property(kId)).Value<int64_t>(), 0);
EXPECT_EQ(edges[0].from().PropsAt(dba.Property(kId)).Value<int64_t>(), 0);
for (int i = 1; i < static_cast<int>(edges.size()); ++i) {
// Check that edges form a connected path.
EXPECT_EQ(edges[i - 1].to(), edges[i].from());
}
auto matched_id =
edges.back().to().PropsAt(dba->Property(kId)).Value<int64_t>();
edges.back().to().PropsAt(dba.Property(kId)).Value<int64_t>();
// Check that we didn't match that node already.
EXPECT_TRUE(matched_ids.insert(matched_id).second);
// Check that shortest path was found.
@ -264,16 +262,16 @@ TEST(Interpreter, Bfs) {
TEST(Interpreter, CreateIndexInMulticommandTransaction) {
query::Interpreter interpreter;
Dbms dbms;
GraphDb db;
{
ResultStreamFaker stream;
auto dba = dbms.active();
GraphDbAccessor dba(db);
ASSERT_THROW(
interpreter.Interpret("CREATE INDEX ON :X(y)", *dba, stream, {}, true),
interpreter.Interpret("CREATE INDEX ON :X(y)", dba, stream, {}, true),
query::IndexInMulticommandTxException);
}
}
}
} // namespace
int main(int argc, char **argv) {
google::InitGoogleLogging(argv[0]);

View File

@ -5,9 +5,8 @@
/// example:
///
/// AstTreeStorage storage; // Macros rely on storage being in scope.
/// // PROPERTY_LOOKUP and PROPERTY_PAIR macros also rely on a graph DB
/// // accessor
/// std::unique_ptr<GraphDbAccessor> dba;
/// // PROPERTY_LOOKUP and PROPERTY_PAIR macros also rely on GraphDb
/// GraphDb db;
///
/// QUERY(MATCH(PATTERN(NODE("n"), EDGE("e"), NODE("m"))),
/// WHERE(LESS(PROPERTY_LOOKUP("e", edge_prop), LITERAL(3))),
@ -30,7 +29,6 @@
#include <utility>
#include <vector>
#include "database/dbms.hpp"
#include "database/graph_db_datatypes.hpp"
#include "query/frontend/ast/ast.hpp"
#include "query/interpret/awesome_memgraph_functions.hpp"
@ -110,29 +108,27 @@ auto GetOrderBy(T... exprs) {
///
/// Name is used to create the Identifier which is used for property lookup.
///
auto GetPropertyLookup(AstTreeStorage &storage,
std::unique_ptr<GraphDbAccessor> &dba,
auto GetPropertyLookup(AstTreeStorage &storage, GraphDb &db,
const std::string &name,
GraphDbTypes::Property property) {
GraphDbAccessor dba(db);
return storage.Create<PropertyLookup>(storage.Create<Identifier>(name),
dba->PropertyName(property), property);
dba.PropertyName(property), property);
}
auto GetPropertyLookup(AstTreeStorage &storage,
std::unique_ptr<GraphDbAccessor> &dba, Expression *expr,
auto GetPropertyLookup(AstTreeStorage &storage, GraphDb &db, Expression *expr,
GraphDbTypes::Property property) {
return storage.Create<PropertyLookup>(expr, dba->PropertyName(property),
GraphDbAccessor dba(db);
return storage.Create<PropertyLookup>(expr, dba.PropertyName(property),
property);
}
auto GetPropertyLookup(
AstTreeStorage &storage, std::unique_ptr<GraphDbAccessor> &,
const std::string &name,
AstTreeStorage &storage, GraphDb &, const std::string &name,
const std::pair<std::string, GraphDbTypes::Property> &prop_pair) {
return storage.Create<PropertyLookup>(storage.Create<Identifier>(name),
prop_pair.first, prop_pair.second);
}
auto GetPropertyLookup(
AstTreeStorage &storage, std::unique_ptr<GraphDbAccessor> &,
Expression *expr,
AstTreeStorage &storage, GraphDb &, Expression *expr,
const std::pair<std::string, GraphDbTypes::Property> &prop_pair) {
return storage.Create<PropertyLookup>(expr, prop_pair.first,
prop_pair.second);
@ -497,9 +493,9 @@ auto GetMerge(AstTreeStorage &storage, Pattern *pattern, OnMatch on_match,
std::unordered_map<std::pair<std::string, GraphDbTypes::Property>, \
query::Expression *>{__VA_ARGS__})
#define PROPERTY_PAIR(property_name) \
std::make_pair(property_name, dba->Property(property_name))
std::make_pair(property_name, GraphDbAccessor(db).Property(property_name))
#define PROPERTY_LOOKUP(...) \
query::test_common::GetPropertyLookup(storage, dba, __VA_ARGS__)
query::test_common::GetPropertyLookup(storage, db, __VA_ARGS__)
#define NEXPR(name, expr) storage.Create<query::NamedExpression>((name), (expr))
// AS is alternative to NEXPR which does not initialize NamedExpression with
// Expression. It should be used with RETURN or WITH. For example:

View File

@ -1,7 +1,6 @@
#include <gtest/gtest.h>
#include <memory>
#include "database/dbms.hpp"
#include "query/frontend/ast/ast.hpp"
#include "query/frontend/semantic/symbol_table.hpp"
#include "query/plan/cost_estimator.hpp"
@ -22,8 +21,8 @@ using MiscParam = CostEstimator<GraphDbAccessor>::MiscParam;
* estimation testing. */
class QueryCostEstimator : public ::testing::Test {
protected:
Dbms dbms;
std::unique_ptr<GraphDbAccessor> dba = dbms.active();
GraphDb db;
std::experimental::optional<GraphDbAccessor> dba{db};
GraphDbTypes::Label label = dba->Label("label");
GraphDbTypes::Property property = dba->Property("property");
@ -39,8 +38,7 @@ class QueryCostEstimator : public ::testing::Test {
void SetUp() {
// create the index in the current db accessor and then swap it to a new one
dba->BuildIndex(label, property);
auto new_dba = dbms.active();
dba.swap(new_dba);
dba.emplace(db);
}
Symbol NextSymbol() {
@ -200,11 +198,12 @@ TEST_F(QueryCostEstimator, ExpandUniquenessFilter) {
}
TEST_F(QueryCostEstimator, UnwindLiteral) {
TEST_OP(MakeOp<query::plan::Unwind>(
last_op_, storage_.Create<ListLiteral>(
std::vector<Expression *>(7, nullptr)),
NextSymbol()),
CostParam::kUnwind, 7);
TEST_OP(
MakeOp<query::plan::Unwind>(
last_op_,
storage_.Create<ListLiteral>(std::vector<Expression *>(7, nullptr)),
NextSymbol()),
CostParam::kUnwind, 7);
}
TEST_F(QueryCostEstimator, UnwindNoLiteral) {

View File

@ -7,7 +7,6 @@
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "database/dbms.hpp"
#include "database/graph_db_accessor.hpp"
#include "database/graph_db_datatypes.hpp"
#include "query/frontend/ast/ast.hpp"
@ -20,9 +19,9 @@
#include "query_common.hpp"
using namespace query;
using testing::UnorderedElementsAre;
using testing::ElementsAre;
using query::test_common::ToList;
using testing::ElementsAre;
using testing::UnorderedElementsAre;
namespace {
@ -30,20 +29,20 @@ struct NoContextExpressionEvaluator {
NoContextExpressionEvaluator() {}
Frame frame{128};
SymbolTable symbol_table;
Dbms dbms;
std::unique_ptr<GraphDbAccessor> dba = dbms.active();
GraphDb db;
GraphDbAccessor dba{db};
Parameters parameters;
ExpressionEvaluator eval{frame, parameters, symbol_table, *dba};
ExpressionEvaluator eval{frame, parameters, symbol_table, dba};
};
TypedValue EvaluateFunction(const std::string &function_name,
const std::vector<TypedValue> &args, Dbms &dbms) {
const std::vector<TypedValue> &args, GraphDb &db) {
AstTreeStorage storage;
SymbolTable symbol_table;
auto dba = dbms.active();
GraphDbAccessor dba(db);
Frame frame{128};
Parameters parameters;
ExpressionEvaluator eval{frame, parameters, symbol_table, *dba};
ExpressionEvaluator eval{frame, parameters, symbol_table, dba};
std::vector<Expression *> expressions;
for (const auto &arg : args) {
@ -56,8 +55,8 @@ TypedValue EvaluateFunction(const std::string &function_name,
TypedValue EvaluateFunction(const std::string &function_name,
const std::vector<TypedValue> &args) {
Dbms dbms;
return EvaluateFunction(function_name, args, dbms);
GraphDb db;
return EvaluateFunction(function_name, args, db);
}
TEST(ExpressionEvaluator, OrOperator) {
@ -372,8 +371,8 @@ TEST(ExpressionEvaluator, ListMapIndexingOperator) {
TEST(ExpressionEvaluator, MapIndexing) {
AstTreeStorage storage;
NoContextExpressionEvaluator eval;
Dbms dbms;
auto dba = dbms.active();
GraphDb db;
GraphDbAccessor dba(db);
auto *map_literal = storage.Create<MapLiteral>(
std::unordered_map<std::pair<std::string, GraphDbTypes::Property>,
Expression *>{
@ -579,8 +578,8 @@ class ExpressionEvaluatorPropertyLookup : public testing::Test {
protected:
AstTreeStorage storage;
NoContextExpressionEvaluator eval;
Dbms dbms;
std::unique_ptr<GraphDbAccessor> dba = dbms.active();
GraphDb db;
GraphDbAccessor dba{db};
std::pair<std::string, GraphDbTypes::Property> prop_age =
PROPERTY_PAIR("age");
std::pair<std::string, GraphDbTypes::Property> prop_height =
@ -597,7 +596,7 @@ class ExpressionEvaluatorPropertyLookup : public testing::Test {
};
TEST_F(ExpressionEvaluatorPropertyLookup, Vertex) {
auto v1 = dba->InsertVertex();
auto v1 = dba.InsertVertex();
v1.PropsSet(prop_age.second, 10);
eval.frame[symbol] = v1;
EXPECT_EQ(Value(prop_age).Value<int64_t>(), 10);
@ -605,9 +604,9 @@ TEST_F(ExpressionEvaluatorPropertyLookup, Vertex) {
}
TEST_F(ExpressionEvaluatorPropertyLookup, Edge) {
auto v1 = dba->InsertVertex();
auto v2 = dba->InsertVertex();
auto e12 = dba->InsertEdge(v1, v2, dba->EdgeType("edge_type"));
auto v1 = dba.InsertVertex();
auto v2 = dba.InsertVertex();
auto e12 = dba.InsertEdge(v1, v2, dba.EdgeType("edge_type"));
e12.PropsSet(prop_age.second, 10);
eval.frame[symbol] = e12;
EXPECT_EQ(Value(prop_age).Value<int64_t>(), 10);
@ -628,28 +627,28 @@ TEST_F(ExpressionEvaluatorPropertyLookup, MapLiteral) {
TEST(ExpressionEvaluator, LabelsTest) {
AstTreeStorage storage;
NoContextExpressionEvaluator eval;
Dbms dbms;
auto dba = dbms.active();
auto v1 = dba->InsertVertex();
v1.add_label(dba->Label("ANIMAL"));
v1.add_label(dba->Label("DOG"));
v1.add_label(dba->Label("NICE_DOG"));
GraphDb db;
GraphDbAccessor dba(db);
auto v1 = dba.InsertVertex();
v1.add_label(dba.Label("ANIMAL"));
v1.add_label(dba.Label("DOG"));
v1.add_label(dba.Label("NICE_DOG"));
auto *identifier = storage.Create<Identifier>("n");
auto node_symbol = eval.symbol_table.CreateSymbol("n", true);
eval.symbol_table[*identifier] = node_symbol;
eval.frame[node_symbol] = v1;
{
auto *op = storage.Create<LabelsTest>(
identifier, std::vector<GraphDbTypes::Label>{dba->Label("DOG"),
dba->Label("ANIMAL")});
identifier, std::vector<GraphDbTypes::Label>{dba.Label("DOG"),
dba.Label("ANIMAL")});
auto value = op->Accept(eval.eval);
EXPECT_EQ(value.Value<bool>(), true);
}
{
auto *op = storage.Create<LabelsTest>(
identifier,
std::vector<GraphDbTypes::Label>{
dba->Label("DOG"), dba->Label("BAD_DOG"), dba->Label("ANIMAL")});
std::vector<GraphDbTypes::Label>{dba.Label("DOG"), dba.Label("BAD_DOG"),
dba.Label("ANIMAL")});
auto value = op->Accept(eval.eval);
EXPECT_EQ(value.Value<bool>(), false);
}
@ -657,8 +656,8 @@ TEST(ExpressionEvaluator, LabelsTest) {
eval.frame[node_symbol] = TypedValue::Null;
auto *op = storage.Create<LabelsTest>(
identifier,
std::vector<GraphDbTypes::Label>{
dba->Label("DOG"), dba->Label("BAD_DOG"), dba->Label("ANIMAL")});
std::vector<GraphDbTypes::Label>{dba.Label("DOG"), dba.Label("BAD_DOG"),
dba.Label("ANIMAL")});
auto value = op->Accept(eval.eval);
EXPECT_TRUE(value.IsNull());
}
@ -673,10 +672,10 @@ TEST(ExpressionEvaluator, Aggregation) {
symbol_table[*aggr] = aggr_sym;
Frame frame{symbol_table.max_position()};
frame[aggr_sym] = TypedValue(1);
Dbms dbms;
auto dba = dbms.active();
GraphDb db;
GraphDbAccessor dba(db);
Parameters parameters;
ExpressionEvaluator eval{frame, parameters, symbol_table, *dba};
ExpressionEvaluator eval{frame, parameters, symbol_table, dba};
auto value = aggr->Accept(eval);
EXPECT_EQ(value.Value<int64_t>(), 1);
}
@ -711,16 +710,16 @@ TEST(ExpressionEvaluator, FunctionEndNode) {
ASSERT_THROW(EvaluateFunction("ENDNODE", {}), QueryRuntimeException);
ASSERT_EQ(EvaluateFunction("ENDNODE", {TypedValue::Null}).type(),
TypedValue::Type::Null);
Dbms dbms;
auto dba = dbms.active();
auto v1 = dba->InsertVertex();
v1.add_label(dba->Label("label1"));
auto v2 = dba->InsertVertex();
v2.add_label(dba->Label("label2"));
auto e = dba->InsertEdge(v1, v2, dba->EdgeType("t"));
GraphDb db;
GraphDbAccessor dba(db);
auto v1 = dba.InsertVertex();
v1.add_label(dba.Label("label1"));
auto v2 = dba.InsertVertex();
v2.add_label(dba.Label("label2"));
auto e = dba.InsertEdge(v1, v2, dba.EdgeType("t"));
ASSERT_TRUE(EvaluateFunction("ENDNODE", {e})
.Value<VertexAccessor>()
.has_label(dba->Label("label2")));
.has_label(dba.Label("label2")));
ASSERT_THROW(EvaluateFunction("ENDNODE", {2}), QueryRuntimeException);
}
@ -740,15 +739,15 @@ TEST(ExpressionEvaluator, FunctionProperties) {
ASSERT_THROW(EvaluateFunction("PROPERTIES", {}), QueryRuntimeException);
ASSERT_EQ(EvaluateFunction("PROPERTIES", {TypedValue::Null}).type(),
TypedValue::Type::Null);
Dbms dbms;
auto dba = dbms.active();
auto v1 = dba->InsertVertex();
v1.PropsSet(dba->Property("height"), 5);
v1.PropsSet(dba->Property("age"), 10);
auto v2 = dba->InsertVertex();
auto e = dba->InsertEdge(v1, v2, dba->EdgeType("type1"));
e.PropsSet(dba->Property("height"), 3);
e.PropsSet(dba->Property("age"), 15);
GraphDb db;
GraphDbAccessor dba(db);
auto v1 = dba.InsertVertex();
v1.PropsSet(dba.Property("height"), 5);
v1.PropsSet(dba.Property("age"), 10);
auto v2 = dba.InsertVertex();
auto e = dba.InsertEdge(v1, v2, dba.EdgeType("type1"));
e.PropsSet(dba.Property("height"), 3);
e.PropsSet(dba.Property("age"), 15);
auto prop_values_to_int = [](TypedValue t) {
std::unordered_map<std::string, int> properties;
@ -792,13 +791,13 @@ TEST(ExpressionEvaluator, FunctionSize) {
3);
ASSERT_THROW(EvaluateFunction("SIZE", {5}), QueryRuntimeException);
Dbms dbms;
auto dba = dbms.active();
auto v0 = dba->InsertVertex();
GraphDb db;
GraphDbAccessor dba(db);
auto v0 = dba.InsertVertex();
query::Path path(v0);
EXPECT_EQ(EvaluateFunction("SIZE", {path}).ValueInt(), 0);
auto v1 = dba->InsertVertex();
path.Expand(dba->InsertEdge(v0, v1, dba->EdgeType("type")));
auto v1 = dba.InsertVertex();
path.Expand(dba.InsertEdge(v0, v1, dba.EdgeType("type")));
path.Expand(v1);
EXPECT_EQ(EvaluateFunction("SIZE", {path}).ValueInt(), 1);
}
@ -807,16 +806,16 @@ TEST(ExpressionEvaluator, FunctionStartNode) {
ASSERT_THROW(EvaluateFunction("STARTNODE", {}), QueryRuntimeException);
ASSERT_EQ(EvaluateFunction("STARTNODE", {TypedValue::Null}).type(),
TypedValue::Type::Null);
Dbms dbms;
auto dba = dbms.active();
auto v1 = dba->InsertVertex();
v1.add_label(dba->Label("label1"));
auto v2 = dba->InsertVertex();
v2.add_label(dba->Label("label2"));
auto e = dba->InsertEdge(v1, v2, dba->EdgeType("t"));
GraphDb db;
GraphDbAccessor dba(db);
auto v1 = dba.InsertVertex();
v1.add_label(dba.Label("label1"));
auto v2 = dba.InsertVertex();
v2.add_label(dba.Label("label2"));
auto e = dba.InsertEdge(v1, v2, dba.EdgeType("t"));
ASSERT_TRUE(EvaluateFunction("STARTNODE", {e})
.Value<VertexAccessor>()
.has_label(dba->Label("label1")));
.has_label(dba.Label("label1")));
ASSERT_THROW(EvaluateFunction("STARTNODE", {2}), QueryRuntimeException);
}
@ -824,13 +823,13 @@ TEST(ExpressionEvaluator, FunctionDegree) {
ASSERT_THROW(EvaluateFunction("DEGREE", {}), QueryRuntimeException);
ASSERT_EQ(EvaluateFunction("DEGREE", {TypedValue::Null}).type(),
TypedValue::Type::Null);
Dbms dbms;
auto dba = dbms.active();
auto v1 = dba->InsertVertex();
auto v2 = dba->InsertVertex();
auto v3 = dba->InsertVertex();
auto e12 = dba->InsertEdge(v1, v2, dba->EdgeType("t"));
dba->InsertEdge(v3, v2, dba->EdgeType("t"));
GraphDb db;
GraphDbAccessor dba(db);
auto v1 = dba.InsertVertex();
auto v2 = dba.InsertVertex();
auto v3 = dba.InsertVertex();
auto e12 = dba.InsertEdge(v1, v2, dba.EdgeType("t"));
dba.InsertEdge(v3, v2, dba.EdgeType("t"));
ASSERT_EQ(EvaluateFunction("DEGREE", {v1}).Value<int64_t>(), 1);
ASSERT_EQ(EvaluateFunction("DEGREE", {v2}).Value<int64_t>(), 2);
ASSERT_EQ(EvaluateFunction("DEGREE", {v3}).Value<int64_t>(), 1);
@ -881,13 +880,13 @@ TEST(ExpressionEvaluator, FunctionType) {
ASSERT_THROW(EvaluateFunction("TYPE", {}), QueryRuntimeException);
ASSERT_EQ(EvaluateFunction("TYPE", {TypedValue::Null}).type(),
TypedValue::Type::Null);
Dbms dbms;
auto dba = dbms.active();
auto v1 = dba->InsertVertex();
v1.add_label(dba->Label("label1"));
auto v2 = dba->InsertVertex();
v2.add_label(dba->Label("label2"));
auto e = dba->InsertEdge(v1, v2, dba->EdgeType("type1"));
GraphDb db;
GraphDbAccessor dba(db);
auto v1 = dba.InsertVertex();
v1.add_label(dba.Label("label1"));
auto v2 = dba.InsertVertex();
v2.add_label(dba.Label("label2"));
auto e = dba.InsertEdge(v1, v2, dba.EdgeType("type1"));
ASSERT_EQ(EvaluateFunction("TYPE", {e}).Value<std::string>(), "type1");
ASSERT_THROW(EvaluateFunction("TYPE", {2}), QueryRuntimeException);
}
@ -896,11 +895,11 @@ TEST(ExpressionEvaluator, FunctionLabels) {
ASSERT_THROW(EvaluateFunction("LABELS", {}), QueryRuntimeException);
ASSERT_EQ(EvaluateFunction("LABELS", {TypedValue::Null}).type(),
TypedValue::Type::Null);
Dbms dbms;
auto dba = dbms.active();
auto v = dba->InsertVertex();
v.add_label(dba->Label("label1"));
v.add_label(dba->Label("label2"));
GraphDb db;
GraphDbAccessor dba(db);
auto v = dba.InsertVertex();
v.add_label(dba.Label("label1"));
v.add_label(dba.Label("label2"));
std::vector<std::string> labels;
auto _labels =
EvaluateFunction("LABELS", {v}).Value<std::vector<TypedValue>>();
@ -941,15 +940,15 @@ TEST(ExpressionEvaluator, FunctionKeys) {
ASSERT_THROW(EvaluateFunction("KEYS", {}), QueryRuntimeException);
ASSERT_EQ(EvaluateFunction("KEYS", {TypedValue::Null}).type(),
TypedValue::Type::Null);
Dbms dbms;
auto dba = dbms.active();
auto v1 = dba->InsertVertex();
v1.PropsSet(dba->Property("height"), 5);
v1.PropsSet(dba->Property("age"), 10);
auto v2 = dba->InsertVertex();
auto e = dba->InsertEdge(v1, v2, dba->EdgeType("type1"));
e.PropsSet(dba->Property("width"), 3);
e.PropsSet(dba->Property("age"), 15);
GraphDb db;
GraphDbAccessor dba(db);
auto v1 = dba.InsertVertex();
v1.PropsSet(dba.Property("height"), 5);
v1.PropsSet(dba.Property("age"), 10);
auto v2 = dba.InsertVertex();
auto e = dba.InsertEdge(v1, v2, dba.EdgeType("type1"));
e.PropsSet(dba.Property("width"), 3);
e.PropsSet(dba.Property("age"), 15);
auto prop_keys_to_string = [](TypedValue t) {
std::vector<std::string> keys;
@ -1175,49 +1174,49 @@ TEST(ExpressionEvaluator, ParameterLookup) {
}
TEST(ExpressionEvaluator, FunctionCounter) {
Dbms dbms;
EXPECT_THROW(EvaluateFunction("COUNTER", {}, dbms), QueryRuntimeException);
EXPECT_THROW(EvaluateFunction("COUNTER", {"a", "b"}, dbms),
GraphDb db;
EXPECT_THROW(EvaluateFunction("COUNTER", {}, db), QueryRuntimeException);
EXPECT_THROW(EvaluateFunction("COUNTER", {"a", "b"}, db),
QueryRuntimeException);
EXPECT_EQ(EvaluateFunction("COUNTER", {"c1"}, dbms).ValueInt(), 0);
EXPECT_EQ(EvaluateFunction("COUNTER", {"c1"}, dbms).ValueInt(), 1);
EXPECT_EQ(EvaluateFunction("COUNTER", {"c2"}, dbms).ValueInt(), 0);
EXPECT_EQ(EvaluateFunction("COUNTER", {"c1"}, dbms).ValueInt(), 2);
EXPECT_EQ(EvaluateFunction("COUNTER", {"c2"}, dbms).ValueInt(), 1);
EXPECT_EQ(EvaluateFunction("COUNTER", {"c1"}, db).ValueInt(), 0);
EXPECT_EQ(EvaluateFunction("COUNTER", {"c1"}, db).ValueInt(), 1);
EXPECT_EQ(EvaluateFunction("COUNTER", {"c2"}, db).ValueInt(), 0);
EXPECT_EQ(EvaluateFunction("COUNTER", {"c1"}, db).ValueInt(), 2);
EXPECT_EQ(EvaluateFunction("COUNTER", {"c2"}, db).ValueInt(), 1);
}
TEST(ExpressionEvaluator, FunctionCounterSet) {
Dbms dbms;
EXPECT_THROW(EvaluateFunction("COUNTERSET", {}, dbms), QueryRuntimeException);
EXPECT_THROW(EvaluateFunction("COUNTERSET", {"a"}, dbms),
GraphDb db;
EXPECT_THROW(EvaluateFunction("COUNTERSET", {}, db), QueryRuntimeException);
EXPECT_THROW(EvaluateFunction("COUNTERSET", {"a"}, db),
QueryRuntimeException);
EXPECT_THROW(EvaluateFunction("COUNTERSET", {"a", "b"}, dbms),
EXPECT_THROW(EvaluateFunction("COUNTERSET", {"a", "b"}, db),
QueryRuntimeException);
EXPECT_THROW(EvaluateFunction("COUNTERSET", {"a", 11, 12}, dbms),
EXPECT_THROW(EvaluateFunction("COUNTERSET", {"a", 11, 12}, db),
QueryRuntimeException);
EXPECT_EQ(EvaluateFunction("COUNTER", {"c1"}, dbms).ValueInt(), 0);
EvaluateFunction("COUNTERSET", {"c1", 12}, dbms);
EXPECT_EQ(EvaluateFunction("COUNTER", {"c1"}, dbms).ValueInt(), 12);
EvaluateFunction("COUNTERSET", {"c2", 42}, dbms);
EXPECT_EQ(EvaluateFunction("COUNTER", {"c2"}, dbms).ValueInt(), 42);
EXPECT_EQ(EvaluateFunction("COUNTER", {"c1"}, dbms).ValueInt(), 13);
EXPECT_EQ(EvaluateFunction("COUNTER", {"c2"}, dbms).ValueInt(), 43);
EXPECT_EQ(EvaluateFunction("COUNTER", {"c1"}, db).ValueInt(), 0);
EvaluateFunction("COUNTERSET", {"c1", 12}, db);
EXPECT_EQ(EvaluateFunction("COUNTER", {"c1"}, db).ValueInt(), 12);
EvaluateFunction("COUNTERSET", {"c2", 42}, db);
EXPECT_EQ(EvaluateFunction("COUNTER", {"c2"}, db).ValueInt(), 42);
EXPECT_EQ(EvaluateFunction("COUNTER", {"c1"}, db).ValueInt(), 13);
EXPECT_EQ(EvaluateFunction("COUNTER", {"c2"}, db).ValueInt(), 43);
}
TEST(ExpressionEvaluator, FunctionIndexInfo) {
Dbms dbms;
EXPECT_THROW(EvaluateFunction("INDEXINFO", {1}, dbms), QueryRuntimeException);
EXPECT_EQ(EvaluateFunction("INDEXINFO", {}, dbms).ValueList().size(), 0);
auto dba = dbms.active();
dba->InsertVertex().add_label(dba->Label("l1"));
GraphDb db;
EXPECT_THROW(EvaluateFunction("INDEXINFO", {1}, db), QueryRuntimeException);
EXPECT_EQ(EvaluateFunction("INDEXINFO", {}, db).ValueList().size(), 0);
GraphDbAccessor dba(db);
dba.InsertVertex().add_label(dba.Label("l1"));
{
auto info = ToList<std::string>(EvaluateFunction("INDEXINFO", {}, dbms));
auto info = ToList<std::string>(EvaluateFunction("INDEXINFO", {}, db));
EXPECT_EQ(info.size(), 1);
EXPECT_EQ(info[0], ":l1");
}
{
dba->BuildIndex(dba->Label("l1"), dba->Property("prop"));
auto info = ToList<std::string>(EvaluateFunction("INDEXINFO", {}, dbms));
dba.BuildIndex(dba.Label("l1"), dba.Property("prop"));
auto info = ToList<std::string>(EvaluateFunction("INDEXINFO", {}, db));
EXPECT_EQ(info.size(), 2);
EXPECT_THAT(info, testing::UnorderedElementsAre(":l1", ":l1(prop)"));
}

View File

@ -12,7 +12,6 @@
#include "gtest/gtest.h"
#include "communication/result_stream_faker.hpp"
#include "database/dbms.hpp"
#include "query/context.hpp"
#include "query/exceptions.hpp"
#include "query/plan/operator.hpp"
@ -21,9 +20,9 @@
using namespace query;
using namespace query::plan;
using testing::UnorderedElementsAre;
using query::test_common::ToList;
using query::test_common::ToMap;
using testing::UnorderedElementsAre;
TEST(QueryPlan, Accumulate) {
// simulate the following two query execution on an empty db
@ -33,16 +32,16 @@ TEST(QueryPlan, Accumulate) {
// with accumulation we expect them to be [[2, 2], [2, 2]]
auto check = [&](bool accumulate) {
Dbms dbms;
auto dba = dbms.active();
auto prop = dba->Property("x");
GraphDb db;
GraphDbAccessor dba(db);
auto prop = dba.Property("x");
auto v1 = dba->InsertVertex();
auto v1 = dba.InsertVertex();
v1.PropsSet(prop, 0);
auto v2 = dba->InsertVertex();
auto v2 = dba.InsertVertex();
v2.PropsSet(prop, 0);
dba->InsertEdge(v1, v2, dba->EdgeType("T"));
dba->AdvanceCommand();
dba.InsertEdge(v1, v2, dba.EdgeType("T"));
dba.AdvanceCommand();
AstTreeStorage storage;
SymbolTable symbol_table;
@ -72,7 +71,7 @@ TEST(QueryPlan, Accumulate) {
auto m_p_ne = NEXPR("m.p", m_p);
symbol_table[*m_p_ne] = symbol_table.CreateSymbol("m_p_ne", true);
auto produce = MakeProduce(last_op, n_p_ne, m_p_ne);
auto results = CollectProduce(produce.get(), symbol_table, *dba);
auto results = CollectProduce(produce.get(), symbol_table, dba);
std::vector<int> results_data;
for (const auto &row : results)
for (const auto &column : row)
@ -92,8 +91,8 @@ TEST(QueryPlan, AccumulateAdvance) {
// to get correct results we need to advance the command
auto check = [&](bool advance) {
Dbms dbms;
auto dba = dbms.active();
GraphDb db;
GraphDbAccessor dba(db);
AstTreeStorage storage;
SymbolTable symbol_table;
@ -104,7 +103,7 @@ TEST(QueryPlan, AccumulateAdvance) {
auto accumulate = std::make_shared<Accumulate>(
create, std::vector<Symbol>{sym_n}, advance);
auto match = MakeScanAll(storage, symbol_table, "m", accumulate);
EXPECT_EQ(advance ? 1 : 0, PullAll(match.op_, *dba, symbol_table));
EXPECT_EQ(advance ? 1 : 0, PullAll(match.op_, dba, symbol_table));
};
check(false);
check(true);
@ -154,9 +153,9 @@ std::shared_ptr<Produce> MakeAggregationProduce(
/** Test fixture for all the aggregation ops in one return. */
class QueryPlanAggregateOps : public ::testing::Test {
protected:
Dbms dbms;
std::unique_ptr<GraphDbAccessor> dba = dbms.active();
GraphDbTypes::Property prop = dba->Property("prop");
GraphDb db;
GraphDbAccessor dba{db};
GraphDbTypes::Property prop = dba.Property("prop");
AstTreeStorage storage;
SymbolTable symbol_table;
@ -165,13 +164,13 @@ class QueryPlanAggregateOps : public ::testing::Test {
// setup is several nodes most of which have an int property set
// we will take the sum, avg, min, max and count
// we won't group by anything
dba->InsertVertex().PropsSet(prop, 5);
dba->InsertVertex().PropsSet(prop, 7);
dba->InsertVertex().PropsSet(prop, 12);
dba.InsertVertex().PropsSet(prop, 5);
dba.InsertVertex().PropsSet(prop, 7);
dba.InsertVertex().PropsSet(prop, 12);
// a missing property (null) gets ignored by all aggregations except
// COUNT(*)
dba->InsertVertex();
dba->AdvanceCommand();
dba.InsertVertex();
dba.AdvanceCommand();
}
auto AggregationResults(bool with_group_by,
@ -193,7 +192,7 @@ class QueryPlanAggregateOps : public ::testing::Test {
auto produce =
MakeAggregationProduce(n.op_, symbol_table, storage,
aggregation_expressions, ops, group_bys, {});
return CollectProduce(produce.get(), symbol_table, *dba);
return CollectProduce(produce.get(), symbol_table, dba);
}
};
@ -293,8 +292,8 @@ TEST(QueryPlan, AggregateGroupByValues) {
// Tests that distinct groups are aggregated properly for values of all types.
// Also test the "remember" part of the Aggregation API as final results are
// obtained via a property lookup of a remembered node.
Dbms dbms;
auto dba = dbms.active();
GraphDb db;
GraphDbAccessor dba(db);
// a vector of TypedValue to be set as property values on vertices
// most of them should result in a distinct group (commented where not)
@ -318,10 +317,10 @@ TEST(QueryPlan, AggregateGroupByValues) {
group_by_vals.emplace_back(std::vector<TypedValue>{1, 2.0});
// generate a lot of vertices and set props on them
auto prop = dba->Property("prop");
auto prop = dba.Property("prop");
for (int i = 0; i < 1000; ++i)
dba->InsertVertex().PropsSet(prop, group_by_vals[i % group_by_vals.size()]);
dba->AdvanceCommand();
dba.InsertVertex().PropsSet(prop, group_by_vals[i % group_by_vals.size()]);
dba.AdvanceCommand();
AstTreeStorage storage;
SymbolTable symbol_table;
@ -335,7 +334,7 @@ TEST(QueryPlan, AggregateGroupByValues) {
MakeAggregationProduce(n.op_, symbol_table, storage, {n_p},
{Aggregation::Op::COUNT}, {n_p}, {n.sym_});
auto results = CollectProduce(produce.get(), symbol_table, *dba);
auto results = CollectProduce(produce.get(), symbol_table, dba);
ASSERT_EQ(results.size(), group_by_vals.size() - 2);
TypedValue::unordered_set result_group_bys;
for (const auto &row : results) {
@ -352,19 +351,19 @@ TEST(QueryPlan, AggregateMultipleGroupBy) {
// in this test we have 3 different properties that have different values
// for different records and assert that we get the correct combination
// of values in our groups
Dbms dbms;
auto dba = dbms.active();
GraphDb db;
GraphDbAccessor dba(db);
auto prop1 = dba->Property("prop1");
auto prop2 = dba->Property("prop2");
auto prop3 = dba->Property("prop3");
auto prop1 = dba.Property("prop1");
auto prop2 = dba.Property("prop2");
auto prop3 = dba.Property("prop3");
for (int i = 0; i < 2 * 3 * 5; ++i) {
auto v = dba->InsertVertex();
auto v = dba.InsertVertex();
v.PropsSet(prop1, (bool)(i % 2));
v.PropsSet(prop2, i % 3);
v.PropsSet(prop3, "value" + std::to_string(i % 5));
}
dba->AdvanceCommand();
dba.AdvanceCommand();
AstTreeStorage storage;
SymbolTable symbol_table;
@ -382,13 +381,13 @@ TEST(QueryPlan, AggregateMultipleGroupBy) {
{Aggregation::Op::COUNT},
{n_p1, n_p2, n_p3}, {n.sym_});
auto results = CollectProduce(produce.get(), symbol_table, *dba);
auto results = CollectProduce(produce.get(), symbol_table, dba);
EXPECT_EQ(results.size(), 2 * 3 * 5);
}
TEST(QueryPlan, AggregateNoInput) {
Dbms dbms;
auto dba = dbms.active();
GraphDb db;
GraphDbAccessor dba(db);
AstTreeStorage storage;
SymbolTable symbol_table;
@ -398,7 +397,7 @@ TEST(QueryPlan, AggregateNoInput) {
auto produce = MakeAggregationProduce(nullptr, symbol_table, storage, {two},
{Aggregation::Op::COUNT}, {}, {});
auto results = CollectProduce(produce.get(), symbol_table, *dba);
auto results = CollectProduce(produce.get(), symbol_table, dba);
EXPECT_EQ(1, results.size());
EXPECT_EQ(1, results[0].size());
EXPECT_EQ(TypedValue::Type::Int, results[0][0].type());
@ -414,9 +413,9 @@ TEST(QueryPlan, AggregateCountEdgeCases) {
// - 2 vertices in database, property set on one
// - 2 vertices in database, property set on both
Dbms dbms;
auto dba = dbms.active();
auto prop = dba->Property("prop");
GraphDb db;
GraphDbAccessor dba(db);
auto prop = dba.Property("prop");
AstTreeStorage storage;
SymbolTable symbol_table;
@ -430,7 +429,7 @@ TEST(QueryPlan, AggregateCountEdgeCases) {
auto count = [&]() {
auto produce = MakeAggregationProduce(n.op_, symbol_table, storage, {n_p},
{Aggregation::Op::COUNT}, {}, {});
auto results = CollectProduce(produce.get(), symbol_table, *dba);
auto results = CollectProduce(produce.get(), symbol_table, dba);
if (results.size() == 0) return -1L;
EXPECT_EQ(1, results.size());
EXPECT_EQ(1, results[0].size());
@ -442,23 +441,23 @@ TEST(QueryPlan, AggregateCountEdgeCases) {
EXPECT_EQ(0, count());
// one vertex, no property set
dba->InsertVertex();
dba->AdvanceCommand();
dba.InsertVertex();
dba.AdvanceCommand();
EXPECT_EQ(0, count());
// one vertex, property set
for (VertexAccessor va : dba->Vertices(false)) va.PropsSet(prop, 42);
dba->AdvanceCommand();
for (VertexAccessor va : dba.Vertices(false)) va.PropsSet(prop, 42);
dba.AdvanceCommand();
EXPECT_EQ(1, count());
// two vertices, one with property set
dba->InsertVertex();
dba->AdvanceCommand();
dba.InsertVertex();
dba.AdvanceCommand();
EXPECT_EQ(1, count());
// two vertices, both with property set
for (VertexAccessor va : dba->Vertices(false)) va.PropsSet(prop, 42);
dba->AdvanceCommand();
for (VertexAccessor va : dba.Vertices(false)) va.PropsSet(prop, 42);
dba.AdvanceCommand();
EXPECT_EQ(2, count());
}
@ -466,15 +465,15 @@ TEST(QueryPlan, AggregateFirstValueTypes) {
// testing exceptions that get emitted by the first-value
// type check
Dbms dbms;
auto dba = dbms.active();
GraphDb db;
GraphDbAccessor dba(db);
auto v1 = dba->InsertVertex();
auto prop_string = dba->Property("string");
auto v1 = dba.InsertVertex();
auto prop_string = dba.Property("string");
v1.PropsSet(prop_string, "johhny");
auto prop_int = dba->Property("int");
auto prop_int = dba.Property("int");
v1.PropsSet(prop_int, 12);
dba->AdvanceCommand();
dba.AdvanceCommand();
AstTreeStorage storage;
SymbolTable symbol_table;
@ -489,7 +488,7 @@ TEST(QueryPlan, AggregateFirstValueTypes) {
auto aggregate = [&](Expression *expression, Aggregation::Op aggr_op) {
auto produce = MakeAggregationProduce(n.op_, symbol_table, storage,
{expression}, {aggr_op}, {}, {});
CollectProduce(produce.get(), symbol_table, *dba);
CollectProduce(produce.get(), symbol_table, dba);
};
// everything except for COUNT and COLLECT fails on a Vertex
@ -523,16 +522,16 @@ TEST(QueryPlan, AggregateTypes) {
// does not check all combinations that can result in an exception
// (that logic is defined and tested by TypedValue)
Dbms dbms;
auto dba = dbms.active();
GraphDb db;
GraphDbAccessor dba(db);
auto p1 = dba->Property("p1"); // has only string props
dba->InsertVertex().PropsSet(p1, "string");
dba->InsertVertex().PropsSet(p1, "str2");
auto p2 = dba->Property("p2"); // combines int and bool
dba->InsertVertex().PropsSet(p2, 42);
dba->InsertVertex().PropsSet(p2, true);
dba->AdvanceCommand();
auto p1 = dba.Property("p1"); // has only string props
dba.InsertVertex().PropsSet(p1, "string");
dba.InsertVertex().PropsSet(p1, "str2");
auto p2 = dba.Property("p2"); // combines int and bool
dba.InsertVertex().PropsSet(p2, 42);
dba.InsertVertex().PropsSet(p2, true);
dba.AdvanceCommand();
AstTreeStorage storage;
SymbolTable symbol_table;
@ -546,7 +545,7 @@ TEST(QueryPlan, AggregateTypes) {
auto aggregate = [&](Expression *expression, Aggregation::Op aggr_op) {
auto produce = MakeAggregationProduce(n.op_, symbol_table, storage,
{expression}, {aggr_op}, {}, {});
CollectProduce(produce.get(), symbol_table, *dba);
CollectProduce(produce.get(), symbol_table, dba);
};
// everything except for COUNT and COLLECT fails on a Vertex
@ -579,8 +578,8 @@ TEST(QueryPlan, AggregateTypes) {
}
TEST(QueryPlan, Unwind) {
Dbms dbms;
auto dba = dbms.active();
GraphDb db;
GraphDbAccessor dba(db);
AstTreeStorage storage;
SymbolTable symbol_table;
@ -603,7 +602,7 @@ TEST(QueryPlan, Unwind) {
symbol_table[*y_ne] = symbol_table.CreateSymbol("y_ne", true);
auto produce = MakeProduce(unwind_1, x_ne, y_ne);
auto results = CollectProduce(produce.get(), symbol_table, *dba);
auto results = CollectProduce(produce.get(), symbol_table, dba);
ASSERT_EQ(4, results.size());
const std::vector<int> expected_x_card{3, 3, 3, 1};
auto expected_x_card_it = expected_x_card.begin();

View File

@ -12,7 +12,6 @@
#include "gtest/gtest.h"
#include "communication/result_stream_faker.hpp"
#include "database/dbms.hpp"
#include "query/context.hpp"
#include "query/exceptions.hpp"
#include "query/plan/operator.hpp"
@ -23,8 +22,8 @@ using namespace query;
using namespace query::plan;
TEST(QueryPlan, Skip) {
Dbms dbms;
auto dba = dbms.active();
GraphDb db;
GraphDbAccessor dba(db);
AstTreeStorage storage;
SymbolTable symbol_table;
@ -32,28 +31,28 @@ TEST(QueryPlan, Skip) {
auto n = MakeScanAll(storage, symbol_table, "n1");
auto skip = std::make_shared<plan::Skip>(n.op_, LITERAL(2));
EXPECT_EQ(0, PullAll(skip, *dba, symbol_table));
EXPECT_EQ(0, PullAll(skip, dba, symbol_table));
dba->InsertVertex();
dba->AdvanceCommand();
EXPECT_EQ(0, PullAll(skip, *dba, symbol_table));
dba.InsertVertex();
dba.AdvanceCommand();
EXPECT_EQ(0, PullAll(skip, dba, symbol_table));
dba->InsertVertex();
dba->AdvanceCommand();
EXPECT_EQ(0, PullAll(skip, *dba, symbol_table));
dba.InsertVertex();
dba.AdvanceCommand();
EXPECT_EQ(0, PullAll(skip, dba, symbol_table));
dba->InsertVertex();
dba->AdvanceCommand();
EXPECT_EQ(1, PullAll(skip, *dba, symbol_table));
dba.InsertVertex();
dba.AdvanceCommand();
EXPECT_EQ(1, PullAll(skip, dba, symbol_table));
for (int i = 0; i < 10; ++i) dba->InsertVertex();
dba->AdvanceCommand();
EXPECT_EQ(11, PullAll(skip, *dba, symbol_table));
for (int i = 0; i < 10; ++i) dba.InsertVertex();
dba.AdvanceCommand();
EXPECT_EQ(11, PullAll(skip, dba, symbol_table));
}
TEST(QueryPlan, Limit) {
Dbms dbms;
auto dba = dbms.active();
GraphDb db;
GraphDbAccessor dba(db);
AstTreeStorage storage;
SymbolTable symbol_table;
@ -61,34 +60,34 @@ TEST(QueryPlan, Limit) {
auto n = MakeScanAll(storage, symbol_table, "n1");
auto skip = std::make_shared<plan::Limit>(n.op_, LITERAL(2));
EXPECT_EQ(0, PullAll(skip, *dba, symbol_table));
EXPECT_EQ(0, PullAll(skip, dba, symbol_table));
dba->InsertVertex();
dba->AdvanceCommand();
EXPECT_EQ(1, PullAll(skip, *dba, symbol_table));
dba.InsertVertex();
dba.AdvanceCommand();
EXPECT_EQ(1, PullAll(skip, dba, symbol_table));
dba->InsertVertex();
dba->AdvanceCommand();
EXPECT_EQ(2, PullAll(skip, *dba, symbol_table));
dba.InsertVertex();
dba.AdvanceCommand();
EXPECT_EQ(2, PullAll(skip, dba, symbol_table));
dba->InsertVertex();
dba->AdvanceCommand();
EXPECT_EQ(2, PullAll(skip, *dba, symbol_table));
dba.InsertVertex();
dba.AdvanceCommand();
EXPECT_EQ(2, PullAll(skip, dba, symbol_table));
for (int i = 0; i < 10; ++i) dba->InsertVertex();
dba->AdvanceCommand();
EXPECT_EQ(2, PullAll(skip, *dba, symbol_table));
for (int i = 0; i < 10; ++i) dba.InsertVertex();
dba.AdvanceCommand();
EXPECT_EQ(2, PullAll(skip, dba, symbol_table));
}
TEST(QueryPlan, CreateLimit) {
// CREATE (n), (m)
// MATCH (n) CREATE (m) LIMIT 1
// in the end we need to have 3 vertices in the db
Dbms dbms;
auto dba = dbms.active();
dba->InsertVertex();
dba->InsertVertex();
dba->AdvanceCommand();
GraphDb db;
GraphDbAccessor dba(db);
dba.InsertVertex();
dba.InsertVertex();
dba.AdvanceCommand();
AstTreeStorage storage;
SymbolTable symbol_table;
@ -99,17 +98,17 @@ TEST(QueryPlan, CreateLimit) {
auto c = std::make_shared<CreateNode>(m, n.op_);
auto skip = std::make_shared<plan::Limit>(c, LITERAL(1));
EXPECT_EQ(1, PullAll(skip, *dba, symbol_table));
dba->AdvanceCommand();
EXPECT_EQ(3, CountIterable(dba->Vertices(false)));
EXPECT_EQ(1, PullAll(skip, dba, symbol_table));
dba.AdvanceCommand();
EXPECT_EQ(3, CountIterable(dba.Vertices(false)));
}
TEST(QueryPlan, OrderBy) {
Dbms dbms;
auto dba = dbms.active();
GraphDb db;
GraphDbAccessor dba(db);
AstTreeStorage storage;
SymbolTable symbol_table;
auto prop = dba->Property("prop");
auto prop = dba.Property("prop");
// contains a series of tests
// each test defines the ordering a vector of values in the desired order
@ -125,9 +124,9 @@ TEST(QueryPlan, OrderBy) {
for (const auto &order_value_pair : orderable) {
const auto &values = order_value_pair.second;
// empty database
for (auto &vertex : dba->Vertices(false)) dba->DetachRemoveVertex(vertex);
dba->AdvanceCommand();
ASSERT_EQ(0, CountIterable(dba->Vertices(false)));
for (auto &vertex : dba.Vertices(false)) dba.DetachRemoveVertex(vertex);
dba.AdvanceCommand();
ASSERT_EQ(0, CountIterable(dba.Vertices(false)));
// take some effort to shuffle the values
// because we are testing that something not ordered gets ordered
@ -144,8 +143,8 @@ TEST(QueryPlan, OrderBy) {
// create the vertices
for (const auto &value : shuffled)
dba->InsertVertex().PropsSet(prop, value);
dba->AdvanceCommand();
dba.InsertVertex().PropsSet(prop, value);
dba.AdvanceCommand();
// order by and collect results
auto n = MakeScanAll(storage, symbol_table, "n");
@ -159,7 +158,7 @@ TEST(QueryPlan, OrderBy) {
auto n_p_ne = NEXPR("n.p", n_p);
symbol_table[*n_p_ne] = symbol_table.CreateSymbol("n.p", true);
auto produce = MakeProduce(order_by, n_p_ne);
auto results = CollectProduce(produce.get(), symbol_table, *dba);
auto results = CollectProduce(produce.get(), symbol_table, dba);
ASSERT_EQ(values.size(), results.size());
for (int j = 0; j < results.size(); ++j)
EXPECT_TRUE(TypedValue::BoolEqual{}(results[j][0], values[j]));
@ -167,13 +166,13 @@ TEST(QueryPlan, OrderBy) {
}
TEST(QueryPlan, OrderByMultiple) {
Dbms dbms;
auto dba = dbms.active();
GraphDb db;
GraphDbAccessor dba(db);
AstTreeStorage storage;
SymbolTable symbol_table;
auto p1 = dba->Property("p1");
auto p2 = dba->Property("p2");
auto p1 = dba.Property("p1");
auto p2 = dba.Property("p2");
// create a bunch of vertices that in two properties
// have all the variations (with repetition) of N values.
@ -184,11 +183,11 @@ TEST(QueryPlan, OrderByMultiple) {
for (int i = 0; i < N * N; ++i) prop_values.emplace_back(i % N, i / N);
std::random_shuffle(prop_values.begin(), prop_values.end());
for (const auto &pair : prop_values) {
auto v = dba->InsertVertex();
auto v = dba.InsertVertex();
v.PropsSet(p1, pair.first);
v.PropsSet(p2, pair.second);
}
dba->AdvanceCommand();
dba.AdvanceCommand();
// order by and collect results
auto n = MakeScanAll(storage, symbol_table, "n");
@ -212,7 +211,7 @@ TEST(QueryPlan, OrderByMultiple) {
auto n_p2_ne = NEXPR("n.p2", n_p2);
symbol_table[*n_p2_ne] = symbol_table.CreateSymbol("n.p2", true);
auto produce = MakeProduce(order_by, n_p1_ne, n_p2_ne);
auto results = CollectProduce(produce.get(), symbol_table, *dba);
auto results = CollectProduce(produce.get(), symbol_table, dba);
ASSERT_EQ(N * N, results.size());
for (int j = 0; j < N * N; ++j) {
ASSERT_EQ(results[j][0].type(), TypedValue::Type::Int);
@ -223,11 +222,11 @@ TEST(QueryPlan, OrderByMultiple) {
}
TEST(QueryPlan, OrderByExceptions) {
Dbms dbms;
auto dba = dbms.active();
GraphDb db;
GraphDbAccessor dba(db);
AstTreeStorage storage;
SymbolTable symbol_table;
auto prop = dba->Property("prop");
auto prop = dba.Property("prop");
// a vector of pairs of typed values that should result
// in an exception when trying to order on them
@ -243,16 +242,16 @@ TEST(QueryPlan, OrderByExceptions) {
for (const auto &pair : exception_pairs) {
// empty database
for (auto &vertex : dba->Vertices(false)) dba->DetachRemoveVertex(vertex);
dba->AdvanceCommand();
ASSERT_EQ(0, CountIterable(dba->Vertices(false)));
for (auto &vertex : dba.Vertices(false)) dba.DetachRemoveVertex(vertex);
dba.AdvanceCommand();
ASSERT_EQ(0, CountIterable(dba.Vertices(false)));
// make two vertices, and set values
dba->InsertVertex().PropsSet(prop, pair.first);
dba->InsertVertex().PropsSet(prop, pair.second);
dba->AdvanceCommand();
ASSERT_EQ(2, CountIterable(dba->Vertices(false)));
for (const auto &va : dba->Vertices(false))
dba.InsertVertex().PropsSet(prop, pair.first);
dba.InsertVertex().PropsSet(prop, pair.second);
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);
// order by and expect an exception
@ -263,6 +262,6 @@ TEST(QueryPlan, OrderByExceptions) {
n.op_,
std::vector<std::pair<Ordering, Expression *>>{{Ordering::ASC, n_p}},
std::vector<Symbol>{});
EXPECT_THROW(PullAll(order_by, *dba, symbol_table), QueryRuntimeException);
EXPECT_THROW(PullAll(order_by, dba, symbol_table), QueryRuntimeException);
}
}

View File

@ -11,7 +11,6 @@
#include "gtest/gtest.h"
#include "communication/result_stream_faker.hpp"
#include "database/dbms.hpp"
#include "query/context.hpp"
#include "query/exceptions.hpp"
#include "query/interpret/frame.hpp"
@ -23,10 +22,10 @@ using namespace query;
using namespace query::plan;
TEST(QueryPlan, CreateNodeWithAttributes) {
Dbms dbms;
auto dba = dbms.active();
GraphDb db;
GraphDbAccessor dba(db);
GraphDbTypes::Label label = dba->Label("Person");
GraphDbTypes::Label label = dba.Label("Person");
auto property = PROPERTY_PAIR("prop");
AstTreeStorage storage;
@ -38,12 +37,12 @@ TEST(QueryPlan, CreateNodeWithAttributes) {
node->properties_[property] = LITERAL(42);
auto create = std::make_shared<CreateNode>(node, nullptr);
PullAll(create, *dba, symbol_table);
dba->AdvanceCommand();
PullAll(create, dba, symbol_table);
dba.AdvanceCommand();
// count the number of vertices
int vertex_count = 0;
for (VertexAccessor vertex : dba->Vertices(false)) {
for (VertexAccessor vertex : dba.Vertices(false)) {
vertex_count++;
EXPECT_EQ(vertex.labels().size(), 1);
EXPECT_EQ(*vertex.labels().begin(), label);
@ -57,10 +56,10 @@ TEST(QueryPlan, CreateNodeWithAttributes) {
TEST(QueryPlan, CreateReturn) {
// test CREATE (n:Person {age: 42}) RETURN n, n.age
Dbms dbms;
auto dba = dbms.active();
GraphDb db;
GraphDbAccessor dba(db);
GraphDbTypes::Label label = dba->Label("Person");
GraphDbTypes::Label label = dba.Label("Person");
auto property = PROPERTY_PAIR("property");
AstTreeStorage storage;
@ -84,7 +83,7 @@ TEST(QueryPlan, CreateReturn) {
symbol_table[*named_expr_n->expression_] = sym_n;
auto produce = MakeProduce(create, named_expr_n, named_expr_n_p);
auto results = CollectProduce(produce.get(), symbol_table, *dba);
auto results = CollectProduce(produce.get(), symbol_table, dba);
EXPECT_EQ(1, results.size());
EXPECT_EQ(2, results[0].size());
EXPECT_EQ(TypedValue::Type::Vertex, results[0][0].type());
@ -93,26 +92,26 @@ TEST(QueryPlan, CreateReturn) {
EXPECT_EQ(TypedValue::Type::Int, results[0][1].type());
EXPECT_EQ(42, results[0][1].Value<int64_t>());
dba->AdvanceCommand();
EXPECT_EQ(1, CountIterable(dba->Vertices(false)));
dba.AdvanceCommand();
EXPECT_EQ(1, CountIterable(dba.Vertices(false)));
}
TEST(QueryPlan, CreateExpand) {
Dbms dbms;
auto dba = dbms.active();
GraphDb db;
GraphDbAccessor dba(db);
GraphDbTypes::Label label_node_1 = dba->Label("Node1");
GraphDbTypes::Label label_node_2 = dba->Label("Node2");
GraphDbTypes::Label label_node_1 = dba.Label("Node1");
GraphDbTypes::Label label_node_2 = dba.Label("Node2");
auto property = PROPERTY_PAIR("property");
GraphDbTypes::EdgeType edge_type = dba->Label("edge_type");
GraphDbTypes::EdgeType edge_type = dba.Label("edge_type");
SymbolTable symbol_table;
AstTreeStorage storage;
auto test_create_path = [&](bool cycle, int expected_nodes_created,
int expected_edges_created) {
int before_v = CountIterable(dba->Vertices(false));
int before_e = CountIterable(dba->Edges(false));
int before_v = CountIterable(dba.Vertices(false));
int before_e = CountIterable(dba.Edges(false));
// data for the first node
auto n = NODE("n");
@ -138,19 +137,19 @@ TEST(QueryPlan, CreateExpand) {
auto create_op = std::make_shared<CreateNode>(n, nullptr);
auto create_expand =
std::make_shared<CreateExpand>(m, r, create_op, n_sym, cycle);
PullAll(create_expand, *dba, symbol_table);
dba->AdvanceCommand();
PullAll(create_expand, dba, symbol_table);
dba.AdvanceCommand();
EXPECT_EQ(CountIterable(dba->Vertices(false)) - before_v,
EXPECT_EQ(CountIterable(dba.Vertices(false)) - before_v,
expected_nodes_created);
EXPECT_EQ(CountIterable(dba->Edges(false)) - before_e,
EXPECT_EQ(CountIterable(dba.Edges(false)) - before_e,
expected_edges_created);
};
test_create_path(false, 2, 1);
test_create_path(true, 1, 1);
for (VertexAccessor vertex : dba->Vertices(false)) {
for (VertexAccessor vertex : dba.Vertices(false)) {
EXPECT_EQ(vertex.labels().size(), 1);
GraphDbTypes::Label label = vertex.labels()[0];
if (label == label_node_1) {
@ -164,7 +163,7 @@ TEST(QueryPlan, CreateExpand) {
FAIL();
}
for (EdgeAccessor edge : dba->Edges(false)) {
for (EdgeAccessor edge : dba.Edges(false)) {
EXPECT_EQ(edge.EdgeType(), edge_type);
EXPECT_EQ(edge.PropsAt(property.second).Value<int64_t>(), 3);
}
@ -172,14 +171,14 @@ TEST(QueryPlan, CreateExpand) {
}
TEST(QueryPlan, MatchCreateNode) {
Dbms dbms;
auto dba = dbms.active();
GraphDb db;
GraphDbAccessor dba(db);
// add three nodes we'll match and expand-create from
dba->InsertVertex();
dba->InsertVertex();
dba->InsertVertex();
dba->AdvanceCommand();
dba.InsertVertex();
dba.InsertVertex();
dba.InsertVertex();
dba.AdvanceCommand();
SymbolTable symbol_table;
AstTreeStorage storage;
@ -192,34 +191,34 @@ TEST(QueryPlan, MatchCreateNode) {
// creation op
auto create_node = std::make_shared<CreateNode>(m, n_scan_all.op_);
EXPECT_EQ(CountIterable(dba->Vertices(false)), 3);
PullAll(create_node, *dba, symbol_table);
dba->AdvanceCommand();
EXPECT_EQ(CountIterable(dba->Vertices(false)), 6);
EXPECT_EQ(CountIterable(dba.Vertices(false)), 3);
PullAll(create_node, dba, symbol_table);
dba.AdvanceCommand();
EXPECT_EQ(CountIterable(dba.Vertices(false)), 6);
}
TEST(QueryPlan, MatchCreateExpand) {
Dbms dbms;
auto dba = dbms.active();
GraphDb db;
GraphDbAccessor dba(db);
// add three nodes we'll match and expand-create from
dba->InsertVertex();
dba->InsertVertex();
dba->InsertVertex();
dba->AdvanceCommand();
dba.InsertVertex();
dba.InsertVertex();
dba.InsertVertex();
dba.AdvanceCommand();
// GraphDbTypes::Label label_node_1 = dba->Label("Node1");
// GraphDbTypes::Label label_node_2 = dba->Label("Node2");
// GraphDbTypes::Property property = dba->Label("prop");
GraphDbTypes::EdgeType edge_type = dba->Label("edge_type");
// GraphDbTypes::Label label_node_1 = dba.Label("Node1");
// GraphDbTypes::Label label_node_2 = dba.Label("Node2");
// GraphDbTypes::Property property = dba.Label("prop");
GraphDbTypes::EdgeType edge_type = dba.Label("edge_type");
SymbolTable symbol_table;
AstTreeStorage storage;
auto test_create_path = [&](bool cycle, int expected_nodes_created,
int expected_edges_created) {
int before_v = CountIterable(dba->Vertices(false));
int before_e = CountIterable(dba->Edges(false));
int before_v = CountIterable(dba.Vertices(false));
int before_e = CountIterable(dba.Edges(false));
// data for the first node
auto n_scan_all = MakeScanAll(storage, symbol_table, "n");
@ -237,12 +236,12 @@ TEST(QueryPlan, MatchCreateExpand) {
auto create_expand = std::make_shared<CreateExpand>(m, r, n_scan_all.op_,
n_scan_all.sym_, cycle);
PullAll(create_expand, *dba, symbol_table);
dba->AdvanceCommand();
PullAll(create_expand, dba, symbol_table);
dba.AdvanceCommand();
EXPECT_EQ(CountIterable(dba->Vertices(false)) - before_v,
EXPECT_EQ(CountIterable(dba.Vertices(false)) - before_v,
expected_nodes_created);
EXPECT_EQ(CountIterable(dba->Edges(false)) - before_e,
EXPECT_EQ(CountIterable(dba.Edges(false)) - before_e,
expected_edges_created);
};
@ -251,20 +250,20 @@ TEST(QueryPlan, MatchCreateExpand) {
}
TEST(QueryPlan, Delete) {
Dbms dbms;
auto dba = dbms.active();
GraphDb db;
GraphDbAccessor dba(db);
// make a fully-connected (one-direction, no cycles) with 4 nodes
std::vector<VertexAccessor> vertices;
for (int i = 0; i < 4; ++i) vertices.push_back(dba->InsertVertex());
auto type = dba->EdgeType("type");
for (int i = 0; i < 4; ++i) vertices.push_back(dba.InsertVertex());
auto type = dba.EdgeType("type");
for (int j = 0; j < 4; ++j)
for (int k = j + 1; k < 4; ++k)
dba->InsertEdge(vertices[j], vertices[k], type);
dba.InsertEdge(vertices[j], vertices[k], type);
dba->AdvanceCommand();
EXPECT_EQ(4, CountIterable(dba->Vertices(false)));
EXPECT_EQ(6, CountIterable(dba->Edges(false)));
dba.AdvanceCommand();
EXPECT_EQ(4, CountIterable(dba.Vertices(false)));
EXPECT_EQ(6, CountIterable(dba.Edges(false)));
AstTreeStorage storage;
SymbolTable symbol_table;
@ -276,10 +275,10 @@ TEST(QueryPlan, Delete) {
symbol_table[*n_get] = n.sym_;
auto delete_op = std::make_shared<plan::Delete>(
n.op_, std::vector<Expression *>{n_get}, false);
EXPECT_THROW(PullAll(delete_op, *dba, symbol_table), QueryRuntimeException);
dba->AdvanceCommand();
EXPECT_EQ(4, CountIterable(dba->Vertices(false)));
EXPECT_EQ(6, CountIterable(dba->Edges(false)));
EXPECT_THROW(PullAll(delete_op, dba, symbol_table), QueryRuntimeException);
dba.AdvanceCommand();
EXPECT_EQ(4, CountIterable(dba.Vertices(false)));
EXPECT_EQ(6, CountIterable(dba.Edges(false)));
}
// detach delete a single vertex
@ -290,12 +289,12 @@ TEST(QueryPlan, Delete) {
auto delete_op = std::make_shared<plan::Delete>(
n.op_, std::vector<Expression *>{n_get}, true);
Frame frame(symbol_table.max_position());
Context context(*dba);
Context context(dba);
context.symbol_table_ = symbol_table;
delete_op->MakeCursor(*dba)->Pull(frame, context);
dba->AdvanceCommand();
EXPECT_EQ(3, CountIterable(dba->Vertices(false)));
EXPECT_EQ(3, CountIterable(dba->Edges(false)));
delete_op->MakeCursor(dba)->Pull(frame, context);
dba.AdvanceCommand();
EXPECT_EQ(3, CountIterable(dba.Vertices(false)));
EXPECT_EQ(3, CountIterable(dba.Edges(false)));
}
// delete all remaining edges
@ -307,10 +306,10 @@ TEST(QueryPlan, Delete) {
symbol_table[*r_get] = r_m.edge_sym_;
auto delete_op = std::make_shared<plan::Delete>(
r_m.op_, std::vector<Expression *>{r_get}, false);
PullAll(delete_op, *dba, symbol_table);
dba->AdvanceCommand();
EXPECT_EQ(3, CountIterable(dba->Vertices(false)));
EXPECT_EQ(0, CountIterable(dba->Edges(false)));
PullAll(delete_op, dba, symbol_table);
dba.AdvanceCommand();
EXPECT_EQ(3, CountIterable(dba.Vertices(false)));
EXPECT_EQ(0, CountIterable(dba.Edges(false)));
}
// delete all remaining vertices
@ -320,10 +319,10 @@ TEST(QueryPlan, Delete) {
symbol_table[*n_get] = n.sym_;
auto delete_op = std::make_shared<plan::Delete>(
n.op_, std::vector<Expression *>{n_get}, false);
PullAll(delete_op, *dba, symbol_table);
dba->AdvanceCommand();
EXPECT_EQ(0, CountIterable(dba->Vertices(false)));
EXPECT_EQ(0, CountIterable(dba->Edges(false)));
PullAll(delete_op, dba, symbol_table);
dba.AdvanceCommand();
EXPECT_EQ(0, CountIterable(dba.Vertices(false)));
EXPECT_EQ(0, CountIterable(dba.Edges(false)));
}
}
@ -340,15 +339,15 @@ TEST(QueryPlan, DeleteTwiceDeleteBlockingEdge) {
// MATCH (n)-[r]-(m) [DETACH] DELETE n, r, m
auto test_delete = [](bool detach) {
Dbms dbms;
auto dba = dbms.active();
GraphDb db;
GraphDbAccessor dba(db);
auto v1 = dba->InsertVertex();
auto v2 = dba->InsertVertex();
dba->InsertEdge(v1, v2, dba->EdgeType("T"));
dba->AdvanceCommand();
EXPECT_EQ(2, CountIterable(dba->Vertices(false)));
EXPECT_EQ(1, CountIterable(dba->Edges(false)));
auto v1 = dba.InsertVertex();
auto v2 = dba.InsertVertex();
dba.InsertEdge(v1, v2, dba.EdgeType("T"));
dba.AdvanceCommand();
EXPECT_EQ(2, CountIterable(dba.Vertices(false)));
EXPECT_EQ(1, CountIterable(dba.Edges(false)));
AstTreeStorage storage;
SymbolTable symbol_table;
@ -367,10 +366,10 @@ TEST(QueryPlan, DeleteTwiceDeleteBlockingEdge) {
auto delete_op = std::make_shared<plan::Delete>(
r_m.op_, std::vector<Expression *>{n_get, r_get, m_get}, detach);
EXPECT_EQ(2, PullAll(delete_op, *dba, symbol_table));
dba->AdvanceCommand();
EXPECT_EQ(0, CountIterable(dba->Vertices(false)));
EXPECT_EQ(0, CountIterable(dba->Edges(false)));
EXPECT_EQ(2, PullAll(delete_op, dba, symbol_table));
dba.AdvanceCommand();
EXPECT_EQ(0, CountIterable(dba.Vertices(false)));
EXPECT_EQ(0, CountIterable(dba.Edges(false)));
};
test_delete(true);
@ -378,19 +377,19 @@ TEST(QueryPlan, DeleteTwiceDeleteBlockingEdge) {
}
TEST(QueryPlan, DeleteReturn) {
Dbms dbms;
auto dba = dbms.active();
GraphDb db;
GraphDbAccessor dba(db);
// make a fully-connected (one-direction, no cycles) with 4 nodes
auto prop = PROPERTY_PAIR("property");
for (int i = 0; i < 4; ++i) {
auto va = dba->InsertVertex();
auto va = dba.InsertVertex();
va.PropsSet(prop.second, 42);
}
dba->AdvanceCommand();
EXPECT_EQ(4, CountIterable(dba->Vertices(false)));
EXPECT_EQ(0, CountIterable(dba->Edges(false)));
dba.AdvanceCommand();
EXPECT_EQ(4, CountIterable(dba.Vertices(false)));
EXPECT_EQ(0, CountIterable(dba.Edges(false)));
AstTreeStorage storage;
SymbolTable symbol_table;
@ -409,23 +408,23 @@ TEST(QueryPlan, DeleteReturn) {
symbol_table[*n_p] = symbol_table.CreateSymbol("bla", true);
auto produce = MakeProduce(delete_op, n_p);
auto results = CollectProduce(produce.get(), symbol_table, *dba);
auto results = CollectProduce(produce.get(), symbol_table, dba);
EXPECT_EQ(4, results.size());
dba->AdvanceCommand();
EXPECT_EQ(0, CountIterable(dba->Vertices(false)));
dba.AdvanceCommand();
EXPECT_EQ(0, CountIterable(dba.Vertices(false)));
}
TEST(QueryPlan, DeleteNull) {
// test (simplified) WITH Null as x delete x
Dbms dbms;
auto dba = dbms.active();
GraphDb db;
GraphDbAccessor dba(db);
AstTreeStorage storage;
SymbolTable symbol_table;
auto once = std::make_shared<Once>();
auto delete_op = std::make_shared<plan::Delete>(
once, std::vector<Expression *>{LITERAL(TypedValue::Null)}, false);
EXPECT_EQ(1, PullAll(delete_op, *dba, symbol_table));
EXPECT_EQ(1, PullAll(delete_op, dba, symbol_table));
}
TEST(QueryPlan, DeleteAdvance) {
@ -438,10 +437,10 @@ TEST(QueryPlan, DeleteAdvance) {
// note that Neo does not fail when the deleted
// record is not used in subsequent clauses, but
// we are not yet compatible with that
Dbms dbms;
auto dba = dbms.active();
dba->InsertVertex();
dba->AdvanceCommand();
GraphDb db;
GraphDbAccessor dba(db);
dba.InsertVertex();
dba.AdvanceCommand();
AstTreeStorage storage;
SymbolTable symbol_table;
@ -453,24 +452,24 @@ TEST(QueryPlan, DeleteAdvance) {
n.op_, std::vector<Expression *>{n_get}, false);
auto advance = std::make_shared<Accumulate>(
delete_op, std::vector<Symbol>{n.sym_}, true);
EXPECT_THROW(PullAll(advance, *dba, symbol_table), QueryRuntimeException);
EXPECT_THROW(PullAll(advance, dba, symbol_table), QueryRuntimeException);
}
TEST(QueryPlan, SetProperty) {
Dbms dbms;
auto dba = dbms.active();
GraphDb db;
GraphDbAccessor dba(db);
// graph with 4 vertices in connected pairs
// the origin vertex in each par and both edges
// have a property set
auto v1 = dba->InsertVertex();
auto v2 = dba->InsertVertex();
auto v3 = dba->InsertVertex();
auto v4 = dba->InsertVertex();
auto edge_type = dba->EdgeType("edge_type");
dba->InsertEdge(v1, v3, edge_type);
dba->InsertEdge(v2, v4, edge_type);
dba->AdvanceCommand();
auto v1 = dba.InsertVertex();
auto v2 = dba.InsertVertex();
auto v3 = dba.InsertVertex();
auto v4 = dba.InsertVertex();
auto edge_type = dba.EdgeType("edge_type");
dba.InsertEdge(v1, v3, edge_type);
dba.InsertEdge(v2, v4, edge_type);
dba.AdvanceCommand();
AstTreeStorage storage;
SymbolTable symbol_table;
@ -481,7 +480,7 @@ TEST(QueryPlan, SetProperty) {
EdgeAtom::Direction::OUT, {}, "m", false);
// set prop1 to 42 on n and r
auto prop1 = dba->Property("prop1");
auto prop1 = dba.Property("prop1");
auto literal = LITERAL(42);
auto n_p = PROPERTY_LOOKUP("n", prop1);
@ -491,11 +490,11 @@ TEST(QueryPlan, SetProperty) {
auto r_p = PROPERTY_LOOKUP("r", prop1);
symbol_table[*r_p->expression_] = r_m.edge_sym_;
auto set_r_p = std::make_shared<plan::SetProperty>(set_n_p, r_p, literal);
EXPECT_EQ(2, PullAll(set_r_p, *dba, symbol_table));
dba->AdvanceCommand();
EXPECT_EQ(2, PullAll(set_r_p, dba, symbol_table));
dba.AdvanceCommand();
EXPECT_EQ(CountIterable(dba->Edges(false)), 2);
for (EdgeAccessor edge : dba->Edges(false)) {
EXPECT_EQ(CountIterable(dba.Edges(false)), 2);
for (EdgeAccessor edge : dba.Edges(false)) {
ASSERT_EQ(edge.PropsAt(prop1).type(), PropertyValue::Type::Int);
EXPECT_EQ(edge.PropsAt(prop1).Value<int64_t>(), 42);
VertexAccessor from = edge.from();
@ -508,20 +507,20 @@ TEST(QueryPlan, SetProperty) {
TEST(QueryPlan, SetProperties) {
auto test_set_properties = [](bool update) {
Dbms dbms;
auto dba = dbms.active();
GraphDb db;
GraphDbAccessor dba(db);
// graph: ({a: 0})-[:R {b:1}]->({c:2})
auto prop_a = dba->Property("a");
auto prop_b = dba->Property("b");
auto prop_c = dba->Property("c");
auto v1 = dba->InsertVertex();
auto v2 = dba->InsertVertex();
auto e = dba->InsertEdge(v1, v2, dba->EdgeType("R"));
auto prop_a = dba.Property("a");
auto prop_b = dba.Property("b");
auto prop_c = dba.Property("c");
auto v1 = dba.InsertVertex();
auto v2 = dba.InsertVertex();
auto e = dba.InsertEdge(v1, v2, dba.EdgeType("R"));
v1.PropsSet(prop_a, 0);
e.PropsSet(prop_b, 1);
v2.PropsSet(prop_c, 2);
dba->AdvanceCommand();
dba.AdvanceCommand();
AstTreeStorage storage;
SymbolTable symbol_table;
@ -543,11 +542,11 @@ TEST(QueryPlan, SetProperties) {
std::make_shared<plan::SetProperties>(r_m.op_, n.sym_, r_ident, op);
auto set_m_to_r = std::make_shared<plan::SetProperties>(
set_r_to_n, r_m.edge_sym_, m_ident, op);
EXPECT_EQ(1, PullAll(set_m_to_r, *dba, symbol_table));
dba->AdvanceCommand();
EXPECT_EQ(1, PullAll(set_m_to_r, dba, symbol_table));
dba.AdvanceCommand();
EXPECT_EQ(CountIterable(dba->Edges(false)), 1);
for (EdgeAccessor edge : dba->Edges(false)) {
EXPECT_EQ(CountIterable(dba.Edges(false)), 1);
for (EdgeAccessor edge : dba.Edges(false)) {
VertexAccessor from = edge.from();
EXPECT_EQ(from.Properties().size(), update ? 2 : 1);
if (update) {
@ -577,15 +576,15 @@ TEST(QueryPlan, SetProperties) {
}
TEST(QueryPlan, SetLabels) {
Dbms dbms;
auto dba = dbms.active();
GraphDb db;
GraphDbAccessor dba(db);
auto label1 = dba->Label("label1");
auto label2 = dba->Label("label2");
auto label3 = dba->Label("label3");
dba->InsertVertex().add_label(label1);
dba->InsertVertex().add_label(label1);
dba->AdvanceCommand();
auto label1 = dba.Label("label1");
auto label2 = dba.Label("label2");
auto label3 = dba.Label("label3");
dba.InsertVertex().add_label(label1);
dba.InsertVertex().add_label(label1);
dba.AdvanceCommand();
AstTreeStorage storage;
SymbolTable symbol_table;
@ -593,9 +592,9 @@ TEST(QueryPlan, SetLabels) {
auto n = MakeScanAll(storage, symbol_table, "n");
auto label_set = std::make_shared<plan::SetLabels>(
n.op_, n.sym_, std::vector<GraphDbTypes::Label>{label2, label3});
EXPECT_EQ(2, PullAll(label_set, *dba, symbol_table));
EXPECT_EQ(2, PullAll(label_set, dba, symbol_table));
for (VertexAccessor vertex : dba->Vertices(false)) {
for (VertexAccessor vertex : dba.Vertices(false)) {
vertex.SwitchNew();
EXPECT_EQ(3, vertex.labels().size());
EXPECT_TRUE(vertex.has_label(label2));
@ -604,27 +603,27 @@ TEST(QueryPlan, SetLabels) {
}
TEST(QueryPlan, RemoveProperty) {
Dbms dbms;
auto dba = dbms.active();
GraphDb db;
GraphDbAccessor dba(db);
// graph with 4 vertices in connected pairs
// the origin vertex in each par and both edges
// have a property set
auto prop1 = dba->Property("prop1");
auto v1 = dba->InsertVertex();
auto v2 = dba->InsertVertex();
auto v3 = dba->InsertVertex();
auto v4 = dba->InsertVertex();
auto edge_type = dba->EdgeType("edge_type");
dba->InsertEdge(v1, v3, edge_type).PropsSet(prop1, 42);
dba->InsertEdge(v2, v4, edge_type);
auto prop1 = dba.Property("prop1");
auto v1 = dba.InsertVertex();
auto v2 = dba.InsertVertex();
auto v3 = dba.InsertVertex();
auto v4 = dba.InsertVertex();
auto edge_type = dba.EdgeType("edge_type");
dba.InsertEdge(v1, v3, edge_type).PropsSet(prop1, 42);
dba.InsertEdge(v2, v4, edge_type);
v2.PropsSet(prop1, 42);
v3.PropsSet(prop1, 42);
v4.PropsSet(prop1, 42);
auto prop2 = dba->Property("prop2");
auto prop2 = dba.Property("prop2");
v1.PropsSet(prop2, 0);
v2.PropsSet(prop2, 0);
dba->AdvanceCommand();
dba.AdvanceCommand();
AstTreeStorage storage;
SymbolTable symbol_table;
@ -641,11 +640,11 @@ TEST(QueryPlan, RemoveProperty) {
auto r_p = PROPERTY_LOOKUP("r", prop1);
symbol_table[*r_p->expression_] = r_m.edge_sym_;
auto set_r_p = std::make_shared<plan::RemoveProperty>(set_n_p, r_p);
EXPECT_EQ(2, PullAll(set_r_p, *dba, symbol_table));
dba->AdvanceCommand();
EXPECT_EQ(2, PullAll(set_r_p, dba, symbol_table));
dba.AdvanceCommand();
EXPECT_EQ(CountIterable(dba->Edges(false)), 2);
for (EdgeAccessor edge : dba->Edges(false)) {
EXPECT_EQ(CountIterable(dba.Edges(false)), 2);
for (EdgeAccessor edge : dba.Edges(false)) {
EXPECT_EQ(edge.PropsAt(prop1).type(), PropertyValue::Type::Null);
VertexAccessor from = edge.from();
VertexAccessor to = edge.to();
@ -656,20 +655,20 @@ TEST(QueryPlan, RemoveProperty) {
}
TEST(QueryPlan, RemoveLabels) {
Dbms dbms;
auto dba = dbms.active();
GraphDb db;
GraphDbAccessor dba(db);
auto label1 = dba->Label("label1");
auto label2 = dba->Label("label2");
auto label3 = dba->Label("label3");
auto v1 = dba->InsertVertex();
auto label1 = dba.Label("label1");
auto label2 = dba.Label("label2");
auto label3 = dba.Label("label3");
auto v1 = dba.InsertVertex();
v1.add_label(label1);
v1.add_label(label2);
v1.add_label(label3);
auto v2 = dba->InsertVertex();
auto v2 = dba.InsertVertex();
v2.add_label(label1);
v2.add_label(label3);
dba->AdvanceCommand();
dba.AdvanceCommand();
AstTreeStorage storage;
SymbolTable symbol_table;
@ -677,9 +676,9 @@ TEST(QueryPlan, RemoveLabels) {
auto n = MakeScanAll(storage, symbol_table, "n");
auto label_remove = std::make_shared<plan::RemoveLabels>(
n.op_, n.sym_, std::vector<GraphDbTypes::Label>{label1, label2});
EXPECT_EQ(2, PullAll(label_remove, *dba, symbol_table));
EXPECT_EQ(2, PullAll(label_remove, dba, symbol_table));
for (VertexAccessor vertex : dba->Vertices(false)) {
for (VertexAccessor vertex : dba.Vertices(false)) {
vertex.SwitchNew();
EXPECT_EQ(1, vertex.labels().size());
EXPECT_FALSE(vertex.has_label(label1));
@ -688,18 +687,18 @@ TEST(QueryPlan, RemoveLabels) {
}
TEST(QueryPlan, NodeFilterSet) {
Dbms dbms;
auto dba = dbms.active();
GraphDb db;
GraphDbAccessor dba(db);
// Create a graph such that (v1 {prop: 42}) is connected to v2 and v3.
auto v1 = dba->InsertVertex();
auto v1 = dba.InsertVertex();
auto prop = PROPERTY_PAIR("property");
v1.PropsSet(prop.second, 42);
auto v2 = dba->InsertVertex();
auto v3 = dba->InsertVertex();
auto edge_type = dba->EdgeType("Edge");
dba->InsertEdge(v1, v2, edge_type);
dba->InsertEdge(v1, v3, edge_type);
dba->AdvanceCommand();
auto v2 = dba.InsertVertex();
auto v3 = dba.InsertVertex();
auto edge_type = dba.EdgeType("Edge");
dba.InsertEdge(v1, v2, edge_type);
dba.InsertEdge(v1, v3, edge_type);
dba.AdvanceCommand();
// Create operations which match (v1 {prop: 42}) -- (v) and increment the
// v1.prop. The expected result is two incremenentations, since v1 is matched
// twice for 2 edges it has.
@ -719,8 +718,8 @@ TEST(QueryPlan, NodeFilterSet) {
symbol_table[*set_prop->expression_] = scan_all.sym_;
auto add = ADD(set_prop, LITERAL(1));
auto set = std::make_shared<plan::SetProperty>(node_filter, set_prop, add);
EXPECT_EQ(2, PullAll(set, *dba, symbol_table));
dba->AdvanceCommand();
EXPECT_EQ(2, PullAll(set, dba, symbol_table));
dba.AdvanceCommand();
v1.Reconstruct();
auto prop_eq = v1.PropsAt(prop.second) == TypedValue(42 + 2);
ASSERT_EQ(prop_eq.type(), TypedValue::Type::Bool);
@ -728,18 +727,18 @@ TEST(QueryPlan, NodeFilterSet) {
}
TEST(QueryPlan, FilterRemove) {
Dbms dbms;
auto dba = dbms.active();
GraphDb db;
GraphDbAccessor dba(db);
// Create a graph such that (v1 {prop: 42}) is connected to v2 and v3.
auto v1 = dba->InsertVertex();
auto v1 = dba.InsertVertex();
auto prop = PROPERTY_PAIR("property");
v1.PropsSet(prop.second, 42);
auto v2 = dba->InsertVertex();
auto v3 = dba->InsertVertex();
auto edge_type = dba->EdgeType("Edge");
dba->InsertEdge(v1, v2, edge_type);
dba->InsertEdge(v1, v3, edge_type);
dba->AdvanceCommand();
auto v2 = dba.InsertVertex();
auto v3 = dba.InsertVertex();
auto edge_type = dba.EdgeType("Edge");
dba.InsertEdge(v1, v2, edge_type);
dba.InsertEdge(v1, v3, edge_type);
dba.AdvanceCommand();
// Create operations which match (v1 {prop: 42}) -- (v) and remove v1.prop.
// The expected result is two matches, for each edge of v1.
AstTreeStorage storage;
@ -757,19 +756,19 @@ TEST(QueryPlan, FilterRemove) {
auto rem_prop = PROPERTY_LOOKUP("n", prop);
symbol_table[*rem_prop->expression_] = scan_all.sym_;
auto rem = std::make_shared<plan::RemoveProperty>(filter, rem_prop);
EXPECT_EQ(2, PullAll(rem, *dba, symbol_table));
dba->AdvanceCommand();
EXPECT_EQ(2, PullAll(rem, dba, symbol_table));
dba.AdvanceCommand();
v1.Reconstruct();
EXPECT_EQ(v1.PropsAt(prop.second).type(), PropertyValue::Type::Null);
}
TEST(QueryPlan, SetRemove) {
Dbms dbms;
auto dba = dbms.active();
auto v = dba->InsertVertex();
auto label1 = dba->Label("label1");
auto label2 = dba->Label("label2");
dba->AdvanceCommand();
GraphDb db;
GraphDbAccessor dba(db);
auto v = dba.InsertVertex();
auto label1 = dba.Label("label1");
auto label2 = dba.Label("label2");
dba.AdvanceCommand();
// Create operations which match (v) and set and remove v :label.
// The expected result is single (v) as it was at the start.
AstTreeStorage storage;
@ -781,8 +780,8 @@ TEST(QueryPlan, SetRemove) {
std::vector<GraphDbTypes::Label>{label1, label2});
auto rem = std::make_shared<plan::RemoveLabels>(
set, scan_all.sym_, std::vector<GraphDbTypes::Label>{label1, label2});
EXPECT_EQ(1, PullAll(rem, *dba, symbol_table));
dba->AdvanceCommand();
EXPECT_EQ(1, PullAll(rem, dba, symbol_table));
dba.AdvanceCommand();
v.Reconstruct();
EXPECT_FALSE(v.has_label(label1));
EXPECT_FALSE(v.has_label(label2));
@ -795,13 +794,13 @@ TEST(QueryPlan, Merge) {
// - merge_match branch looks for an expansion (any direction)
// and sets some property (for result validation)
// - merge_create branch just sets some other property
Dbms dbms;
auto dba = dbms.active();
auto v1 = dba->InsertVertex();
auto v2 = dba->InsertVertex();
dba->InsertEdge(v1, v2, dba->EdgeType("Type"));
auto v3 = dba->InsertVertex();
dba->AdvanceCommand();
GraphDb db;
GraphDbAccessor dba(db);
auto v1 = dba.InsertVertex();
auto v2 = dba.InsertVertex();
dba.InsertEdge(v1, v2, dba.EdgeType("Type"));
auto v3 = dba.InsertVertex();
dba.AdvanceCommand();
AstTreeStorage storage;
SymbolTable symbol_table;
@ -823,8 +822,8 @@ TEST(QueryPlan, Merge) {
n_p, LITERAL(2));
auto merge = std::make_shared<plan::Merge>(n.op_, m_set, n_set);
ASSERT_EQ(3, PullAll(merge, *dba, symbol_table));
dba->AdvanceCommand();
ASSERT_EQ(3, PullAll(merge, dba, symbol_table));
dba.AdvanceCommand();
v1.Reconstruct();
v2.Reconstruct();
v3.Reconstruct();
@ -840,8 +839,8 @@ TEST(QueryPlan, Merge) {
TEST(QueryPlan, MergeNoInput) {
// merge with no input, creates a single node
Dbms dbms;
auto dba = dbms.active();
GraphDb db;
GraphDbAccessor dba(db);
AstTreeStorage storage;
SymbolTable symbol_table;
@ -851,16 +850,16 @@ TEST(QueryPlan, MergeNoInput) {
auto create = std::make_shared<CreateNode>(node, nullptr);
auto merge = std::make_shared<plan::Merge>(nullptr, create, create);
EXPECT_EQ(0, CountIterable(dba->Vertices(false)));
EXPECT_EQ(1, PullAll(merge, *dba, symbol_table));
dba->AdvanceCommand();
EXPECT_EQ(1, CountIterable(dba->Vertices(false)));
EXPECT_EQ(0, CountIterable(dba.Vertices(false)));
EXPECT_EQ(1, PullAll(merge, dba, symbol_table));
dba.AdvanceCommand();
EXPECT_EQ(1, CountIterable(dba.Vertices(false)));
}
TEST(QueryPlan, SetPropertyOnNull) {
// SET (Null).prop = 42
Dbms dbms;
auto dba = dbms.active();
GraphDb db;
GraphDbAccessor dba(db);
AstTreeStorage storage;
SymbolTable symbol_table;
auto prop = PROPERTY_PAIR("property");
@ -869,13 +868,13 @@ TEST(QueryPlan, SetPropertyOnNull) {
auto n_prop = storage.Create<PropertyLookup>(null, prop);
auto once = std::make_shared<Once>();
auto set_op = std::make_shared<plan::SetProperty>(once, n_prop, literal);
EXPECT_EQ(1, PullAll(set_op, *dba, symbol_table));
EXPECT_EQ(1, PullAll(set_op, dba, symbol_table));
}
TEST(QueryPlan, SetPropertiesOnNull) {
// OPTIONAL MATCH (n) SET n = n
Dbms dbms;
auto dba = dbms.active();
GraphDb db;
GraphDbAccessor dba(db);
AstTreeStorage storage;
SymbolTable symbol_table;
auto n = MakeScanAll(storage, symbol_table, "n");
@ -885,15 +884,15 @@ TEST(QueryPlan, SetPropertiesOnNull) {
std::vector<Symbol>{n.sym_});
auto set_op = std::make_shared<plan::SetProperties>(
optional, n.sym_, n_ident, plan::SetProperties::Op::REPLACE);
EXPECT_EQ(0, CountIterable(dba->Vertices(false)));
EXPECT_EQ(1, PullAll(set_op, *dba, symbol_table));
EXPECT_EQ(0, CountIterable(dba.Vertices(false)));
EXPECT_EQ(1, PullAll(set_op, dba, symbol_table));
}
TEST(QueryPlan, SetLabelsOnNull) {
// OPTIONAL MATCH (n) SET n :label
Dbms dbms;
auto dba = dbms.active();
auto label = dba->Label("label");
GraphDb db;
GraphDbAccessor dba(db);
auto label = dba.Label("label");
AstTreeStorage storage;
SymbolTable symbol_table;
auto n = MakeScanAll(storage, symbol_table, "n");
@ -903,14 +902,14 @@ TEST(QueryPlan, SetLabelsOnNull) {
std::vector<Symbol>{n.sym_});
auto set_op = std::make_shared<plan::SetLabels>(
optional, n.sym_, std::vector<GraphDbTypes::Label>{label});
EXPECT_EQ(0, CountIterable(dba->Vertices(false)));
EXPECT_EQ(1, PullAll(set_op, *dba, symbol_table));
EXPECT_EQ(0, CountIterable(dba.Vertices(false)));
EXPECT_EQ(1, PullAll(set_op, dba, symbol_table));
}
TEST(QueryPlan, RemovePropertyOnNull) {
// REMOVE (Null).prop
Dbms dbms;
auto dba = dbms.active();
GraphDb db;
GraphDbAccessor dba(db);
AstTreeStorage storage;
SymbolTable symbol_table;
auto prop = PROPERTY_PAIR("property");
@ -918,14 +917,14 @@ TEST(QueryPlan, RemovePropertyOnNull) {
auto n_prop = storage.Create<PropertyLookup>(null, prop);
auto once = std::make_shared<Once>();
auto remove_op = std::make_shared<plan::RemoveProperty>(once, n_prop);
EXPECT_EQ(1, PullAll(remove_op, *dba, symbol_table));
EXPECT_EQ(1, PullAll(remove_op, dba, symbol_table));
}
TEST(QueryPlan, RemoveLabelsOnNull) {
// OPTIONAL MATCH (n) REMOVE n :label
Dbms dbms;
auto dba = dbms.active();
auto label = dba->Label("label");
GraphDb db;
GraphDbAccessor dba(db);
auto label = dba.Label("label");
AstTreeStorage storage;
SymbolTable symbol_table;
auto n = MakeScanAll(storage, symbol_table, "n");
@ -935,19 +934,19 @@ TEST(QueryPlan, RemoveLabelsOnNull) {
std::vector<Symbol>{n.sym_});
auto remove_op = std::make_shared<plan::RemoveLabels>(
optional, n.sym_, std::vector<GraphDbTypes::Label>{label});
EXPECT_EQ(0, CountIterable(dba->Vertices(false)));
EXPECT_EQ(1, PullAll(remove_op, *dba, symbol_table));
EXPECT_EQ(0, CountIterable(dba.Vertices(false)));
EXPECT_EQ(1, PullAll(remove_op, dba, symbol_table));
}
TEST(QueryPlan, CreateIndex) {
// CREATE INDEX ON :Label(property)
Dbms dbms;
auto dba = dbms.active();
auto label = dba->Label("label");
auto property = dba->Property("property");
EXPECT_FALSE(dba->LabelPropertyIndexExists(label, property));
GraphDb db;
GraphDbAccessor dba(db);
auto label = dba.Label("label");
auto property = dba.Property("property");
EXPECT_FALSE(dba.LabelPropertyIndexExists(label, property));
auto create_index = std::make_shared<plan::CreateIndex>(label, property);
SymbolTable symbol_table;
EXPECT_EQ(PullAll(create_index, *dba, symbol_table), 1);
EXPECT_TRUE(dba->LabelPropertyIndexExists(label, property));
EXPECT_EQ(PullAll(create_index, dba, symbol_table), 1);
EXPECT_TRUE(dba.LabelPropertyIndexExists(label, property));
}

View File

@ -2,31 +2,41 @@
// that's not easily testable with single-phase testing. instead, for
// easy testing and latter readability they are tested end-to-end.
#include <experimental/optional>
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "communication/result_stream_faker.hpp"
#include "database/dbms.hpp"
#include "query/interpreter.hpp"
class QueryExecution : public testing::Test {
protected:
Dbms dbms_;
std::unique_ptr<GraphDbAccessor> db_ = dbms_.active();
std::experimental::optional<GraphDb> db_;
std::experimental::optional<GraphDbAccessor> dba_;
/** Commits the current transaction and refreshes the db_
void SetUp() {
db_.emplace();
dba_.emplace(*db_);
}
void TearDown() {
dba_ = std::experimental::nullopt;
db_ = std::experimental::nullopt;
}
/** Commits the current transaction and refreshes the dba_
* variable to hold a new accessor with a new transaction */
void Commit() {
db_->Commit();
auto next_db = dbms_.active();
db_.swap(next_db);
dba_->Commit();
dba_.emplace(*db_);
}
/** Executes the query and returns the results.
* Does NOT commit the transaction */
auto Execute(const std::string &query) {
ResultStreamFaker results;
query::Interpreter().Interpret(query, *db_, results, {}, false);
query::Interpreter().Interpret(query, *dba_, results, {}, false);
return results.GetResults();
}
};

View File

@ -15,7 +15,7 @@
#include "gtest/gtest.h"
#include "communication/result_stream_faker.hpp"
#include "database/dbms.hpp"
#include "database/graph_db.hpp"
#include "query/context.hpp"
#include "query/exceptions.hpp"
#include "query/plan/operator.hpp"
@ -27,19 +27,19 @@ using namespace query::plan;
class MatchReturnFixture : public testing::Test {
protected:
Dbms dbms;
std::unique_ptr<GraphDbAccessor> dba = dbms.active();
GraphDb db_;
GraphDbAccessor dba_{db_};
AstTreeStorage storage;
SymbolTable symbol_table;
void AddVertices(int count) {
for (int i = 0; i < count; i++) dba->InsertVertex();
for (int i = 0; i < count; i++) dba_.InsertVertex();
}
template <typename TResult>
std::vector<TResult> Results(std::shared_ptr<Produce> &op) {
std::vector<TResult> res;
for (const auto &row : CollectProduce(op.get(), symbol_table, *dba))
for (const auto &row : CollectProduce(op.get(), symbol_table, dba_))
res.emplace_back(row[0].Value<TResult>());
return res;
}
@ -47,7 +47,7 @@ class MatchReturnFixture : public testing::Test {
TEST_F(MatchReturnFixture, MatchReturn) {
AddVertices(2);
dba->AdvanceCommand();
dba_.AdvanceCommand();
auto test_pull_count = [&](GraphView graph_view) {
auto scan_all =
@ -57,21 +57,21 @@ TEST_F(MatchReturnFixture, MatchReturn) {
symbol_table[*output->expression_] = scan_all.sym_;
symbol_table[*output] =
symbol_table.CreateSymbol("named_expression_1", true);
return PullAll(produce, *dba, symbol_table);
return PullAll(produce, dba_, symbol_table);
};
EXPECT_EQ(2, test_pull_count(GraphView::NEW));
EXPECT_EQ(2, test_pull_count(GraphView::OLD));
dba->InsertVertex();
dba_.InsertVertex();
EXPECT_EQ(3, test_pull_count(GraphView::NEW));
EXPECT_EQ(2, test_pull_count(GraphView::OLD));
dba->AdvanceCommand();
dba_.AdvanceCommand();
EXPECT_EQ(3, test_pull_count(GraphView::OLD));
}
TEST_F(MatchReturnFixture, MatchReturnPath) {
AddVertices(2);
dba->AdvanceCommand();
dba_.AdvanceCommand();
auto scan_all = MakeScanAll(storage, symbol_table, "n", nullptr);
Symbol path_sym = symbol_table.CreateSymbol("path", true);
@ -84,19 +84,19 @@ TEST_F(MatchReturnFixture, MatchReturnPath) {
auto results = Results<query::Path>(produce);
ASSERT_EQ(results.size(), 2);
std::vector<query::Path> expected_paths;
for (const auto &v : dba->Vertices(false)) expected_paths.emplace_back(v);
for (const auto &v : dba_.Vertices(false)) expected_paths.emplace_back(v);
ASSERT_EQ(expected_paths.size(), 2);
EXPECT_TRUE(std::is_permutation(expected_paths.begin(), expected_paths.end(),
results.begin()));
}
TEST(QueryPlan, MatchReturnCartesian) {
Dbms dbms;
auto dba = dbms.active();
GraphDb db;
GraphDbAccessor dba(db);
dba->InsertVertex().add_label(dba->Label("l1"));
dba->InsertVertex().add_label(dba->Label("l2"));
dba->AdvanceCommand();
dba.InsertVertex().add_label(dba.Label("l1"));
dba.InsertVertex().add_label(dba.Label("l2"));
dba.AdvanceCommand();
AstTreeStorage storage;
SymbolTable symbol_table;
@ -113,7 +113,7 @@ TEST(QueryPlan, MatchReturnCartesian) {
symbol_table.CreateSymbol("named_expression_2", true);
auto produce = MakeProduce(m.op_, return_n, return_m);
auto results = CollectProduce(produce.get(), symbol_table, *dba);
auto results = CollectProduce(produce.get(), symbol_table, dba);
EXPECT_EQ(results.size(), 4);
// ensure the result ordering is OK:
// "n" from the results is the same for the first two rows, while "m" isn't
@ -124,13 +124,13 @@ TEST(QueryPlan, MatchReturnCartesian) {
}
TEST(QueryPlan, StandaloneReturn) {
Dbms dbms;
auto dba = dbms.active();
GraphDb db;
GraphDbAccessor dba(db);
// add a few nodes to the database
dba->InsertVertex();
dba->InsertVertex();
dba->AdvanceCommand();
dba.InsertVertex();
dba.InsertVertex();
dba.AdvanceCommand();
AstTreeStorage storage;
SymbolTable symbol_table;
@ -139,25 +139,25 @@ TEST(QueryPlan, StandaloneReturn) {
auto produce = MakeProduce(std::shared_ptr<LogicalOperator>(nullptr), output);
symbol_table[*output] = symbol_table.CreateSymbol("named_expression_1", true);
auto results = CollectProduce(produce.get(), symbol_table, *dba);
auto results = CollectProduce(produce.get(), symbol_table, dba);
EXPECT_EQ(results.size(), 1);
EXPECT_EQ(results[0].size(), 1);
EXPECT_EQ(results[0][0].Value<int64_t>(), 42);
}
TEST(QueryPlan, NodeFilterLabelsAndProperties) {
Dbms dbms;
auto dba = dbms.active();
GraphDb db;
GraphDbAccessor dba(db);
// add a few nodes to the database
GraphDbTypes::Label label = dba->Label("Label");
GraphDbTypes::Label label = dba.Label("Label");
auto property = PROPERTY_PAIR("Property");
auto v1 = dba->InsertVertex();
auto v2 = dba->InsertVertex();
auto v3 = dba->InsertVertex();
auto v4 = dba->InsertVertex();
auto v5 = dba->InsertVertex();
dba->InsertVertex();
auto v1 = dba.InsertVertex();
auto v2 = dba.InsertVertex();
auto v3 = dba.InsertVertex();
auto v4 = dba.InsertVertex();
auto v5 = dba.InsertVertex();
dba.InsertVertex();
// test all combination of (label | no_label) * (no_prop | wrong_prop |
// right_prop)
// only v1-v3 will have the right labels
@ -169,7 +169,7 @@ TEST(QueryPlan, NodeFilterLabelsAndProperties) {
v2.PropsSet(property.second, 1);
v4.PropsSet(property.second, 42);
v5.PropsSet(property.second, 1);
dba->AdvanceCommand();
dba.AdvanceCommand();
AstTreeStorage storage;
SymbolTable symbol_table;
@ -191,40 +191,40 @@ TEST(QueryPlan, NodeFilterLabelsAndProperties) {
symbol_table[*output] = symbol_table.CreateSymbol("named_expression_1", true);
auto produce = MakeProduce(node_filter, output);
EXPECT_EQ(1, PullAll(produce, *dba, symbol_table));
EXPECT_EQ(1, PullAll(produce, dba, symbol_table));
// test that filtering works with old records
v4.Reconstruct();
v4.add_label(label);
EXPECT_EQ(1, PullAll(produce, *dba, symbol_table));
dba->AdvanceCommand();
EXPECT_EQ(2, PullAll(produce, *dba, symbol_table));
EXPECT_EQ(1, PullAll(produce, dba, symbol_table));
dba.AdvanceCommand();
EXPECT_EQ(2, PullAll(produce, dba, symbol_table));
}
TEST(QueryPlan, NodeFilterMultipleLabels) {
Dbms dbms;
auto dba = dbms.active();
GraphDb db;
GraphDbAccessor dba(db);
// add a few nodes to the database
GraphDbTypes::Label label1 = dba->Label("label1");
GraphDbTypes::Label label2 = dba->Label("label2");
GraphDbTypes::Label label3 = dba->Label("label3");
GraphDbTypes::Label label1 = dba.Label("label1");
GraphDbTypes::Label label2 = dba.Label("label2");
GraphDbTypes::Label label3 = dba.Label("label3");
// the test will look for nodes that have label1 and label2
dba->InsertVertex(); // NOT accepted
dba->InsertVertex().add_label(label1); // NOT accepted
dba->InsertVertex().add_label(label2); // NOT accepted
dba->InsertVertex().add_label(label3); // NOT accepted
auto v1 = dba->InsertVertex(); // YES accepted
dba.InsertVertex(); // NOT accepted
dba.InsertVertex().add_label(label1); // NOT accepted
dba.InsertVertex().add_label(label2); // NOT accepted
dba.InsertVertex().add_label(label3); // NOT accepted
auto v1 = dba.InsertVertex(); // YES accepted
v1.add_label(label1);
v1.add_label(label2);
auto v2 = dba->InsertVertex(); // NOT accepted
auto v2 = dba.InsertVertex(); // NOT accepted
v2.add_label(label1);
v2.add_label(label3);
auto v3 = dba->InsertVertex(); // YES accepted
auto v3 = dba.InsertVertex(); // YES accepted
v3.add_label(label1);
v3.add_label(label2);
v3.add_label(label3);
dba->AdvanceCommand();
dba.AdvanceCommand();
AstTreeStorage storage;
SymbolTable symbol_table;
@ -247,30 +247,30 @@ TEST(QueryPlan, NodeFilterMultipleLabels) {
symbol_table[*output] = symbol_table.CreateSymbol("named_expression_1", true);
symbol_table[*output->expression_] = n.sym_;
auto results = CollectProduce(produce.get(), symbol_table, *dba);
auto results = CollectProduce(produce.get(), symbol_table, dba);
EXPECT_EQ(results.size(), 2);
}
class ExpandFixture : public testing::Test {
protected:
Dbms dbms;
std::unique_ptr<GraphDbAccessor> dba = dbms.active();
GraphDb db_;
GraphDbAccessor dba_{db_};
AstTreeStorage storage;
SymbolTable symbol_table;
// make a V-graph (v3)<-[r2]-(v1)-[r1]->(v2)
VertexAccessor v1 = dba->InsertVertex();
VertexAccessor v2 = dba->InsertVertex();
VertexAccessor v3 = dba->InsertVertex();
GraphDbTypes::EdgeType edge_type = dba->EdgeType("Edge");
EdgeAccessor r1 = dba->InsertEdge(v1, v2, edge_type);
EdgeAccessor r2 = dba->InsertEdge(v1, v3, edge_type);
VertexAccessor v1 = dba_.InsertVertex();
VertexAccessor v2 = dba_.InsertVertex();
VertexAccessor v3 = dba_.InsertVertex();
GraphDbTypes::EdgeType edge_type = dba_.EdgeType("Edge");
EdgeAccessor r1 = dba_.InsertEdge(v1, v2, edge_type);
EdgeAccessor r2 = dba_.InsertEdge(v1, v3, edge_type);
void SetUp() override {
v1.add_label((GraphDbTypes::Label)1);
v2.add_label((GraphDbTypes::Label)2);
v3.add_label((GraphDbTypes::Label)3);
dba->AdvanceCommand();
dba_.AdvanceCommand();
}
};
@ -287,7 +287,7 @@ TEST_F(ExpandFixture, Expand) {
symbol_table.CreateSymbol("named_expression_1", true);
auto produce = MakeProduce(r_m.op_, output);
return PullAll(produce, *dba, symbol_table);
return PullAll(produce, dba_, symbol_table);
};
EXPECT_EQ(2, test_expand(EdgeAtom::Direction::OUT, GraphView::AS_IS));
@ -298,15 +298,15 @@ TEST_F(ExpandFixture, Expand) {
v1.Reconstruct();
v2.Reconstruct();
v3.Reconstruct();
dba->InsertEdge(v1, v2, edge_type);
dba->InsertEdge(v1, v3, edge_type);
dba_.InsertEdge(v1, v2, edge_type);
dba_.InsertEdge(v1, v3, edge_type);
EXPECT_EQ(2, test_expand(EdgeAtom::Direction::OUT, GraphView::OLD));
EXPECT_EQ(2, test_expand(EdgeAtom::Direction::IN, GraphView::OLD));
EXPECT_EQ(4, test_expand(EdgeAtom::Direction::BOTH, GraphView::OLD));
EXPECT_EQ(4, test_expand(EdgeAtom::Direction::OUT, GraphView::NEW));
EXPECT_EQ(4, test_expand(EdgeAtom::Direction::IN, GraphView::NEW));
EXPECT_EQ(8, test_expand(EdgeAtom::Direction::BOTH, GraphView::NEW));
dba->AdvanceCommand();
dba_.AdvanceCommand();
EXPECT_EQ(4, test_expand(EdgeAtom::Direction::OUT, GraphView::OLD));
EXPECT_EQ(4, test_expand(EdgeAtom::Direction::IN, GraphView::OLD));
EXPECT_EQ(8, test_expand(EdgeAtom::Direction::BOTH, GraphView::OLD));
@ -326,7 +326,7 @@ TEST_F(ExpandFixture, ExpandPath) {
auto produce = MakeProduce(path, output);
std::vector<query::Path> expected_paths{{v1, r2, v3}, {v1, r1, v2}};
auto results = CollectProduce(produce.get(), symbol_table, *dba);
auto results = CollectProduce(produce.get(), symbol_table, dba_);
ASSERT_EQ(results.size(), 2);
std::vector<query::Path> results_paths;
for (const auto &result : results)
@ -353,12 +353,12 @@ class QueryPlanExpandVariable : public testing::Test {
// a lot below in test declaration
using map_int = std::unordered_map<int, int>;
Dbms dbms;
std::unique_ptr<GraphDbAccessor> dba = dbms.active();
GraphDb db_;
GraphDbAccessor dba_{db_};
// labels for layers in the double chain
std::vector<GraphDbTypes::Label> labels;
// for all the edges
GraphDbTypes::EdgeType edge_type = dba->EdgeType("edge_type");
GraphDbTypes::EdgeType edge_type = dba_.EdgeType("edge_type");
AstTreeStorage storage;
SymbolTable symbol_table;
@ -372,26 +372,26 @@ class QueryPlanExpandVariable : public testing::Test {
std::vector<VertexAccessor> layer;
for (int from_layer_ind = -1; from_layer_ind < chain_length - 1;
from_layer_ind++) {
std::vector<VertexAccessor> new_layer{dba->InsertVertex(),
dba->InsertVertex()};
auto label = dba->Label(std::to_string(from_layer_ind + 1));
std::vector<VertexAccessor> new_layer{dba_.InsertVertex(),
dba_.InsertVertex()};
auto label = dba_.Label(std::to_string(from_layer_ind + 1));
labels.push_back(label);
for (size_t v_to_ind = 0; v_to_ind < new_layer.size(); v_to_ind++) {
auto &v_to = new_layer[v_to_ind];
v_to.add_label(label);
for (size_t v_from_ind = 0; v_from_ind < layer.size(); v_from_ind++) {
auto &v_from = layer[v_from_ind];
auto edge = dba->InsertEdge(v_from, v_to, edge_type);
edge.PropsSet(dba->Property("p"),
auto edge = dba_.InsertEdge(v_from, v_to, edge_type);
edge.PropsSet(dba_.Property("p"),
fmt::format("V{}{}->V{}{}", from_layer_ind, v_from_ind,
from_layer_ind + 1, v_to_ind));
}
}
layer = new_layer;
}
dba->AdvanceCommand();
ASSERT_EQ(CountIterable(dba->Vertices(false)), 2 * chain_length);
ASSERT_EQ(CountIterable(dba->Edges(false)), 4 * (chain_length - 1));
dba_.AdvanceCommand();
ASSERT_EQ(CountIterable(dba_.Vertices(false)), 2 * chain_length);
ASSERT_EQ(CountIterable(dba_.Edges(false)), 4 * (chain_length - 1));
}
/**
@ -457,8 +457,8 @@ class QueryPlanExpandVariable : public testing::Test {
template <typename TResult>
auto GetResults(std::shared_ptr<LogicalOperator> input_op, Symbol symbol) {
Frame frame(symbol_table.max_position());
auto cursor = input_op->MakeCursor(*dba);
Context context(*dba);
auto cursor = input_op->MakeCursor(dba_);
Context context(dba_);
context.symbol_table_ = symbol_table;
std::vector<TResult> results;
while (cursor->Pull(frame, context))
@ -619,32 +619,32 @@ TEST_F(QueryPlanExpandVariable, EdgeUniquenessTwoVariableExpansions) {
}
TEST_F(QueryPlanExpandVariable, GraphState) {
auto test_expand = [&](
GraphView graph_view,
const std::vector<GraphDbTypes::EdgeType> &edge_types) {
auto e = Edge("r", EdgeAtom::Direction::OUT);
return GetEdgeListSizes(
AddMatch<ExpandVariable>(nullptr, "n", 0, EdgeAtom::Direction::OUT,
edge_types, 2, 2, e, "m", graph_view),
e);
};
auto test_expand =
[&](GraphView graph_view,
const std::vector<GraphDbTypes::EdgeType> &edge_types) {
auto e = Edge("r", EdgeAtom::Direction::OUT);
return GetEdgeListSizes(
AddMatch<ExpandVariable>(nullptr, "n", 0, EdgeAtom::Direction::OUT,
edge_types, 2, 2, e, "m", graph_view),
e);
};
auto new_edge_type = dba->EdgeType("some_type");
auto new_edge_type = dba_.EdgeType("some_type");
// add two vertices branching out from the second layer
for (VertexAccessor &vertex : dba->Vertices(true))
for (VertexAccessor &vertex : dba_.Vertices(true))
if (vertex.has_label(labels[1])) {
auto new_vertex = dba->InsertVertex();
dba->InsertEdge(vertex, new_vertex, new_edge_type);
auto new_vertex = dba_.InsertVertex();
dba_.InsertEdge(vertex, new_vertex, new_edge_type);
}
ASSERT_EQ(CountIterable(dba->Vertices(false)), 6);
ASSERT_EQ(CountIterable(dba->Vertices(true)), 8);
ASSERT_EQ(CountIterable(dba_.Vertices(false)), 6);
ASSERT_EQ(CountIterable(dba_.Vertices(true)), 8);
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();
dba_.AdvanceCommand();
for (const auto graph_view : {GraphView::OLD, GraphView::NEW}) {
EXPECT_EQ(test_expand(graph_view, {}), (map_int{{2, 12}}));
EXPECT_EQ(test_expand(graph_view, {edge_type}), (map_int{{2, 8}}));
@ -669,7 +669,7 @@ TEST_F(QueryPlanExpandVariable, NamedPath) {
std::vector<Symbol>{find_symbol("n"), e, find_symbol("m")});
std::vector<query::Path> expected_paths;
for (const auto &v : dba->Vertices(labels[0], false))
for (const auto &v : dba_.Vertices(labels[0], false))
for (const auto &e1 : v.out())
for (const auto &e2 : e1.to().out())
expected_paths.emplace_back(v, e1, e1.to(), e2, e2.to());
@ -689,20 +689,20 @@ struct hash<std::pair<int, int>> {
return p.first + 31 * p.second;
}
};
}
} // namespace std
// TODO test optional + variable length
/** A test fixture for breadth first expansion */
class QueryPlanExpandBreadthFirst : public testing::Test {
protected:
Dbms dbms_;
// style-guide non-conformant name due to PROPERTY_PAIR and PROPERTY_LOOKUP
// macro requirements
std::unique_ptr<GraphDbAccessor> dba = dbms_.active();
GraphDb db;
GraphDbAccessor dba{db};
std::pair<std::string, GraphDbTypes::Property> prop =
PROPERTY_PAIR("property");
GraphDbTypes::EdgeType edge_type = dba->EdgeType("edge_type");
GraphDbTypes::EdgeType edge_type = dba.EdgeType("edge_type");
// make 4 vertices because we'll need to compare against them exactly
// v[0] has `prop` with the value 0
@ -721,12 +721,12 @@ class QueryPlanExpandBreadthFirst : public testing::Test {
void SetUp() {
for (int i = 0; i < 4; i++) {
v.push_back(dba->InsertVertex());
v.push_back(dba.InsertVertex());
v.back().PropsSet(prop.second, i);
}
auto add_edge = [&](int from, int to) {
EdgeAccessor edge = dba->InsertEdge(v[from], v[to], edge_type);
EdgeAccessor edge = dba.InsertEdge(v[from], v[to], edge_type);
edge.PropsSet(prop.second, from * 10 + to);
e.emplace(std::make_pair(from, to), edge);
};
@ -738,7 +738,7 @@ class QueryPlanExpandBreadthFirst : public testing::Test {
add_edge(3, 2);
add_edge(2, 2);
dba->AdvanceCommand();
dba.AdvanceCommand();
for (auto &vertex : v) vertex.Reconstruct();
for (auto &edge : e) edge.second.Reconstruct();
}
@ -772,9 +772,9 @@ class QueryPlanExpandBreadthFirst : public testing::Test {
inner_edge, inner_node, where, graph_view);
Frame frame(symbol_table.max_position());
auto cursor = last_op->MakeCursor(*dba);
auto cursor = last_op->MakeCursor(dba);
std::vector<std::pair<std::vector<EdgeAccessor>, VertexAccessor>> results;
Context context(*dba);
Context context(dba);
context.symbol_table_ = symbol_table;
while (cursor->Pull(frame, context)) {
results.emplace_back(std::vector<EdgeAccessor>(),
@ -867,14 +867,14 @@ TEST_F(QueryPlanExpandBreadthFirst, GraphState) {
};
EXPECT_EQ(ExpandSize(GraphView::OLD), 3);
EXPECT_EQ(ExpandSize(GraphView::NEW), 3);
auto new_vertex = dba->InsertVertex();
auto new_vertex = dba.InsertVertex();
new_vertex.PropsSet(prop.second, 4);
dba->InsertEdge(v[3], new_vertex, edge_type);
EXPECT_EQ(CountIterable(dba->Vertices(false)), 4);
EXPECT_EQ(CountIterable(dba->Vertices(true)), 5);
dba.InsertEdge(v[3], new_vertex, edge_type);
EXPECT_EQ(CountIterable(dba.Vertices(false)), 4);
EXPECT_EQ(CountIterable(dba.Vertices(true)), 5);
EXPECT_EQ(ExpandSize(GraphView::OLD), 3);
EXPECT_EQ(ExpandSize(GraphView::NEW), 4);
dba->AdvanceCommand();
dba.AdvanceCommand();
EXPECT_EQ(ExpandSize(GraphView::OLD), 4);
EXPECT_EQ(ExpandSize(GraphView::NEW), 4);
}
@ -916,24 +916,24 @@ TEST_F(QueryPlanExpandBreadthFirst, ExistingNode) {
}
TEST(QueryPlan, ExpandOptional) {
Dbms dbms;
auto dba = dbms.active();
GraphDb db;
GraphDbAccessor dba(db);
AstTreeStorage storage;
SymbolTable symbol_table;
// graph (v2 {p: 2})<-[:T]-(v1 {p: 1})-[:T]->(v3 {p: 2})
auto prop = dba->Property("p");
auto edge_type = dba->EdgeType("T");
auto v1 = dba->InsertVertex();
auto prop = dba.Property("p");
auto edge_type = dba.EdgeType("T");
auto v1 = dba.InsertVertex();
v1.PropsSet(prop, 1);
auto v2 = dba->InsertVertex();
auto v2 = dba.InsertVertex();
v2.PropsSet(prop, 2);
dba->InsertEdge(v1, v2, edge_type);
auto v3 = dba->InsertVertex();
dba.InsertEdge(v1, v2, edge_type);
auto v3 = dba.InsertVertex();
v3.PropsSet(prop, 2);
dba->InsertEdge(v1, v3, edge_type);
dba->AdvanceCommand();
dba.InsertEdge(v1, v3, edge_type);
dba.AdvanceCommand();
// MATCH (n) OPTIONAL MATCH (n)-[r]->(m)
auto n = MakeScanAll(storage, symbol_table, "n");
@ -954,7 +954,7 @@ TEST(QueryPlan, ExpandOptional) {
symbol_table[*m_ne] = symbol_table.CreateSymbol("m", true);
auto produce = MakeProduce(optional, n_ne, r_ne, m_ne);
auto results = CollectProduce(produce.get(), symbol_table, *dba);
auto results = CollectProduce(produce.get(), symbol_table, dba);
ASSERT_EQ(4, results.size());
int v1_is_n_count = 0;
for (auto &row : results) {
@ -975,8 +975,8 @@ TEST(QueryPlan, ExpandOptional) {
}
TEST(QueryPlan, OptionalMatchEmptyDB) {
Dbms dbms;
auto dba = dbms.active();
GraphDb db;
GraphDbAccessor dba(db);
AstTreeStorage storage;
SymbolTable symbol_table;
@ -991,14 +991,14 @@ TEST(QueryPlan, OptionalMatchEmptyDB) {
std::vector<Symbol>{n.sym_});
auto produce = MakeProduce(optional, n_ne);
auto results = CollectProduce(produce.get(), symbol_table, *dba);
auto results = CollectProduce(produce.get(), symbol_table, dba);
ASSERT_EQ(1, results.size());
EXPECT_EQ(results[0][0].type(), TypedValue::Type::Null);
}
TEST(QueryPlan, OptionalMatchEmptyDBExpandFromNode) {
Dbms dbms;
auto dba = dbms.active();
GraphDb db;
GraphDbAccessor dba(db);
AstTreeStorage storage;
SymbolTable symbol_table;
// OPTIONAL MATCH (n)
@ -1019,26 +1019,26 @@ TEST(QueryPlan, OptionalMatchEmptyDBExpandFromNode) {
symbol_table[*m_ne->expression_] = r_m.node_sym_;
symbol_table[*m_ne] = symbol_table.CreateSymbol("m", true);
auto produce = MakeProduce(r_m.op_, m_ne);
auto results = CollectProduce(produce.get(), symbol_table, *dba);
auto results = CollectProduce(produce.get(), symbol_table, dba);
EXPECT_EQ(0, results.size());
}
TEST(QueryPlan, OptionalMatchThenExpandToMissingNode) {
Dbms dbms;
auto dba = dbms.active();
GraphDb db;
GraphDbAccessor dba(db);
// Make a graph with 2 connected, unlabeled nodes.
auto v1 = dba->InsertVertex();
auto v2 = dba->InsertVertex();
auto edge_type = dba->EdgeType("edge_type");
dba->InsertEdge(v1, v2, edge_type);
dba->AdvanceCommand();
EXPECT_EQ(2, CountIterable(dba->Vertices(false)));
EXPECT_EQ(1, CountIterable(dba->Edges(false)));
auto v1 = dba.InsertVertex();
auto v2 = dba.InsertVertex();
auto edge_type = dba.EdgeType("edge_type");
dba.InsertEdge(v1, v2, edge_type);
dba.AdvanceCommand();
EXPECT_EQ(2, CountIterable(dba.Vertices(false)));
EXPECT_EQ(1, CountIterable(dba.Edges(false)));
AstTreeStorage storage;
SymbolTable symbol_table;
// OPTIONAL MATCH (n :missing)
auto n = MakeScanAll(storage, symbol_table, "n");
auto label_missing = dba->Label("missing");
auto label_missing = dba.Label("missing");
n.node_->labels_.emplace_back(label_missing);
auto *filter_expr =
@ -1068,22 +1068,22 @@ TEST(QueryPlan, OptionalMatchThenExpandToMissingNode) {
symbol_table[*m_ne->expression_] = m.sym_;
symbol_table[*m_ne] = symbol_table.CreateSymbol("m", true);
auto produce = MakeProduce(expand, m_ne);
auto results = CollectProduce(produce.get(), symbol_table, *dba);
auto results = CollectProduce(produce.get(), symbol_table, dba);
EXPECT_EQ(0, results.size());
}
TEST(QueryPlan, ExpandExistingNode) {
Dbms dbms;
auto dba = dbms.active();
GraphDb db;
GraphDbAccessor dba(db);
// make a graph (v1)->(v2) that
// has a recursive edge (v1)->(v1)
auto v1 = dba->InsertVertex();
auto v2 = dba->InsertVertex();
auto edge_type = dba->EdgeType("Edge");
dba->InsertEdge(v1, v1, edge_type);
dba->InsertEdge(v1, v2, edge_type);
dba->AdvanceCommand();
auto v1 = dba.InsertVertex();
auto v2 = dba.InsertVertex();
auto edge_type = dba.EdgeType("Edge");
dba.InsertEdge(v1, v1, edge_type);
dba.InsertEdge(v1, v2, edge_type);
dba.AdvanceCommand();
AstTreeStorage storage;
SymbolTable symbol_table;
@ -1093,10 +1093,9 @@ TEST(QueryPlan, ExpandExistingNode) {
auto r_n = MakeExpand(storage, symbol_table, n.op_, n.sym_, "r",
EdgeAtom::Direction::OUT, {}, "n", with_existing);
if (with_existing)
r_n.op_ =
std::make_shared<Expand>(n.sym_, r_n.edge_sym_, r_n.edge_->direction_,
std::vector<GraphDbTypes::EdgeType>{}, n.op_,
n.sym_, with_existing);
r_n.op_ = std::make_shared<Expand>(
n.sym_, r_n.edge_sym_, r_n.edge_->direction_,
std::vector<GraphDbTypes::EdgeType>{}, n.op_, n.sym_, with_existing);
// make a named expression and a produce
auto output = NEXPR("n", IDENT("n"));
@ -1105,7 +1104,7 @@ TEST(QueryPlan, ExpandExistingNode) {
symbol_table.CreateSymbol("named_expression_1", true);
auto produce = MakeProduce(r_n.op_, output);
auto results = CollectProduce(produce.get(), symbol_table, *dba);
auto results = CollectProduce(produce.get(), symbol_table, dba);
EXPECT_EQ(results.size(), expected_result_count);
};
@ -1116,12 +1115,12 @@ TEST(QueryPlan, ExpandExistingNode) {
TEST(QueryPlan, ExpandBothCycleEdgeCase) {
// we're testing that expanding on BOTH
// does only one expansion for a cycle
Dbms dbms;
auto dba = dbms.active();
GraphDb db;
GraphDbAccessor dba(db);
auto v = dba->InsertVertex();
dba->InsertEdge(v, v, dba->EdgeType("et"));
dba->AdvanceCommand();
auto v = dba.InsertVertex();
dba.InsertEdge(v, v, dba.EdgeType("et"));
dba.AdvanceCommand();
AstTreeStorage storage;
SymbolTable symbol_table;
@ -1129,12 +1128,12 @@ TEST(QueryPlan, ExpandBothCycleEdgeCase) {
auto n = MakeScanAll(storage, symbol_table, "n");
auto r_ = MakeExpand(storage, symbol_table, n.op_, n.sym_, "r",
EdgeAtom::Direction::BOTH, {}, "_", false);
EXPECT_EQ(1, PullAll(r_.op_, *dba, symbol_table));
EXPECT_EQ(1, PullAll(r_.op_, dba, symbol_table));
}
TEST(QueryPlan, EdgeFilter) {
Dbms dbms;
auto dba = dbms.active();
GraphDb db;
GraphDbAccessor dba(db);
// make an N-star expanding from (v1)
// where only one edge will qualify
@ -1142,14 +1141,14 @@ TEST(QueryPlan, EdgeFilter) {
// (edge_type yes|no) * (property yes|absent|no)
std::vector<GraphDbTypes::EdgeType> edge_types;
for (int j = 0; j < 2; ++j)
edge_types.push_back(dba->EdgeType("et" + std::to_string(j)));
edge_types.push_back(dba.EdgeType("et" + std::to_string(j)));
std::vector<VertexAccessor> vertices;
for (int i = 0; i < 7; ++i) vertices.push_back(dba->InsertVertex());
for (int i = 0; i < 7; ++i) vertices.push_back(dba.InsertVertex());
auto prop = PROPERTY_PAIR("property");
std::vector<EdgeAccessor> edges;
for (int i = 0; i < 6; ++i) {
edges.push_back(
dba->InsertEdge(vertices[0], vertices[i + 1], edge_types[i % 2]));
dba.InsertEdge(vertices[0], vertices[i + 1], edge_types[i % 2]));
switch (i % 3) {
case 0:
edges.back().PropsSet(prop.second, 42);
@ -1161,7 +1160,7 @@ TEST(QueryPlan, EdgeFilter) {
break;
}
}
dba->AdvanceCommand();
dba.AdvanceCommand();
for (auto &vertex : vertices) vertex.Reconstruct();
for (auto &edge : edges) edge.Reconstruct();
@ -1189,30 +1188,30 @@ TEST(QueryPlan, EdgeFilter) {
symbol_table.CreateSymbol("named_expression_1", true);
auto produce = MakeProduce(edge_filter, output);
return PullAll(produce, *dba, symbol_table);
return PullAll(produce, dba, symbol_table);
};
EXPECT_EQ(1, test_filter());
// test that edge filtering always filters on old state
for (auto &edge : edges) edge.PropsSet(prop.second, 42);
EXPECT_EQ(1, test_filter());
dba->AdvanceCommand();
dba.AdvanceCommand();
EXPECT_EQ(3, test_filter());
}
TEST(QueryPlan, EdgeFilterMultipleTypes) {
Dbms dbms;
auto dba = dbms.active();
GraphDb db;
GraphDbAccessor dba(db);
auto v1 = dba->InsertVertex();
auto v2 = dba->InsertVertex();
auto type_1 = dba->EdgeType("type_1");
auto type_2 = dba->EdgeType("type_2");
auto type_3 = dba->EdgeType("type_3");
dba->InsertEdge(v1, v2, type_1);
dba->InsertEdge(v1, v2, type_2);
dba->InsertEdge(v1, v2, type_3);
dba->AdvanceCommand();
auto v1 = dba.InsertVertex();
auto v2 = dba.InsertVertex();
auto type_1 = dba.EdgeType("type_1");
auto type_2 = dba.EdgeType("type_2");
auto type_3 = dba.EdgeType("type_3");
dba.InsertEdge(v1, v2, type_1);
dba.InsertEdge(v1, v2, type_2);
dba.InsertEdge(v1, v2, type_3);
dba.AdvanceCommand();
AstTreeStorage storage;
SymbolTable symbol_table;
@ -1230,20 +1229,20 @@ TEST(QueryPlan, EdgeFilterMultipleTypes) {
symbol_table[*output] = symbol_table.CreateSymbol("named_expression_1", true);
symbol_table[*output->expression_] = r_m.node_sym_;
auto results = CollectProduce(produce.get(), symbol_table, *dba);
auto results = CollectProduce(produce.get(), symbol_table, dba);
EXPECT_EQ(results.size(), 2);
}
TEST(QueryPlan, Filter) {
Dbms dbms;
auto dba = dbms.active();
GraphDb db;
GraphDbAccessor dba(db);
// add a 6 nodes with property 'prop', 2 have true as value
auto property = PROPERTY_PAIR("property");
for (int i = 0; i < 6; ++i)
dba->InsertVertex().PropsSet(property.second, i % 3 == 0);
dba->InsertVertex(); // prop not set, gives NULL
dba->AdvanceCommand();
dba.InsertVertex().PropsSet(property.second, i % 3 == 0);
dba.InsertVertex(); // prop not set, gives NULL
dba.AdvanceCommand();
AstTreeStorage storage;
SymbolTable symbol_table;
@ -1260,20 +1259,20 @@ TEST(QueryPlan, Filter) {
symbol_table[*output] = symbol_table.CreateSymbol("named_expression_1", true);
auto produce = MakeProduce(f, output);
EXPECT_EQ(CollectProduce(produce.get(), symbol_table, *dba).size(), 2);
EXPECT_EQ(CollectProduce(produce.get(), symbol_table, dba).size(), 2);
}
TEST(QueryPlan, ExpandUniquenessFilter) {
Dbms dbms;
auto dba = dbms.active();
GraphDb db;
GraphDbAccessor dba(db);
// make a graph that has (v1)->(v2) and a recursive edge (v1)->(v1)
auto v1 = dba->InsertVertex();
auto v2 = dba->InsertVertex();
auto edge_type = dba->EdgeType("edge_type");
dba->InsertEdge(v1, v2, edge_type);
dba->InsertEdge(v1, v1, edge_type);
dba->AdvanceCommand();
auto v1 = dba.InsertVertex();
auto v2 = dba.InsertVertex();
auto edge_type = dba.EdgeType("edge_type");
dba.InsertEdge(v1, v2, edge_type);
dba.InsertEdge(v1, v1, edge_type);
dba.AdvanceCommand();
auto check_expand_results = [&](bool vertex_uniqueness,
bool edge_uniqueness) {
@ -1298,7 +1297,7 @@ TEST(QueryPlan, ExpandUniquenessFilter) {
last_op, r2_n3.node_sym_,
std::vector<Symbol>{n1.sym_, r1_n2.node_sym_});
return PullAll(last_op, *dba, symbol_table);
return PullAll(last_op, dba, symbol_table);
};
EXPECT_EQ(2, check_expand_results(false, false));
@ -1310,8 +1309,8 @@ TEST(QueryPlan, Distinct) {
// test queries like
// UNWIND [1, 2, 3, 3] AS x RETURN DISTINCT x
Dbms dbms;
auto dba = dbms.active();
GraphDb db;
GraphDbAccessor dba(db);
AstTreeStorage storage;
SymbolTable symbol_table;
@ -1333,7 +1332,7 @@ TEST(QueryPlan, Distinct) {
symbol_table[*x_ne] = symbol_table.CreateSymbol("x_ne", true);
auto produce = MakeProduce(distinct, x_ne);
auto results = CollectProduce(produce.get(), symbol_table, *dba);
auto results = CollectProduce(produce.get(), symbol_table, dba);
ASSERT_EQ(output.size(), results.size());
auto output_it = output.begin();
for (const auto &row : results) {
@ -1353,15 +1352,15 @@ TEST(QueryPlan, Distinct) {
}
TEST(QueryPlan, ScanAllByLabel) {
Dbms dbms;
auto dba = dbms.active();
GraphDb db;
GraphDbAccessor dba(db);
// Add a vertex with a label and one without.
auto label = dba->Label("label");
auto labeled_vertex = dba->InsertVertex();
auto label = dba.Label("label");
auto labeled_vertex = dba.InsertVertex();
labeled_vertex.add_label(label);
dba->InsertVertex();
dba->AdvanceCommand();
EXPECT_EQ(2, CountIterable(dba->Vertices(false)));
dba.InsertVertex();
dba.AdvanceCommand();
EXPECT_EQ(2, CountIterable(dba.Vertices(false)));
// MATCH (n :label)
AstTreeStorage storage;
SymbolTable symbol_table;
@ -1372,7 +1371,7 @@ TEST(QueryPlan, ScanAllByLabel) {
auto produce = MakeProduce(scan_all_by_label.op_, output);
symbol_table[*output->expression_] = scan_all_by_label.sym_;
symbol_table[*output] = symbol_table.CreateSymbol("n", true);
auto results = CollectProduce(produce.get(), symbol_table, *dba);
auto results = CollectProduce(produce.get(), symbol_table, dba);
ASSERT_EQ(results.size(), 1);
auto result_row = results[0];
ASSERT_EQ(result_row.size(), 1);
@ -1380,12 +1379,10 @@ TEST(QueryPlan, ScanAllByLabel) {
}
TEST(QueryPlan, ScanAllByLabelProperty) {
Dbms dbms;
auto dba = dbms.active();
GraphDb db;
// Add 5 vertices with same label, but with different property values.
auto label = dba->Label("label");
auto prop = dba->Property("prop");
auto label = GraphDbAccessor(db).Label("label");
auto prop = GraphDbAccessor(db).Property("prop");
// vertex property values that will be stored into the DB
// clang-format off
std::vector<TypedValue> values{
@ -1393,18 +1390,18 @@ TEST(QueryPlan, ScanAllByLabelProperty) {
std::vector<TypedValue>{0}, std::vector<TypedValue>{1},
std::vector<TypedValue>{2}};
// clang-format on
for (const auto &value : values) {
auto vertex = dba->InsertVertex();
vertex.add_label(label);
vertex.PropsSet(prop, value);
{
GraphDbAccessor dba(db);
for (const auto &value : values) {
auto vertex = dba.InsertVertex();
vertex.add_label(label);
vertex.PropsSet(prop, value);
}
dba.Commit();
GraphDbAccessor(db).BuildIndex(label, prop);
}
dba->Commit();
dba = dbms.active();
dba->BuildIndex(label, prop);
dba->Commit();
dba = dbms.active();
ASSERT_EQ(14, CountIterable(dba->Vertices(false)));
GraphDbAccessor dba(db);
ASSERT_EQ(14, CountIterable(dba.Vertices(false)));
auto check = [&dba, label, prop](TypedValue lower, Bound::Type lower_type,
TypedValue upper, Bound::Type upper_type,
@ -1419,7 +1416,7 @@ TEST(QueryPlan, ScanAllByLabelProperty) {
auto produce = MakeProduce(scan_all.op_, output);
symbol_table[*output->expression_] = scan_all.sym_;
symbol_table[*output] = symbol_table.CreateSymbol("n", true);
auto results = CollectProduce(produce.get(), symbol_table, *dba);
auto results = CollectProduce(produce.get(), symbol_table, dba);
ASSERT_EQ(results.size(), expected.size());
for (size_t i = 0; i < expected.size(); i++) {
TypedValue equal =
@ -1452,23 +1449,24 @@ TEST(QueryPlan, ScanAllByLabelProperty) {
}
TEST(QueryPlan, ScanAllByLabelPropertyEqualityNoError) {
Dbms dbms;
auto dba = dbms.active();
GraphDb db;
// Add 2 vertices with same label, but with property values that cannot be
// compared. On the other hand, equality works fine.
auto label = dba->Label("label");
auto prop = dba->Property("prop");
auto number_vertex = dba->InsertVertex();
number_vertex.add_label(label);
number_vertex.PropsSet(prop, 42);
auto string_vertex = dba->InsertVertex();
string_vertex.add_label(label);
string_vertex.PropsSet(prop, "string");
dba->Commit();
dba = dbms.active();
dba->BuildIndex(label, prop);
dba = dbms.active();
EXPECT_EQ(2, CountIterable(dba->Vertices(false)));
auto label = GraphDbAccessor(db).Label("label");
auto prop = GraphDbAccessor(db).Property("prop");
{
GraphDbAccessor dba(db);
auto number_vertex = dba.InsertVertex();
number_vertex.add_label(label);
number_vertex.PropsSet(prop, 42);
auto string_vertex = dba.InsertVertex();
string_vertex.add_label(label);
string_vertex.PropsSet(prop, "string");
dba.Commit();
GraphDbAccessor(db).BuildIndex(label, prop);
}
GraphDbAccessor dba(db);
EXPECT_EQ(2, CountIterable(dba.Vertices(false)));
// MATCH (n :label {prop: 42})
AstTreeStorage storage;
SymbolTable symbol_table;
@ -1479,7 +1477,7 @@ TEST(QueryPlan, ScanAllByLabelPropertyEqualityNoError) {
auto produce = MakeProduce(scan_all.op_, output);
symbol_table[*output->expression_] = scan_all.sym_;
symbol_table[*output] = symbol_table.CreateSymbol("n", true);
auto results = CollectProduce(produce.get(), symbol_table, *dba);
auto results = CollectProduce(produce.get(), symbol_table, dba);
ASSERT_EQ(results.size(), 1);
const auto &row = results[0];
ASSERT_EQ(row.size(), 1);
@ -1490,24 +1488,25 @@ TEST(QueryPlan, ScanAllByLabelPropertyEqualityNoError) {
}
TEST(QueryPlan, ScanAllByLabelPropertyEqualNull) {
Dbms dbms;
auto dba = dbms.active();
GraphDb db;
// Add 2 vertices with the same label, but one has a property value while
// the
// other does not. Checking if the value is equal to null, should yield no
// results.
auto label = dba->Label("label");
auto prop = dba->Property("prop");
auto vertex = dba->InsertVertex();
vertex.add_label(label);
auto vertex_with_prop = dba->InsertVertex();
vertex_with_prop.add_label(label);
vertex_with_prop.PropsSet(prop, 42);
dba->Commit();
dba = dbms.active();
dba->BuildIndex(label, prop);
dba = dbms.active();
EXPECT_EQ(2, CountIterable(dba->Vertices(false)));
auto label = GraphDbAccessor(db).Label("label");
auto prop = GraphDbAccessor(db).Property("prop");
{
GraphDbAccessor dba(db);
auto vertex = dba.InsertVertex();
vertex.add_label(label);
auto vertex_with_prop = dba.InsertVertex();
vertex_with_prop.add_label(label);
vertex_with_prop.PropsSet(prop, 42);
dba.Commit();
GraphDbAccessor(db).BuildIndex(label, prop);
}
GraphDbAccessor dba(db);
EXPECT_EQ(2, CountIterable(dba.Vertices(false)));
// MATCH (n :label {prop: 42})
AstTreeStorage storage;
SymbolTable symbol_table;
@ -1518,7 +1517,7 @@ TEST(QueryPlan, ScanAllByLabelPropertyEqualNull) {
auto produce = MakeProduce(scan_all.op_, output);
symbol_table[*output->expression_] = scan_all.sym_;
symbol_table[*output] = symbol_table.CreateSymbol("n", true);
auto results = CollectProduce(produce.get(), symbol_table, *dba);
auto results = CollectProduce(produce.get(), symbol_table, dba);
EXPECT_EQ(results.size(), 0);
}

View File

@ -4,7 +4,6 @@
#include "gtest/gtest.h"
#include "database/dbms.hpp"
#include "query/frontend/ast/ast.hpp"
#include "query/frontend/semantic/symbol_generator.hpp"
#include "query/frontend/semantic/symbol_table.hpp"
@ -320,9 +319,9 @@ auto CheckPlan(LogicalOperator &plan, const SymbolTable &symbol_table,
template <class... TChecker>
auto CheckPlan(AstTreeStorage &storage, TChecker... checker) {
auto symbol_table = MakeSymbolTable(*storage.query());
Dbms dbms;
auto planning_context =
MakePlanningContext(storage, symbol_table, *dbms.active());
GraphDb db;
GraphDbAccessor dba(db);
auto planning_context = MakePlanningContext(storage, symbol_table, dba);
auto plan = MakeLogicalPlan<RuleBasedPlanner>(planning_context);
CheckPlan(*plan, symbol_table, checker...);
}
@ -341,9 +340,9 @@ TEST(TestLogicalPlanner, CreateNodeReturn) {
auto query = QUERY(CREATE(PATTERN(NODE("n"))), RETURN(ident_n, AS("n")));
auto symbol_table = MakeSymbolTable(*query);
auto acc = ExpectAccumulate({symbol_table.at(*ident_n)});
Dbms dbms;
auto planning_context =
MakePlanningContext(storage, symbol_table, *dbms.active());
GraphDb db;
GraphDbAccessor dba(db);
auto planning_context = MakePlanningContext(storage, symbol_table, dba);
auto plan = MakeLogicalPlan<RuleBasedPlanner>(planning_context);
CheckPlan(*plan, symbol_table, ExpectCreateNode(), acc, ExpectProduce());
}
@ -351,9 +350,9 @@ TEST(TestLogicalPlanner, CreateNodeReturn) {
TEST(TestLogicalPlanner, CreateExpand) {
// Test CREATE (n) -[r :rel1]-> (m)
AstTreeStorage storage;
Dbms dbms;
auto dba = dbms.active();
auto relationship = dba->EdgeType("relationship");
GraphDb db;
GraphDbAccessor dba(db);
auto relationship = dba.EdgeType("relationship");
QUERY(CREATE(PATTERN(NODE("n"), EDGE("r", Direction::OUT, {relationship}),
NODE("m"))));
CheckPlan(storage, ExpectCreateNode(), ExpectCreateExpand());
@ -369,9 +368,9 @@ TEST(TestLogicalPlanner, CreateMultipleNode) {
TEST(TestLogicalPlanner, CreateNodeExpandNode) {
// Test CREATE (n) -[r :rel]-> (m), (l)
AstTreeStorage storage;
Dbms dbms;
auto dba = dbms.active();
auto relationship = dba->EdgeType("rel");
GraphDb db;
GraphDbAccessor dba(db);
auto relationship = dba.EdgeType("rel");
QUERY(CREATE(
PATTERN(NODE("n"), EDGE("r", Direction::OUT, {relationship}), NODE("m")),
PATTERN(NODE("l"))));
@ -382,9 +381,9 @@ TEST(TestLogicalPlanner, CreateNodeExpandNode) {
TEST(TestLogicalPlanner, CreateNamedPattern) {
// Test CREATE p = (n) -[r :rel]-> (m)
AstTreeStorage storage;
Dbms dbms;
auto dba = dbms.active();
auto relationship = dba->EdgeType("rel");
GraphDb db;
GraphDbAccessor dba(db);
auto relationship = dba.EdgeType("rel");
QUERY(CREATE(NAMED_PATTERN(
"p", NODE("n"), EDGE("r", Direction::OUT, {relationship}), NODE("m"))));
CheckPlan(storage, ExpectCreateNode(), ExpectCreateExpand(),
@ -394,9 +393,9 @@ TEST(TestLogicalPlanner, CreateNamedPattern) {
TEST(TestLogicalPlanner, MatchCreateExpand) {
// Test MATCH (n) CREATE (n) -[r :rel1]-> (m)
AstTreeStorage storage;
Dbms dbms;
auto dba = dbms.active();
auto relationship = dba->EdgeType("relationship");
GraphDb db;
GraphDbAccessor dba(db);
auto relationship = dba.EdgeType("relationship");
QUERY(MATCH(PATTERN(NODE("n"))),
CREATE(PATTERN(NODE("n"), EDGE("r", Direction::OUT, {relationship}),
NODE("m"))));
@ -406,9 +405,9 @@ TEST(TestLogicalPlanner, MatchCreateExpand) {
TEST(TestLogicalPlanner, MatchLabeledNodes) {
// Test MATCH (n :label) RETURN n
AstTreeStorage storage;
Dbms dbms;
auto dba = dbms.active();
auto label = dba->Label("label");
GraphDb db;
GraphDbAccessor dba(db);
auto label = dba.Label("label");
QUERY(MATCH(PATTERN(NODE("n", label))), RETURN("n"));
CheckPlan(storage, ExpectScanAllByLabel(), ExpectProduce());
}
@ -416,9 +415,9 @@ TEST(TestLogicalPlanner, MatchLabeledNodes) {
TEST(TestLogicalPlanner, MatchPathReturn) {
// Test MATCH (n) -[r :relationship]- (m) RETURN n
AstTreeStorage storage;
Dbms dbms;
auto dba = dbms.active();
auto relationship = dba->EdgeType("relationship");
GraphDb db;
GraphDbAccessor dba(db);
auto relationship = dba.EdgeType("relationship");
QUERY(MATCH(PATTERN(NODE("n"), EDGE("r", Direction::BOTH, {relationship}),
NODE("m"))),
RETURN("n"));
@ -428,9 +427,9 @@ TEST(TestLogicalPlanner, MatchPathReturn) {
TEST(TestLogicalPlanner, MatchNamedPatternReturn) {
// Test MATCH p = (n) -[r :relationship]- (m) RETURN p
AstTreeStorage storage;
Dbms dbms;
auto dba = dbms.active();
auto relationship = dba->EdgeType("relationship");
GraphDb db;
GraphDbAccessor dba(db);
auto relationship = dba.EdgeType("relationship");
QUERY(MATCH(NAMED_PATTERN("p", NODE("n"),
EDGE("r", Direction::BOTH, {relationship}),
NODE("m"))),
@ -442,9 +441,9 @@ TEST(TestLogicalPlanner, MatchNamedPatternReturn) {
TEST(TestLogicalPlanner, MatchNamedPatternWithPredicateReturn) {
// Test MATCH p = (n) -[r :relationship]- (m) RETURN p
AstTreeStorage storage;
Dbms dbms;
auto dba = dbms.active();
auto relationship = dba->EdgeType("relationship");
GraphDb db;
GraphDbAccessor dba(db);
auto relationship = dba.EdgeType("relationship");
QUERY(MATCH(NAMED_PATTERN("p", NODE("n"),
EDGE("r", Direction::BOTH, {relationship}),
NODE("m"))),
@ -456,9 +455,9 @@ TEST(TestLogicalPlanner, MatchNamedPatternWithPredicateReturn) {
TEST(TestLogicalPlanner, MatchWhereReturn) {
// Test MATCH (n) WHERE n.property < 42 RETURN n
AstTreeStorage storage;
Dbms dbms;
auto dba = dbms.active();
auto property = dba->Property("property");
GraphDb db;
GraphDbAccessor dba(db);
auto property = dba.Property("property");
QUERY(MATCH(PATTERN(NODE("n"))),
WHERE(LESS(PROPERTY_LOOKUP("n", property), LITERAL(42))), RETURN("n"));
CheckPlan(storage, ExpectScanAll(), ExpectFilter(), ExpectProduce());
@ -474,10 +473,10 @@ TEST(TestLogicalPlanner, MatchDelete) {
TEST(TestLogicalPlanner, MatchNodeSet) {
// Test MATCH (n) SET n.prop = 42, n = n, n :label
AstTreeStorage storage;
Dbms dbms;
auto dba = dbms.active();
auto prop = dba->Property("prop");
auto label = dba->Label("label");
GraphDb db;
GraphDbAccessor dba(db);
auto prop = dba.Property("prop");
auto label = dba.Label("label");
QUERY(MATCH(PATTERN(NODE("n"))), SET(PROPERTY_LOOKUP("n", prop), LITERAL(42)),
SET("n", IDENT("n")), SET("n", {label}));
CheckPlan(storage, ExpectScanAll(), ExpectSetProperty(),
@ -487,10 +486,10 @@ TEST(TestLogicalPlanner, MatchNodeSet) {
TEST(TestLogicalPlanner, MatchRemove) {
// Test MATCH (n) REMOVE n.prop REMOVE n :label
AstTreeStorage storage;
Dbms dbms;
auto dba = dbms.active();
auto prop = dba->Property("prop");
auto label = dba->Label("label");
GraphDb db;
GraphDbAccessor dba(db);
auto prop = dba.Property("prop");
auto label = dba.Label("label");
QUERY(MATCH(PATTERN(NODE("n"))), REMOVE(PROPERTY_LOOKUP("n", prop)),
REMOVE("n", {label}));
CheckPlan(storage, ExpectScanAll(), ExpectRemoveProperty(),
@ -566,9 +565,9 @@ TEST(TestLogicalPlanner, MatchWithReturn) {
TEST(TestLogicalPlanner, MatchWithWhereReturn) {
// Test MATCH (old) WITH old AS new WHERE new.prop < 42 RETURN new
Dbms dbms;
auto dba = dbms.active();
auto prop = dba->Property("prop");
GraphDb db;
GraphDbAccessor dba(db);
auto prop = dba.Property("prop");
AstTreeStorage storage;
QUERY(MATCH(PATTERN(NODE("old"))), WITH("old", AS("new")),
WHERE(LESS(PROPERTY_LOOKUP("new", prop), LITERAL(42))), RETURN("new"));
@ -579,10 +578,10 @@ TEST(TestLogicalPlanner, MatchWithWhereReturn) {
TEST(TestLogicalPlanner, CreateMultiExpand) {
// Test CREATE (n) -[r :r]-> (m), (n) - [p :p]-> (l)
Dbms dbms;
auto dba = dbms.active();
auto r = dba->EdgeType("r");
auto p = dba->EdgeType("p");
GraphDb db;
GraphDbAccessor dba(db);
auto r = dba.EdgeType("r");
auto p = dba.EdgeType("p");
AstTreeStorage storage;
QUERY(CREATE(PATTERN(NODE("n"), EDGE("r", Direction::OUT, {r}), NODE("m")),
PATTERN(NODE("n"), EDGE("p", Direction::OUT, {p}), NODE("l"))));
@ -593,9 +592,9 @@ TEST(TestLogicalPlanner, CreateMultiExpand) {
TEST(TestLogicalPlanner, MatchWithSumWhereReturn) {
// Test MATCH (n) WITH SUM(n.prop) + 42 AS sum WHERE sum < 42
// RETURN sum AS result
Dbms dbms;
auto dba = dbms.active();
auto prop = dba->Property("prop");
GraphDb db;
GraphDbAccessor dba(db);
auto prop = dba.Property("prop");
AstTreeStorage storage;
auto sum = SUM(PROPERTY_LOOKUP("n", prop));
auto literal = LITERAL(42);
@ -608,10 +607,10 @@ TEST(TestLogicalPlanner, MatchWithSumWhereReturn) {
TEST(TestLogicalPlanner, MatchReturnSum) {
// Test MATCH (n) RETURN SUM(n.prop1) AS sum, n.prop2 AS group
Dbms dbms;
auto dba = dbms.active();
auto prop1 = dba->Property("prop1");
auto prop2 = dba->Property("prop2");
GraphDb db;
GraphDbAccessor dba(db);
auto prop1 = dba.Property("prop1");
auto prop2 = dba.Property("prop2");
AstTreeStorage storage;
auto sum = SUM(PROPERTY_LOOKUP("n", prop1));
auto n_prop2 = PROPERTY_LOOKUP("n", prop2);
@ -623,9 +622,9 @@ TEST(TestLogicalPlanner, MatchReturnSum) {
TEST(TestLogicalPlanner, CreateWithSum) {
// Test CREATE (n) WITH SUM(n.prop) AS sum
Dbms dbms;
auto dba = dbms.active();
auto prop = dba->Property("prop");
GraphDb db;
GraphDbAccessor dba(db);
auto prop = dba.Property("prop");
AstTreeStorage storage;
auto n_prop = PROPERTY_LOOKUP("n", prop);
auto sum = SUM(n_prop);
@ -633,7 +632,7 @@ TEST(TestLogicalPlanner, CreateWithSum) {
auto symbol_table = MakeSymbolTable(*query);
auto acc = ExpectAccumulate({symbol_table.at(*n_prop->expression_)});
auto aggr = ExpectAggregate({sum}, {});
auto planning_context = MakePlanningContext(storage, symbol_table, *dba);
auto planning_context = MakePlanningContext(storage, symbol_table, dba);
auto plan = MakeLogicalPlan<RuleBasedPlanner>(planning_context);
// We expect both the accumulation and aggregation because the part before
// WITH updates the database.
@ -643,9 +642,9 @@ TEST(TestLogicalPlanner, CreateWithSum) {
TEST(TestLogicalPlanner, MatchWithCreate) {
// Test MATCH (n) WITH n AS a CREATE (a) -[r :r]-> (b)
Dbms dbms;
auto dba = dbms.active();
auto r_type = dba->EdgeType("r");
GraphDb db;
GraphDbAccessor dba(db);
auto r_type = dba.EdgeType("r");
AstTreeStorage storage;
QUERY(MATCH(PATTERN(NODE("n"))), WITH("n", AS("a")),
CREATE(PATTERN(NODE("a"), EDGE("r", Direction::OUT, {r_type}),
@ -671,9 +670,9 @@ TEST(TestLogicalPlanner, CreateWithSkipReturnLimit) {
RETURN("m", LIMIT(LITERAL(1))));
auto symbol_table = MakeSymbolTable(*query);
auto acc = ExpectAccumulate({symbol_table.at(*ident_n)});
Dbms dbms;
auto planning_context =
MakePlanningContext(storage, symbol_table, *dbms.active());
GraphDb db;
GraphDbAccessor dba(db);
auto planning_context = MakePlanningContext(storage, symbol_table, dba);
auto plan = MakeLogicalPlan<RuleBasedPlanner>(planning_context);
// Since we have a write query, we need to have Accumulate. This is a bit
// different than Neo4j 3.0, which optimizes WITH followed by RETURN as a
@ -686,9 +685,9 @@ TEST(TestLogicalPlanner, CreateWithSkipReturnLimit) {
TEST(TestLogicalPlanner, CreateReturnSumSkipLimit) {
// Test CREATE (n) RETURN SUM(n.prop) AS s SKIP 2 LIMIT 1
Dbms dbms;
auto dba = dbms.active();
auto prop = dba->Property("prop");
GraphDb db;
GraphDbAccessor dba(db);
auto prop = dba.Property("prop");
AstTreeStorage storage;
auto n_prop = PROPERTY_LOOKUP("n", prop);
auto sum = SUM(n_prop);
@ -697,7 +696,7 @@ TEST(TestLogicalPlanner, CreateReturnSumSkipLimit) {
auto symbol_table = MakeSymbolTable(*query);
auto acc = ExpectAccumulate({symbol_table.at(*n_prop->expression_)});
auto aggr = ExpectAggregate({sum}, {});
auto planning_context = MakePlanningContext(storage, symbol_table, *dba);
auto planning_context = MakePlanningContext(storage, symbol_table, dba);
auto plan = MakeLogicalPlan<RuleBasedPlanner>(planning_context);
CheckPlan(*plan, symbol_table, ExpectCreateNode(), acc, aggr, ExpectProduce(),
ExpectSkip(), ExpectLimit());
@ -705,9 +704,9 @@ TEST(TestLogicalPlanner, CreateReturnSumSkipLimit) {
TEST(TestLogicalPlanner, MatchReturnOrderBy) {
// Test MATCH (n) RETURN n ORDER BY n.prop
Dbms dbms;
auto dba = dbms.active();
auto prop = dba->Property("prop");
GraphDb db;
GraphDbAccessor dba(db);
auto prop = dba.Property("prop");
AstTreeStorage storage;
auto ret = RETURN("n", ORDER_BY(PROPERTY_LOOKUP("n", prop)));
QUERY(MATCH(PATTERN(NODE("n"))), ret);
@ -717,10 +716,10 @@ TEST(TestLogicalPlanner, MatchReturnOrderBy) {
TEST(TestLogicalPlanner, CreateWithOrderByWhere) {
// Test CREATE (n) -[r :r]-> (m)
// WITH n AS new ORDER BY new.prop, r.prop WHERE m.prop < 42
Dbms dbms;
auto dba = dbms.active();
auto prop = dba->Property("prop");
auto r_type = dba->EdgeType("r");
GraphDb db;
GraphDbAccessor dba(db);
auto prop = dba.Property("prop");
auto r_type = dba.EdgeType("r");
AstTreeStorage storage;
auto ident_n = IDENT("n");
auto new_prop = PROPERTY_LOOKUP("new", prop);
@ -738,7 +737,7 @@ TEST(TestLogicalPlanner, CreateWithOrderByWhere) {
symbol_table.at(*r_prop->expression_), // `r` in ORDER BY
symbol_table.at(*m_prop->expression_), // `m` in WHERE
});
auto planning_context = MakePlanningContext(storage, symbol_table, *dba);
auto planning_context = MakePlanningContext(storage, symbol_table, dba);
auto plan = MakeLogicalPlan<RuleBasedPlanner>(planning_context);
CheckPlan(*plan, symbol_table, ExpectCreateNode(), ExpectCreateExpand(), acc,
ExpectProduce(), ExpectOrderBy(), ExpectFilter());
@ -758,10 +757,10 @@ TEST(TestLogicalPlanner, MatchMerge) {
// Test MATCH (n) MERGE (n) -[r :r]- (m)
// ON MATCH SET n.prop = 42 ON CREATE SET m = n
// RETURN n AS n
Dbms dbms;
auto dba = dbms.active();
auto r_type = dba->EdgeType("r");
auto prop = dba->Property("prop");
GraphDb db;
GraphDbAccessor dba(db);
auto r_type = dba.EdgeType("r");
auto prop = dba.Property("prop");
AstTreeStorage storage;
auto ident_n = IDENT("n");
auto query = QUERY(
@ -777,7 +776,7 @@ TEST(TestLogicalPlanner, MatchMerge) {
auto symbol_table = MakeSymbolTable(*query);
// We expect Accumulate after Merge, because it is considered as a write.
auto acc = ExpectAccumulate({symbol_table.at(*ident_n)});
auto planning_context = MakePlanningContext(storage, symbol_table, *dba);
auto planning_context = MakePlanningContext(storage, symbol_table, dba);
auto plan = MakeLogicalPlan<RuleBasedPlanner>(planning_context);
CheckPlan(*plan, symbol_table, ExpectScanAll(),
ExpectMerge(on_match, on_create), acc, ExpectProduce());
@ -789,9 +788,9 @@ TEST(TestLogicalPlanner, MatchMerge) {
TEST(TestLogicalPlanner, MatchOptionalMatchWhereReturn) {
// Test MATCH (n) OPTIONAL MATCH (n) -[r]- (m) WHERE m.prop < 42 RETURN r
Dbms dbms;
auto dba = dbms.active();
auto prop = dba->Property("prop");
GraphDb db;
GraphDbAccessor dba(db);
auto prop = dba.Property("prop");
AstTreeStorage storage;
QUERY(MATCH(PATTERN(NODE("n"))),
OPTIONAL_MATCH(PATTERN(NODE("n"), EDGE("r"), NODE("m"))),
@ -822,9 +821,9 @@ TEST(TestLogicalPlanner, ReturnDistinctOrderBySkipLimit) {
TEST(TestLogicalPlanner, CreateWithDistinctSumWhereReturn) {
// Test CREATE (n) WITH DISTINCT SUM(n.prop) AS s WHERE s < 42 RETURN s
Dbms dbms;
auto dba = dbms.active();
auto prop = dba->Property("prop");
GraphDb db;
GraphDbAccessor dba(db);
auto prop = dba.Property("prop");
AstTreeStorage storage;
auto node_n = NODE("n");
auto sum = SUM(PROPERTY_LOOKUP("n", prop));
@ -833,7 +832,7 @@ TEST(TestLogicalPlanner, CreateWithDistinctSumWhereReturn) {
auto symbol_table = MakeSymbolTable(*query);
auto acc = ExpectAccumulate({symbol_table.at(*node_n->identifier_)});
auto aggr = ExpectAggregate({sum}, {});
auto planning_context = MakePlanningContext(storage, symbol_table, *dba);
auto planning_context = MakePlanningContext(storage, symbol_table, dba);
auto plan = MakeLogicalPlan<RuleBasedPlanner>(planning_context);
CheckPlan(*plan, symbol_table, ExpectCreateNode(), acc, aggr, ExpectProduce(),
ExpectDistinct(), ExpectFilter(), ExpectProduce());
@ -841,8 +840,8 @@ TEST(TestLogicalPlanner, CreateWithDistinctSumWhereReturn) {
TEST(TestLogicalPlanner, MatchCrossReferenceVariable) {
// Test MATCH (n {prop: m.prop}), (m {prop: n.prop}) RETURN n
Dbms dbms;
auto dba = dbms.active();
GraphDb db;
GraphDbAccessor dba(db);
auto prop = PROPERTY_PAIR("prop");
AstTreeStorage storage;
auto node_n = NODE("n");
@ -860,9 +859,9 @@ TEST(TestLogicalPlanner, MatchCrossReferenceVariable) {
TEST(TestLogicalPlanner, MatchWhereBeforeExpand) {
// Test MATCH (n) -[r]- (m) WHERE n.prop < 42 RETURN n
Dbms dbms;
auto dba = dbms.active();
auto prop = dba->Property("prop");
GraphDb db;
GraphDbAccessor dba(db);
auto prop = dba.Property("prop");
AstTreeStorage storage;
QUERY(MATCH(PATTERN(NODE("n"), EDGE("r"), NODE("m"))),
WHERE(LESS(PROPERTY_LOOKUP("n", prop), LITERAL(42))), RETURN("n"));
@ -873,9 +872,9 @@ TEST(TestLogicalPlanner, MatchWhereBeforeExpand) {
TEST(TestLogicalPlanner, MultiMatchWhere) {
// Test MATCH (n) -[r]- (m) MATCH (l) WHERE n.prop < 42 RETURN n
Dbms dbms;
auto dba = dbms.active();
auto prop = dba->Property("prop");
GraphDb db;
GraphDbAccessor dba(db);
auto prop = dba.Property("prop");
AstTreeStorage storage;
QUERY(MATCH(PATTERN(NODE("n"), EDGE("r"), NODE("m"))),
MATCH(PATTERN(NODE("l"))),
@ -888,9 +887,9 @@ TEST(TestLogicalPlanner, MultiMatchWhere) {
TEST(TestLogicalPlanner, MatchOptionalMatchWhere) {
// Test MATCH (n) -[r]- (m) OPTIONAL MATCH (l) WHERE n.prop < 42 RETURN n
Dbms dbms;
auto dba = dbms.active();
auto prop = dba->Property("prop");
GraphDb db;
GraphDbAccessor dba(db);
auto prop = dba.Property("prop");
AstTreeStorage storage;
QUERY(MATCH(PATTERN(NODE("n"), EDGE("r"), NODE("m"))),
OPTIONAL_MATCH(PATTERN(NODE("l"))),
@ -905,15 +904,15 @@ TEST(TestLogicalPlanner, MatchOptionalMatchWhere) {
TEST(TestLogicalPlanner, MatchReturnAsterisk) {
// Test MATCH (n) -[e]- (m) RETURN *, m.prop
Dbms dbms;
auto dba = dbms.active();
auto prop = dba->Property("prop");
GraphDb db;
GraphDbAccessor dba(db);
auto prop = dba.Property("prop");
AstTreeStorage storage;
auto ret = RETURN(PROPERTY_LOOKUP("m", prop), AS("m.prop"));
ret->body_.all_identifiers = true;
auto query = QUERY(MATCH(PATTERN(NODE("n"), EDGE("e"), NODE("m"))), ret);
auto symbol_table = MakeSymbolTable(*query);
auto planning_context = MakePlanningContext(storage, symbol_table, *dba);
auto planning_context = MakePlanningContext(storage, symbol_table, dba);
auto plan = MakeLogicalPlan<RuleBasedPlanner>(planning_context);
CheckPlan(*plan, symbol_table, ExpectScanAll(), ExpectExpand(),
ExpectProduce());
@ -927,16 +926,16 @@ TEST(TestLogicalPlanner, MatchReturnAsterisk) {
TEST(TestLogicalPlanner, MatchReturnAsteriskSum) {
// Test MATCH (n) RETURN *, SUM(n.prop) AS s
Dbms dbms;
auto dba = dbms.active();
auto prop = dba->Property("prop");
GraphDb db;
GraphDbAccessor dba(db);
auto prop = dba.Property("prop");
AstTreeStorage storage;
auto sum = SUM(PROPERTY_LOOKUP("n", prop));
auto ret = RETURN(sum, AS("s"));
ret->body_.all_identifiers = true;
auto query = QUERY(MATCH(PATTERN(NODE("n"))), ret);
auto symbol_table = MakeSymbolTable(*query);
auto planning_context = MakePlanningContext(storage, symbol_table, *dba);
auto planning_context = MakePlanningContext(storage, symbol_table, dba);
auto plan = MakeLogicalPlan<RuleBasedPlanner>(planning_context);
auto *produce = dynamic_cast<Produce *>(plan.get());
ASSERT_TRUE(produce);
@ -957,8 +956,8 @@ TEST(TestLogicalPlanner, MatchReturnAsteriskSum) {
TEST(TestLogicalPlanner, UnwindMergeNodeProperty) {
// Test UNWIND [1] AS i MERGE (n {prop: i})
Dbms dbms;
auto dba = dbms.active();
GraphDb db;
GraphDbAccessor dba(db);
AstTreeStorage storage;
auto node_n = NODE("n");
node_n->properties_[PROPERTY_PAIR("prop")] = IDENT("i");
@ -1011,8 +1010,8 @@ TEST(TestLogicalPlanner, ListLiteralAggregationReturn) {
TEST(TestLogicalPlanner, MapLiteralAggregationReturn) {
// Test RETURN {sum: SUM(2)} AS result, 42 AS group_by
AstTreeStorage storage;
Dbms dbms;
auto dba = dbms.active();
GraphDb db;
GraphDbAccessor dba(db);
auto sum = SUM(LITERAL(2));
auto group_by_literal = LITERAL(42);
QUERY(RETURN(MAP({PROPERTY_PAIR("sum"), sum}), AS("result"), group_by_literal,
@ -1052,10 +1051,10 @@ TEST(TestLogicalPlanner, ListSliceAggregationReturn) {
TEST(TestLogicalPlanner, CreateIndex) {
// Test CREATE INDEX ON :Label(property)
Dbms dbms;
auto dba = dbms.active();
auto label = dba->Label("label");
auto property = dba->Property("property");
GraphDb db;
GraphDbAccessor dba(db);
auto label = dba.Label("label");
auto property = dba.Property("property");
AstTreeStorage storage;
QUERY(CREATE_INDEX_ON(label, property));
CheckPlan(storage, ExpectCreateIndex(label, property));
@ -1064,124 +1063,129 @@ TEST(TestLogicalPlanner, CreateIndex) {
TEST(TestLogicalPlanner, AtomIndexedLabelProperty) {
// Test MATCH (n :label {property: 42, not_indexed: 0}) RETURN n
AstTreeStorage storage;
Dbms dbms;
auto dba = dbms.active();
auto label = dba->Label("label");
GraphDb db;
GraphDbAccessor dba(db);
auto label = dba.Label("label");
auto property = PROPERTY_PAIR("property");
auto not_indexed = PROPERTY_PAIR("not_indexed");
auto vertex = dba->InsertVertex();
auto vertex = dba.InsertVertex();
vertex.add_label(label);
vertex.PropsSet(property.second, 42);
dba->Commit();
dba = dbms.active();
dba->BuildIndex(label, property.second);
dba = dbms.active();
auto node = NODE("n", label);
auto lit_42 = LITERAL(42);
node->properties_[property] = lit_42;
node->properties_[not_indexed] = LITERAL(0);
QUERY(MATCH(PATTERN(node)), RETURN("n"));
auto symbol_table = MakeSymbolTable(*storage.query());
auto planning_context = MakePlanningContext(storage, symbol_table, *dba);
auto plan = MakeLogicalPlan<RuleBasedPlanner>(planning_context);
CheckPlan(*plan, symbol_table,
ExpectScanAllByLabelPropertyValue(label, property, lit_42),
ExpectFilter(), ExpectProduce());
dba.Commit();
GraphDbAccessor(db).BuildIndex(label, property.second);
{
GraphDbAccessor dba(db);
auto node = NODE("n", label);
auto lit_42 = LITERAL(42);
node->properties_[property] = lit_42;
node->properties_[not_indexed] = LITERAL(0);
QUERY(MATCH(PATTERN(node)), RETURN("n"));
auto symbol_table = MakeSymbolTable(*storage.query());
auto planning_context = MakePlanningContext(storage, symbol_table, dba);
auto plan = MakeLogicalPlan<RuleBasedPlanner>(planning_context);
CheckPlan(*plan, symbol_table,
ExpectScanAllByLabelPropertyValue(label, property, lit_42),
ExpectFilter(), ExpectProduce());
}
}
TEST(TestLogicalPlanner, AtomPropertyWhereLabelIndexing) {
// Test MATCH (n {property: 42}) WHERE n.not_indexed AND n:label RETURN n
AstTreeStorage storage;
Dbms dbms;
auto dba = dbms.active();
auto label = dba->Label("label");
GraphDb db;
GraphDbAccessor dba(db);
auto label = dba.Label("label");
auto property = PROPERTY_PAIR("property");
auto not_indexed = PROPERTY_PAIR("not_indexed");
dba->BuildIndex(label, property.second);
dba = dbms.active();
auto node = NODE("n");
auto lit_42 = LITERAL(42);
node->properties_[property] = lit_42;
QUERY(MATCH(PATTERN(node)),
WHERE(AND(PROPERTY_LOOKUP("n", not_indexed),
storage.Create<query::LabelsTest>(
IDENT("n"), std::vector<GraphDbTypes::Label>{label}))),
RETURN("n"));
auto symbol_table = MakeSymbolTable(*storage.query());
auto planning_context = MakePlanningContext(storage, symbol_table, *dba);
auto plan = MakeLogicalPlan<RuleBasedPlanner>(planning_context);
CheckPlan(*plan, symbol_table,
ExpectScanAllByLabelPropertyValue(label, property, lit_42),
ExpectFilter(), ExpectProduce());
dba.BuildIndex(label, property.second);
{
GraphDbAccessor dba(db);
auto node = NODE("n");
auto lit_42 = LITERAL(42);
node->properties_[property] = lit_42;
QUERY(MATCH(PATTERN(node)),
WHERE(AND(PROPERTY_LOOKUP("n", not_indexed),
storage.Create<query::LabelsTest>(
IDENT("n"), std::vector<GraphDbTypes::Label>{label}))),
RETURN("n"));
auto symbol_table = MakeSymbolTable(*storage.query());
auto planning_context = MakePlanningContext(storage, symbol_table, dba);
auto plan = MakeLogicalPlan<RuleBasedPlanner>(planning_context);
CheckPlan(*plan, symbol_table,
ExpectScanAllByLabelPropertyValue(label, property, lit_42),
ExpectFilter(), ExpectProduce());
}
}
TEST(TestLogicalPlanner, WhereIndexedLabelProperty) {
// Test MATCH (n :label) WHERE n.property = 42 RETURN n
AstTreeStorage storage;
Dbms dbms;
auto dba = dbms.active();
auto label = dba->Label("label");
GraphDb db;
GraphDbAccessor dba(db);
auto label = dba.Label("label");
auto property = PROPERTY_PAIR("property");
dba->BuildIndex(label, property.second);
dba = dbms.active();
auto lit_42 = LITERAL(42);
QUERY(MATCH(PATTERN(NODE("n", label))),
WHERE(EQ(PROPERTY_LOOKUP("n", property), lit_42)), RETURN("n"));
auto symbol_table = MakeSymbolTable(*storage.query());
auto planning_context = MakePlanningContext(storage, symbol_table, *dba);
auto plan = MakeLogicalPlan<RuleBasedPlanner>(planning_context);
CheckPlan(*plan, symbol_table,
ExpectScanAllByLabelPropertyValue(label, property, lit_42),
ExpectProduce());
dba.BuildIndex(label, property.second);
{
GraphDbAccessor dba(db);
auto lit_42 = LITERAL(42);
QUERY(MATCH(PATTERN(NODE("n", label))),
WHERE(EQ(PROPERTY_LOOKUP("n", property), lit_42)), RETURN("n"));
auto symbol_table = MakeSymbolTable(*storage.query());
auto planning_context = MakePlanningContext(storage, symbol_table, dba);
auto plan = MakeLogicalPlan<RuleBasedPlanner>(planning_context);
CheckPlan(*plan, symbol_table,
ExpectScanAllByLabelPropertyValue(label, property, lit_42),
ExpectProduce());
}
}
TEST(TestLogicalPlanner, BestPropertyIndexed) {
// Test MATCH (n :label) WHERE n.property = 1 AND n.better = 42 RETURN n
AstTreeStorage storage;
Dbms dbms;
auto dba = dbms.active();
auto label = dba->Label("label");
auto property = dba->Property("property");
dba->BuildIndex(label, property);
dba = dbms.active();
// Add a vertex with :label+property combination, so that the best
// :label+better remains empty and thus better choice.
auto vertex = dba->InsertVertex();
vertex.add_label(label);
vertex.PropsSet(property, 1);
dba->Commit();
dba = dbms.active();
ASSERT_EQ(dba->VerticesCount(label, property), 1);
GraphDb db;
auto label = GraphDbAccessor(db).Label("label");
auto property = GraphDbAccessor(db).Property("property");
{
GraphDbAccessor(db).BuildIndex(label, property);
GraphDbAccessor dba(db);
// Add a vertex with :label+property combination, so that the best
// :label+better remains empty and thus better choice.
auto vertex = dba.InsertVertex();
vertex.add_label(label);
vertex.PropsSet(property, 1);
dba.Commit();
}
ASSERT_EQ(GraphDbAccessor(db).VerticesCount(label, property), 1);
auto better = PROPERTY_PAIR("better");
dba->BuildIndex(label, better.second);
dba = dbms.active();
ASSERT_EQ(dba->VerticesCount(label, better.second), 0);
auto lit_42 = LITERAL(42);
QUERY(MATCH(PATTERN(NODE("n", label))),
WHERE(AND(EQ(PROPERTY_LOOKUP("n", property), LITERAL(1)),
EQ(PROPERTY_LOOKUP("n", better), lit_42))),
RETURN("n"));
auto symbol_table = MakeSymbolTable(*storage.query());
auto planning_context = MakePlanningContext(storage, symbol_table, *dba);
auto plan = MakeLogicalPlan<RuleBasedPlanner>(planning_context);
CheckPlan(*plan, symbol_table,
ExpectScanAllByLabelPropertyValue(label, better, lit_42),
ExpectFilter(), ExpectProduce());
GraphDbAccessor(db).BuildIndex(label, better.second);
{
GraphDbAccessor dba(db);
ASSERT_EQ(dba.VerticesCount(label, better.second), 0);
auto lit_42 = LITERAL(42);
QUERY(MATCH(PATTERN(NODE("n", label))),
WHERE(AND(EQ(PROPERTY_LOOKUP("n", property), LITERAL(1)),
EQ(PROPERTY_LOOKUP("n", better), lit_42))),
RETURN("n"));
auto symbol_table = MakeSymbolTable(*storage.query());
auto planning_context = MakePlanningContext(storage, symbol_table, dba);
auto plan = MakeLogicalPlan<RuleBasedPlanner>(planning_context);
CheckPlan(*plan, symbol_table,
ExpectScanAllByLabelPropertyValue(label, better, lit_42),
ExpectFilter(), ExpectProduce());
}
}
TEST(TestLogicalPlanner, MultiPropertyIndexScan) {
// Test MATCH (n :label1), (m :label2) WHERE n.prop1 = 1 AND m.prop2 = 2
// RETURN n, m
Dbms dbms;
auto dba = dbms.active();
auto label1 = dba->Label("label1");
auto label2 = dba->Label("label2");
GraphDb db;
auto label1 = GraphDbAccessor(db).Label("label1");
auto label2 = GraphDbAccessor(db).Label("label2");
auto prop1 = PROPERTY_PAIR("prop1");
auto prop2 = PROPERTY_PAIR("prop2");
dba->BuildIndex(label1, prop1.second);
dba = dbms.active();
dba->BuildIndex(label2, prop2.second);
dba = dbms.active();
GraphDbAccessor(db).BuildIndex(label1, prop1.second);
GraphDbAccessor(db).BuildIndex(label2, prop2.second);
GraphDbAccessor dba(db);
AstTreeStorage storage;
auto lit_1 = LITERAL(1);
auto lit_2 = LITERAL(2);
@ -1190,7 +1194,7 @@ TEST(TestLogicalPlanner, MultiPropertyIndexScan) {
EQ(PROPERTY_LOOKUP("m", prop2), lit_2))),
RETURN("n", "m"));
auto symbol_table = MakeSymbolTable(*storage.query());
auto planning_context = MakePlanningContext(storage, symbol_table, *dba);
auto planning_context = MakePlanningContext(storage, symbol_table, dba);
auto plan = MakeLogicalPlan<RuleBasedPlanner>(planning_context);
CheckPlan(*plan, symbol_table,
ExpectScanAllByLabelPropertyValue(label1, prop1, lit_1),
@ -1201,12 +1205,11 @@ TEST(TestLogicalPlanner, MultiPropertyIndexScan) {
TEST(TestLogicalPlanner, WhereIndexedLabelPropertyRange) {
// Test MATCH (n :label) WHERE n.property REL_OP 42 RETURN n
// REL_OP is one of: `<`, `<=`, `>`, `>=`
Dbms dbms;
auto dba = dbms.active();
auto label = dba->Label("label");
auto property = dba->Property("property");
dba->BuildIndex(label, property);
dba = dbms.active();
GraphDb db;
auto label = GraphDbAccessor(db).Label("label");
auto property = GraphDbAccessor(db).Property("property");
GraphDbAccessor(db).BuildIndex(label, property);
GraphDbAccessor dba(db);
AstTreeStorage storage;
auto lit_42 = LITERAL(42);
auto n_prop = PROPERTY_LOOKUP("n", property);
@ -1217,7 +1220,7 @@ TEST(TestLogicalPlanner, WhereIndexedLabelPropertyRange) {
AstTreeStorage storage;
QUERY(MATCH(PATTERN(NODE("n", label))), WHERE(rel_expr), RETURN("n"));
auto symbol_table = MakeSymbolTable(*storage.query());
auto planning_context = MakePlanningContext(storage, symbol_table, *dba);
auto planning_context = MakePlanningContext(storage, symbol_table, dba);
auto plan = MakeLogicalPlan<RuleBasedPlanner>(planning_context);
CheckPlan(*plan, symbol_table,
ExpectScanAllByLabelPropertyRange(label, property, lower_bound,
@ -1252,24 +1255,26 @@ TEST(TestLogicalPlanner, WhereIndexedLabelPropertyRange) {
TEST(TestLogicalPlanner, UnableToUsePropertyIndex) {
// Test MATCH (n: label) WHERE n.property = n.property RETURN n
Dbms dbms;
auto dba = dbms.active();
auto label = dba->Label("label");
auto property = dba->Property("property");
dba->BuildIndex(label, property);
dba = dbms.active();
AstTreeStorage storage;
QUERY(
MATCH(PATTERN(NODE("n", label))),
WHERE(EQ(PROPERTY_LOOKUP("n", property), PROPERTY_LOOKUP("n", property))),
RETURN("n"));
auto symbol_table = MakeSymbolTable(*storage.query());
auto planning_context = MakePlanningContext(storage, symbol_table, *dba);
auto plan = MakeLogicalPlan<RuleBasedPlanner>(planning_context);
// We can only get ScanAllByLabelIndex, because we are comparing properties
// with those on the same node.
CheckPlan(*plan, symbol_table, ExpectScanAllByLabel(), ExpectFilter(),
ExpectProduce());
GraphDb db;
GraphDbAccessor dba(db);
auto label = dba.Label("label");
auto property = dba.Property("property");
dba.BuildIndex(label, property);
{
GraphDbAccessor dba(db);
AstTreeStorage storage;
QUERY(MATCH(PATTERN(NODE("n", label))),
WHERE(EQ(PROPERTY_LOOKUP("n", property),
PROPERTY_LOOKUP("n", property))),
RETURN("n"));
auto symbol_table = MakeSymbolTable(*storage.query());
auto planning_context = MakePlanningContext(storage, symbol_table, dba);
auto plan = MakeLogicalPlan<RuleBasedPlanner>(planning_context);
// We can only get ScanAllByLabelIndex, because we are comparing properties
// with those on the same node.
CheckPlan(*plan, symbol_table, ExpectScanAllByLabel(), ExpectFilter(),
ExpectProduce());
}
}
TEST(TestLogicalPlanner, ReturnSumGroupByAll) {
@ -1301,9 +1306,9 @@ TEST(TestLogicalPlanner, MatchExpandVariableNoBounds) {
TEST(TestLogicalPlanner, MatchExpandVariableInlinedFilter) {
// Test MATCH (n) -[r :type * {prop: 42}]-> (m) RETURN r
Dbms dbms;
auto dba = dbms.active();
auto type = dba->EdgeType("type");
GraphDb db;
GraphDbAccessor dba(db);
auto type = dba.EdgeType("type");
auto prop = PROPERTY_PAIR("prop");
AstTreeStorage storage;
auto edge = EDGE_VARIABLE("r", Direction::BOTH, {type});
@ -1316,9 +1321,9 @@ TEST(TestLogicalPlanner, MatchExpandVariableInlinedFilter) {
TEST(TestLogicalPlanner, MatchExpandVariableNotInlinedFilter) {
// Test MATCH (n) -[r :type * {prop: m.prop}]-> (m) RETURN r
Dbms dbms;
auto dba = dbms.active();
auto type = dba->EdgeType("type");
GraphDb db;
GraphDbAccessor dba(db);
auto type = dba.EdgeType("type");
auto prop = PROPERTY_PAIR("prop");
AstTreeStorage storage;
auto edge = EDGE_VARIABLE("r", Direction::BOTH, {type});
@ -1342,9 +1347,9 @@ TEST(TestLogicalPlanner, UnwindMatchVariable) {
TEST(TestLogicalPlanner, MatchBreadthFirst) {
// Test MATCH (n) -[r:type *..10 (r, n|n)]-> (m) RETURN r
Dbms dbms;
auto dba = dbms.active();
auto edge_type = dba->EdgeType("type");
GraphDb db;
GraphDbAccessor dba(db);
auto edge_type = dba.EdgeType("type");
AstTreeStorage storage;
auto *bfs = storage.Create<query::EdgeAtom>(
IDENT("r"), query::EdgeAtom::Type::BREADTH_FIRST, Direction::OUT,
@ -1360,14 +1365,13 @@ TEST(TestLogicalPlanner, MatchBreadthFirst) {
TEST(TestLogicalPlanner, MatchDoubleScanToExpandExisting) {
// Test MATCH (n) -[r]- (m :label) RETURN r
Dbms dbms;
auto dba = dbms.active();
auto label = dba->Label("label");
dba = dbms.active();
GraphDb db;
GraphDbAccessor dba(db);
auto label = dba.Label("label");
AstTreeStorage storage;
QUERY(MATCH(PATTERN(NODE("n"), EDGE("r"), NODE("m", label))), RETURN("r"));
auto symbol_table = MakeSymbolTable(*storage.query());
auto planning_context = MakePlanningContext(storage, symbol_table, *dba);
auto planning_context = MakePlanningContext(storage, symbol_table, dba);
auto plan = MakeLogicalPlan<RuleBasedPlanner>(planning_context);
// We expect 2x ScanAll and then Expand, since we are guessing that is
// faster (due to low label index vertex count).
@ -1377,41 +1381,42 @@ TEST(TestLogicalPlanner, MatchDoubleScanToExpandExisting) {
TEST(TestLogicalPlanner, MatchScanToExpand) {
// Test MATCH (n) -[r]- (m :label {property: 1}) RETURN r
Dbms dbms;
auto dba = dbms.active();
auto label = dba->Label("label");
auto property = dba->Property("property");
dba->BuildIndex(label, property);
dba = dbms.active();
GraphDb db;
auto label = GraphDbAccessor(db).Label("label");
auto property = GraphDbAccessor(db).Property("property");
GraphDbAccessor(db).BuildIndex(label, property);
GraphDbAccessor dba(db);
// Fill vertices to the max.
for (int64_t i = 0; i < FLAGS_query_vertex_count_to_expand_existing; ++i) {
auto vertex = dba->InsertVertex();
auto vertex = dba.InsertVertex();
vertex.PropsSet(property, 1);
vertex.add_label(label);
}
// Add one more above the max.
auto vertex = dba->InsertVertex();
auto vertex = dba.InsertVertex();
vertex.add_label(label);
vertex.PropsSet(property, 1);
dba->Commit();
dba = dbms.active();
AstTreeStorage storage;
auto node_m = NODE("m", label);
node_m->properties_[std::make_pair("property", property)] = LITERAL(1);
QUERY(MATCH(PATTERN(NODE("n"), EDGE("r"), node_m)), RETURN("r"));
auto symbol_table = MakeSymbolTable(*storage.query());
auto planning_context = MakePlanningContext(storage, symbol_table, *dba);
auto plan = MakeLogicalPlan<RuleBasedPlanner>(planning_context);
// We expect 1x ScanAllByLabel and then Expand, since we are guessing that is
// faster (due to high label index vertex count).
CheckPlan(*plan, symbol_table, ExpectScanAll(), ExpectExpand(),
ExpectFilter(), ExpectProduce());
dba.Commit();
{
GraphDbAccessor dba(db);
AstTreeStorage storage;
auto node_m = NODE("m", label);
node_m->properties_[std::make_pair("property", property)] = LITERAL(1);
QUERY(MATCH(PATTERN(NODE("n"), EDGE("r"), node_m)), RETURN("r"));
auto symbol_table = MakeSymbolTable(*storage.query());
auto planning_context = MakePlanningContext(storage, symbol_table, dba);
auto plan = MakeLogicalPlan<RuleBasedPlanner>(planning_context);
// We expect 1x ScanAllByLabel and then Expand, since we are guessing that
// is faster (due to high label index vertex count).
CheckPlan(*plan, symbol_table, ExpectScanAll(), ExpectExpand(),
ExpectFilter(), ExpectProduce());
}
}
TEST(TestLogicalPlanner, MatchWhereAndSplit) {
// Test MATCH (n) -[r]- (m) WHERE n.prop AND r.prop RETURN m
Dbms dbms;
auto dba = dbms.active();
GraphDb db;
GraphDbAccessor dba(db);
auto prop = PROPERTY_PAIR("prop");
AstTreeStorage storage;
QUERY(MATCH(PATTERN(NODE("n"), EDGE("r"), NODE("m"))),

View File

@ -2,7 +2,6 @@
#include "gtest/gtest.h"
#include "database/dbms.hpp"
#include "query/frontend/ast/ast.hpp"
#include "query/frontend/semantic/symbol_generator.hpp"
#include "query/frontend/semantic/symbol_table.hpp"
@ -85,8 +84,8 @@ TEST(TestSymbolGenerator, CreatePropertyUnbound) {
AstTreeStorage storage;
// AST with unbound variable in create: CREATE ({prop: x})
auto node = NODE("anon");
Dbms dbms;
auto dba = dbms.active();
GraphDb db;
GraphDbAccessor dba(db);
node->properties_[PROPERTY_PAIR("prop")] = IDENT("x");
auto query_ast = QUERY(CREATE(PATTERN(node)));
SymbolGenerator symbol_generator(symbol_table);
@ -151,9 +150,9 @@ TEST(TestSymbolGenerator, MatchCreateRedeclareEdge) {
AstTreeStorage storage;
// AST with redeclaring a match edge variable in create:
// MATCH (n) -[r]- (m) CREATE (n) -[r :relationship]-> (l)
Dbms dbms;
auto dba = dbms.active();
auto relationship = dba->EdgeType("relationship");
GraphDb db;
GraphDbAccessor dba(db);
auto relationship = dba.EdgeType("relationship");
auto query =
QUERY(MATCH(PATTERN(NODE("n"), EDGE("r"), NODE("m"))),
CREATE(PATTERN(NODE("n"),
@ -190,10 +189,10 @@ TEST(TestSymbolGenerator, CreateMultipleEdgeType) {
AstTreeStorage storage;
// Multiple edge relationship are not allowed when creating edges.
// CREATE (n) -[r :rel1 | :rel2]-> (m)
Dbms dbms;
auto dba = dbms.active();
auto rel1 = dba->EdgeType("rel1");
auto rel2 = dba->EdgeType("rel2");
GraphDb db;
GraphDbAccessor dba(db);
auto rel1 = dba.EdgeType("rel1");
auto rel2 = dba.EdgeType("rel2");
auto edge = EDGE("r", EdgeAtom::Direction::OUT, {rel1});
edge->edge_types_.emplace_back(rel2);
auto query = QUERY(CREATE(PATTERN(NODE("n"), edge, NODE("m"))));
@ -206,9 +205,9 @@ TEST(TestSymbolGenerator, CreateBidirectionalEdge) {
AstTreeStorage storage;
// Bidirectional relationships are not allowed when creating edges.
// CREATE (n) -[r :rel1]- (m)
Dbms dbms;
auto dba = dbms.active();
auto rel1 = dba->EdgeType("rel1");
GraphDb db;
GraphDbAccessor dba(db);
auto rel1 = dba.EdgeType("rel1");
auto query = QUERY(CREATE(PATTERN(
NODE("n"), EDGE("r", EdgeAtom::Direction::BOTH, {rel1}), NODE("m"))));
SymbolTable symbol_table;
@ -290,9 +289,9 @@ TEST(TestSymbolGenerator, MatchWithReturnUnbound) {
TEST(TestSymbolGenerator, MatchWithWhere) {
// Test MATCH (old) WITH old AS n WHERE n.prop < 42
Dbms dbms;
auto dba = dbms.active();
auto prop = dba->Property("prop");
GraphDb db;
GraphDbAccessor dba(db);
auto prop = dba.Property("prop");
AstTreeStorage storage;
auto node = NODE("old");
auto old_ident = IDENT("old");
@ -316,9 +315,9 @@ TEST(TestSymbolGenerator, MatchWithWhere) {
TEST(TestSymbolGenerator, MatchWithWhereUnbound) {
// Test MATCH (old) WITH COUNT(old) AS c WHERE old.prop < 42
Dbms dbms;
auto dba = dbms.active();
auto prop = dba->Property("prop");
GraphDb db;
GraphDbAccessor dba(db);
auto prop = dba.Property("prop");
AstTreeStorage storage;
auto query =
QUERY(MATCH(PATTERN(NODE("old"))), WITH(COUNT(IDENT("old")), AS("c")),
@ -330,10 +329,10 @@ TEST(TestSymbolGenerator, MatchWithWhereUnbound) {
TEST(TestSymbolGenerator, CreateMultiExpand) {
// Test CREATE (n) -[r :r]-> (m), (n) - [p :p]-> (l)
Dbms dbms;
auto dba = dbms.active();
auto r_type = dba->EdgeType("r");
auto p_type = dba->EdgeType("p");
GraphDb db;
GraphDbAccessor dba(db);
auto r_type = dba.EdgeType("r");
auto p_type = dba.EdgeType("p");
AstTreeStorage storage;
auto node_n1 = NODE("n");
auto edge_r = EDGE("r", EdgeAtom::Direction::OUT, {r_type});
@ -368,10 +367,10 @@ TEST(TestSymbolGenerator, CreateMultiExpand) {
TEST(TestSymbolGenerator, MatchCreateExpandLabel) {
// Test MATCH (n) CREATE (m) -[r :r]-> (n:label)
Dbms dbms;
auto dba = dbms.active();
auto r_type = dba->EdgeType("r");
auto label = dba->Label("label");
GraphDb db;
GraphDbAccessor dba(db);
auto r_type = dba.EdgeType("r");
auto label = dba.Label("label");
AstTreeStorage storage;
auto query = QUERY(
MATCH(PATTERN(NODE("n"))),
@ -384,9 +383,9 @@ TEST(TestSymbolGenerator, MatchCreateExpandLabel) {
TEST(TestSymbolGenerator, CreateExpandProperty) {
// Test CREATE (n) -[r :r]-> (n {prop: 42})
Dbms dbms;
auto dba = dbms.active();
auto r_type = dba->EdgeType("r");
GraphDb db;
GraphDbAccessor dba(db);
auto r_type = dba.EdgeType("r");
AstTreeStorage storage;
auto n_prop = NODE("n");
n_prop->properties_[PROPERTY_PAIR("prop")] = LITERAL(42);
@ -399,9 +398,9 @@ TEST(TestSymbolGenerator, CreateExpandProperty) {
TEST(TestSymbolGenerator, MatchReturnSum) {
// Test MATCH (n) RETURN SUM(n.prop) + 42 AS result
Dbms dbms;
auto dba = dbms.active();
auto prop = dba->Property("prop");
GraphDb db;
GraphDbAccessor dba(db);
auto prop = dba.Property("prop");
AstTreeStorage storage;
auto node = NODE("n");
auto sum = SUM(PROPERTY_LOOKUP("n", prop));
@ -423,9 +422,9 @@ TEST(TestSymbolGenerator, MatchReturnSum) {
TEST(TestSymbolGenerator, NestedAggregation) {
// Test MATCH (n) RETURN SUM(42 + SUM(n.prop)) AS s
Dbms dbms;
auto dba = dbms.active();
auto prop = dba->Property("prop");
GraphDb db;
GraphDbAccessor dba(db);
auto prop = dba.Property("prop");
AstTreeStorage storage;
auto query = QUERY(
MATCH(PATTERN(NODE("n"))),
@ -437,9 +436,9 @@ TEST(TestSymbolGenerator, NestedAggregation) {
TEST(TestSymbolGenerator, WrongAggregationContext) {
// Test MATCH (n) WITH n.prop AS prop WHERE SUM(prop) < 42
Dbms dbms;
auto dba = dbms.active();
auto prop = dba->Property("prop");
GraphDb db;
GraphDbAccessor dba(db);
auto prop = dba.Property("prop");
AstTreeStorage storage;
auto query = QUERY(MATCH(PATTERN(NODE("n"))),
WITH(PROPERTY_LOOKUP("n", prop), AS("prop")),
@ -451,8 +450,8 @@ TEST(TestSymbolGenerator, WrongAggregationContext) {
TEST(TestSymbolGenerator, MatchPropCreateNodeProp) {
// Test MATCH (n) CREATE (m {prop: n.prop})
Dbms dbms;
auto dba = dbms.active();
GraphDb db;
GraphDbAccessor dba(db);
auto prop = PROPERTY_PAIR("prop");
AstTreeStorage storage;
auto node_n = NODE("n");
@ -473,9 +472,9 @@ TEST(TestSymbolGenerator, MatchPropCreateNodeProp) {
TEST(TestSymbolGenerator, CreateNodeEdge) {
// Test CREATE (n), (n) -[r :r]-> (n)
Dbms dbms;
auto dba = dbms.active();
auto r_type = dba->EdgeType("r");
GraphDb db;
GraphDbAccessor dba(db);
auto r_type = dba.EdgeType("r");
AstTreeStorage storage;
auto node_1 = NODE("n");
auto node_2 = NODE("n");
@ -495,9 +494,9 @@ TEST(TestSymbolGenerator, CreateNodeEdge) {
TEST(TestSymbolGenerator, MatchWithCreate) {
// Test MATCH (n) WITH n AS m CREATE (m) -[r :r]-> (m)
Dbms dbms;
auto dba = dbms.active();
auto r_type = dba->EdgeType("r");
GraphDb db;
GraphDbAccessor dba(db);
auto r_type = dba.EdgeType("r");
AstTreeStorage storage;
auto node_1 = NODE("n");
auto node_2 = NODE("m");
@ -643,9 +642,9 @@ TEST(TestSymbolGenerator, MergeVariableError) {
}
// Test MATCH (n) -[r]- (m) MERGE (a) -[r :rel]- (b)
{
Dbms dbms;
auto dba = dbms.active();
auto rel = dba->EdgeType("rel");
GraphDb db;
GraphDbAccessor dba(db);
auto rel = dba.EdgeType("rel");
AstTreeStorage storage;
auto query = QUERY(
MATCH(PATTERN(NODE("n"), EDGE("r"), NODE("m"))),
@ -670,10 +669,10 @@ TEST(TestSymbolGenerator, MergeEdgeWithoutType) {
TEST(TestSymbolGenerator, MergeOnMatchOnCreate) {
// Test MATCH (n) MERGE (n) -[r :rel]- (m) ON MATCH SET n.prop = 42
// ON CREATE SET m.prop = 42 RETURN r AS r
Dbms dbms;
auto dba = dbms.active();
auto rel = dba->EdgeType("rel");
auto prop = dba->Property("prop");
GraphDb db;
GraphDbAccessor dba(db);
auto rel = dba.EdgeType("rel");
auto prop = dba.Property("prop");
AstTreeStorage storage;
auto match_n = NODE("n");
auto merge_n = NODE("n");
@ -745,8 +744,8 @@ TEST(TestSymbolGenerator, WithUnwindReturn) {
TEST(TestSymbolGenerator, MatchCrossReferenceVariable) {
// MATCH (n {prop: m.prop}), (m {prop: n.prop}) RETURN n
Dbms dbms;
auto dba = dbms.active();
GraphDb db;
GraphDbAccessor dba(db);
auto prop = PROPERTY_PAIR("prop");
AstTreeStorage storage;
auto node_n = NODE("n");
@ -776,9 +775,9 @@ TEST(TestSymbolGenerator, MatchCrossReferenceVariable) {
TEST(TestSymbolGenerator, MatchWithAsteriskReturnAsterisk) {
// MATCH (n) -[e]- (m) WITH * RETURN *, n.prop
Dbms dbms;
auto dba = dbms.active();
auto prop = dba->Property("prop");
GraphDb db;
GraphDbAccessor dba(db);
auto prop = dba.Property("prop");
AstTreeStorage storage;
auto n_prop = PROPERTY_LOOKUP("n", prop);
auto ret = RETURN(n_prop, AS("n.prop"));
@ -824,10 +823,10 @@ TEST(TestSymbolGenerator, MatchReturnAsteriskNoUserVariables) {
TEST(TestSymbolGenerator, MatchMergeExpandLabel) {
// Test MATCH (n) MERGE (m) -[r :r]-> (n:label)
Dbms dbms;
auto dba = dbms.active();
auto r_type = dba->EdgeType("r");
auto label = dba->Label("label");
GraphDb db;
GraphDbAccessor dba(db);
auto r_type = dba.EdgeType("r");
auto label = dba.Label("label");
AstTreeStorage storage;
auto query = QUERY(
MATCH(PATTERN(NODE("n"))),
@ -840,8 +839,8 @@ TEST(TestSymbolGenerator, MatchMergeExpandLabel) {
TEST(TestSymbolGenerator, MatchEdgeWithIdentifierInProperty) {
// Test MATCH (n) -[r {prop: n.prop}]- (m) RETURN r
Dbms dbms;
auto dba = dbms.active();
GraphDb db;
GraphDbAccessor dba(db);
auto prop = PROPERTY_PAIR("prop");
AstTreeStorage storage;
auto edge = EDGE("r");
@ -860,9 +859,9 @@ TEST(TestSymbolGenerator, MatchEdgeWithIdentifierInProperty) {
TEST(TestSymbolGenerator, MatchVariablePathUsingIdentifier) {
// Test MATCH (n) -[r *..l.prop]- (m), (l) RETURN r
Dbms dbms;
auto dba = dbms.active();
auto prop = dba->Property("prop");
GraphDb db;
GraphDbAccessor dba(db);
auto prop = dba.Property("prop");
AstTreeStorage storage;
auto edge = EDGE_VARIABLE("r");
auto l_prop = PROPERTY_LOOKUP("l", prop);
@ -884,9 +883,9 @@ TEST(TestSymbolGenerator, MatchVariablePathUsingIdentifier) {
TEST(TestSymbolGenerator, MatchVariablePathUsingUnboundIdentifier) {
// Test MATCH (n) -[r *..l.prop]- (m) MATCH (l) RETURN r
Dbms dbms;
auto dba = dbms.active();
auto prop = dba->Property("prop");
GraphDb db;
GraphDbAccessor dba(db);
auto prop = dba.Property("prop");
AstTreeStorage storage;
auto edge = EDGE_VARIABLE("r");
auto l_prop = PROPERTY_LOOKUP("l", prop);
@ -938,9 +937,9 @@ TEST(TestSymbolGenerator, VariablePathSameIdentifier) {
// Test MATCH (n) -[r *r.prop..]-> (m) RETURN r raises UnboundVariableError.
// `r` cannot be used inside the range expression, since it is bound by the
// variable expansion itself.
Dbms dbms;
auto dba = dbms.active();
auto prop = dba->Property("prop");
GraphDb db;
GraphDbAccessor dba(db);
auto prop = dba.Property("prop");
AstTreeStorage storage;
auto edge = EDGE_VARIABLE("r", EdgeAtom::Direction::OUT);
edge->lower_bound_ = PROPERTY_LOOKUP("r", prop);
@ -954,8 +953,8 @@ TEST(TestSymbolGenerator, MatchPropertySameIdentifier) {
// Test MATCH (n {prop: n.prop}) RETURN n
// Using `n.prop` needs to work, because filters are run after the value for
// matched symbol is obtained.
Dbms dbms;
auto dba = dbms.active();
GraphDb db;
GraphDbAccessor dba(db);
auto prop = PROPERTY_PAIR("prop");
AstTreeStorage storage;
auto node_n = NODE("n");
@ -997,9 +996,9 @@ TEST(TestSymbolGenerator, WithReturnAll) {
TEST(TestSymbolGenerator, MatchBfsReturn) {
// Test MATCH (n) -[r *bfs..n.prop] (r, n | r.prop)]-> (m) RETURN r AS r
Dbms dbms;
auto dba = dbms.active();
auto prop = dba->Property("prop");
GraphDb db;
GraphDbAccessor dba(db);
auto prop = dba.Property("prop");
AstTreeStorage storage;
auto *node_n = NODE("n");
auto *r_prop = PROPERTY_LOOKUP("r", prop);

View File

@ -2,7 +2,6 @@
#include "gtest/gtest.h"
#include "database/dbms.hpp"
#include "query/frontend/semantic/symbol_generator.hpp"
#include "query/frontend/semantic/symbol_table.hpp"
#include "query/plan/planner.hpp"
@ -79,34 +78,34 @@ void CheckPlansProduce(
}
TEST(TestVariableStartPlanner, MatchReturn) {
Dbms dbms;
auto dba = dbms.active();
GraphDb db;
GraphDbAccessor dba(db);
// Make a graph (v1) -[:r]-> (v2)
auto v1 = dba->InsertVertex();
auto v2 = dba->InsertVertex();
dba->InsertEdge(v1, v2, dba->EdgeType("r"));
dba->AdvanceCommand();
auto v1 = dba.InsertVertex();
auto v2 = dba.InsertVertex();
dba.InsertEdge(v1, v2, dba.EdgeType("r"));
dba.AdvanceCommand();
// Test MATCH (n) -[r]-> (m) RETURN n
AstTreeStorage storage;
QUERY(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.
CheckPlansProduce(2, storage, *dba, [&](const auto &results) {
CheckPlansProduce(2, storage, dba, [&](const auto &results) {
// We expect to produce only a single (v1) node.
AssertRows(results, {{v1}});
});
}
TEST(TestVariableStartPlanner, MatchTripletPatternReturn) {
Dbms dbms;
auto dba = dbms.active();
GraphDb db;
GraphDbAccessor dba(db);
// 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"));
dba->AdvanceCommand();
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"));
dba.AdvanceCommand();
{
// Test `MATCH (n) -[r]-> (m) -[e]-> (l) RETURN n`
AstTreeStorage storage;
@ -114,7 +113,7 @@ TEST(TestVariableStartPlanner, MatchTripletPatternReturn) {
EDGE("e", Direction::OUT), NODE("l"))),
RETURN("n"));
// We have 3 nodes: `n`, `m` and `l` from which we could start.
CheckPlansProduce(3, storage, *dba, [&](const auto &results) {
CheckPlansProduce(3, storage, dba, [&](const auto &results) {
// We expect to produce only a single (v1) node.
AssertRows(results, {{v1}});
});
@ -125,22 +124,22 @@ TEST(TestVariableStartPlanner, MatchTripletPatternReturn) {
QUERY(MATCH(PATTERN(NODE("n"), EDGE("r", Direction::OUT), NODE("m")),
PATTERN(NODE("m"), EDGE("e", Direction::OUT), NODE("l"))),
RETURN("n"));
CheckPlansProduce(3, storage, *dba, [&](const auto &results) {
CheckPlansProduce(3, storage, dba, [&](const auto &results) {
AssertRows(results, {{v1}});
});
}
}
TEST(TestVariableStartPlanner, MatchOptionalMatchReturn) {
Dbms dbms;
auto dba = dbms.active();
GraphDb db;
GraphDbAccessor dba(db);
// 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"));
dba->AdvanceCommand();
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"));
dba.AdvanceCommand();
// Test MATCH (n) -[r]-> (m) OPTIONAL MATCH (m) -[e]-> (l) RETURN n, l
AstTreeStorage storage;
QUERY(
@ -149,7 +148,7 @@ 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.
CheckPlansProduce(4, storage, *dba, [&](const auto &results) {
CheckPlansProduce(4, storage, dba, [&](const auto &results) {
// We expect to produce 2 rows:
// * (v1), (v3)
// * (v2), null
@ -158,14 +157,14 @@ TEST(TestVariableStartPlanner, MatchOptionalMatchReturn) {
}
TEST(TestVariableStartPlanner, MatchOptionalMatchMergeReturn) {
Dbms dbms;
auto dba = dbms.active();
GraphDb db;
GraphDbAccessor dba(db);
// Graph (v1) -[:r]-> (v2)
auto v1 = dba->InsertVertex();
auto v2 = dba->InsertVertex();
auto r_type = dba->EdgeType("r");
dba->InsertEdge(v1, v2, r_type);
dba->AdvanceCommand();
auto v1 = dba.InsertVertex();
auto v2 = dba.InsertVertex();
auto r_type = dba.EdgeType("r");
dba.InsertEdge(v1, v2, r_type);
dba.AdvanceCommand();
// Test MATCH (n) -[r]-> (m) OPTIONAL MATCH (m) -[e]-> (l)
// MERGE (u) -[q:r]-> (v) RETURN n, m, l, u, v
AstTreeStorage storage;
@ -176,20 +175,20 @@ 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.
CheckPlansProduce(8, storage, *dba, [&](const auto &results) {
CheckPlansProduce(8, storage, dba, [&](const auto &results) {
// We expect to produce a single row: (v1), (v2), null, (v1), (v2)
AssertRows(results, {{v1, v2, TypedValue::Null, v1, v2}});
});
}
TEST(TestVariableStartPlanner, MatchWithMatchReturn) {
Dbms dbms;
auto dba = dbms.active();
GraphDb db;
GraphDbAccessor dba(db);
// Graph (v1) -[:r]-> (v2)
auto v1 = dba->InsertVertex();
auto v2 = dba->InsertVertex();
dba->InsertEdge(v1, v2, dba->EdgeType("r"));
dba->AdvanceCommand();
auto v1 = dba.InsertVertex();
auto v2 = dba.InsertVertex();
dba.InsertEdge(v1, v2, dba.EdgeType("r"));
dba.AdvanceCommand();
// Test MATCH (n) -[r]-> (m) WITH n MATCH (m) -[r]-> (l) RETURN n, m, l
AstTreeStorage storage;
QUERY(MATCH(PATTERN(NODE("n"), EDGE("r", Direction::OUT), NODE("m"))),
@ -198,22 +197,22 @@ 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.
CheckPlansProduce(4, storage, *dba, [&](const auto &results) {
CheckPlansProduce(4, storage, dba, [&](const auto &results) {
// We expect to produce a single row: (v1), (v1), (v2)
AssertRows(results, {{v1, v1, v2}});
});
}
TEST(TestVariableStartPlanner, MatchVariableExpand) {
Dbms dbms;
auto dba = dbms.active();
GraphDb db;
GraphDbAccessor dba(db);
// Graph (v1) -[:r1]-> (v2) -[:r2]-> (v3)
auto v1 = dba->InsertVertex();
auto v2 = dba->InsertVertex();
auto v3 = dba->InsertVertex();
auto r1 = dba->InsertEdge(v1, v2, dba->EdgeType("r1"));
auto r2 = dba->InsertEdge(v2, v3, dba->EdgeType("r2"));
dba->AdvanceCommand();
auto v1 = dba.InsertVertex();
auto v2 = dba.InsertVertex();
auto v3 = dba.InsertVertex();
auto r1 = dba.InsertEdge(v1, v2, dba.EdgeType("r1"));
auto r2 = dba.InsertEdge(v2, v3, dba.EdgeType("r2"));
dba.AdvanceCommand();
// Test MATCH (n) -[r*]-> (m) RETURN r
AstTreeStorage storage;
auto edge = EDGE_VARIABLE("r", Direction::OUT);
@ -222,25 +221,25 @@ TEST(TestVariableStartPlanner, MatchVariableExpand) {
TypedValue r1_list(std::vector<TypedValue>{r1}); // [r1]
TypedValue r2_list(std::vector<TypedValue>{r2}); // [r2]
TypedValue r1_r2_list(std::vector<TypedValue>{r1, r2}); // [r1, r2]
CheckPlansProduce(2, storage, *dba, [&](const auto &results) {
CheckPlansProduce(2, storage, dba, [&](const auto &results) {
AssertRows(results, {{r1_list}, {r2_list}, {r1_r2_list}});
});
}
TEST(TestVariableStartPlanner, MatchVariableExpandReferenceNode) {
Dbms dbms;
auto dba = dbms.active();
auto id = dba->Property("id");
GraphDb db;
GraphDbAccessor dba(db);
auto id = dba.Property("id");
// Graph (v1 {id:1}) -[:r1]-> (v2 {id: 2}) -[:r2]-> (v3 {id: 3})
auto v1 = dba->InsertVertex();
auto v1 = dba.InsertVertex();
v1.PropsSet(id, 1);
auto v2 = dba->InsertVertex();
auto v2 = dba.InsertVertex();
v2.PropsSet(id, 2);
auto v3 = dba->InsertVertex();
auto v3 = dba.InsertVertex();
v3.PropsSet(id, 3);
auto r1 = dba->InsertEdge(v1, v2, dba->EdgeType("r1"));
auto r2 = dba->InsertEdge(v2, v3, dba->EdgeType("r2"));
dba->AdvanceCommand();
auto r1 = dba.InsertEdge(v1, v2, dba.EdgeType("r1"));
auto r2 = dba.InsertEdge(v2, v3, dba.EdgeType("r2"));
dba.AdvanceCommand();
// Test MATCH (n) -[r*..n.id]-> (m) RETURN r
AstTreeStorage storage;
auto edge = EDGE_VARIABLE("r", Direction::OUT);
@ -249,23 +248,23 @@ TEST(TestVariableStartPlanner, MatchVariableExpandReferenceNode) {
// We expect to get a single column with the following rows:
TypedValue r1_list(std::vector<TypedValue>{r1}); // [r1] (v1 -[*..1]-> v2)
TypedValue r2_list(std::vector<TypedValue>{r2}); // [r2] (v2 -[*..2]-> v3)
CheckPlansProduce(2, storage, *dba, [&](const auto &results) {
CheckPlansProduce(2, storage, dba, [&](const auto &results) {
AssertRows(results, {{r1_list}, {r2_list}});
});
}
TEST(TestVariableStartPlanner, MatchVariableExpandBoth) {
Dbms dbms;
auto dba = dbms.active();
auto id = dba->Property("id");
GraphDb db;
GraphDbAccessor dba(db);
auto id = dba.Property("id");
// Graph (v1 {id:1}) -[:r1]-> (v2) -[:r2]-> (v3)
auto v1 = dba->InsertVertex();
auto v1 = dba.InsertVertex();
v1.PropsSet(id, 1);
auto v2 = dba->InsertVertex();
auto v3 = dba->InsertVertex();
auto r1 = dba->InsertEdge(v1, v2, dba->EdgeType("r1"));
auto r2 = dba->InsertEdge(v2, v3, dba->EdgeType("r2"));
dba->AdvanceCommand();
auto v2 = dba.InsertVertex();
auto v3 = dba.InsertVertex();
auto r1 = dba.InsertEdge(v1, v2, dba.EdgeType("r1"));
auto r2 = dba.InsertEdge(v2, v3, dba.EdgeType("r2"));
dba.AdvanceCommand();
// Test MATCH (n {id:1}) -[r*]- (m) RETURN r
AstTreeStorage storage;
auto edge = EDGE_VARIABLE("r", Direction::BOTH);
@ -275,25 +274,25 @@ TEST(TestVariableStartPlanner, MatchVariableExpandBoth) {
// We expect to get a single column with the following rows:
TypedValue r1_list(std::vector<TypedValue>{r1}); // [r1]
TypedValue r1_r2_list(std::vector<TypedValue>{r1, r2}); // [r1, r2]
CheckPlansProduce(2, storage, *dba, [&](const auto &results) {
CheckPlansProduce(2, storage, dba, [&](const auto &results) {
AssertRows(results, {{r1_list}, {r1_r2_list}});
});
}
TEST(TestVariableStartPlanner, MatchBfs) {
Dbms dbms;
auto dba = dbms.active();
auto id = dba->Property("id");
GraphDb db;
GraphDbAccessor dba(db);
auto id = dba.Property("id");
// Graph (v1 {id:1}) -[:r1]-> (v2 {id: 2}) -[:r2]-> (v3 {id: 3})
auto v1 = dba->InsertVertex();
auto v1 = dba.InsertVertex();
v1.PropsSet(id, 1);
auto v2 = dba->InsertVertex();
auto v2 = dba.InsertVertex();
v2.PropsSet(id, 2);
auto v3 = dba->InsertVertex();
auto v3 = dba.InsertVertex();
v3.PropsSet(id, 3);
auto r1 = dba->InsertEdge(v1, v2, dba->EdgeType("r1"));
dba->InsertEdge(v2, v3, dba->EdgeType("r2"));
dba->AdvanceCommand();
auto r1 = dba.InsertEdge(v1, v2, dba.EdgeType("r1"));
dba.InsertEdge(v2, v3, dba.EdgeType("r2"));
dba.AdvanceCommand();
// Test MATCH (n) -[r *bfs..10](r, n | n.id <> 3)]-> (m) RETURN r
AstTreeStorage storage;
auto *bfs = storage.Create<query::EdgeAtom>(
@ -306,7 +305,7 @@ TEST(TestVariableStartPlanner, MatchBfs) {
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>{r1}); // [r1]
CheckPlansProduce(2, storage, *dba, [&](const auto &results) {
CheckPlansProduce(2, storage, dba, [&](const auto &results) {
AssertRows(results, {{r1_list}});
});
}

View File

@ -3,7 +3,6 @@
#include "gtest/gtest.h"
#include "database/dbms.hpp"
#include "database/graph_db.hpp"
#include "database/graph_db_accessor.hpp"
@ -12,14 +11,14 @@
#include "storage/vertex_accessor.hpp"
TEST(RecordAccessor, Properties) {
Dbms dbms;
auto dba = dbms.active();
GraphDb db;
GraphDbAccessor dba(db);
auto vertex = dba->InsertVertex();
auto vertex = dba.InsertVertex();
auto &properties = vertex.Properties();
auto property = dba->Property("PropName");
auto property_other = dba->Property("Other");
auto property = dba.Property("PropName");
auto property_other = dba.Property("Other");
EXPECT_EQ(vertex.PropsAt(property).type(), PropertyValue::Type::Null);
vertex.PropsSet(property, 42);
@ -34,43 +33,43 @@ TEST(RecordAccessor, Properties) {
}
TEST(RecordAccessor, DbAccessor) {
Dbms dbms;
auto dba = dbms.active();
GraphDb db;
GraphDbAccessor dba(db);
auto vertex = dba->InsertVertex();
auto vertex = dba.InsertVertex();
const auto &const_vertex_dba = vertex.db_accessor();
EXPECT_EQ(dba.get(), &const_vertex_dba);
EXPECT_EQ(&dba, &const_vertex_dba);
auto &vertex_dba = vertex.db_accessor();
EXPECT_EQ(dba.get(), &vertex_dba);
EXPECT_EQ(&dba, &vertex_dba);
}
TEST(RecordAccessor, RecordEquality) {
Dbms dbms;
auto dba = dbms.active();
GraphDb db;
GraphDbAccessor dba(db);
auto v1 = dba->InsertVertex();
auto v2 = dba->InsertVertex();
auto v1 = dba.InsertVertex();
auto v2 = dba.InsertVertex();
EXPECT_EQ(v1, v1);
EXPECT_NE(v1, v2);
auto e1 = dba->InsertEdge(v1, v2, dba->EdgeType("type"));
auto e2 = dba->InsertEdge(v1, v2, dba->EdgeType("type"));
auto e1 = dba.InsertEdge(v1, v2, dba.EdgeType("type"));
auto e2 = dba.InsertEdge(v1, v2, dba.EdgeType("type"));
EXPECT_EQ(e1, e1);
EXPECT_NE(e1, e2);
}
TEST(RecordAccessor, RecordLessThan) {
Dbms dbms;
auto dba = dbms.active();
GraphDb db;
GraphDbAccessor dba(db);
auto v1 = dba->InsertVertex();
auto v2 = dba->InsertVertex();
auto v1 = dba.InsertVertex();
auto v2 = dba.InsertVertex();
EXPECT_NE(v1, v2);
EXPECT_TRUE(v1 < v2 || v2 < v1);
EXPECT_FALSE(v1 < v1);
EXPECT_FALSE(v2 < v2);
auto e1 = dba->InsertEdge(v1, v2, dba->EdgeType("type"));
auto e2 = dba->InsertEdge(v1, v2, dba->EdgeType("type"));
auto e1 = dba.InsertEdge(v1, v2, dba.EdgeType("type"));
auto e2 = dba.InsertEdge(v1, v2, dba.EdgeType("type"));
EXPECT_NE(e1, e2);
EXPECT_TRUE(e1 < e2 || e2 < e1);
EXPECT_FALSE(e1 < e1);
@ -78,30 +77,30 @@ TEST(RecordAccessor, RecordLessThan) {
}
TEST(RecordAccessor, SwitchOldAndSwitchNewMemberFunctionTest) {
Dbms dbms;
GraphDb db;
// test both Switches work on new record
{
auto dba = dbms.active();
auto v1 = dba->InsertVertex();
GraphDbAccessor dba(db);
auto v1 = dba.InsertVertex();
v1.SwitchOld();
v1.SwitchNew();
dba->Commit();
dba.Commit();
}
// test both Switches work on existing record
{
auto dba = dbms.active();
auto v1 = *dba->Vertices(false).begin();
GraphDbAccessor dba(db);
auto v1 = *dba.Vertices(false).begin();
v1.SwitchOld();
v1.SwitchNew();
}
// ensure switch exposes the right data
{
auto dba = dbms.active();
auto label = dba->Label("label");
auto v1 = *dba->Vertices(false).begin();
GraphDbAccessor dba(db);
auto label = dba.Label("label");
auto v1 = *dba.Vertices(false).begin();
EXPECT_FALSE(v1.has_label(label)); // old record
v1.add_label(label); // modifying data does not switch to new
@ -114,27 +113,27 @@ TEST(RecordAccessor, SwitchOldAndSwitchNewMemberFunctionTest) {
}
TEST(RecordAccessor, Reconstruct) {
Dbms dbms;
auto label = dbms.active()->Label("label");
GraphDb db;
auto label = GraphDbAccessor(db).Label("label");
{
// we must operate on an old vertex
// because otherwise we only have new
// so create a vertex and commit it
auto dba = dbms.active();
dba->InsertVertex();
dba->Commit();
GraphDbAccessor dba(db);
dba.InsertVertex();
dba.Commit();
}
// ensure we don't have label set
auto dba = dbms.active();
auto v1 = *dba->Vertices(false).begin();
GraphDbAccessor dba(db);
auto v1 = *dba.Vertices(false).begin();
v1.SwitchNew();
EXPECT_FALSE(v1.has_label(label));
{
// update the record through a different accessor
auto v1_other_accessor = *dba->Vertices(false).begin();
auto v1_other_accessor = *dba.Vertices(false).begin();
v1_other_accessor.add_label(label);
EXPECT_FALSE(v1.has_label(label));
v1_other_accessor.SwitchNew();
@ -148,15 +147,15 @@ TEST(RecordAccessor, Reconstruct) {
}
TEST(RecordAccessor, VertexLabels) {
Dbms dbms;
auto dba = dbms.active();
auto v1 = dba->InsertVertex();
GraphDb db;
GraphDbAccessor dba(db);
auto v1 = dba.InsertVertex();
auto &labels = v1.labels();
EXPECT_EQ(v1.labels().size(), 0);
GraphDbTypes::Label l1 = dba->Label("label1");
GraphDbTypes::Label l2 = dba->Label("label2");
GraphDbTypes::Label l1 = dba.Label("label1");
GraphDbTypes::Label l2 = dba.Label("label2");
// adding labels
EXPECT_FALSE(v1.has_label(l1));
@ -176,7 +175,7 @@ TEST(RecordAccessor, VertexLabels) {
EXPECT_EQ(labels.size(), 2);
// removing labels
GraphDbTypes::Label l3 = dba->Label("label3");
GraphDbTypes::Label l3 = dba.Label("label3");
EXPECT_EQ(v1.remove_label(l3), 0);
EXPECT_EQ(labels.size(), 2);
@ -189,39 +188,39 @@ TEST(RecordAccessor, VertexLabels) {
}
TEST(RecordAccessor, EdgeType) {
Dbms dbms;
auto dba = dbms.active();
auto v1 = dba->InsertVertex();
auto v2 = dba->InsertVertex();
GraphDb db;
GraphDbAccessor dba(db);
auto v1 = dba.InsertVertex();
auto v2 = dba.InsertVertex();
GraphDbTypes::EdgeType likes = dba->EdgeType("likes");
GraphDbTypes::EdgeType hates = dba->EdgeType("hates");
GraphDbTypes::EdgeType likes = dba.EdgeType("likes");
GraphDbTypes::EdgeType hates = dba.EdgeType("hates");
auto edge = dba->InsertEdge(v1, v2, likes);
auto edge = dba.InsertEdge(v1, v2, likes);
EXPECT_EQ(edge.EdgeType(), likes);
EXPECT_NE(edge.EdgeType(), hates);
}
TEST(RecordAccessor, EdgeIsCycle) {
Dbms dbms;
auto dba = dbms.active();
auto v1 = dba->InsertVertex();
auto v2 = dba->InsertVertex();
auto likes = dba->EdgeType("edge_type");
GraphDb db;
GraphDbAccessor dba(db);
auto v1 = dba.InsertVertex();
auto v2 = dba.InsertVertex();
auto likes = dba.EdgeType("edge_type");
EXPECT_TRUE(dba->InsertEdge(v1, v1, likes).is_cycle());
EXPECT_TRUE(dba->InsertEdge(v2, v2, likes).is_cycle());
EXPECT_FALSE(dba->InsertEdge(v1, v2, likes).is_cycle());
EXPECT_FALSE(dba->InsertEdge(v2, v1, likes).is_cycle());
EXPECT_TRUE(dba.InsertEdge(v1, v1, likes).is_cycle());
EXPECT_TRUE(dba.InsertEdge(v2, v2, likes).is_cycle());
EXPECT_FALSE(dba.InsertEdge(v1, v2, likes).is_cycle());
EXPECT_FALSE(dba.InsertEdge(v2, v1, likes).is_cycle());
}
TEST(RecordAccessor, VertexEdgeConnections) {
Dbms dbms;
auto dba = dbms.active();
auto v1 = dba->InsertVertex();
auto v2 = dba->InsertVertex();
auto edge = dba->InsertEdge(v1, v2, dba->EdgeType("likes"));
dba->AdvanceCommand();
GraphDb db;
GraphDbAccessor dba(db);
auto v1 = dba.InsertVertex();
auto v2 = dba.InsertVertex();
auto edge = dba.InsertEdge(v1, v2, dba.EdgeType("likes"));
dba.AdvanceCommand();
EXPECT_EQ(edge.from(), v1);
EXPECT_NE(edge.from(), v2);
@ -248,18 +247,18 @@ TEST(RecordAccessor, VertexEdgeConnections) {
}
TEST(RecordAccessor, VertexEdgeConnectionsWithExistingVertex) {
Dbms dbms;
auto dba = dbms.active();
auto v1 = dba->InsertVertex();
auto v2 = dba->InsertVertex();
auto v3 = dba->InsertVertex();
auto edge_type = dba->EdgeType("edge type");
auto e12 = dba->InsertEdge(v1, v2, edge_type);
auto e22 = dba->InsertEdge(v2, v2, edge_type);
auto e23a = dba->InsertEdge(v2, v3, edge_type);
auto e23b = dba->InsertEdge(v2, v3, edge_type);
auto e32 = dba->InsertEdge(v3, v2, edge_type);
dba->AdvanceCommand();
GraphDb db;
GraphDbAccessor dba(db);
auto v1 = dba.InsertVertex();
auto v2 = dba.InsertVertex();
auto v3 = dba.InsertVertex();
auto edge_type = dba.EdgeType("edge type");
auto e12 = dba.InsertEdge(v1, v2, edge_type);
auto e22 = dba.InsertEdge(v2, v2, edge_type);
auto e23a = dba.InsertEdge(v2, v3, edge_type);
auto e23b = dba.InsertEdge(v2, v3, edge_type);
auto e32 = dba.InsertEdge(v3, v2, edge_type);
dba.AdvanceCommand();
TEST_EDGE_ITERABLE(v1.out(v1));
TEST_EDGE_ITERABLE(v1.out(v2), {e12});
@ -283,18 +282,18 @@ TEST(RecordAccessor, VertexEdgeConnectionsWithExistingVertex) {
}
TEST(RecordAccessor, VertexEdgeConnectionsWithEdgeType) {
Dbms dbms;
auto dba = dbms.active();
auto v1 = dba->InsertVertex();
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();
GraphDb db;
GraphDbAccessor dba(db);
auto v1 = dba.InsertVertex();
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, ec});

View File

@ -6,7 +6,6 @@
#include "gtest/gtest.h"
#include "communication/bolt/v1/decoder/decoder.hpp"
#include "database/dbms.hpp"
#include "durability/hashed_file_reader.hpp"
#include "durability/recovery.hpp"
#include "durability/version.hpp"
@ -16,9 +15,7 @@ DECLARE_int32(snapshot_cycle_sec);
namespace fs = std::experimental::filesystem;
char tmp[] = "XXXXXX";
const fs::path SNAPSHOTS_RECOVERY_ALL_DB_DIR = mkdtemp(tmp);
const fs::path SNAPSHOTS_RECOVERY_DEFAULT_DB_DIR =
SNAPSHOTS_RECOVERY_ALL_DB_DIR / "default";
const fs::path SNAPSHOTS_DIR = mkdtemp(tmp);
std::vector<fs::path> GetFilesFromDir(
const std::string &snapshots_default_db_dir) {
@ -29,9 +26,8 @@ std::vector<fs::path> GetFilesFromDir(
}
void CleanDbDir() {
if (!fs::exists(SNAPSHOTS_RECOVERY_DEFAULT_DB_DIR)) return;
std::vector<fs::path> files =
GetFilesFromDir(SNAPSHOTS_RECOVERY_DEFAULT_DB_DIR);
if (!fs::exists(SNAPSHOTS_DIR)) return;
std::vector<fs::path> files = GetFilesFromDir(SNAPSHOTS_DIR);
for (auto file : files) {
fs::remove(file);
}
@ -48,47 +44,45 @@ class RecoveryTest : public ::testing::Test {
const int snapshot_max_retained_ = 10;
};
void CreateSmallGraph(Dbms &dbms) {
auto dba = dbms.active();
void CreateSmallGraph(GraphDb &db) {
GraphDbAccessor dba(db);
// setup (v1) - [:likes] -> (v2) <- [:hates] - (v3)
auto va1 = dba->InsertVertex();
auto va2 = dba->InsertVertex();
dba->InsertEdge(va1, va2, dba->EdgeType("likes"));
auto va3 = dba->InsertVertex();
dba->InsertEdge(va3, va2, dba->EdgeType("hates"));
dba->Commit();
auto va1 = dba.InsertVertex();
auto va2 = dba.InsertVertex();
dba.InsertEdge(va1, va2, dba.EdgeType("likes"));
auto va3 = dba.InsertVertex();
dba.InsertEdge(va3, va2, dba.EdgeType("hates"));
dba.Commit();
}
void CreateBigGraph(Dbms &dbms) {
void CreateBigGraph(GraphDb &db) {
// creates graph with one inner vertex connected with other 999 outer vertices
// relationships are directed from outer vertices to the inner vertex
// every vertex hash label "label" and property "prop" with value "prop"
// every relationship has type "type" and property "prop" with value "prop"
auto dba = dbms.active();
auto va_middle = dba->InsertVertex();
va_middle.add_label(dba->Label("label"));
va_middle.PropsSet(dba->Property("prop"), "prop");
GraphDbAccessor dba(db);
auto va_middle = dba.InsertVertex();
va_middle.add_label(dba.Label("label"));
va_middle.PropsSet(dba.Property("prop"), "prop");
for (int i = 1; i < 1000; ++i) {
auto va = dba->InsertVertex();
va.add_label(dba->Label("label"));
va.PropsSet(dba->Property("prop"), "prop");
auto ea = dba->InsertEdge(va, va_middle, dba->EdgeType("type"));
ea.PropsSet(dba->Property("prop"), "prop");
auto va = dba.InsertVertex();
va.add_label(dba.Label("label"));
va.PropsSet(dba.Property("prop"), "prop");
auto ea = dba.InsertEdge(va, va_middle, dba.EdgeType("type"));
ea.PropsSet(dba.Property("prop"), "prop");
}
dba->Commit();
dba.Commit();
}
void TakeSnapshot(Dbms &dbms, int snapshot_max_retained_) {
auto dba = dbms.active();
void TakeSnapshot(GraphDb &db, int snapshot_max_retained_) {
GraphDbAccessor dba(db);
Snapshooter snapshooter;
snapshooter.MakeSnapshot(*dba.get(), SNAPSHOTS_RECOVERY_DEFAULT_DB_DIR,
snapshot_max_retained_);
snapshooter.MakeSnapshot(dba, SNAPSHOTS_DIR, snapshot_max_retained_);
}
std::string GetLatestSnapshot() {
std::vector<fs::path> files =
GetFilesFromDir(SNAPSHOTS_RECOVERY_DEFAULT_DB_DIR);
std::vector<fs::path> files = GetFilesFromDir(SNAPSHOTS_DIR);
CHECK(static_cast<int>(files.size()) == 1) << "No snapshot files in folder.";
std::sort(files.rbegin(), files.rend());
return files[0];
@ -98,9 +92,9 @@ TEST_F(RecoveryTest, TestEncoding) {
// Creates snapshot of the small graph. Uses file_reader_buffer and bolt
// decoder to read data from the snapshot and reads graph from it. After
// reading graph is tested.
Dbms dbms;
CreateSmallGraph(dbms);
TakeSnapshot(dbms, snapshot_max_retained_);
GraphDb db;
CreateSmallGraph(db);
TakeSnapshot(db, snapshot_max_retained_);
std::string snapshot = GetLatestSnapshot();
HashedFileReader buffer;
@ -165,31 +159,31 @@ TEST_F(RecoveryTest, TestEncoding) {
TEST_F(RecoveryTest, TestEncodingAndDecoding) {
// Creates snapshot of the small graph. Uses Recovery to recover graph from
// the snapshot file. After creation graph is tested.
Dbms dbms;
CreateSmallGraph(dbms);
TakeSnapshot(dbms, snapshot_max_retained_);
GraphDb db;
CreateSmallGraph(db);
TakeSnapshot(db, snapshot_max_retained_);
std::string snapshot = GetLatestSnapshot();
// New dbms is needed - old dbms has database "default"
Dbms dbms_recover;
auto dba_recover = dbms_recover.active();
// New db is needed - old db has database "default"
GraphDb db_recover;
GraphDbAccessor dba_recover(db_recover);
Recovery recovery;
ASSERT_TRUE(recovery.Recover(snapshot, *dba_recover));
ASSERT_TRUE(recovery.Recover(snapshot, dba_recover));
std::vector<VertexAccessor> vertices;
std::vector<EdgeAccessor> edges;
auto dba = dbms_recover.active();
GraphDbAccessor dba(db_recover);
int64_t vertex_count = 0;
for (const auto &vertex : dba->Vertices(false)) {
for (const auto &vertex : dba.Vertices(false)) {
vertices.push_back(vertex);
vertex_count++;
}
EXPECT_EQ(vertex_count, 3);
int64_t edge_count = 0;
for (const auto &edge : dba->Edges(false)) {
for (const auto &edge : dba.Edges(false)) {
EXPECT_NE(vertices.end(),
std::find(vertices.begin(), vertices.end(), edge.to()));
EXPECT_NE(vertices.end(),
@ -207,25 +201,25 @@ TEST_F(RecoveryTest, TestEncodingAndDecoding) {
TEST_F(RecoveryTest, TestEncodingAndRecovering) {
// Creates snapshot of the big graph. Uses Recovery to recover graph from
// the snapshot file. After creation graph is tested.
Dbms dbms;
CreateBigGraph(dbms);
TakeSnapshot(dbms, snapshot_max_retained_);
GraphDb db;
CreateBigGraph(db);
TakeSnapshot(db, snapshot_max_retained_);
std::string snapshot = GetLatestSnapshot();
// New dbms is needed - old dbms has database "default"
Dbms dbms_recover;
auto dba_recover = dbms_recover.active();
// New db is needed - old db has database "default"
GraphDb db_recover;
GraphDbAccessor dba_recover(db_recover);
Recovery recovery;
EXPECT_TRUE(recovery.Recover(snapshot, *dba_recover));
EXPECT_TRUE(recovery.Recover(snapshot, dba_recover));
auto dba_get = dbms_recover.active();
GraphDbAccessor dba_get(db_recover);
int64_t vertex_count = 0;
for (const auto &vertex : dba_get->Vertices(false)) {
for (const auto &vertex : dba_get.Vertices(false)) {
EXPECT_EQ(vertex.labels().size(), 1);
EXPECT_TRUE(vertex.has_label(dba_get->Label("label")));
EXPECT_TRUE(vertex.has_label(dba_get.Label("label")));
query::TypedValue prop =
query::TypedValue(vertex.PropsAt(dba_get->Property("prop")));
query::TypedValue(vertex.PropsAt(dba_get.Property("prop")));
query::TypedValue expected_prop = query::TypedValue(PropertyValue("prop"));
EXPECT_TRUE((prop == expected_prop).Value<bool>());
vertex_count++;
@ -233,45 +227,45 @@ TEST_F(RecoveryTest, TestEncodingAndRecovering) {
EXPECT_EQ(vertex_count, 1000);
int64_t edge_count = 0;
for (const auto &edge : dba_get->Edges(false)) {
EXPECT_EQ(edge.EdgeType(), dba_get->EdgeType("type"));
for (const auto &edge : dba_get.Edges(false)) {
EXPECT_EQ(edge.EdgeType(), dba_get.EdgeType("type"));
query::TypedValue prop =
query::TypedValue(edge.PropsAt(dba_get->Property("prop")));
query::TypedValue(edge.PropsAt(dba_get.Property("prop")));
query::TypedValue expected_prop = query::TypedValue(PropertyValue("prop"));
EXPECT_TRUE((prop == expected_prop).Value<bool>());
edge_count++;
}
EXPECT_EQ(edge_count, 999);
dba_get->Commit();
dba_get.Commit();
}
TEST_F(RecoveryTest, TestLabelPropertyIndexRecovery) {
// Creates snapshot of the graph with indices.
Dbms dbms;
auto dba = dbms.active();
dba->BuildIndex(dba->Label("label"), dba->Property("prop"));
dba->Commit();
CreateBigGraph(dbms);
TakeSnapshot(dbms, snapshot_max_retained_);
GraphDb db;
GraphDbAccessor dba(db);
dba.BuildIndex(dba.Label("label"), dba.Property("prop"));
dba.Commit();
CreateBigGraph(db);
TakeSnapshot(db, snapshot_max_retained_);
std::string snapshot = GetLatestSnapshot();
Dbms dbms_recover;
auto dba_recover = dbms_recover.active();
GraphDb db_recover;
GraphDbAccessor dba_recover(db_recover);
Recovery recovery;
EXPECT_TRUE(recovery.Recover(snapshot, *dba_recover));
EXPECT_TRUE(recovery.Recover(snapshot, dba_recover));
auto dba_get = dbms_recover.active();
EXPECT_EQ(dba_get->GetIndicesKeys().size(), 1);
EXPECT_TRUE(dba_get->LabelPropertyIndexExists(dba_get->Label("label"),
dba_get->Property("prop")));
GraphDbAccessor dba_get(db_recover);
EXPECT_EQ(dba_get.GetIndicesKeys().size(), 1);
EXPECT_TRUE(dba_get.LabelPropertyIndexExists(dba_get.Label("label"),
dba_get.Property("prop")));
int64_t vertex_count = 0;
for (const auto &vertex : dba_get->Vertices(false)) {
for (const auto &vertex : dba_get.Vertices(false)) {
EXPECT_EQ(vertex.labels().size(), 1);
EXPECT_TRUE(vertex.has_label(dba_get->Label("label")));
EXPECT_TRUE(vertex.has_label(dba_get.Label("label")));
query::TypedValue prop =
query::TypedValue(vertex.PropsAt(dba_get->Property("prop")));
query::TypedValue(vertex.PropsAt(dba_get.Property("prop")));
query::TypedValue expected_prop = query::TypedValue(PropertyValue("prop"));
EXPECT_TRUE((prop == expected_prop).Value<bool>());
vertex_count++;
@ -279,16 +273,16 @@ TEST_F(RecoveryTest, TestLabelPropertyIndexRecovery) {
EXPECT_EQ(vertex_count, 1000);
int64_t edge_count = 0;
for (const auto &edge : dba_get->Edges(false)) {
EXPECT_EQ(edge.EdgeType(), dba_get->EdgeType("type"));
for (const auto &edge : dba_get.Edges(false)) {
EXPECT_EQ(edge.EdgeType(), dba_get.EdgeType("type"));
query::TypedValue prop =
query::TypedValue(edge.PropsAt(dba_get->Property("prop")));
query::TypedValue(edge.PropsAt(dba_get.Property("prop")));
query::TypedValue expected_prop = query::TypedValue(PropertyValue("prop"));
EXPECT_TRUE((prop == expected_prop).Value<bool>());
edge_count++;
}
EXPECT_EQ(edge_count, 999);
dba_get->Commit();
dba_get.Commit();
}
int main(int argc, char **argv) {

View File

@ -3,7 +3,8 @@
#include "gflags/gflags.h"
#include "gtest/gtest.h"
#include "database/dbms.hpp"
#include "database/graph_db.hpp"
#include "database/graph_db_accessor.hpp"
#include "durability/snapshooter.hpp"
DECLARE_bool(snapshot_on_exit);
@ -13,9 +14,7 @@ DECLARE_string(snapshot_directory);
namespace fs = std::experimental::filesystem;
char tmp[] = "XXXXXX";
const fs::path SNAPSHOTS_FOLDER_ALL_DB = mkdtemp(tmp);
const fs::path SNAPSHOTS_TEST_DEFAULT_DB_DIR =
SNAPSHOTS_FOLDER_ALL_DB / "default";
const fs::path SNAPSHOTS_DIR = mkdtemp(tmp);
// Other functionality is tested in recovery tests.
@ -28,8 +27,8 @@ std::vector<fs::path> GetFilesFromDir(
}
void CleanDbDir() {
if (!fs::exists(SNAPSHOTS_TEST_DEFAULT_DB_DIR)) return;
std::vector<fs::path> files = GetFilesFromDir(SNAPSHOTS_TEST_DEFAULT_DB_DIR);
if (!fs::exists(SNAPSHOTS_DIR)) return;
std::vector<fs::path> files = GetFilesFromDir(SNAPSHOTS_DIR);
for (auto file : files) {
fs::remove(file);
}
@ -48,66 +47,66 @@ class SnapshotTest : public ::testing::Test {
TEST_F(SnapshotTest, CreateLessThanMaxRetainedSnapshotsTests) {
const int snapshot_max_retained = 10;
Dbms dbms;
GraphDb db;
for (int i = 0; i < 3; ++i) {
auto dba = dbms.active();
GraphDbAccessor dba(db);
Snapshooter snapshooter;
snapshooter.MakeSnapshot(*dba.get(), SNAPSHOTS_TEST_DEFAULT_DB_DIR,
snapshooter.MakeSnapshot(dba, SNAPSHOTS_DIR,
snapshot_max_retained);
}
std::vector<fs::path> files = GetFilesFromDir(SNAPSHOTS_TEST_DEFAULT_DB_DIR);
std::vector<fs::path> files = GetFilesFromDir(SNAPSHOTS_DIR);
EXPECT_EQ(files.size(), 3);
}
TEST_F(SnapshotTest, CreateMoreThanMaxRetainedSnapshotsTests) {
const int snapshot_max_retained = 2;
Dbms dbms;
GraphDb db;
fs::path first_snapshot;
for (int i = 0; i < 3; ++i) {
auto dba = dbms.active();
GraphDbAccessor dba(db);
Snapshooter snapshooter;
snapshooter.MakeSnapshot(*dba.get(), SNAPSHOTS_TEST_DEFAULT_DB_DIR,
snapshooter.MakeSnapshot(dba, SNAPSHOTS_DIR,
snapshot_max_retained);
if (i == 0) {
std::vector<fs::path> files_begin =
GetFilesFromDir(SNAPSHOTS_TEST_DEFAULT_DB_DIR);
GetFilesFromDir(SNAPSHOTS_DIR);
EXPECT_EQ(files_begin.size(), 1);
first_snapshot = files_begin[0];
}
}
std::vector<fs::path> files_end =
GetFilesFromDir(SNAPSHOTS_TEST_DEFAULT_DB_DIR);
GetFilesFromDir(SNAPSHOTS_DIR);
EXPECT_EQ(files_end.size(), 2);
EXPECT_EQ(fs::exists(first_snapshot), false);
}
TEST_F(SnapshotTest, CreateSnapshotWithUnlimitedMaxRetainedSnapshots) {
const int snapshot_max_retained = -1;
Dbms dbms;
GraphDb db;
for (int i = 0; i < 10; ++i) {
auto dba = dbms.active();
GraphDbAccessor dba(db);
Snapshooter snapshooter;
snapshooter.MakeSnapshot(*dba.get(), SNAPSHOTS_TEST_DEFAULT_DB_DIR,
snapshooter.MakeSnapshot(dba, SNAPSHOTS_DIR,
snapshot_max_retained);
}
std::vector<fs::path> files = GetFilesFromDir(SNAPSHOTS_TEST_DEFAULT_DB_DIR);
std::vector<fs::path> files = GetFilesFromDir(SNAPSHOTS_DIR);
EXPECT_EQ(files.size(), 10);
}
TEST_F(SnapshotTest, TestSnapshotFileOnDbDestruct) {
{
FLAGS_snapshot_directory = SNAPSHOTS_FOLDER_ALL_DB;
FLAGS_snapshot_directory = SNAPSHOTS_DIR;
FLAGS_snapshot_on_exit = true;
Dbms dbms;
auto dba = dbms.active();
GraphDb db;
GraphDbAccessor dba(db);
}
std::vector<fs::path> files = GetFilesFromDir(SNAPSHOTS_TEST_DEFAULT_DB_DIR);
std::vector<fs::path> files = GetFilesFromDir(SNAPSHOTS_DIR);
// snapshot is created on dbms destruction
EXPECT_EQ(files.size(), 1);
}

View File

@ -7,8 +7,9 @@
#include <set>
#include <vector>
#include "database/dbms.hpp"
#include "gtest/gtest.h"
#include "database/graph_db_accessor.hpp"
#include "query/typed_value.hpp"
using query::TypedValue;
@ -17,8 +18,8 @@ using query::TypedValueException;
class AllTypesFixture : public testing::Test {
protected:
std::vector<TypedValue> values_;
Dbms dbms_;
std::unique_ptr<GraphDbAccessor> dba_ = dbms_.active();
GraphDb db_;
GraphDbAccessor dba_{db_};
void SetUp() override {
values_.emplace_back(TypedValue::Null);
@ -34,11 +35,10 @@ class AllTypesFixture : public testing::Test {
{"c", 42},
{"d", 0.5},
{"e", TypedValue::Null}});
auto vertex = dba_->InsertVertex();
auto vertex = dba_.InsertVertex();
values_.emplace_back(vertex);
values_.emplace_back(
dba_->InsertEdge(vertex, vertex, dba_->EdgeType("et")));
values_.emplace_back(query::Path(dba_->InsertVertex()));
values_.emplace_back(dba_.InsertEdge(vertex, vertex, dba_.EdgeType("et")));
values_.emplace_back(query::Path(dba_.InsertVertex()));
}
};

View File

@ -4,7 +4,6 @@ add_executable(mg_recovery_check
mg_recovery_check.cpp
${memgraph_src_dir}/communication/bolt/v1/decoder/decoded_value.cpp
${memgraph_src_dir}/data_structures/concurrent/skiplist_gc.cpp
${memgraph_src_dir}/database/dbms.cpp
${memgraph_src_dir}/database/graph_db.cpp
${memgraph_src_dir}/database/graph_db_accessor.cpp
${memgraph_src_dir}/durability/recovery.cpp

View File

@ -3,7 +3,8 @@
#include "gflags/gflags.h"
#include "gtest/gtest.h"
#include "database/dbms.hpp"
#include "database/graph_db.hpp"
#include "durability/recovery.hpp"
#include "query/typed_value.hpp"
static const char *usage =
@ -19,28 +20,29 @@ class RecoveryTest : public ::testing::Test {
void SetUp() override {
Recovery recovery;
std::string snapshot(FLAGS_snapshot_dir + "/snapshot");
recovery.Recover(snapshot, *dbms_.active());
GraphDbAccessor dba(db_);
recovery.Recover(snapshot, dba);
}
Dbms dbms_;
GraphDb db_;
};
TEST_F(RecoveryTest, TestVerticesRecovered) {
auto dba = dbms_.active();
EXPECT_EQ(dba->VerticesCount(), 10);
EXPECT_EQ(dba->VerticesCount(dba->Label("Comment")), 5);
for (const auto &vertex : dba->Vertices(dba->Label("Comment"), false)) {
EXPECT_TRUE(vertex.has_label(dba->Label("Message")));
GraphDbAccessor dba(db_);
EXPECT_EQ(dba.VerticesCount(), 10);
EXPECT_EQ(dba.VerticesCount(dba.Label("Comment")), 5);
for (const auto &vertex : dba.Vertices(dba.Label("Comment"), false)) {
EXPECT_TRUE(vertex.has_label(dba.Label("Message")));
}
EXPECT_EQ(dba->VerticesCount(dba->Label("Forum")), 5);
EXPECT_EQ(dba.VerticesCount(dba.Label("Forum")), 5);
}
TEST_F(RecoveryTest, TestPropertyNull) {
auto dba = dbms_.active();
GraphDbAccessor dba(db_);
bool found = false;
for (const auto &vertex : dba->Vertices(dba->Label("Comment"), false)) {
auto id_prop = query::TypedValue(vertex.PropsAt(dba->Property("id")));
auto browser = query::TypedValue(vertex.PropsAt(dba->Property("browser")));
for (const auto &vertex : dba.Vertices(dba.Label("Comment"), false)) {
auto id_prop = query::TypedValue(vertex.PropsAt(dba.Property("id")));
auto browser = query::TypedValue(vertex.PropsAt(dba.Property("browser")));
if (id_prop.IsString() && id_prop.Value<std::string>() == "2") {
EXPECT_FALSE(found);
found = true;
@ -53,10 +55,10 @@ TEST_F(RecoveryTest, TestPropertyNull) {
}
TEST_F(RecoveryTest, TestEdgesRecovered) {
auto dba = dbms_.active();
EXPECT_EQ(dba->EdgesCount(), 5);
for (const auto &edge : dba->Edges(false)) {
EXPECT_TRUE(edge.EdgeType() == dba->EdgeType("POSTED_ON"));
GraphDbAccessor dba(db_);
EXPECT_EQ(dba.EdgesCount(), 5);
for (const auto &edge : dba.Edges(false)) {
EXPECT_TRUE(edge.EdgeType() == dba.EdgeType("POSTED_ON"));
}
}