Query - entry.hpp renamed to interpreter.hpp, Engine renamed to Interpreter

Summary: Query - interpreter console hack

Reviewers: buda, teon.banek, mislav.bradac

Reviewed By: buda

Subscribers: pullbot

Differential Revision: https://phabricator.memgraph.io/D157
This commit is contained in:
florijan 2017-03-22 16:38:43 +01:00
parent 8da6ce67c0
commit b236694fd2
11 changed files with 201 additions and 157 deletions

View File

@ -351,7 +351,6 @@ set(memgraph_src_files
${src_dir}/database/graph_db_accessor.cpp
${src_dir}/query/stripper.cpp
${src_dir}/query/frontend/ast/cypher_main_visitor.cpp
${src_dir}/query/context.cpp
${src_dir}/query/backend/cpp/typed_value.cpp
${src_dir}/query/frontend/logical/planner.cpp
)

View File

@ -26,6 +26,7 @@ constexpr const char *SNAPSHOTS_PATH = "snapshots_path";
constexpr const char *CLEANING_CYCLE_SEC = "cleaning_cycle_sec";
constexpr const char *SNAPSHOT_CYCLE_SEC = "snapshot_cycle_sec";
constexpr const char *MAX_RETAINED_SNAPSHOTS = "max_retained_snapshots";
constexpr const char *INTERPRET = "interpret";
// -- all possible Memgraph's keys --
inline size_t to_int(std::string &&s) { return stoull(s); }

View File

@ -1,12 +0,0 @@
#include "query/context.hpp"
#include "query/frontend/ast/cypher_main_visitor.hpp"
namespace query {
Query *HighLevelAstConversion::Apply(Context &ctx,
antlr4::tree::ParseTree *tree) {
query::frontend::CypherMainVisitor visitor(ctx);
visitor.visit(tree);
return visitor.query();
}
}

View File

@ -30,22 +30,4 @@ public:
Config config_;
GraphDbAccessor &db_accessor_;
};
class LogicalPlanner {
public:
LogicalPlanner(Context ctx) : ctx_(ctx) {}
LogicalPlan Apply(TypedcheckedTree typedchecked_tree) {
return ctx_.config_.logical_plan_generator.Generate(typedchecked_tree,
ctx_)[0];
}
private:
Context ctx_;
};
class HighLevelAstConversion {
public:
Query *Apply(Context &ctx, antlr4::tree::ParseTree *tree);
};
}

View File

