First version which will be sent to the pilot users

This commit is contained in:
Marko Budiselic 2016-08-30 20:52:46 +01:00
parent 035e508840
commit 781376a960
15 changed files with 114 additions and 22 deletions

View File

@ -9,6 +9,8 @@ namespace bolt
class Error : public State
{
public:
Error();
State *run(Session &session) override;
};

View File

@ -20,12 +20,10 @@ public:
State* run(Session& session) override final;
protected:
Logger logger;
/* Execute an incoming query
*
*/
void run(Session& session, Query& query);
State* run(Session& session, Query& query);
/* Send all remaining results to the client
*

View File

@ -4,6 +4,8 @@
#include <cstdint>
#include <memory>
#include "logging/default.hpp"
namespace bolt
{
@ -15,9 +17,14 @@ public:
using uptr = std::unique_ptr<State>;
State() = default;
State(Logger logger) : logger(logger) {}
virtual ~State() = default;
virtual State* run(Session& session) = 0;
protected:
Logger logger;
};
}

View File

@ -249,7 +249,7 @@ public:
void message_ignored()
{
write_struct_header(1);
write_struct_header(0);
write(underlying_cast(MessageCode::Ignored));
}

View File

@ -42,6 +42,7 @@ enum class EntitySource : uint8_t
None,
InternalId,
LabelIndex,
TypeIndex,
MainStorage
};

View File

@ -26,6 +26,7 @@ using cost_t = uint64_t;
constexpr cost_t internal_id_cost = 10;
constexpr cost_t property_cost = 100;
constexpr cost_t label_cost = 1000;
constexpr cost_t type_cost = 1000;
constexpr cost_t max_cost = max<cost_t>();
template <typename T>
@ -36,6 +37,7 @@ public:
{
internal_id,
label_index,
type_index,
property_index,
main_storage
};
@ -47,6 +49,7 @@ public:
{
costs[SearchPlace::internal_id] = max<T>();
costs[SearchPlace::label_index] = max<T>();
costs[SearchPlace::type_index] = max<T>();
costs[SearchPlace::property_index] = max<T>();
costs[SearchPlace::main_storage] = max<T>();
}
@ -80,6 +83,7 @@ using search_cost_t = SearchCost<cost_t>;
constexpr auto search_internal_id = search_cost_t::SearchPlace::internal_id;
constexpr auto search_label_index = search_cost_t::SearchPlace::label_index;
constexpr auto search_type_index = search_cost_t::SearchPlace::type_index;
constexpr auto search_property_index =
search_cost_t::SearchPlace::property_index;
constexpr auto search_main_storage = search_cost_t::SearchPlace::main_storage;

View File

@ -32,6 +32,7 @@ auto match_query_action =
auto name = kv.first;
// TODO: duplicated code -> BIG PROBLEM
// find node
if (kv.second == ClauseAction::MatchNode) {
if (already_matched(cypher_data, name, EntityType::Node))
@ -69,6 +70,13 @@ auto match_query_action =
if (place == entity_search::search_main_storage) {
cypher_data.source(name, EntitySource::MainStorage);
}
if (place == entity_search::search_type_index) {
if (action_data.entity_data.at(name).tags.size() > 1) {
throw SemanticError("Multiple type match (currently NOT supported)");
}
cypher_data.source(name, EntitySource::TypeIndex);
cypher_data.tags(name, action_data.entity_data.at(name).tags);
}
}
}

View File

@ -43,12 +43,23 @@ auto return_query_action =
{
if (cypher_data.type(entity) == EntityType::Node) {
if (cypher_data.tags(entity).size() == 0)
throw CppGeneratorException("entity has no tags");
throw CppGeneratorException("node has no labels");
auto label = cypher_data.tags(entity).at(0);
code += code_line(code::fine_and_write_vertices_by_label,
code += code_line(code::find_and_write_vertices_by_label,
entity, label);
}
}
if (cypher_data.source(entity) == EntitySource::TypeIndex)
{
if (cypher_data.type(entity) == EntityType::Relationship) {
if (cypher_data.tags(entity).size() == 0)
throw CppGeneratorException("edge has no tag");
auto type = cypher_data.tags(entity).at(0);
code += code_line(code::find_and_write_edges_by_type,
entity, type);
}
}
}
else if (element.is_projection())
{

View File

@ -332,13 +332,13 @@ auto load_queries(Db &db)
if (it_type.count() > it_vertex.count()) {
// Going through vertices wiil probably be faster
it_vertex.to().for_all([&](auto m) {
// PRINT n,m
// PRINT n, m
});
} else {
// Going through edges wiil probably be faster
it_type.to().for_all([&](auto m) {
// PRINT n,m
// PRINT n, m
});
}

View File

@ -71,7 +71,7 @@ const std::string write_all_vertices =
" }});\n"
" stream.write_meta(\"rw\");\n";
const std::string fine_and_write_vertices_by_label =
const std::string find_and_write_vertices_by_label =
"auto &label = t.label_find_or_create(\"{1}\");\n"
" stream.write_field(\"{0}\");\n"
" label.index().for_range(t)->for_all([&](auto vertex) {{\n"
@ -94,6 +94,17 @@ const std::string write_all_edges =
" }});\n"
" stream.write_meta(\"rw\");\n";
const std::string find_and_write_edges_by_type =
"auto &type = t.type_find_or_create(\"{1}\");\n"
" stream.write_field(\"{0}\");\n"
" type.index().for_range(t)->for_all([&](auto edge) {{\n"
" stream.write_record();\n"
" stream.write_list_header(1);\n"
" stream.write(edge);\n"
" stream.chunk();\n"
" }});\n"
" stream.write_meta(\"rw\");\n";
const std::string return_true = "return true;";
const std::string todo = "// TODO: {}";

View File

@ -358,11 +358,14 @@ public:
void visit(ast::RelationshipTypeList &ast_relationship_type_list) override
{
auto &data = generator.action_data();
auto &action_data = generator.action_data();
if (ast_relationship_type_list.has_value()) {
auto type = ast_relationship_type_list.value->name;
data.add_entity_tag(entity, type);
action_data.add_entity_tag(entity, type);
action_data.csm.search_cost(
entity, entity_search::search_type_index,
entity_search::type_cost);
}
Traverser::visit(ast_relationship_type_list);

View File

@ -9,16 +9,26 @@
class BasicException : public std::exception
{
public:
BasicException(const std::string& message) noexcept : message(message)
BasicException(const std::string& message) noexcept
: message(message),
stacktrace_size(3)
{
#ifndef NDEBUG
this->message += '\n';
Stacktrace stacktrace;
for(auto& line : stacktrace)
// TODO: write this better
// (limit the size of stacktrace)
uint64_t count = 0;
for(auto& line : stacktrace) {
this->message += fmt::format(" at {} ({})\n",
line.function, line.location);
if (++count >= stacktrace_size)
break;
}
#endif
}
@ -33,5 +43,6 @@ public:
private:
std::string message;
uint64_t stacktrace_size;
};

View File

@ -3,13 +3,28 @@
namespace bolt
{
Error::Error() : State(logging::log->logger("Error State")) {}
State* Error::run(Session& session)
{
logger.trace("Run");
session.decoder.read_byte();
auto message_type = session.decoder.read_byte();
if(message_type == MessageCode::AckFailure)
logger.trace("Message type byte is: {:02X}", message_type);
if (message_type == MessageCode::PullAll)
{
session.output_stream.write_ignored();
session.output_stream.chunk();
session.output_stream.send();
return this;
}
else if(message_type == MessageCode::AckFailure)
{
// TODO reset current statement? is it even necessary?
logger.trace("AckFailure received");
session.output_stream.write_success_empty();
session.output_stream.chunk();

View File

@ -8,7 +8,7 @@
namespace bolt
{
Executor::Executor() : logger(logging::log->logger("Executor")) {}
Executor::Executor() : State(logging::log->logger("Executor")) {}
State *Executor::run(Session &session)
{
@ -25,15 +25,22 @@ State *Executor::run(Session &session)
q.statement = session.decoder.read_string();
this->run(session, q);
try {
return this->run(session, q);
} catch (QueryEngineException &e) {
session.output_stream.write_failure(
{{"code", "Memgraph.QueryEngineException"},
{"message", e.what()}});
session.output_stream.send();
return session.bolt.states.error.get();
}
} else if (message_type == MessageCode::PullAll) {
pull_all(session);
} else if (message_type == MessageCode::DiscardAll) {
discard_all(session);
} else if (message_type == MessageCode::Reset) {
// todo rollback current transaction
// TODO: rollback current transaction
// discard all records waiting to be sent
return this;
} else {
logger.error("Unrecognized message recieved");
@ -45,20 +52,28 @@ State *Executor::run(Session &session)
return this;
}
void Executor::run(Session &session, Query &query)
State* Executor::run(Session &session, Query &query)
{
logger.trace("[Run] '{}'", query.statement);
auto &db = session.active_db();
logger.debug("[ActiveDB] '{}'", db.name());
try {
auto is_successfully_executed =
query_engine.execute(query.statement, db, session.output_stream);
} catch (QueryEngineException &e) {
if (!is_successfully_executed) {
session.output_stream.write_failure(
{{"code", "unknown"}, {"message", e.what()}});
{{"code", "Memgraph.QueryExecutionFail"},
{"message", "Query execution has failed (probably there is no "
"element or there are some problems with concurrent "
"access -> client has to resolve problems with "
"concurrent access)"}});
session.output_stream.send();
return session.bolt.states.error.get();
}
return this;
}
void Executor::pull_all(Session &session)

View File

@ -21,14 +21,20 @@ queries.append((True, "MATCH (n) WHERE ID(n)=2 RETURN n"))
queries.append((True, "MATCH (n) WHERE ID(n)=3 RETURN n"))
queries.append((True, "MATCH (n) WHERE ID(n)=4 RETURN n"))
queries.append((True, "MATCH (n) WHERE ID(n)=5 RETURN n"))
queries.append((True, "MATCH (n) RETURN n"));
queries.append((True, "MATCH (n:PERSON) RETURN n"));
queries.append((True, "MATCH (n1), (n2) WHERE ID(n1)=0 AND ID(n2)=1 CREATE (n1)-[r:IS]->(n2) RETURN r"))
queries.append((True, "MATCH (n1), (n2) WHERE ID(n1)=1 AND ID(n2)=2 CREATE (n1)-[r:IS {name: \"test\", age: 23}]->(n2) RETURN r"))
queries.append((True, "MATCH (n1), (n2) WHERE ID(n1)=2 AND ID(n2)=0 CREATE (n1)-[r:IS {name: \"test\", age: 23}]->(n2) RETURN r"))
queries.append((True, "MATCH (n1), (n2) WHERE ID(n1)=2 AND ID(n2)=0 CREATE (n1)-[r:ARE {name: \"test\", age: 23}]->(n2) RETURN r"))
queries.append((True, "MATCH ()-[r]-() WHERE ID(r)=0 RETURN r"))
queries.append((True, "MATCH ()-[r]-() WHERE ID(r)=1 RETURN r"))
queries.append((True, "MATCH ()-[r]-() WHERE ID(r)=2 RETURN r"))
queries.append((True, "MATCH ()-[r:IS]-() RETURN r"))
queries.append((True, "MATCH ()-[r:ARE]-() RETURN r"))
queries.append((True, "MATCH ()-[r]-() RETURN r"))
queries.append((True, "MATCH (n) WHERE ID(n)=1 SET n.name = \"updated_name\" RETURN n"))
queries.append((True, "MATCH (n) WHERE ID(n)=1 RETURN n"))