Serialize Ast via SLK

Reviewers: mtomic, llugovic

Reviewed By: mtomic

Subscribers: pullbot

Differential Revision: https://phabricator.memgraph.io/D1764
This commit is contained in:
Teon Banek 2018-12-11 17:13:28 +01:00
parent 00506b9962
commit 8ed1e3509d
5 changed files with 2861 additions and 135 deletions

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,8 @@
#>cpp
#pragma once
#include <type_traits>
#include "query/frontend/ast/ast.hpp"
#include "query/frontend/ast/ast_serialization.capnp.h"
#include "query/serialization.hpp"
@ -12,12 +14,72 @@ cpp<#
(lcp:namespace query)
#>cpp
/// Primary function for saving Ast nodes via SLK.
void SaveAstPointer(const Tree *ast, slk::Builder *builder,
std::vector<int32_t> *saved_uids);
Tree *Load(AstStorage *ast, const capnp::Tree::Reader &tree,
std::vector<int> *loaded_uids);
std::vector<int32_t> *loaded_uids);
Tree *Load(AstStorage *ast, slk::Reader *reader,
std::vector<int32_t> *loaded_uids);
/// Primary function for loading Ast nodes via SLK.
template <class TAst>
TAst *LoadAstPointer(AstStorage *ast, slk::Reader *reader,
std::vector<int32_t> *loaded_uids) {
static_assert(std::is_base_of<query::Tree, TAst>::value);
bool has_ptr = false;
slk::Load(&has_ptr, reader);
if (!has_ptr) {
return nullptr;
}
auto *ret = dynamic_cast<TAst *>(Load(ast, reader, loaded_uids));
if (!ret) {
throw slk::SlkDecodeException("Loading unknown Ast node type");
}
return ret;
}
cpp<#
(lcp:in-impl
#>cpp
void SaveAstPointer(const Tree *ast, slk::Builder *builder,
std::vector<int32_t> *saved_uids) {
slk::Save(static_cast<bool>(ast), builder);
if (!ast) {
return;
}
slk::Save(ast->uid_, builder);
if (utils::Contains(*saved_uids, ast->uid_)) {
return;
}
slk::Save(*ast, builder, saved_uids);
CHECK(!utils::Contains(*saved_uids, ast->uid_)) << "Serializing cyclic AST";
saved_uids->push_back(ast->uid_);
}
Tree *Load(AstStorage *ast, slk::Reader *reader,
std::vector<int32_t> *loaded_uids) {
// Check if element already deserialized and if yes, return existing
// element from storage.
int32_t uid;
slk::Load(&uid, reader);
if (utils::Contains(*loaded_uids, uid)) {
auto found = std::find_if(ast->storage_.begin(), ast->storage_.end(),
[&](const auto &n) { return n->uid_ == uid; });
CHECK(found != ast->storage_.end());
return found->get();
}
std::unique_ptr<Tree> root;
slk::ConstructAndLoad(&root, reader, ast, loaded_uids);
root->uid_ = uid;
ast->storage_.emplace_back(std::move(root));
loaded_uids->push_back(uid);
ast->max_existing_uid_ = std::max(ast->max_existing_uid_, uid);
return ast->storage_.back().get();
}
Tree *Load(AstStorage *ast, const capnp::Tree::Reader &tree,
std::vector<int> *loaded_uids) {
// Check if element already deserialized and if yes, return existing

View File

@ -19,6 +19,9 @@ function(add_unit_test test_cpp)
add_dependencies(memgraph__unit ${target_name})
endfunction(add_unit_test)
add_unit_test(ast_serialization.cpp)
target_link_libraries(${test_prefix}ast_serialization mg-distributed kvstore_dummy_lib)
add_unit_test(bolt_encoder.cpp)
target_link_libraries(${test_prefix}bolt_encoder mg-single-node kvstore_dummy_lib)

File diff suppressed because it is too large Load Diff

View File

@ -11,17 +11,11 @@
#include "query/context.hpp"
#include "query/frontend/ast/ast.hpp"
// TODO: FIXME
// #include "query/frontend/ast/ast_serialization.hpp"
#include "query/frontend/ast/cypher_main_visitor.hpp"
#include "query/frontend/opencypher/parser.hpp"
#include "query/frontend/stripped.hpp"
#include "query/typed_value.hpp"
// TODO: FIXME
// #include "capnp/message.h"
// #include "query/frontend/ast/ast_serialization.capnp.h"
namespace {
using namespace query;
@ -140,52 +134,13 @@ class CachedAstGenerator : public Base {
Query *query_;
};
/* TODO: FIXME
class CapnpAstGenerator : public Base {
public:
CapnpAstGenerator(const std::string &query)
: Base(query),
storage_([&]() {
::frontend::opencypher::Parser parser(query);
CypherMainVisitor visitor(context_, db_accessor_.get());
visitor.visit(parser.tree());
::capnp::MallocMessageBuilder message;
{
query::capnp::Tree::Builder builder =
message.initRoot<query::capnp::Tree>();
std::vector<int> saved_uids;
Save(*visitor.query(), &builder, &saved_uids);
}
AstStorage new_ast;
{
const query::capnp::Tree::Reader reader =
message.getRoot<query::capnp::Tree>();
std::vector<int> loaded_uids;
Load(&new_ast, reader, &loaded_uids);
}
return new_ast;
}()),
query_(storage_.query()) {}
AstStorage storage_;
Query *query_;
};
*/
template <typename T>
class CypherMainVisitorTest : public ::testing::Test {};
/* TODO: FIXME I have removed `CapnpAstGenerator` from the lower list
typedef ::testing::Types<AstGenerator, OriginalAfterCloningAstGenerator,
ClonedAstGenerator, CachedAstGenerator,
CapnpAstGenerator>
AstGeneratorTypes;
*/
typedef ::testing::Types<AstGenerator, OriginalAfterCloningAstGenerator,
ClonedAstGenerator, CachedAstGenerator>
AstGeneratorTypes;
TYPED_TEST_CASE(CypherMainVisitorTest, AstGeneratorTypes);
TYPED_TEST(CypherMainVisitorTest, SyntaxException) {