Add generating Capnp schema in LCP

Summary:
Add additional structs and functions for handling C++ meta information.
Add capnp-file and capnp-id arguments to lcp:process-file.
Generate cpp along with hpp and capnp in lcp.
Wrap LogicalOperator base class in lcp:define-class.
Modify logical operators for capnp serialization.
Add query/common.capnp.

Reviewers: mculinovic, buda, mtomic, msantl, ipaljak, dgleich, mferencevic

Reviewed By: msantl

Subscribers: pullbot

Differential Revision: https://phabricator.memgraph.io/D1391
This commit is contained in:
Teon Banek 2018-05-16 13:48:56 +02:00
parent c7b6cae526
commit e56ed0acce
16 changed files with 1917 additions and 426 deletions

4
.gitignore vendored
View File

@ -38,5 +38,7 @@ TAGS
*.capnp.c++
*.capnp.h
# LCP generated C++ files
# LCP generated C++ & Cap'n Proto files
src/query/plan/operator.hpp
src/query/plan/operator.lcp.cpp
src/query/plan/operator.capnp

View File

@ -73,30 +73,6 @@ set(memgraph_src_files
)
# -----------------------------------------------------------------------------
# Lisp C++ Preprocessing
set(lcp_exe ${CMAKE_SOURCE_DIR}/tools/lcp)
set(lcp_src_files lisp/lcp.lisp ${lcp_exe})
# Use this function to add each lcp file to generation. This way each file is
# standalone and we avoid recompiling everything.
# NOTE: Only .hpp files are generated from .lcp, so there's no need to update memgraph_src_files.
# NOTE: generated_lcp_files are globally updated.
function(add_lcp lcp_file)
string(REGEX REPLACE "\.lcp$" ".hpp" h_file
"${CMAKE_CURRENT_SOURCE_DIR}/${lcp_file}")
add_custom_command(OUTPUT ${h_file}
COMMAND ${lcp_exe} ${lcp_file} > ${h_file}
DEPENDS ${lcp_file} ${lcp_src_files}
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
# Update *global* generated_lcp_files
set(generated_lcp_files ${generated_lcp_files} ${h_file} PARENT_SCOPE)
endfunction(add_lcp)
add_lcp(query/plan/operator.lcp)
add_custom_target(generate_lcp DEPENDS ${generated_lcp_files})
# Use this function to add each capnp file to generation. This way each file is
# standalone and we avoid recompiling everything.
# NOTE: memgraph_src_files and generated_capnp_files are globally updated.
@ -105,7 +81,7 @@ function(add_capnp capnp_src_file)
set(h_file ${CMAKE_CURRENT_SOURCE_DIR}/${capnp_src_file}.h)
add_custom_command(OUTPUT ${cpp_file} ${h_file}
COMMAND ${CAPNP_EXE} compile -o${CAPNP_CXX_EXE} ${capnp_src_file} -I ${CMAKE_CURRENT_SOURCE_DIR}
DEPENDS ${capnp_src_file} capnproto-proj
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${capnp_src_file} capnproto-proj
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
# Update *global* generated_capnp_files
set(generated_capnp_files ${generated_capnp_files} ${cpp_file} ${h_file} PARENT_SCOPE)
@ -113,12 +89,52 @@ function(add_capnp capnp_src_file)
set(memgraph_src_files ${memgraph_src_files} ${cpp_file} PARENT_SCOPE)
endfunction(add_capnp)
# Lisp C++ Preprocessing
set(lcp_exe ${CMAKE_SOURCE_DIR}/tools/lcp)
set(lcp_src_files lisp/lcp.lisp ${lcp_exe})
# Use this function to add each lcp file to generation. This way each file is
# standalone and we avoid recompiling everything.
# NOTE: memgraph_src_files and generated_lcp_files are globally updated.
function(add_lcp lcp_file)
set(options CAPNP_SCHEMA)
cmake_parse_arguments(KW "${options}" "" "" ${ARGN})
string(REGEX REPLACE "\.lcp$" ".hpp" h_file
"${CMAKE_CURRENT_SOURCE_DIR}/${lcp_file}")
if (KW_CAPNP_SCHEMA)
string(REGEX REPLACE "\.lcp$" ".capnp" capnp_file
"${CMAKE_CURRENT_SOURCE_DIR}/${lcp_file}")
set(capnp_id_command ${CAPNP_EXE})
set(capnp_depend capnproto-proj)
set(cpp_file ${CMAKE_CURRENT_SOURCE_DIR}/${lcp_file}.cpp)
# Update *global* memgraph_src_files
set(memgraph_src_files ${memgraph_src_files} ${cpp_file} PARENT_SCOPE)
endif()
add_custom_command(OUTPUT ${h_file} ${cpp_file} ${capnp_file}
COMMAND ${lcp_exe} ${lcp_file} ${capnp_id_command}
VERBATIM
DEPENDS ${lcp_file} ${lcp_src_files} ${capnp_depend}
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
# Update *global* generated_lcp_files
set(generated_lcp_files ${generated_lcp_files} ${h_file} ${cpp_file} ${capnp_file} PARENT_SCOPE)
endfunction(add_lcp)
add_lcp(query/plan/operator.lcp CAPNP_SCHEMA)
add_capnp(query/plan/operator.capnp)
add_custom_target(generate_lcp DEPENDS ${generated_lcp_files})
# Registering capnp must come after registering lcp files.
add_capnp(query/frontend/semantic/symbol.capnp)
add_capnp(query/frontend/ast/ast.capnp)
add_capnp(utils/serialization.capnp)
add_capnp(storage/types.capnp)
add_capnp(query/common.capnp)
add_custom_target(generate_capnp DEPENDS generate_lcp ${generated_capnp_files})
add_custom_target(generate_capnp DEPENDS ${generated_capnp_files})
# -----------------------------------------------------------------------------
string(TOLOWER ${CMAKE_BUILD_TYPE} lower_build_type)

File diff suppressed because it is too large Load Diff

15
src/query/common.capnp Normal file
View File

@ -0,0 +1,15 @@
@0xcbc2c66202fdf643;
using Cxx = import "/capnp/c++.capnp";
$Cxx.namespace("query::capnp");
using Ast = import "/query/frontend/ast/ast.capnp";
enum GraphView {
old @0;
new @1;
}
struct TypedValueVectorCompare {
ordering @0 :List(Ast.Ordering);
}

View File

@ -8,6 +8,7 @@
#include "glog/logging.h"
#include "query/exceptions.hpp"
#include "utils/serialization.hpp"
#include "utils/string.hpp"
namespace query {
@ -280,6 +281,28 @@ bool TypedValueVectorCompare::TypedValueCompare(const TypedValue &a,
}
}
void TypedValueVectorCompare::Save(
capnp::TypedValueVectorCompare::Builder *builder) const {
auto ordering_builder = builder->initOrdering(ordering_.size());
for (size_t i = 0; i < ordering_.size(); ++i) {
ordering_builder.set(i, ordering_[i] == Ordering::ASC
? capnp::Ordering::ASC
: capnp::Ordering::DESC);
}
}
void TypedValueVectorCompare::Load(
const capnp::TypedValueVectorCompare::Reader &reader) {
std::vector<Ordering> ordering;
ordering.reserve(reader.getOrdering().size());
for (auto ordering_reader : reader.getOrdering()) {
ordering.push_back(ordering_reader == capnp::Ordering::ASC
? Ordering::ASC
: Ordering::DESC);
}
ordering_ = ordering;
}
template <typename TAccessor>
void SwitchAccessor(TAccessor &accessor, GraphView graph_view) {
switch (graph_view) {

View File

@ -7,6 +7,8 @@
#include "query/frontend/ast/ast.hpp"
#include "query/typed_value.hpp"
#include "query/common.capnp.h"
namespace query {
// These are the functions for parsing literals and parameter names from
@ -37,7 +39,7 @@ void ReconstructTypedValue(TypedValue &value);
// Does lexicographical ordering of elements based on the above
// defined TypedValueCompare, and also accepts a vector of Orderings
// the define how respective elements compare.
class TypedValueVectorCompare {
class TypedValueVectorCompare final {
public:
TypedValueVectorCompare() {}
explicit TypedValueVectorCompare(const std::vector<Ordering> &ordering)
@ -47,6 +49,9 @@ class TypedValueVectorCompare {
const auto &ordering() const { return ordering_; }
void Save(capnp::TypedValueVectorCompare::Builder *builder) const;
void Load(const capnp::TypedValueVectorCompare::Reader &reader);
private:
std::vector<Ordering> ordering_;

View File

@ -309,7 +309,7 @@ void MapLiteral::Save(capnp::BaseLiteral::Builder *base_literal_builder,
auto key_builder = entry_builder.getKey();
key_builder.setFirst(entry.first.first);
auto storage_property_builder = key_builder.getSecond();
entry.first.second.Save(storage_property_builder);
entry.first.second.Save(&storage_property_builder);
auto value_builder = entry_builder.getValue();
if (entry.second) entry.second->Save(&value_builder, saved_uids);
++i;
@ -976,11 +976,10 @@ void LabelsTest::Save(capnp::LabelsTest::Builder *builder,
auto expr_builder = builder->initExpression();
expression_->Save(&expr_builder, saved_uids);
}
::capnp::List<storage::capnp::Common>::Builder common_builders =
builder->initLabels(labels_.size());
auto common_builders = builder->initLabels(labels_.size());
for (size_t i = 0; i < labels_.size(); ++i) {
auto common_builder = common_builders[i];
labels_[i].Save(common_builder);
labels_[i].Save(&common_builder);
}
}
@ -1040,7 +1039,7 @@ void PropertyLookup::Save(capnp::PropertyLookup::Builder *builder,
}
builder->setPropertyName(property_name_);
auto storage_property_builder = builder->initProperty();
property_.Save(storage_property_builder);
property_.Save(&storage_property_builder);
}
void PropertyLookup::Load(const capnp::Tree::Reader &base_reader,
@ -1297,9 +1296,9 @@ void CreateIndex::Save(capnp::Clause::Builder *builder,
void CreateIndex::Save(capnp::CreateIndex::Builder *builder,
std::vector<int> *saved_uids) {
auto label_builder = builder->getLabel();
label_.Save(label_builder);
label_.Save(&label_builder);
auto property_builder = builder->getProperty();
property_.Save(property_builder);
property_.Save(&property_builder);
}
CreateIndex *CreateIndex::Construct(const capnp::CreateIndex::Reader &reader,
@ -1458,13 +1457,13 @@ void RemoveLabels::Save(capnp::RemoveLabels::Builder *builder,
auto id_builder = builder->getIdentifier();
identifier_->Save(&id_builder, saved_uids);
}
::capnp::List<storage::capnp::Common>::Builder common_builders =
builder->initLabels(labels_.size());
auto common_builders = builder->initLabels(labels_.size());
for (size_t i = 0; i < labels_.size(); ++i) {
auto common_builder = common_builders[i];
labels_[i].Save(common_builder);
labels_[i].Save(&common_builder);
}
}
void RemoveLabels::Load(const capnp::Tree::Reader &base_reader,
AstTreeStorage *storage,
std::vector<int> *loaded_uids) {
@ -1628,11 +1627,10 @@ void SetLabels::Save(capnp::SetLabels::Builder *builder,
auto id_builder = builder->getIdentifier();
identifier_->Save(&id_builder, saved_uids);
}
::capnp::List<storage::capnp::Common>::Builder common_builders =
builder->initLabels(labels_.size());
auto common_builders = builder->initLabels(labels_.size());
for (size_t i = 0; i < labels_.size(); ++i) {
auto common_builder = common_builders[i];
labels_[i].Save(common_builder);
labels_[i].Save(&common_builder);
}
}
@ -1827,11 +1825,10 @@ void CypherUnion::Save(capnp::CypherUnion::Builder *builder,
single_query_->Save(&sq_builder, saved_uids);
}
builder->setDistinct(distinct_);
::capnp::List<capnp::Symbol>::Builder symbol_builders =
builder->initUnionSymbols(union_symbols_.size());
auto symbol_builders = builder->initUnionSymbols(union_symbols_.size());
for (size_t i = 0; i < union_symbols_.size(); ++i) {
auto symbol_builder = symbol_builders[i];
union_symbols_[i].Save(symbol_builder);
union_symbols_[i].Save(&symbol_builder);
}
}
@ -2007,16 +2004,15 @@ void NodeAtom::Save(capnp::NodeAtom::Builder *builder,
auto key_builder = entry_builder.getKey();
key_builder.setFirst(entry.first.first);
auto storage_property_builder = key_builder.getSecond();
entry.first.second.Save(storage_property_builder);
entry.first.second.Save(&storage_property_builder);
auto value_builder = entry_builder.getValue();
if (entry.second) entry.second->Save(&value_builder, saved_uids);
++i;
}
::capnp::List<storage::capnp::Common>::Builder common_builders =
builder->initLabels(labels_.size());
auto common_builders = builder->initLabels(labels_.size());
for (size_t i = 0; i < labels_.size(); ++i) {
auto common_builder = common_builders[i];
labels_[i].Save(common_builder);
labels_[i].Save(&common_builder);
}
}
@ -2102,11 +2098,10 @@ void EdgeAtom::Save(capnp::EdgeAtom::Builder *builder,
break;
}
::capnp::List<storage::capnp::Common>::Builder common_builders =
builder->initEdgeTypes(edge_types_.size());
auto common_builders = builder->initEdgeTypes(edge_types_.size());
for (size_t i = 0; i < edge_types_.size(); ++i) {
auto common_builder = common_builders[i];
edge_types_[i].Save(common_builder);
edge_types_[i].Save(&common_builder);
}
::capnp::List<capnp::EdgeAtom::Entry>::Builder map_builder =
@ -2117,7 +2112,7 @@ void EdgeAtom::Save(capnp::EdgeAtom::Builder *builder,
auto key_builder = entry_builder.getKey();
key_builder.setFirst(entry.first.first);
auto storage_property_builder = key_builder.getSecond();
entry.first.second.Save(storage_property_builder);
entry.first.second.Save(&storage_property_builder);
auto value_builder = entry_builder.getValue();
if (entry.second) entry.second->Save(&value_builder, saved_uids);
++i;

View File

@ -42,29 +42,29 @@ class Symbol {
bool user_declared() const { return user_declared_; }
int token_position() const { return token_position_; }
void Save(capnp::Symbol::Builder &builder) {
builder.setName(name_);
builder.setPosition(position_);
builder.setUserDeclared(user_declared_);
builder.setTokenPosition(token_position_);
void Save(capnp::Symbol::Builder *builder) const {
builder->setName(name_);
builder->setPosition(position_);
builder->setUserDeclared(user_declared_);
builder->setTokenPosition(token_position_);
switch (type_) {
case Type::Any:
builder.setType(capnp::Symbol::Type::ANY);
builder->setType(capnp::Symbol::Type::ANY);
break;
case Type::Edge:
builder.setType(capnp::Symbol::Type::EDGE);
builder->setType(capnp::Symbol::Type::EDGE);
break;
case Type::EdgeList:
builder.setType(capnp::Symbol::Type::EDGE_LIST);
builder->setType(capnp::Symbol::Type::EDGE_LIST);
break;
case Type::Number:
builder.setType(capnp::Symbol::Type::NUMBER);
builder->setType(capnp::Symbol::Type::NUMBER);
break;
case Type::Path:
builder.setType(capnp::Symbol::Type::PATH);
builder->setType(capnp::Symbol::Type::PATH);
break;
case Type::Vertex:
builder.setType(capnp::Symbol::Type::VERTEX);
builder->setType(capnp::Symbol::Type::VERTEX);
break;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -56,11 +56,11 @@ class Common : public utils::TotalOrdering<TSpecificType> {
size_t operator()(const TSpecificType &t) const { return hash(t.id_); }
};
virtual void Save(capnp::Common::Builder &builder) const {
builder.setStorage(id_);
virtual void Save(capnp::Common::Builder *builder) const {
builder->setStorage(id_);
}
virtual void Load(capnp::Common::Reader &reader) {
virtual void Load(const capnp::Common::Reader &reader) {
id_ = reader.getStorage();
}

View File

@ -62,7 +62,8 @@ struct SharedPtr(T) {
}
}
# TypedValue.
# Our types
struct TypedValue {
union {
nullType @0 :Void;
@ -82,3 +83,13 @@ struct TypedValue {
value @1 :TypedValue;
}
}
struct Bound(T) {
type @0 :Type;
value @1 :T;
enum Type {
inclusive @0;
exclusive @1;
}
}

View File

@ -203,13 +203,13 @@ inline void SaveUniquePtr(
template <typename TCapnp, typename T>
inline std::unique_ptr<T> LoadUniquePtr(
const typename capnp::UniquePtr<TCapnp>::Reader &reader,
const std::function<T(const typename TCapnp::Reader &reader)> &load) {
const std::function<T*(const typename TCapnp::Reader &reader)> &load) {
switch (reader.which()) {
case capnp::UniquePtr<TCapnp>::NULLPTR:
return nullptr;
case capnp::UniquePtr<TCapnp>::VALUE:
auto value_reader = reader.getValue();
return std::make_unique<T>(load(value_reader));
return std::unique_ptr<T>(load(value_reader));
}
}
@ -236,9 +236,9 @@ inline void SaveSharedPtr(
}
template <typename TCapnp, typename T>
inline std::shared_ptr<T> LoadSharedPtr(
std::shared_ptr<T> LoadSharedPtr(
const typename capnp::SharedPtr<TCapnp>::Reader &reader,
const std::function<T(const typename TCapnp::Reader &reader)> &load,
const std::function<T *(const typename TCapnp::Reader &reader)> &load,
std::vector<std::pair<uint64_t, std::shared_ptr<T>>> *loaded_pointers) {
std::shared_ptr<T> ret;
switch (reader.which()) {
@ -255,7 +255,7 @@ inline std::shared_ptr<T> LoadSharedPtr(
});
if (found != loaded_pointers->end()) return found->second;
auto value_reader = entry_reader.getValue();
ret = std::make_shared<T>(load(value_reader));
ret = std::shared_ptr<T>(load(value_reader));
loaded_pointers->emplace_back(std::make_pair(pointer_id, ret));
}
return ret;

View File

@ -19,7 +19,6 @@
#include "query/typed_value.hpp"
#include "capnp/message.h"
#include "capnp/serialize-packed.h"
#include "query/frontend/ast/ast.capnp.h"
namespace {

View File

@ -17,6 +17,9 @@
#include "query/plan/operator.hpp"
#include "query/plan/planner.hpp"
#include "capnp/message.h"
#include "query/plan/operator.capnp.h"
#include "query_common.hpp"
namespace query {
@ -505,6 +508,42 @@ class SerializedPlanner {
std::unique_ptr<LogicalOperator> plan_;
};
void SavePlan(const LogicalOperator &plan, ::capnp::MessageBuilder *message) {
auto builder = message->initRoot<query::plan::capnp::LogicalOperator>();
LogicalOperator::SaveHelper helper;
plan.Save(&builder, &helper);
}
auto LoadPlan(const ::query::plan::capnp::LogicalOperator::Reader &reader) {
auto plan = LogicalOperator::Construct(reader);
LogicalOperator::LoadHelper helper;
plan->Load(reader, &helper);
return std::make_pair(std::move(plan), std::move(helper.ast_storage));
}
class CapnpPlanner {
public:
CapnpPlanner(std::vector<SingleQueryPart> single_query_parts,
PlanningContext<database::GraphDbAccessor> &context) {
::capnp::MallocMessageBuilder message;
{
auto original_plan = MakeLogicalPlanForSingleQuery<RuleBasedPlanner>(
single_query_parts, context);
SavePlan(*original_plan, &message);
}
{
auto reader = message.getRoot<query::plan::capnp::LogicalOperator>();
std::tie(plan_, ast_storage_) = LoadPlan(reader);
}
}
auto &plan() { return *plan_; }
private:
AstTreeStorage ast_storage_;
std::unique_ptr<LogicalOperator> plan_;
};
template <class TPlanner>
TPlanner MakePlanner(database::MasterBase &master_db, AstTreeStorage &storage,
SymbolTable &symbol_table) {
@ -637,7 +676,7 @@ ExpectedDistributedPlan ExpectDistributed(
template <class T>
class TestPlanner : public ::testing::Test {};
using PlannerTypes = ::testing::Types<Planner, SerializedPlanner>;
using PlannerTypes = ::testing::Types<Planner, SerializedPlanner, CapnpPlanner>;
TYPED_TEST_CASE(TestPlanner, PlannerTypes);
@ -2234,4 +2273,111 @@ TYPED_TEST(TestPlanner, DistributedCartesianCreate) {
CheckDistributedPlan(planner.plan(), symbol_table, expected);
}
TEST(CapnpSerial, Union) {
std::vector<Symbol> left_symbols{
Symbol("symbol", 1, true, Symbol::Type::Edge)};
std::vector<Symbol> right_symbols{
Symbol("symbol", 3, true, Symbol::Type::Any)};
auto union_symbols = right_symbols;
auto union_op = std::make_unique<Union>(nullptr, nullptr, union_symbols,
left_symbols, right_symbols);
std::unique_ptr<LogicalOperator> loaded_plan;
::capnp::MallocMessageBuilder message;
SavePlan(*union_op, &message);
AstTreeStorage new_storage;
std::tie(loaded_plan, new_storage) =
LoadPlan(message.getRoot<query::plan::capnp::LogicalOperator>());
ASSERT_TRUE(loaded_plan);
auto *loaded_op = dynamic_cast<Union *>(loaded_plan.get());
ASSERT_TRUE(loaded_op);
EXPECT_FALSE(loaded_op->left_op());
EXPECT_FALSE(loaded_op->right_op());
EXPECT_EQ(loaded_op->left_symbols(), left_symbols);
EXPECT_EQ(loaded_op->right_symbols(), right_symbols);
EXPECT_EQ(loaded_op->union_symbols(), union_symbols);
}
TEST(CapnpSerial, Cartesian) {
std::vector<Symbol> left_symbols{
Symbol("left_symbol", 1, true, Symbol::Type::Edge)};
std::vector<Symbol> right_symbols{
Symbol("right_symbol", 3, true, Symbol::Type::Any)};
auto cartesian = std::make_unique<Cartesian>(nullptr, left_symbols, nullptr,
right_symbols);
std::unique_ptr<LogicalOperator> loaded_plan;
::capnp::MallocMessageBuilder message;
SavePlan(*cartesian, &message);
AstTreeStorage new_storage;
std::tie(loaded_plan, new_storage) =
LoadPlan(message.getRoot<query::plan::capnp::LogicalOperator>());
ASSERT_TRUE(loaded_plan);
auto *loaded_op = dynamic_cast<Cartesian *>(loaded_plan.get());
ASSERT_TRUE(loaded_op);
EXPECT_FALSE(loaded_op->left_op());
EXPECT_FALSE(loaded_op->right_op());
EXPECT_EQ(loaded_op->left_symbols(), left_symbols);
EXPECT_EQ(loaded_op->right_symbols(), right_symbols);
}
TEST(CapnpSerial, Synchronize) {
auto synchronize = std::make_unique<Synchronize>(nullptr, nullptr, true);
std::unique_ptr<LogicalOperator> loaded_plan;
::capnp::MallocMessageBuilder message;
SavePlan(*synchronize, &message);
AstTreeStorage new_storage;
std::tie(loaded_plan, new_storage) =
LoadPlan(message.getRoot<query::plan::capnp::LogicalOperator>());
ASSERT_TRUE(loaded_plan);
auto *loaded_op = dynamic_cast<Synchronize *>(loaded_plan.get());
ASSERT_TRUE(loaded_op);
EXPECT_FALSE(loaded_op->input());
EXPECT_FALSE(loaded_op->pull_remote());
EXPECT_TRUE(loaded_op->advance_command());
}
TEST(CapnpSerial, PullRemote) {
std::vector<Symbol> symbols{
Symbol("symbol", 1, true, Symbol::Type::Edge)};
auto pull_remote = std::make_unique<PullRemote>(nullptr, 42, symbols);
std::unique_ptr<LogicalOperator> loaded_plan;
::capnp::MallocMessageBuilder message;
SavePlan(*pull_remote, &message);
AstTreeStorage new_storage;
std::tie(loaded_plan, new_storage) =
LoadPlan(message.getRoot<query::plan::capnp::LogicalOperator>());
ASSERT_TRUE(loaded_plan);
auto *loaded_op = dynamic_cast<PullRemote *>(loaded_plan.get());
ASSERT_TRUE(loaded_op);
EXPECT_FALSE(loaded_op->input());
EXPECT_EQ(loaded_op->plan_id(), 42);
EXPECT_EQ(loaded_op->symbols(), symbols);
}
TEST(CapnpSerial, PullRemoteOrderBy) {
auto once = std::make_shared<Once>();
AstTreeStorage storage;
std::vector<Symbol> symbols{
Symbol("my_symbol", 2, true, Symbol::Type::Vertex, 3)};
std::vector<std::pair<query::Ordering, query::Expression *>> order_by{
{query::Ordering::ASC, IDENT("my_symbol")}};
auto pull_remote_order_by =
std::make_unique<PullRemoteOrderBy>(once, 42, order_by, symbols);
std::unique_ptr<LogicalOperator> loaded_plan;
::capnp::MallocMessageBuilder message;
SavePlan(*pull_remote_order_by, &message);
AstTreeStorage new_storage;
std::tie(loaded_plan, new_storage) =
LoadPlan(message.getRoot<query::plan::capnp::LogicalOperator>());
ASSERT_TRUE(loaded_plan);
auto *loaded_op = dynamic_cast<PullRemoteOrderBy *>(loaded_plan.get());
ASSERT_TRUE(loaded_op);
ASSERT_TRUE(std::dynamic_pointer_cast<Once>(loaded_op->input()));
EXPECT_EQ(loaded_op->plan_id(), 42);
EXPECT_EQ(loaded_op->symbols(), symbols);
ASSERT_EQ(loaded_op->order_by().size(), 1);
EXPECT_TRUE(dynamic_cast<query::Identifier *>(loaded_op->order_by()[0]));
ASSERT_EQ(loaded_op->compare().ordering().size(), 1);
EXPECT_EQ(loaded_op->compare().ordering()[0], query::Ordering::ASC);
}
} // namespace

View File

@ -91,7 +91,6 @@ void CheckOptionalInt(const std::experimental::optional<int> &x1) {
TEST(Serialization, CapnpOptional) {
std::experimental::optional<int> x1 = {};
std::experimental::optional<int> x2 = 42;
std::experimental::optional<int> y1, y2;
CheckOptionalInt(x1);
CheckOptionalInt(x2);
@ -104,13 +103,11 @@ TEST(Serialization, CapnpOptionalNonCopyable) {
{
auto builder = message.initRoot<utils::capnp::Optional<
utils::capnp::UniquePtr<utils::capnp::BoxInt32>>>();
auto save = [](
utils::capnp::UniquePtr<utils::capnp::BoxInt32>::Builder *builder,
const std::unique_ptr<int> &data) {
auto save_int = [](utils::capnp::BoxInt32::Builder *builder, int value) {
builder->setValue(value);
auto save = [](auto *ptr_builder, const auto &data) {
auto save_int = [](auto *int_builder, int value) {
int_builder->setValue(value);
};
utils::SaveUniquePtr<utils::capnp::BoxInt32, int>(data, builder,
utils::SaveUniquePtr<utils::capnp::BoxInt32, int>(data, ptr_builder,
save_int);
};
utils::SaveOptional<utils::capnp::UniquePtr<utils::capnp::BoxInt32>,
@ -120,13 +117,11 @@ TEST(Serialization, CapnpOptionalNonCopyable) {
{
auto reader = message.getRoot<utils::capnp::Optional<
utils::capnp::UniquePtr<utils::capnp::BoxInt32>>>();
auto load = [](
const utils::capnp::UniquePtr<utils::capnp::BoxInt32>::Reader &reader)
-> std::unique_ptr<int> {
auto load_int = [](const utils::capnp::BoxInt32::Reader &reader) -> int {
return reader.getValue();
auto load = [](const auto &ptr_reader) {
auto load_int = [](const auto &int_reader) {
return new int(int_reader.getValue());
};
return utils::LoadUniquePtr<utils::capnp::BoxInt32, int>(reader,
return utils::LoadUniquePtr<utils::capnp::BoxInt32, int>(ptr_reader,
load_int);
};
element =
@ -150,8 +145,8 @@ void CheckUniquePtrInt(const std::unique_ptr<int> &x1) {
{
auto reader =
message.getRoot<utils::capnp::UniquePtr<utils::capnp::BoxInt32>>();
auto load = [](const utils::capnp::BoxInt32::Reader &reader) -> int {
return reader.getValue();
auto load = [](const auto &int_reader) {
return new int(int_reader.getValue());
};
y1 = utils::LoadUniquePtr<utils::capnp::BoxInt32, int>(reader, load);
}
@ -176,13 +171,11 @@ TEST(Serialization, CapnpUniquePtrNonCopyable) {
{
auto builder = message.initRoot<utils::capnp::UniquePtr<
utils::capnp::UniquePtr<utils::capnp::BoxInt32>>>();
auto save = [](
utils::capnp::UniquePtr<utils::capnp::BoxInt32>::Builder *builder,
const std::unique_ptr<int> &data) {
auto save_int = [](utils::capnp::BoxInt32::Builder *builder, int value) {
builder->setValue(value);
auto save = [](auto *ptr_builder, const auto &data) {
auto save_int = [](auto *int_builder, int value) {
int_builder->setValue(value);
};
utils::SaveUniquePtr<utils::capnp::BoxInt32, int>(data, builder,
utils::SaveUniquePtr<utils::capnp::BoxInt32, int>(data, ptr_builder,
save_int);
};
utils::SaveUniquePtr<utils::capnp::UniquePtr<utils::capnp::BoxInt32>,
@ -192,14 +185,13 @@ TEST(Serialization, CapnpUniquePtrNonCopyable) {
{
auto reader = message.getRoot<utils::capnp::UniquePtr<
utils::capnp::UniquePtr<utils::capnp::BoxInt32>>>();
auto load = [](
const utils::capnp::UniquePtr<utils::capnp::BoxInt32>::Reader &reader)
-> std::unique_ptr<int> {
auto load_int = [](const utils::capnp::BoxInt32::Reader &reader) -> int {
return reader.getValue();
auto load = [](const auto &ptr_reader) {
auto load_int = [](const auto &int_reader) {
return new int(int_reader.getValue());
};
return utils::LoadUniquePtr<utils::capnp::BoxInt32, int>(reader,
load_int);
return new std::unique_ptr<int>(
utils::LoadUniquePtr<utils::capnp::BoxInt32, int>(ptr_reader,
load_int));
};
element =
utils::LoadUniquePtr<utils::capnp::UniquePtr<utils::capnp::BoxInt32>,
@ -233,8 +225,8 @@ TEST(Serialization, CapnpSharedPtr) {
{
auto reader = message.getRoot<
::capnp::List<utils::capnp::SharedPtr<utils::capnp::BoxInt32>>>();
auto load = [](const utils::capnp::BoxInt32::Reader &reader) -> int {
return reader.getValue();
auto load = [](const auto &int_reader) {
return new int(int_reader.getValue());
};
for (const auto ptr_reader : reader) {
elements.emplace_back(utils::LoadSharedPtr<utils::capnp::BoxInt32, int>(
@ -256,13 +248,11 @@ TEST(Serialization, CapnpSharedPtrNonCopyable) {
{
auto builder = message.initRoot<utils::capnp::SharedPtr<
utils::capnp::UniquePtr<utils::capnp::BoxInt32>>>();
auto save = [](
utils::capnp::UniquePtr<utils::capnp::BoxInt32>::Builder *builder,
const std::unique_ptr<int> &data) {
auto save_int = [](utils::capnp::BoxInt32::Builder *builder, int value) {
builder->setValue(value);
auto save = [](auto *ptr_builder, const auto &data) {
auto save_int = [](auto *int_builder, int value) {
int_builder->setValue(value);
};
utils::SaveUniquePtr<utils::capnp::BoxInt32, int>(data, builder,
utils::SaveUniquePtr<utils::capnp::BoxInt32, int>(data, ptr_builder,
save_int);
};
utils::SaveSharedPtr<utils::capnp::UniquePtr<utils::capnp::BoxInt32>,
@ -275,14 +265,13 @@ TEST(Serialization, CapnpSharedPtrNonCopyable) {
{
auto reader = message.getRoot<utils::capnp::SharedPtr<
utils::capnp::UniquePtr<utils::capnp::BoxInt32>>>();
auto load = [](
const utils::capnp::UniquePtr<utils::capnp::BoxInt32>::Reader &reader)
-> std::unique_ptr<int> {
auto load_int = [](const utils::capnp::BoxInt32::Reader &reader) -> int {
return reader.getValue();
auto load = [](const auto &ptr_reader) {
auto load_int = [](const auto &int_reader) {
return new int(int_reader.getValue());
};
return utils::LoadUniquePtr<utils::capnp::BoxInt32, int>(reader,
load_int);
return new std::unique_ptr<int>(
utils::LoadUniquePtr<utils::capnp::BoxInt32, int>(ptr_reader,
load_int));
};
element =
utils::LoadSharedPtr<utils::capnp::UniquePtr<utils::capnp::BoxInt32>,
@ -344,13 +333,11 @@ TEST(Serialization, CapnpVectorNonCopyable) {
auto list_builder = message.initRoot<
::capnp::List<utils::capnp::UniquePtr<utils::capnp::BoxInt32>>>(
data.size());
auto save = [](
utils::capnp::UniquePtr<utils::capnp::BoxInt32>::Builder *builder,
const std::unique_ptr<int> &data) {
auto save_int = [](utils::capnp::BoxInt32::Builder *builder, int value) {
builder->setValue(value);
auto save = [](auto *ptr_builder, const auto &data) {
auto save_int = [](auto *int_builder, int value) {
int_builder->setValue(value);
};
utils::SaveUniquePtr<utils::capnp::BoxInt32, int>(data, builder,
utils::SaveUniquePtr<utils::capnp::BoxInt32, int>(data, ptr_builder,
save_int);
};
utils::SaveVector<utils::capnp::UniquePtr<utils::capnp::BoxInt32>,
@ -360,13 +347,11 @@ TEST(Serialization, CapnpVectorNonCopyable) {
{
auto reader = message.getRoot<
::capnp::List<utils::capnp::UniquePtr<utils::capnp::BoxInt32>>>();
auto load = [](
const utils::capnp::UniquePtr<utils::capnp::BoxInt32>::Reader &reader)
-> std::unique_ptr<int> {
auto load_int = [](const utils::capnp::BoxInt32::Reader &reader) -> int {
return reader.getValue();
auto load = [](const auto &ptr_reader) {
auto load_int = [](const auto &int_reader) {
return new int(int_reader.getValue());
};
return utils::LoadUniquePtr<utils::capnp::BoxInt32, int>(reader,
return utils::LoadUniquePtr<utils::capnp::BoxInt32, int>(ptr_reader,
load_int);
};
utils::LoadVector<utils::capnp::UniquePtr<utils::capnp::BoxInt32>,

View File

@ -1,8 +1,9 @@
#!/bin/bash -e
if [[ $# -ne 1 ]]; then
echo "Usage: $0 LCP_FILE"
echo "Convert a LCP_FILE to C++ header file and output to stdout"
if [[ $# -ne 1 && $# -ne 2 ]]; then
echo "Usage: $0 LCP_FILE [CAPNP_EXE]"
echo "Convert a LCP_FILE to C++ header file and output to stdout."
echo "If CAPNP_EXE is provided, then the Cap'n Proto schema generated."
exit 1
fi
@ -14,17 +15,28 @@ fi
lcp_file=`realpath $1`
script_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
cd $script_dir
quicklisp_install_dir="$HOME/quicklisp"
if [[ -v QUICKLISP_HOME ]]; then
quicklisp_install_dir="${QUICKLISP_HOME}"
fi
capnp=""
if [[ $# -eq 2 ]]; then
capnp=":capnp-id \"$($2 id)\""
fi
echo \
"
(load \"${quicklisp_install_dir}/setup.lisp\")
(ql:quickload :cl-ppcre :silent t)
(load \"../src/lisp/lcp.lisp\")
(lcp:process-file \"$lcp_file\" :out-stream t)
" | sbcl --script | clang-format -style=file
(load \"$script_dir/../src/lisp/lcp.lisp\")
(lcp:process-file \"$lcp_file\" $capnp)
" | sbcl --script
filename=`basename $lcp_file .lcp`
hpp_file="$(dirname $lcp_file)/$filename.hpp"
clang-format -style=file -i $hpp_file
if [[ $# -eq 2 ]]; then
clang-format -style=file -i "$lcp_file.cpp"
fi