Remove manual/repl test

Reviewers: teon.banek

Reviewed By: teon.banek

Subscribers: pullbot

Differential Revision: https://phabricator.memgraph.io/D2548
This commit is contained in:
Matej Ferencevic 2019-11-13 15:31:20 +01:00
parent edaa03a960
commit 40ae31e9a0
6 changed files with 5 additions and 423 deletions

View File

@ -64,7 +64,6 @@ set(mg_single_node_sources
query/plan/variable_start_planner.cpp
query/procedure/mg_procedure_impl.cpp
query/procedure/module.cpp
query/repl.cpp
query/typed_value.cpp
storage/common/constraints/record.cpp
storage/common/constraints/unique_constraints.cpp
@ -95,10 +94,6 @@ if (USE_LTALLOC)
# set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -flto")
endif()
if (READLINE_FOUND)
list(APPEND MG_SINGLE_NODE_LIBS readline)
endif()
add_library(mg-single-node STATIC ${mg_single_node_sources})
target_include_directories(mg-single-node PRIVATE ${CMAKE_SOURCE_DIR}/include)
target_link_libraries(mg-single-node ${MG_SINGLE_NODE_LIBS})
@ -211,7 +206,6 @@ set(mg_single_node_ha_sources
query/plan/variable_start_planner.cpp
query/procedure/mg_procedure_impl.cpp
query/procedure/module.cpp
query/repl.cpp
query/typed_value.cpp
storage/common/constraints/record.cpp
storage/common/constraints/unique_constraints.cpp
@ -248,10 +242,6 @@ if (USE_LTALLOC)
# set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -flto")
endif()
if (READLINE_FOUND)
list(APPEND MG_SINGLE_NODE_HA_LIBS readline)
endif()
add_library(mg-single-node-ha STATIC ${mg_single_node_ha_sources})
target_include_directories(mg-single-node-ha PRIVATE ${CMAKE_SOURCE_DIR}/include)
target_link_libraries(mg-single-node-ha ${MG_SINGLE_NODE_HA_LIBS})

View File

@ -1,86 +0,0 @@
#include "repl.hpp"
#include <algorithm>
#include <iostream>
#include <iterator>
#include <sstream>
#include <vector>
#include "communication/result_stream_faker.hpp"
#include "query/exceptions.hpp"
#include "query/interpreter.hpp"
#include "query/typed_value.hpp"
#include "utils/algorithm.hpp"
#include "utils/exceptions.hpp"
#ifdef HAS_READLINE
#include "readline/history.h"
#include "readline/readline.h"
/**
* Helper function that reads a line from the
* standard input using the 'readline' lib.
* Adds support for history and reverse-search.
*
* @param prompt The prompt to display.
* @return A single command the user entered.
* Possibly empty.
*/
std::string ReadLine(const char *prompt) {
char *line = readline(prompt);
if (!line) return "";
if (*line) add_history(line);
std::string r_val(line);
free(line);
return r_val;
}
#else
std::string ReadLine(const char *prompt) {
std::cout << prompt;
std::string line;
std::getline(std::cin, line);
return line;
}
#endif // HAS_READLINE
void query::Repl(database::GraphDb *db, query::Interpreter *interpreter) {
std::cout
<< "Welcome to *Awesome* Memgraph Read Evaluate Print Loop (AM-REPL)"
<< std::endl;
while (true) {
std::string command = ReadLine(">");
if (command.size() == 0) continue;
// special commands
if (command == "quit") break;
// regular cypher queries
try {
ResultStreamFaker stream;
auto [header, _] = interpreter->Prepare(command, {});
stream.Header(header);
auto summary = interpreter->PullAll(&stream);
stream.Summary(summary);
std::cout << stream;
} catch (const query::SyntaxException &e) {
std::cout << "SYNTAX EXCEPTION: " << e.what() << std::endl;
} catch (const query::LexingException &e) {
std::cout << "LEXING EXCEPTION: " << e.what() << std::endl;
} catch (const query::SemanticException &e) {
std::cout << "SEMANTIC EXCEPTION: " << e.what() << std::endl;
} catch (const query::QueryRuntimeException &e) {
std::cout << "RUNTIME EXCEPTION: " << e.what() << std::endl;
} catch (const query::TypedValueException &e) {
std::cout << "TYPED VALUE EXCEPTION: " << e.what() << std::endl;
} catch (const query::HintedAbortError &e) {
std::cout << "HINTED ABORT ERROR: " << e.what() << std::endl;
} catch (const utils::NotYetImplemented &e) {
std::cout << e.what() << std::endl;
}
}
}

View File

@ -1,16 +0,0 @@
#pragma once
#include "database/graph_db.hpp"
namespace query {
class Interpreter;
/**
* Read Evaluate Print Loop, for interacting with a database (the database in
* the given database::GraphDb). Immediately starts the user-input loop and
* interprets the entered queries.
*/
void Repl(database::GraphDb *, query::Interpreter *);
} // namespace query

View File

@ -45,13 +45,13 @@ target_link_libraries(${test_prefix}query_hash mg-single-node kvstore_dummy_lib)
add_manual_test(query_planner.cpp interactive_planning.cpp)
target_link_libraries(${test_prefix}query_planner mg-single-node kvstore_dummy_lib)
if (READLINE_FOUND)
target_link_libraries(${test_prefix}query_planner readline)
endif()
add_manual_test(expression_pretty_printer.cpp)
target_link_libraries(${test_prefix}expression_pretty_printer mg-single-node kvstore_dummy_lib)
add_manual_test(repl.cpp)
target_link_libraries(${test_prefix}repl mg-single-node kvstore_dummy_lib)
add_manual_test(single_query.cpp)
target_link_libraries(${test_prefix}single_query mg-single-node kvstore_dummy_lib)

View File

@ -26,8 +26,7 @@ DEFINE_string(load_mock_db_file, "",
"File from which the mock database should be loaded");
#ifdef HAS_READLINE
// TODO: This is copied from src/query/repl.cpp
// It should probably be moved to some utils file.
// TODO: This should probably be moved to some utils file.
#include "readline/history.h"
#include "readline/readline.h"
@ -514,8 +513,7 @@ void RunInteractivePlanning(database::GraphDbAccessor *dba) {
if (line->empty()) continue;
try {
query::AstStorage ast;
auto *query =
dynamic_cast<query::CypherQuery *>(MakeAst(*line, &ast));
auto *query = dynamic_cast<query::CypherQuery *>(MakeAst(*line, &ast));
if (!query) {
throw utils::BasicException(
"Interactive planning is only avaialable for regular openCypher "

View File

@ -1,304 +0,0 @@
#include <iostream>
#include <mutex>
#include <thread>
#include <gflags/gflags.h>
#include <glog/logging.h>
#include "database/single_node/graph_db.hpp"
#include "query/interpreter.hpp"
#include "query/repl.hpp"
#include "storage/common/types/types.hpp"
DECLARE_int32(min_log_level);
/**
* Returns a lambda that generates random ints
* in the [from, to) range.
*/
auto RandomIntGenerator(int from, int to) {
CHECK(from < to) << "Must have from < to";
int range = to - from;
return [from, range]() -> int { return rand() % range + from; };
}
/**
* Random graph generator. Create a graph
* with a sequence of steps.
*/
class RandomGraphGenerator {
public:
explicit RandomGraphGenerator(database::GraphDb &db) : db_(db) {}
/**
* Adds a progress listener that gets notified when
* edges / vertices get created.
*
* A listener is a function that gets notified after every
* vertex / edge insertion. If data creation is multi-threaded,
* then so is progress listener notification.
*/
void AddProgressListener(
std::function<void(RandomGraphGenerator &)> listener) {
progress_listeners_.emplace_back(listener);
}
/**
* Adds the given number of vertices, with
* the given labels.
*
* @param count the number of vertices to add
* @param label_names a vector of label names to assign to each
* created vertex
* @param thread_count The number of threads in which to add edges
* @param batch_size The number of vertices to be created in
* a single transcation
*/
void AddVertices(int count, const std::vector<std::string> &label_names,
int thread_count, int batch_size = 2000) {
auto dba = db_.Access();
std::vector<storage::Label> labels;
for (const auto &label_name : label_names)
labels.push_back(dba.Label(label_name));
Map(
[&labels, this](database::GraphDbAccessor &dba) {
auto vertex = dba.InsertVertex();
for (auto label : labels) vertex.add_label(label);
NotifyProgressListeners();
},
count, thread_count, batch_size);
NotifyProgressListeners();
}
/**
* Returns the number of vertices created by this generator,
* regardless of their labels.
*/
int64_t VertexCount() const {
auto accessor = db_.Access();
return CountIterable(accessor.Vertices(true));
}
/**
* Adds the given number of edges to the graph.
*
* @param count The number of edges to add.
* @param edge_type_name Name of the edge type.
* @param thread_count The number of threads in which to add edges.
* @param batch_size The number of vertices to be created in
* a single transcation
* @param from_filter Filter of from vertices for new edges.
* By default all vertices are accepted.
* @param to_filter Filter of to vertices for new edges.
* By default all vertices are accepted.
*/
void AddEdges(int count, const std::string &edge_type_name, int thread_count,
int batch_size = 50,
const std::function<bool(VertexAccessor &va)> &from_filter = {},
const std::function<bool(VertexAccessor &va)> &to_filter = {}) {
// create two temporary sets of vertices we will poll from
auto vertices_from = FilterVertices(from_filter);
auto vertices_to = FilterVertices(to_filter);
auto dba = db_.Access();
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));
Map(
[&vertices_from, &vertices_to, edge_type,
this](database::GraphDbAccessor &dba) {
auto from =
dba.Transfer(vertices_from[rand() % vertices_from.size()]);
auto to = dba.Transfer(vertices_to[rand() % vertices_to.size()]);
DCHECK(from) << "From not visible in current GraphDbAccessor";
DCHECK(to) << "From not visible in current GraphDbAccessor";
dba.InsertEdge(from.value(), to.value(), edge_type);
NotifyProgressListeners();
},
count, thread_count, batch_size);
NotifyProgressListeners();
}
/**
* Returns the number of edges created by this generator,
* regardless of their types and origin/destination labels.
*/
int64_t EdgeCount() const {
auto accessor = db_.Access();
return CountIterable(accessor.Edges(true));
}
/**
* Sets a generated property on a random vertex.
*
* @tparam TValue Type of value to set.
* @param prop_name Name of the property.
* @param predicate Filter that accepts or rejects a Vertex.
* @param value_generator Function that accepts nothing and
* returns a property.
*/
template <typename TValue>
void SetVertexProperty(
const std::string &prop_name, std::function<TValue()> value_generator,
std::function<bool(VertexAccessor &va)> predicate = {}) {
if (!predicate) predicate = [](VertexAccessor &) { return true; };
auto dba = db_.Access();
auto property = dba.Property(prop_name);
for (VertexAccessor va : dba.Vertices(false))
if (predicate(va))
va.PropsSet(property, PropertyValue(value_generator()));
dba.Commit();
}
private:
database::GraphDb &db_;
// progress listeners, they get notified about vertices and edges being
// created
std::vector<std::function<void(RandomGraphGenerator &)>> progress_listeners_;
/**
* Helper function for filtering. Accepts a vector of TItems, a predicate
* that accepts it or not, and returns a vector of reference wrappers to
* accepted items.
*
*
* @param predicate A predicate. By default always true.
* @return A vector of vertex accessors. They belong to a GraphDbAccessor
* that is dead when this function retuns, make sure to
* GraphDbAccessor::Transfer them.
*/
std::vector<VertexAccessor> FilterVertices(
std::function<bool(VertexAccessor &item)> predicate = {}) {
if (!predicate) predicate = [](VertexAccessor &) { return true; };
std::vector<VertexAccessor> r_val;
auto dba = db_.Access();
for (VertexAccessor &item : dba.Vertices(false))
if (predicate(item)) r_val.emplace_back(item);
return r_val;
}
/** Sends notifications to all progress listeners */
void NotifyProgressListeners() {
for (const auto &listener : progress_listeners_) listener(*this);
}
/**
* Performs function `f` `count` times across `thread_count`
* threads. Returns only once all of the threads have
* finished.
*/
void Map(std::function<void(database::GraphDbAccessor &)> f, int count,
int thread_count, int elements_per_commit) {
DCHECK(thread_count > 0) << "Can't work on less then 1 thread";
// split count across thread_count
int count_per_thread = count / thread_count;
int count_remainder = count % thread_count;
std::vector<std::thread> threads;
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]() {
for (int i = 0; i < count_per_thread; i += elements_per_commit) {
while (true) {
auto dba = db_.Access();
try {
int apply_count =
std::min(elements_per_commit, count_per_thread - i);
while (apply_count--) {
f(dba);
}
dba.Commit();
break;
} catch (...) {
}
}
}
});
}
for (auto &thread : threads) thread.join();
}
template <typename TIterable>
size_t CountIterable(TIterable iterable) const {
return std::distance(iterable.begin(), iterable.end());
}
};
/** A graph-generation progress reporter */
class ProgressReporter {
public:
ProgressReporter(int64_t node_count, int64_t edge_count, int64_t skip)
: node_count_(node_count), edge_count_(edge_count), skip_(skip) {}
void operator()(RandomGraphGenerator &rgg) {
auto vc = rgg.VertexCount();
auto ec = rgg.EdgeCount();
bool last = ec + vc == node_count_ + edge_count_;
auto percent = std::lround(100. * (vc + ec) / (node_count_ + edge_count_));
if (last || (vc + ec) % skip_ == 0) {
std::lock_guard<std::mutex> lock(mutex_);
std::cout << "\rCreated " << rgg.VertexCount() << " vertices and "
<< rgg.EdgeCount() << " edges (" << percent
<< "% of all elements)";
std::flush(std::cout);
}
if (last) std::cout << std::endl;
}
private:
// the desired counts of nodes and edges
const int64_t node_count_;
const int64_t edge_count_;
// how many notifications we skip between each report
const int64_t skip_;
// std output synchronization
std::mutex mutex_{};
};
void random_generate(database::GraphDb &db, int64_t node_count,
int64_t edge_count) {
RandomGraphGenerator generator(db);
ProgressReporter reporter(node_count, edge_count,
std::max(1l, (node_count + edge_count) / 100));
generator.AddProgressListener([&reporter](auto &rgg) { reporter(rgg); });
utils::Timer generation_timer;
generator.AddVertices(node_count, {"Person"}, 4);
generator.AddEdges(edge_count, "Friend", 7);
generator.SetVertexProperty<int>("age", RandomIntGenerator(3, 60));
generator.SetVertexProperty<int>("height", RandomIntGenerator(120, 200));
std::cout << "Generation done in " << generation_timer.Elapsed().count()
<< " seconds" << std::endl;
}
int main(int argc, char *argv[]) {
gflags::ParseCommandLineFlags(&argc, &argv, true);
FLAGS_min_log_level = google::ERROR;
google::InitGoogleLogging(argv[0]);
// parse the first cmd line argument as the count of nodes to randomly create
int node_count = argc > 1 ? std::stoi(argv[1]) : 0;
int edge_count = argc > 2 ? std::stoi(argv[2]) : 0;
// TODO switch to GFlags, once finally available
if (argc > 3) google::InitGoogleLogging(argv[0]);
database::GraphDb db;
std::cout << "Generating graph..." << std::endl;
// fill_db;
random_generate(db, node_count, edge_count);
query::InterpreterContext interpreter_context{&db};
query::Interpreter interpreter{&interpreter_context};
query::Repl(&db, &interpreter);
return 0;
}