@ -12,6 +12,7 @@ namespace fs = std::experimental::filesystem;
#include "query/plan_compiler.hpp"
#include "query/plan_interface.hpp"
#include "query/preprocessor.hpp"
#include "query/interpreter.hpp"
#include "utils/dynamic_lib.hpp"
/**
@ -62,6 +63,12 @@ public:
*/
auto Run(const std::string &query, GraphDbAccessor &db_accessor,
Stream &stream) {
if (CONFIG[config::INTERPRET]) {
query::Interpret(query, db_accessor, stream);
return true;
}
auto preprocessed = preprocessor.preprocess(query);
auto plan = LoadCypher(preprocessed);
auto result = plan->run(db_accessor, preprocessed.arguments, stream);

View File

@ -1,97 +0,0 @@
#pragma once
#include "database/graph_db_accessor.hpp"
#include "query/context.hpp"
#include "query/context.hpp"
#include "query/frontend/interpret/interpret.hpp"
#include "query/frontend/logical/planner.hpp"
#include "query/frontend/opencypher/parser.hpp"
#include "query/frontend/semantic/symbol_generator.hpp"
namespace query {
/**
* A Stream implementation that writes out to the
* console (for testing and debugging only).
*/
// TODO move somewhere to /test/manual or so
class ConsoleResultStream : public Loggable {
public:
ConsoleResultStream() : Loggable("ConsoleResultStream") {}
void Header(const std::vector<std::string> &) { logger.info("header"); }
void Result(std::vector<TypedValue> &values) {
for (auto value : values) {
auto va = value.Value<VertexAccessor>();
logger.info(" {}", va.labels().size());
}
}
void Summary(const std::map<std::string, TypedValue> &) {
logger.info("summary");
}
};
template <typename Stream>
class Engine {
public:
Engine() {}
auto Execute(const std::string &query, GraphDbAccessor &db_accessor,
Stream &stream) {
Config config;
Context ctx(config, db_accessor);
// query -> AST
::frontend::opencypher::Parser parser(query);
auto low_level_tree = parser.tree();
// AST -> high level tree
HighLevelAstConversion low2high_tree;
auto high_level_tree = low2high_tree.Apply(ctx, low_level_tree);
Execute(*high_level_tree, db_accessor, stream);
}
auto Execute(Query &query, GraphDbAccessor &db_accessor, Stream stream) {
// symbol table fill
SymbolTable symbol_table;
SymbolGenerator symbol_generator(symbol_table);
query.Accept(symbol_generator);
// high level tree -> logical plan
auto logical_plan = MakeLogicalPlan(query, symbol_table);
// generate frame based on symbol table max_position
Frame frame(symbol_table.max_position());
auto *produce = dynamic_cast<Produce *>(logical_plan.get());
if (produce) {
// top level node in the operator tree is a produce (return)
// so stream out results
// generate header
std::vector<std::string> header;
for (auto named_expression : produce->named_expressions())
header.push_back(named_expression->name_);
stream.Header(header);
// collect the symbols from the return clause
std::vector<Symbol> symbols;
for (auto named_expression : produce->named_expressions())
symbols.emplace_back(symbol_table[*named_expression]);
// stream out results
auto cursor = produce->MakeCursor(db_accessor);
while (cursor->Pull(frame, symbol_table)) {
std::vector<TypedValue> values;
for (auto &symbol : symbols)
values.emplace_back(frame[symbol]);
stream.Result(values);
}
stream.Summary({{std::string("type"), TypedValue("r")}});
}
}
};
}

87
src/query/interpreter.hpp Normal file
View File

@ -0,0 +1,87 @@
#pragma once
#include <ctime>
#include "database/graph_db_accessor.hpp"
#include "query/context.hpp"
#include "query/frontend/ast/cypher_main_visitor.hpp"
#include "query/frontend/interpret/interpret.hpp"
#include "query/frontend/logical/planner.hpp"
#include "query/frontend/opencypher/parser.hpp"
#include "query/frontend/semantic/symbol_generator.hpp"
namespace query {
template <typename Stream>
void Interpret(const std::string &query, GraphDbAccessor &db_accessor,
Stream &stream) {
clock_t start_time = clock();
Config config;
Context ctx(config, db_accessor);
std::map<std::string, TypedValue> summary;
// query -> AST
::frontend::opencypher::Parser parser(query);
auto low_level_tree = parser.tree();
// AST -> high level tree
query::frontend::CypherMainVisitor visitor(ctx);
visitor.visit(low_level_tree);
auto high_level_tree = visitor.query();
// symbol table fill
SymbolTable symbol_table;
SymbolGenerator symbol_generator(symbol_table);
high_level_tree->Accept(symbol_generator);
// high level tree -> logical plan
auto logical_plan = MakeLogicalPlan(*high_level_tree, symbol_table);
// generate frame based on symbol table max_position
Frame frame(symbol_table.max_position());
if (auto produce = dynamic_cast<Produce *>(logical_plan.get())) {
// top level node in the operator tree is a produce (return)
// so stream out results
// generate header
std::vector<std::string> header;
for (auto named_expression : produce->named_expressions())
header.push_back(named_expression->name_);
stream.Header(header);
// collect the symbols from the return clause
std::vector<Symbol> symbols;
for (auto named_expression : produce->named_expressions())
symbols.emplace_back(symbol_table[*named_expression]);
// stream out results
auto cursor = produce->MakeCursor(db_accessor);
while (cursor->Pull(frame, symbol_table)) {
std::vector<TypedValue> values;
for (auto &symbol : symbols) values.emplace_back(frame[symbol]);
stream.Result(values);
}
summary["type"] = "r";
} else if (auto create = dynamic_cast<CreateOp *>(logical_plan.get())) {
auto cursor = create->MakeCursor(db_accessor);
while (cursor->Pull(frame, symbol_table)) {
continue;
}
} else if (auto create = dynamic_cast<CreateExpand *>(logical_plan.get())) {
auto cursor = create->MakeCursor(db_accessor);
while (cursor->Pull(frame, symbol_table)) {
continue;
}
}
clock_t end_time = clock();
double time_second = double(end_time - start_time) / CLOCKS_PER_SEC;
summary["query_time_sec"] = TypedValue(time_second);
stream.Summary(summary);
}
}

View File

@ -5,9 +5,9 @@
#include "query/backend/cpp/typed_value.hpp"
#include "storage/property_value_store.hpp"
#include "parameters.hpp"
#include "utils/assert.hpp"
#include "utils/hashing/fnv.hpp"
#include "parameters.hpp"
/*
* StrippedQuery contains:
@ -16,10 +16,12 @@
* * hash of stripped query
*/
struct StrippedQuery {
StrippedQuery(const std::string &&query,
const Parameters &arguments,
HashType hash)
: query(query), arguments(arguments), hash(hash) {}
StrippedQuery(const std::string &unstripped_query, const std::string &&query,
const Parameters &arguments, HashType hash)
: unstripped_query(unstripped_query),
query(query),
arguments(arguments),
hash(hash) {}
/**
* Copy constructor is deleted because we don't want to make unnecessary
@ -35,18 +37,15 @@ struct StrippedQuery {
StrippedQuery(StrippedQuery &&other) = default;
StrippedQuery &operator=(StrippedQuery &&other) = default;
/**
* Stripped query
*/
// original, unstripped query
const std::string unstripped_query;
// stripped query
const std::string query;
/**
* Stripped arguments
*/
// striped arguments
const Parameters arguments;
/**
* Hash based on stripped query.
*/
// hash based on the stripped query
const HashType hash;
};

View File

@ -214,7 +214,8 @@ StrippedQuery Strip(const std::string &query) {
}
// return stripped query, stripped arguments and stripped query hash
return StrippedQuery(std::move(stripped_query),
return StrippedQuery(query,
std::move(stripped_query),
std::move(stripped_arguments),
fnv(stripped_query));
}

View File

@ -1,9 +1,10 @@
#include <iostream>
#include <sstream>
#include "dbms/dbms.hpp"
#include "logging/default.hpp"
#include "logging/streams/stdout.cpp"
#include "query/entry.hpp"
#include "query/interpreter.hpp"
#include "query/backend/cpp/typed_value.hpp"
#include "query/frontend/logical/operator.hpp"
@ -11,6 +12,77 @@ using std::cout;
using std::cin;
using std::endl;
/**
* A Stream implementation that writes out to the
* console (for testing and debugging only).
*/
// TODO move somewhere to /test/manual or so
class ConsoleResultStream : public Loggable {
public:
ConsoleResultStream() : Loggable("ConsoleResultStream") {}
void Header(const std::vector<std::string> &) { logger.info("header"); }
void Result(std::vector<TypedValue> &values) {
std::stringstream ss;
bool first = true;
for (auto value : values) {
if (first) {
ss << "\t";
first = false;
}
else
ss << " | ";
switch (value.type()) {
case TypedValue::Type::Vertex: {
auto va = value.Value<VertexAccessor>();
ss << "Vertex(";
for (auto label : va.labels())
ss << ":" << va.db_accessor().label_name(label) << " ";
ss << "{";
for (auto kv : va.Properties()) {
ss << va.db_accessor().property_name(kv.first) << ": ";
ss << kv.second << ", ";
}
ss << "}";
ss << ")";
break;
}
case TypedValue::Type::Edge: {
auto ea = value.Value<EdgeAccessor>();
ss << "Edge[" << ea.db_accessor().edge_type_name(ea.edge_type()) << "}";
ss << "{";
for (auto kv : ea.Properties()) {
ss << ea.db_accessor().property_name(kv.first) << ": ";
ss << kv.second << ", ";
}
ss << "}";
ss << "]";
break;
}
case TypedValue::Type::List:break;
case TypedValue::Type::Map:break;
case TypedValue::Type::Path:break;
default:
ss << value;
}
}
logger.info("{}", ss.str());
}
void Summary(const std::map<std::string, TypedValue> &summary) {
std::stringstream ss;
ss << "Summary {";
bool first = true;
for (auto kv : summary)
ss << kv.first << " : " << kv.second << ", ";
ss << "}";
logger.info("{}", ss.str());
}
};
int main(int argc, char* argv[]) {
// init arguments
REGISTER_ARGS(argc, argv);
@ -21,8 +93,7 @@ int main(int argc, char* argv[]) {
// init db context
Dbms dbms;
query::ConsoleResultStream stream;
query::Engine<query::ConsoleResultStream> query_engine;
ConsoleResultStream stream;
// initialize the database
auto dba = dbms.active();
@ -42,20 +113,20 @@ int main(int argc, char* argv[]) {
memgraph.PropsSet(name, "Memgraph");
memgraph.add_label(company);
auto teon = dba->insert_vertex();
memgraph.PropsSet(name, "Teon");
memgraph.PropsSet(age, 26);
teon.PropsSet(name, "Teon");
teon.PropsSet(age, 26);
teon.add_label(person);
auto mislav = dba->insert_vertex();
memgraph.PropsSet(name, "Mislav");
memgraph.PropsSet(age, 22);
mislav.PropsSet(name, "Mislav");
mislav.PropsSet(age, 22);
mislav.add_label(person);
auto florijan = dba->insert_vertex();
memgraph.PropsSet(name, "Florijan");
memgraph.PropsSet(age, 31);
florijan.PropsSet(name, "Florijan");
florijan.PropsSet(age, 31);
florijan.add_label(person);
auto xps_15 = dba->insert_vertex();
memgraph.PropsSet(type, "PC");
memgraph.PropsSet(name, "Dell XPS 15");
xps_15.PropsSet(type, "PC");
xps_15.PropsSet(name, "Dell XPS 15");
xps_15.add_label(device);
// edges
@ -76,11 +147,12 @@ int main(int argc, char* argv[]) {
dba->insert_edge(mislav, xps_15, dba->edge_type("USES"));
dba->insert_edge(florijan, xps_15, dba->edge_type("USES"));
dba->advance_command();
dba->commit();
cout << "-- Memgraph Query Engine --" << endl;
while (true) {
auto inner_dba = dbms.active();
// read command
cout << "> ";
std::string command;
@ -89,7 +161,8 @@ int main(int argc, char* argv[]) {
// execute command / query
// try {
// auto db_accessor = dbms.active();
query_engine.Execute(command, *dba, stream);
query::Interpret(command, *inner_dba, stream);
inner_dba->commit();
// } catch (const std::exception& e) {
// cout << e.what() << endl;
// } catch (...) {

View File

@ -12,7 +12,11 @@
#include "communication/result_stream_faker.hpp"
#include "dbms/dbms.hpp"
#include "query/entry.hpp"
#include "query/context.hpp"
#include "query/frontend/interpret/interpret.hpp"
#include "query/frontend/logical/planner.hpp"
#include "query/frontend/opencypher/parser.hpp"
#include "query/frontend/semantic/symbol_generator.hpp"
using namespace query;