diff --git a/.gitignore b/.gitignore index 8e041cdea..04424bbf8 100644 --- a/.gitignore +++ b/.gitignore @@ -34,6 +34,6 @@ TAGS *.fas *.fasl -# Cap'n Proto geenrated files +# Cap'n Proto generated files *.capnp.c++ *.capnp.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index a7a288b71..8643d943d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -103,7 +103,7 @@ function(add_capnp capnp_src_file) set(cpp_file ${CMAKE_CURRENT_SOURCE_DIR}/${capnp_src_file}.c++) 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} + COMMAND ${CAPNP_EXE} compile -o${CAPNP_CXX_EXE} ${capnp_src_file} -I ${CMAKE_CURRENT_SOURCE_DIR} DEPENDS ${capnp_src_file} capnproto-proj WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) # Update *global* generated_capnp_files @@ -113,6 +113,9 @@ function(add_capnp capnp_src_file) endfunction(add_capnp) add_capnp(query/frontend/semantic/symbol.capnp) +add_capnp(query/frontend/ast/ast.capnp) +add_capnp(utils/typed_value.capnp) +add_capnp(storage/types.capnp) add_custom_target(generate_capnp DEPENDS ${generated_capnp_files}) # ----------------------------------------------------------------------------- diff --git a/src/query/frontend/ast/ast.capnp b/src/query/frontend/ast/ast.capnp new file mode 100644 index 000000000..5b5cc658a --- /dev/null +++ b/src/query/frontend/ast/ast.capnp @@ -0,0 +1,385 @@ +@0xb107d3d6b4b1600b; + +using Cxx = import "/capnp/c++.capnp"; +$Cxx.namespace("query::capnp"); + +using Utils = import "/utils/typed_value.capnp"; +using Storage = import "/storage/types.capnp"; +using Symbols = import "/query/frontend/semantic/symbol.capnp"; + +struct Tree { + uid @0 :Int64; + + union { + expression @1 :Expression; + where @2 :Where; + namedExpression @3 :NamedExpression; + patternAtom @4 :PatternAtom; + pattern @5 :Pattern; + clause @6 :Clause; + singleQuery @7 :SingleQuery; + cypherUnion @8 :CypherUnion; + query @9 :Query; + } +} + +struct Expression { + union { + binaryOperator @0 :BinaryOperator; + unaryOperator @1 :UnaryOperator; + baseLiteral @2 :BaseLiteral; + listSlicingOperator @3 :ListSlicingOperator; + ifOperator @4 :IfOperator; + identifier @5 :Identifier; + propertyLookup @6 :PropertyLookup; + labelsTest @7 :LabelsTest; + function @8 :Function; + reduce @9 :Reduce; + all @10 :All; + single @11 :Single; + parameterLookup @12 :ParameterLookup; + } +} + +struct Where { + expression @0 :Tree; +} + +struct NamedExpression { + name @0 :Text; + expression @1 :Tree; + tokenPosition @2 :Int32; +} + +struct PatternAtom { + union { + nodeAtom @0 :NodeAtom; + edgeAtom @1 :EdgeAtom; + } + identifier @2 :Tree; +} + +struct Pair(First, Second) { + first @0 :First; + second @1 :Second; +} + +struct NodeAtom { + properties @0 :List(Entry); + struct Entry { + key @0 :Pair(Text, Storage.Common); + value @1 :Tree; + } + + labels @1 :List(Storage.Common); +} + +struct EdgeAtom { + enum Type { + single @0; + depthFirst @1; + breadthFirst @2; + weightedShortestPath @3; + } + type @0 :Type; + + enum Direction { + in @0; + out @1; + both @2; + } + direction @1 :Direction; + + properties @2 :List(Entry); + struct Entry { + key @0 :Pair(Text, Storage.Common); + value @1 :Tree; + } + + lowerBound @3 :Tree; + upperBound @4 :Tree; + + filterLambda @5 :Lambda; + weightLambda @6 :Lambda; + struct Lambda { + innerEdge @0 :Tree; + innerNode @1 :Tree; + expression @2 :Tree; + } + + totalWeight @7 :Tree; + edgeTypes @8 :List(Storage.Common); +} + +struct Pattern { + identifier @0 :Tree; + atoms @1 :List(Tree); +} + +struct Clause { + union { + create @0 :Create; + match @1 :Match; + return @2 :Return; + with @3 :With; + delete @4 :Delete; + setProperty @5 :SetProperty; + setProperties @6 :SetProperties; + setLabels @7 :SetLabels; + removeProperty @8 :RemoveProperty; + removeLabels @9 :RemoveLabels; + merge @10 :Merge; + unwind @11 :Unwind; + createIndex @12 :CreateIndex; + } +} + +struct SingleQuery { + clauses @0 :List(Tree); +} + +struct CypherUnion { + singleQuery @0 :Tree; + distinct @1 :Bool; + unionSymbols @2 :List(Symbols.Symbol); +} + +struct Query { + singleQuery @0 :Tree; + cypherUnions @1 :List(Tree); +} + +struct BinaryOperator { + union { + orOperator @0 :OrOperator; + xorOperator @1 :XorOperator; + andOperator @2 :AndOperator; + additionOperator @3 :AdditionOperator; + subtractionOperator @4 :SubtractionOperator; + multiplicationOperator @5 :MultiplicationOperator; + divisionOperator @6 :DivisionOperator; + modOperator @7 :ModOperator; + notEqualOperator @8 :NotEqualOperator; + equalOperator @9 :EqualOperator; + lessOperator @10 :LessOperator; + greaterOperator @11 :GreaterOperator; + lessEqualOperator @12 :LessEqualOperator; + greaterEqualOperator @13 :GreaterEqualOperator; + inListOperator @14 :InListOperator; + listMapIndexingOperator @15 :ListMapIndexingOperator; + aggregation @16 :Aggregation; + } + expression1 @17 :Tree; + expression2 @18 :Tree; +} + +struct OrOperator {} +struct XorOperator {} +struct AndOperator {} +struct AdditionOperator {} +struct SubtractionOperator {} +struct MultiplicationOperator {} +struct DivisionOperator {} +struct ModOperator {} +struct NotEqualOperator {} +struct EqualOperator {} +struct LessOperator {} +struct GreaterOperator {} +struct LessEqualOperator {} +struct GreaterEqualOperator {} +struct InListOperator {} +struct ListMapIndexingOperator {} +struct Aggregation { + enum Op { + count @0; + min @1; + max @2; + sum @3; + avg @4 ; + collectList @5; + collectMap @6; + } + op @0 :Op; +} + +struct UnaryOperator { + union { + notOperator @0 :NotOperator; + unaryPlusOperator @1 :UnaryPlusOperator; + unaryMinusOperator @2 :UnaryMinusOperator; + isNullOperator @3 :IsNullOperator; + } + expression @4 :Tree; +} + +struct NotOperator {} +struct UnaryPlusOperator {} +struct UnaryMinusOperator {} +struct IsNullOperator {} + +struct BaseLiteral { + union { + primitiveLiteral @0 :PrimitiveLiteral; + listLiteral @1 :ListLiteral; + mapLiteral @2 :MapLiteral; + } +} + +struct PrimitiveLiteral { + tokenPosition @0 :Int32; + value @1 :Utils.TypedValue; +} + +struct ListLiteral { + elements @0 :List(Tree); +} + +struct MapLiteral { + elements @0 :List(Entry); + struct Entry { + key @0 :Pair(Text, Storage.Common); + value @1 :Tree; + } +} + +struct ListSlicingOperator { + list @0 :Tree; + lowerBound @1 :Tree; + upperBound @2 :Tree; +} + +struct IfOperator { + condition @0 :Tree; + thenExpression @1 :Tree; + elseExpression @2 :Tree; +} + +struct Identifier { + name @0 :Text; + userDeclared @1 :Bool; +} + +struct PropertyLookup { + expression @0 :Tree; + propertyName @1 :Text; + property @2 :Storage.Common; +} + +struct LabelsTest { + expression @0 :Tree; + labels @1 :List(Storage.Common); +} + +struct Function { + functionName @0 :Text; + arguments @1 :List(Tree); +} + +struct Reduce { + accumulator @0 :Tree; + initializer @1 :Tree; + identifier @2 :Tree; + list @3 :Tree; + expression @4 :Tree; +} + +struct All { + identifier @0 :Tree; + listExpression @1 :Tree; + where @2 :Tree; +} + +struct Single { + identifier @0 :Tree; + listExpression @1 :Tree; + where @2 :Tree; +} + +struct ParameterLookup { + tokenPosition @0 :Int32; +} + +struct Create { + patterns @0 :List(Tree); +} + +struct Match { + patterns @0 :List(Tree); + where @1 :Tree; + optional @2 :Bool; +} + +enum Ordering { + asc @0; + desc @1; +} + +struct ReturnBody { + distinct @0 :Bool; + allIdentifiers @1 :Bool; + namedExpressions @2 :List(Tree); + orderBy @3 :List(Pair); + + struct Pair { + ordering @0 :Ordering; + expression @1 :Tree; + } + + skip @4 :Tree; + limit @5 :Tree; +} + +struct Return { + returnBody @0 :ReturnBody; +} + +struct With { + returnBody @0 :ReturnBody; + where @1 :Tree; +} + +struct Delete { + detach @0 :Bool; + expressions @1 :List(Tree); +} + +struct SetProperty { + propertyLookup @0 :Tree; + expression @1 :Tree; +} + +struct SetProperties { + identifier @0 :Tree; + expression @1 :Tree; + update @2 :Bool; +} + +struct SetLabels { + identifier @0 :Tree; + labels @1 :List(Storage.Common); +} + +struct RemoveProperty { + propertyLookup @0 :Tree; +} + +struct RemoveLabels { + identifier @0 :Tree; + labels @1 :List(Storage.Common); +} + +struct Merge { + pattern @0 :Tree; + onMatch @1 :List(Tree); + onCreate @2 :List(Tree); +} + +struct Unwind { + namedExpression @0 :Tree; +} + +struct CreateIndex { + label @0 :Storage.Common; + property @1 :Storage.Common; +} + diff --git a/src/query/frontend/ast/ast.cpp b/src/query/frontend/ast/ast.cpp index 0359c494c..9230324ed 100644 --- a/src/query/frontend/ast/ast.cpp +++ b/src/query/frontend/ast/ast.cpp @@ -5,6 +5,8 @@ #include "boost/archive/binary_oarchive.hpp" #include "boost/serialization/export.hpp" +#include "utils/typed_value.capnp.h" + namespace query { // Id for boost's archive get_helper needs to be unique among all ids. If it @@ -42,6 +44,1920 @@ ReturnBody CloneReturnBody(AstTreeStorage &storage, const ReturnBody &body) { return new_body; } +// capnproto serialization + +Tree *AstTreeStorage::Load(capnp::Tree::Reader &tree) { + switch (tree.which()) { + case capnp::Tree::EXPRESSION: { + auto expr_reader = tree.getExpression(); + auto *ret = Expression::Construct(expr_reader, *this); + ret->Load(tree, *this); + return ret; + } + case capnp::Tree::WHERE: { + auto where_reader = tree.getWhere(); + auto *ret = Where::Construct(where_reader, *this); + ret->Load(tree, *this); + return ret; + } + case capnp::Tree::CLAUSE: { + auto clause_reader = tree.getClause(); + auto *ret = Clause::Construct(clause_reader, *this); + ret->Load(tree, *this); + return ret; + } + case capnp::Tree::CYPHER_UNION: { + auto cu_reader = tree.getCypherUnion(); + auto *ret = CypherUnion::Construct(cu_reader, *this); + ret->Load(tree, *this); + return ret; + } + case capnp::Tree::NAMED_EXPRESSION: { + auto ne_reader = tree.getNamedExpression(); + auto *ret = NamedExpression::Construct(ne_reader, *this); + ret->Load(tree, *this); + return ret; + } + case capnp::Tree::PATTERN: { + auto pattern_reader = tree.getPattern(); + auto *ret = Pattern::Construct(pattern_reader, *this); + ret->Load(tree, *this); + return ret; + } + case capnp::Tree::PATTERN_ATOM: { + auto pa_reader = tree.getPatternAtom(); + auto *ret = PatternAtom::Construct(pa_reader, *this); + ret->Load(tree, *this); + return ret; + } + case capnp::Tree::QUERY: { + auto query_reader = tree.getQuery(); + auto *ret = Query::Construct(query_reader, *this); + ret->Load(tree, *this); + return ret; + } + case capnp::Tree::SINGLE_QUERY: { + auto single_reader = tree.getSingleQuery(); + auto *ret = SingleQuery::Construct(single_reader, *this); + ret->Load(tree, *this); + return ret; + } + } +} + +// Tree. +void Tree::Save(capnp::Tree::Builder &tree_builder) { + tree_builder.setUid(uid_); +} + +void Tree::Load(capnp::Tree::Reader &reader, AstTreeStorage &storage) { + uid_ = reader.getUid(); +} + +// Expression. +void Expression::Save(capnp::Tree::Builder &tree_builder) { + Tree::Save(tree_builder); + auto expr_builder = tree_builder.initExpression(); + Save(expr_builder); +} + +Expression *Expression::Construct(capnp::Expression::Reader &reader, + AstTreeStorage &storage) { + switch (reader.which()) { + case capnp::Expression::BINARY_OPERATOR: { + auto bop_reader = reader.getBinaryOperator(); + return BinaryOperator::Construct(bop_reader, storage); + } + case capnp::Expression::UNARY_OPERATOR: { + auto uop_reader = reader.getUnaryOperator(); + return UnaryOperator::Construct(uop_reader, storage); + } + case capnp::Expression::BASE_LITERAL: { + auto bl_reader = reader.getBaseLiteral(); + return BaseLiteral::Construct(bl_reader, storage); + } + case capnp::Expression::LIST_SLICING_OPERATOR: { + auto lso_reader = reader.getListSlicingOperator(); + return ListSlicingOperator::Construct(lso_reader, storage); + } + case capnp::Expression::IF_OPERATOR: { + auto if_reader = reader.getIfOperator(); + return IfOperator::Construct(if_reader, storage); + } + case capnp::Expression::ALL: { + auto all_reader = reader.getAll(); + return All::Construct(all_reader, storage); + } + case capnp::Expression::FUNCTION: { + auto func_reader = reader.getFunction(); + return Function::Construct(func_reader, storage); + } + case capnp::Expression::IDENTIFIER: { + auto id_reader = reader.getIdentifier(); + return Identifier::Construct(id_reader, storage); + } + case capnp::Expression::LABELS_TEST: { + auto labels_reader = reader.getLabelsTest(); + return LabelsTest::Construct(labels_reader, storage); + } + case capnp::Expression::PARAMETER_LOOKUP: { + auto pl_reader = reader.getParameterLookup(); + return ParameterLookup::Construct(pl_reader, storage); + } + case capnp::Expression::PROPERTY_LOOKUP: { + auto pl_reader = reader.getPropertyLookup(); + return PropertyLookup::Construct(pl_reader, storage); + } + case capnp::Expression::REDUCE: { + auto reduce_reader = reader.getReduce(); + return Reduce::Construct(reduce_reader, storage); + } + case capnp::Expression::SINGLE: { + auto single_reader = reader.getSingle(); + return Single::Construct(single_reader, storage); + } + } +} + +// Base Literal. +void BaseLiteral::Save(capnp::Expression::Builder &expr_builder) { + Expression::Save(expr_builder); + auto base_literal_builder = expr_builder.initBaseLiteral(); + Save(base_literal_builder); +} + +BaseLiteral *BaseLiteral::Construct(capnp::BaseLiteral::Reader &reader, + AstTreeStorage &storage) { + switch (reader.which()) { + case capnp::BaseLiteral::PRIMITIVE_LITERAL: { + auto literal = reader.getPrimitiveLiteral(); + return PrimitiveLiteral::Construct(literal, storage); + } + case capnp::BaseLiteral::LIST_LITERAL: { + auto literal = reader.getListLiteral(); + return ListLiteral::Construct(literal, storage); + } + case capnp::BaseLiteral::MAP_LITERAL: { + auto literal = reader.getMapLiteral(); + return MapLiteral::Construct(literal, storage); + } + } +} + +// Primitive Literal. +void PrimitiveLiteral::Save(capnp::BaseLiteral::Builder &base_literal_builder) { + BaseLiteral::Save(base_literal_builder); + auto primitive_literal_builder = base_literal_builder.initPrimitiveLiteral(); + primitive_literal_builder.setTokenPosition(token_position_); + auto typed_value_builder = primitive_literal_builder.getValue(); + utils::SaveCapnpTypedValue(value_, typed_value_builder); +} + +PrimitiveLiteral *PrimitiveLiteral::Construct( + capnp::PrimitiveLiteral::Reader &reader, AstTreeStorage &storage) { + auto typed_value_reader = reader.getValue(); + TypedValue value; + utils::LoadCapnpTypedValue(value, typed_value_reader); + return storage.Create(value, reader.getTokenPosition()); +} + +// List Literal. +void ListLiteral::Save(capnp::BaseLiteral::Builder &base_literal_builder) { + BaseLiteral::Save(base_literal_builder); + auto list_literal_builder = base_literal_builder.initListLiteral(); + ::capnp::List::Builder tree_builders = + list_literal_builder.initElements(elements_.size()); + for (size_t i = 0; i < elements_.size(); ++i) { + auto tree_builder = tree_builders[i]; + elements_[i]->Save(tree_builder); + } +} + +ListLiteral *ListLiteral::Construct(capnp::ListLiteral::Reader &reader, + AstTreeStorage &storage) { + auto *list = storage.Create(); + for (auto tree_reader : reader.getElements()) { + auto tree = storage.Load(tree_reader); + list->elements_.push_back(dynamic_cast(tree)); + } + return list; +} + +// Map Literal. +void MapLiteral::Save(capnp::BaseLiteral::Builder &base_literal_builder) { + BaseLiteral::Save(base_literal_builder); + auto map_literal_builder = base_literal_builder.initMapLiteral(); + ::capnp::List::Builder map_builder = + map_literal_builder.initElements(elements_.size()); + size_t i = 0; + for (auto &entry : elements_) { + auto entry_builder = map_builder[i]; + 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); + auto value_builder = entry_builder.getValue(); + if (entry.second) entry.second->Save(value_builder); + ++i; + } +} + +MapLiteral *MapLiteral::Construct(capnp::MapLiteral::Reader &reader, + AstTreeStorage &storage) { + auto *map = storage.Create(); + for (auto entry_reader : reader.getElements()) { + auto key_pair_reader = entry_reader.getKey(); + auto key_first = key_pair_reader.getFirst().cStr(); + auto storage_property_reader = key_pair_reader.getSecond(); + storage::Property key_second; + key_second.Load(storage_property_reader); + auto value_reader = entry_reader.getValue(); + auto value = storage.Load(value_reader); + auto key = std::make_pair(key_first, key_second); + // TODO Maybe check for nullptr expression? + map->elements_.emplace(key, dynamic_cast(value)); + } + return map; +} + +// Binary Operator. +void BinaryOperator::Save(capnp::Expression::Builder &expr_builder) { + Expression::Save(expr_builder); + auto builder = expr_builder.initBinaryOperator(); + Save(builder); +} + +void BinaryOperator::Save(capnp::BinaryOperator::Builder &builder) { + if (expression1_) { + auto expr1_builder = builder.getExpression1(); + expression1_->Save(expr1_builder); + } + if (expression2_) { + auto expr2_builder = builder.getExpression2(); + expression2_->Save(expr2_builder); + } +} + +void BinaryOperator::Load(capnp::Tree::Reader &reader, + AstTreeStorage &storage) { + Expression::Load(reader, storage); + auto bop_reader = reader.getExpression().getBinaryOperator(); + if (bop_reader.hasExpression1()) { + auto expr1_reader = bop_reader.getExpression1(); + expression1_ = dynamic_cast(storage.Load(expr1_reader)); + } + if (bop_reader.hasExpression2()) { + auto expr2_reader = bop_reader.getExpression2(); + expression2_ = dynamic_cast(storage.Load(expr2_reader)); + } +} + +BinaryOperator *BinaryOperator::Construct(capnp::BinaryOperator::Reader &reader, + AstTreeStorage &storage) { + switch (reader.which()) { + case capnp::BinaryOperator::ADDITION_OPERATOR: { + auto literal = reader.getAdditionOperator(); + return AdditionOperator::Construct(literal, storage); + } + case capnp::BinaryOperator::AGGREGATION: { + auto literal = reader.getAggregation(); + return Aggregation::Construct(literal, storage); + } + case capnp::BinaryOperator::AND_OPERATOR: { + auto literal = reader.getAndOperator(); + return AndOperator::Construct(literal, storage); + } + case capnp::BinaryOperator::DIVISION_OPERATOR: { + auto literal = reader.getDivisionOperator(); + return DivisionOperator::Construct(literal, storage); + } + case capnp::BinaryOperator::EQUAL_OPERATOR: { + auto literal = reader.getEqualOperator(); + return EqualOperator::Construct(literal, storage); + } + case capnp::BinaryOperator::GREATER_EQUAL_OPERATOR: { + auto literal = reader.getGreaterEqualOperator(); + return GreaterEqualOperator::Construct(literal, storage); + } + case capnp::BinaryOperator::GREATER_OPERATOR: { + auto literal = reader.getGreaterOperator(); + return GreaterOperator::Construct(literal, storage); + } + case capnp::BinaryOperator::IN_LIST_OPERATOR: { + auto literal = reader.getInListOperator(); + return InListOperator::Construct(literal, storage); + } + case capnp::BinaryOperator::LESS_EQUAL_OPERATOR: { + auto literal = reader.getLessEqualOperator(); + return LessEqualOperator::Construct(literal, storage); + } + case capnp::BinaryOperator::LESS_OPERATOR: { + auto literal = reader.getLessOperator(); + return LessOperator::Construct(literal, storage); + } + case capnp::BinaryOperator::LIST_MAP_INDEXING_OPERATOR: { + auto literal = reader.getListMapIndexingOperator(); + return ListMapIndexingOperator::Construct(literal, storage); + } + case capnp::BinaryOperator::MOD_OPERATOR: { + auto literal = reader.getModOperator(); + return ModOperator::Construct(literal, storage); + } + case capnp::BinaryOperator::MULTIPLICATION_OPERATOR: { + auto literal = reader.getMultiplicationOperator(); + return MultiplicationOperator::Construct(literal, storage); + } + case capnp::BinaryOperator::NOT_EQUAL_OPERATOR: { + auto literal = reader.getNotEqualOperator(); + return NotEqualOperator::Construct(literal, storage); + } + case capnp::BinaryOperator::OR_OPERATOR: { + auto literal = reader.getOrOperator(); + return OrOperator::Construct(literal, storage); + } + case capnp::BinaryOperator::SUBTRACTION_OPERATOR: { + auto literal = reader.getSubtractionOperator(); + return SubtractionOperator::Construct(literal, storage); + } + case capnp::BinaryOperator::XOR_OPERATOR: { + auto literal = reader.getXorOperator(); + return XorOperator::Construct(literal, storage); + } + } +} + +void OrOperator::Save(capnp::BinaryOperator::Builder &builder) { + BinaryOperator::Save(builder); + builder.initOrOperator(); +} + +OrOperator *OrOperator::Construct(capnp::OrOperator::Reader &, + AstTreeStorage &storage) { + return storage.Create(); +} + +void XorOperator::Save(capnp::BinaryOperator::Builder &builder) { + BinaryOperator::Save(builder); + builder.initXorOperator(); +} + +XorOperator *XorOperator::Construct(capnp::XorOperator::Reader &, + AstTreeStorage &storage) { + return storage.Create(); +} + +void AndOperator::Save(capnp::BinaryOperator::Builder &builder) { + BinaryOperator::Save(builder); + builder.initAndOperator(); +} + +AndOperator *AndOperator::Construct(capnp::AndOperator::Reader &, + AstTreeStorage &storage) { + return storage.Create(); +} + +void AdditionOperator::Save(capnp::BinaryOperator::Builder &builder) { + BinaryOperator::Save(builder); + builder.initAdditionOperator(); +} + +AdditionOperator *AdditionOperator::Construct(capnp::AdditionOperator::Reader &, + AstTreeStorage &storage) { + return storage.Create(); +} + +void SubtractionOperator::Save(capnp::BinaryOperator::Builder &builder) { + BinaryOperator::Save(builder); + builder.initSubtractionOperator(); +} + +SubtractionOperator *SubtractionOperator::Construct( + capnp::SubtractionOperator::Reader &, AstTreeStorage &storage) { + return storage.Create(); +} + +void MultiplicationOperator::Save(capnp::BinaryOperator::Builder &builder) { + BinaryOperator::Save(builder); + builder.initMultiplicationOperator(); +} + +MultiplicationOperator *MultiplicationOperator::Construct( + capnp::MultiplicationOperator::Reader &, AstTreeStorage &storage) { + return storage.Create(); +} + +void DivisionOperator::Save(capnp::BinaryOperator::Builder &builder) { + BinaryOperator::Save(builder); + builder.initDivisionOperator(); +} + +DivisionOperator *DivisionOperator::Construct(capnp::DivisionOperator::Reader &, + AstTreeStorage &storage) { + return storage.Create(); +} + +void ModOperator::Save(capnp::BinaryOperator::Builder &builder) { + BinaryOperator::Save(builder); + builder.initModOperator(); +} + +ModOperator *ModOperator::Construct(capnp::ModOperator::Reader &, + AstTreeStorage &storage) { + return storage.Create(); +} + +void NotEqualOperator::Save(capnp::BinaryOperator::Builder &builder) { + BinaryOperator::Save(builder); + builder.initNotEqualOperator(); +} + +NotEqualOperator *NotEqualOperator::Construct(capnp::NotEqualOperator::Reader &, + AstTreeStorage &storage) { + return storage.Create(); +} + +void EqualOperator::Save(capnp::BinaryOperator::Builder &builder) { + BinaryOperator::Save(builder); + builder.initEqualOperator(); +} + +EqualOperator *EqualOperator::Construct(capnp::EqualOperator::Reader &, + AstTreeStorage &storage) { + return storage.Create(); +} + +void LessOperator::Save(capnp::BinaryOperator::Builder &builder) { + BinaryOperator::Save(builder); + builder.initLessOperator(); +} + +LessOperator *LessOperator::Construct(capnp::LessOperator::Reader &, + AstTreeStorage &storage) { + return storage.Create(); +} + +void GreaterOperator::Save(capnp::BinaryOperator::Builder &builder) { + BinaryOperator::Save(builder); + builder.initGreaterOperator(); +} + +GreaterOperator *GreaterOperator::Construct(capnp::GreaterOperator::Reader &, + AstTreeStorage &storage) { + return storage.Create(); +} + +void LessEqualOperator::Save(capnp::BinaryOperator::Builder &builder) { + BinaryOperator::Save(builder); + builder.initLessEqualOperator(); +} + +LessEqualOperator *LessEqualOperator::Construct( + capnp::LessEqualOperator::Reader &, AstTreeStorage &storage) { + return storage.Create(); +} + +void GreaterEqualOperator::Save(capnp::BinaryOperator::Builder &builder) { + BinaryOperator::Save(builder); + builder.initGreaterEqualOperator(); +} + +GreaterEqualOperator *GreaterEqualOperator::Construct( + capnp::GreaterEqualOperator::Reader &, AstTreeStorage &storage) { + return storage.Create(); +} + +void InListOperator::Save(capnp::BinaryOperator::Builder &builder) { + BinaryOperator::Save(builder); + builder.initInListOperator(); +} + +InListOperator *InListOperator::Construct(capnp::InListOperator::Reader &, + AstTreeStorage &storage) { + return storage.Create(); +} + +void ListMapIndexingOperator::Save(capnp::BinaryOperator::Builder &builder) { + BinaryOperator::Save(builder); + builder.initListMapIndexingOperator(); +} + +ListMapIndexingOperator *ListMapIndexingOperator::Construct( + capnp::ListMapIndexingOperator::Reader &, AstTreeStorage &storage) { + return storage.Create(); +} + +void Aggregation::Save(capnp::BinaryOperator::Builder &builder) { + BinaryOperator::Save(builder); + auto ag_builder = builder.initAggregation(); + switch (op_) { + case Op::AVG: + ag_builder.setOp(capnp::Aggregation::Op::AVG); + break; + case Op::COLLECT_LIST: + ag_builder.setOp(capnp::Aggregation::Op::COLLECT_LIST); + break; + case Op::COLLECT_MAP: + ag_builder.setOp(capnp::Aggregation::Op::COLLECT_MAP); + break; + case Op::COUNT: + ag_builder.setOp(capnp::Aggregation::Op::COUNT); + break; + case Op::MAX: + ag_builder.setOp(capnp::Aggregation::Op::MAX); + break; + case Op::MIN: + ag_builder.setOp(capnp::Aggregation::Op::MIN); + break; + case Op::SUM: + ag_builder.setOp(capnp::Aggregation::Op::SUM); + break; + } +} + +Aggregation *Aggregation::Construct(capnp::Aggregation::Reader &reader, + AstTreeStorage &storage) { + Op op; + switch (reader.getOp()) { + case capnp::Aggregation::Op::AVG: + op = Op::AVG; + break; + case capnp::Aggregation::Op::COLLECT_LIST: + op = Op::COLLECT_LIST; + break; + case capnp::Aggregation::Op::COLLECT_MAP: + op = Op::COLLECT_MAP; + break; + case capnp::Aggregation::Op::COUNT: + op = Op::COUNT; + break; + case capnp::Aggregation::Op::MAX: + op = Op::MAX; + break; + case capnp::Aggregation::Op::MIN: + op = Op::MIN; + break; + case capnp::Aggregation::Op::SUM: + op = Op::SUM; + break; + } + return storage.Create(op); +} + +// Unary Operator. +void UnaryOperator::Save(capnp::Expression::Builder &expr_builder) { + Expression::Save(expr_builder); + auto builder = expr_builder.initUnaryOperator(); + Save(builder); +} + +void UnaryOperator::Save(capnp::UnaryOperator::Builder &builder) { + if (expression_) { + auto expr_builder = builder.getExpression(); + expression_->Save(expr_builder); + } +} + +void UnaryOperator::Load(capnp::Tree::Reader &reader, AstTreeStorage &storage) { + Expression::Load(reader, storage); + if (reader.hasExpression()) { + auto expr_reader = + reader.getExpression().getUnaryOperator().getExpression(); + expression_ = dynamic_cast(storage.Load(expr_reader)); + } +} + +UnaryOperator *UnaryOperator::Construct(capnp::UnaryOperator::Reader &reader, + AstTreeStorage &storage) { + switch (reader.which()) { + case capnp::UnaryOperator::IS_NULL_OPERATOR: { + auto op = reader.getIsNullOperator(); + return IsNullOperator::Construct(op, storage); + } + case capnp::UnaryOperator::NOT_OPERATOR: { + auto op = reader.getNotOperator(); + return NotOperator::Construct(op, storage); + } + case capnp::UnaryOperator::UNARY_MINUS_OPERATOR: { + auto op = reader.getUnaryMinusOperator(); + return UnaryMinusOperator::Construct(op, storage); + } + case capnp::UnaryOperator::UNARY_PLUS_OPERATOR: { + auto op = reader.getUnaryPlusOperator(); + return UnaryPlusOperator::Construct(op, storage); + } + } +} + +// IsNull Operator. +void IsNullOperator::Save(capnp::UnaryOperator::Builder &builder) { + UnaryOperator::Save(builder); + builder.initIsNullOperator(); +} + +IsNullOperator *IsNullOperator::Construct(capnp::IsNullOperator::Reader &, + AstTreeStorage &storage) { + return storage.Create(); +} + +// Not Operator. +void NotOperator::Save(capnp::UnaryOperator::Builder &builder) { + UnaryOperator::Save(builder); + builder.initNotOperator(); +} + +NotOperator *NotOperator::Construct(capnp::NotOperator::Reader &, + AstTreeStorage &storage) { + return storage.Create(); +} + +// UnaryPlus Operator. +void UnaryPlusOperator::Save(capnp::UnaryOperator::Builder &builder) { + UnaryOperator::Save(builder); + builder.initUnaryPlusOperator(); +} + +UnaryPlusOperator *UnaryPlusOperator::Construct( + capnp::UnaryPlusOperator::Reader &, AstTreeStorage &storage) { + return storage.Create(); +} + +// UnaryMinus Operator. +void UnaryMinusOperator::Save(capnp::UnaryOperator::Builder &builder) { + UnaryOperator::Save(builder); + builder.initUnaryMinusOperator(); +} + +UnaryMinusOperator *UnaryMinusOperator::Construct( + capnp::UnaryMinusOperator::Reader &, AstTreeStorage &storage) { + return storage.Create(); +} + +// ListSlicing Operator. +void ListSlicingOperator::Save(capnp::Expression::Builder &expr_builder) { + Expression::Save(expr_builder); + auto builder = expr_builder.initListSlicingOperator(); + Save(builder); +} + +void ListSlicingOperator::Save(capnp::ListSlicingOperator::Builder &builder) { + if (list_) { + auto list_builder = builder.getList(); + list_->Save(list_builder); + } + if (lower_bound_) { + auto lb_builder = builder.getLowerBound(); + lower_bound_->Save(lb_builder); + } + if (upper_bound_) { + auto up_builder = builder.getUpperBound(); + upper_bound_->Save(up_builder); + } +} + +ListSlicingOperator *ListSlicingOperator::Construct( + capnp::ListSlicingOperator::Reader &reader, AstTreeStorage &storage) { + Expression *list = nullptr; + Expression *upper_bound = nullptr; + Expression *lower_bound = nullptr; + if (reader.hasList()) { + auto list_reader = reader.getList(); + list = dynamic_cast(storage.Load(list_reader)); + } + if (reader.hasUpperBound()) { + auto ub_reader = reader.getUpperBound(); + upper_bound = dynamic_cast(storage.Load(ub_reader)); + } + if (reader.hasLowerBound()) { + auto lb_reader = reader.getLowerBound(); + lower_bound = dynamic_cast(storage.Load(lb_reader)); + } + return storage.Create(list, lower_bound, upper_bound); +} + +// If Operator. +void IfOperator::Save(capnp::Expression::Builder &expr_builder) { + Expression::Save(expr_builder); + auto builder = expr_builder.initIfOperator(); + Save(builder); +} + +void IfOperator::Save(capnp::IfOperator::Builder &builder) { + auto condition_builder = builder.getCondition(); + condition_->Save(condition_builder); + auto then_builder = builder.getThenExpression(); + then_expression_->Save(then_builder); + auto else_builder = builder.getElseExpression(); + else_expression_->Save(else_builder); +} + +IfOperator *IfOperator::Construct(capnp::IfOperator::Reader &reader, + AstTreeStorage &storage) { + auto condition_reader = reader.getCondition(); + auto condition = dynamic_cast(storage.Load(condition_reader)); + auto then_reader = reader.getThenExpression(); + auto then_expression = dynamic_cast(storage.Load(then_reader)); + auto else_reader = reader.getElseExpression(); + auto else_expression = dynamic_cast(storage.Load(else_reader)); + return storage.Create(condition, then_expression, + else_expression); +} + +// All +void All::Save(capnp::Expression::Builder &expr_builder) { + Expression::Save(expr_builder); + auto builder = expr_builder.initAll(); + Save(builder); +} + +void All::Save(capnp::All::Builder &builder) { + auto identifier_builder = builder.getIdentifier(); + identifier_->Save(identifier_builder); + auto expr_builder = builder.getListExpression(); + list_expression_->Save(expr_builder); + auto where_builder = builder.getWhere(); + where_->Save(where_builder); +} + +All *All::Construct(capnp::All::Reader &reader, AstTreeStorage &storage) { + auto id_reader = reader.getIdentifier(); + auto identifier = dynamic_cast(storage.Load(id_reader)); + auto expr_reader = reader.getListExpression(); + auto list_expression = dynamic_cast(storage.Load(expr_reader)); + auto where_reader = reader.getWhere(); + auto where = dynamic_cast(storage.Load(where_reader)); + return storage.Create(identifier, list_expression, where); +} + +// Function +void Function::Save(capnp::Expression::Builder &expr_builder) { + Expression::Save(expr_builder); + auto builder = expr_builder.initFunction(); + Save(builder); +} + +void Function::Save(capnp::Function::Builder &builder) { + builder.setFunctionName(function_name_); + ::capnp::List::Builder tree_builders = + builder.initArguments(arguments_.size()); + for (size_t i = 0; i < arguments_.size(); ++i) { + auto tree_builder = tree_builders[i]; + arguments_[i]->Save(tree_builder); + } +} + +Function *Function::Construct(capnp::Function::Reader &reader, + AstTreeStorage &storage) { + auto name = reader.getFunctionName().cStr(); + std::vector arguments; + for (auto tree_reader : reader.getArguments()) { + auto tree = storage.Load(tree_reader); + arguments.push_back(dynamic_cast(tree)); + } + return storage.Create(name, arguments); +} + +// Identifier +void Identifier::Save(capnp::Expression::Builder &expr_builder) { + Expression::Save(expr_builder); + auto builder = expr_builder.initIdentifier(); + Save(builder); +} + +void Identifier::Save(capnp::Identifier::Builder &builder) { + builder.setName(name_); + builder.setUserDeclared(user_declared_); +} + +Identifier *Identifier::Construct(capnp::Identifier::Reader &reader, + AstTreeStorage &storage) { + auto name = reader.getName().cStr(); + auto user_declared = reader.getUserDeclared(); + return storage.Create(name, user_declared); +} + +// LabelsTest +void LabelsTest::Save(capnp::Expression::Builder &expr_builder) { + Expression::Save(expr_builder); + auto builder = expr_builder.initLabelsTest(); + Save(builder); +} + +void LabelsTest::Save(capnp::LabelsTest::Builder &builder) { + if (expression_) { + auto expr_builder = builder.initExpression(); + expression_->Save(expr_builder); + } + ::capnp::List::Builder 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); + } +} + +LabelsTest *LabelsTest::Construct(capnp::LabelsTest::Reader &reader, + AstTreeStorage &storage) { + Expression *expression = nullptr; + if (reader.hasExpression()) { + auto expr_reader = reader.getExpression(); + expression = dynamic_cast(storage.Load(expr_reader)); + } + std::vector labels; + for (auto label_reader : reader.getLabels()) { + storage::Label label; + label.Load(label_reader); + labels.push_back(label); + } + return storage.Create(expression, labels); +} + +// ParameterLookup +void ParameterLookup::Save(capnp::Expression::Builder &expr_builder) { + Expression::Save(expr_builder); + auto builder = expr_builder.initParameterLookup(); + Save(builder); +} + +void ParameterLookup::Save(capnp::ParameterLookup::Builder &builder) { + builder.setTokenPosition(token_position_); +} + +ParameterLookup *ParameterLookup::Construct( + capnp::ParameterLookup::Reader &reader, AstTreeStorage &storage) { + auto token_position = reader.getTokenPosition(); + return storage.Create(token_position); +} + +// PropertyLookup +void PropertyLookup::Save(capnp::Expression::Builder &expr_builder) { + Expression::Save(expr_builder); + auto builder = expr_builder.initPropertyLookup(); + Save(builder); +} + +void PropertyLookup::Save(capnp::PropertyLookup::Builder &builder) { + if (expression_) { + auto expr_builder = builder.initExpression(); + expression_->Save(expr_builder); + } + builder.setPropertyName(property_name_); + auto storage_property_builder = builder.initProperty(); + property_.Save(storage_property_builder); +} + +PropertyLookup *PropertyLookup::Construct(capnp::PropertyLookup::Reader &reader, + AstTreeStorage &storage) { + Expression *expression = nullptr; + if (reader.hasExpression()) { + auto expr_reader = reader.getExpression(); + expression = dynamic_cast(storage.Load(expr_reader)); + } + auto property_name = reader.getPropertyName().cStr(); + auto storage_property_reader = reader.getProperty(); + storage::Property property; + property.Load(storage_property_reader); + return storage.Create(expression, property_name, property); +} + +// Reduce +void Reduce::Save(capnp::Expression::Builder &expr_builder) { + Expression::Save(expr_builder); + auto builder = expr_builder.initReduce(); + Save(builder); +} + +void Reduce::Save(capnp::Reduce::Builder &builder) { + auto acc_builder = builder.initAccumulator(); + accumulator_->Save(acc_builder); + auto init_builder = builder.initInitializer(); + initializer_->Save(init_builder); + auto id_builder = builder.initIdentifier(); + identifier_->Save(id_builder); + auto list_builder = builder.initList(); + list_->Save(list_builder); + auto expr_builder = builder.initExpression(); + expression_->Save(expr_builder); +} + +Reduce *Reduce::Construct(capnp::Reduce::Reader &reader, + AstTreeStorage &storage) { + auto acc_reader = reader.getAccumulator(); + auto accumulator = dynamic_cast(storage.Load(acc_reader)); + auto init_reader = reader.getInitializer(); + auto initializer = dynamic_cast(storage.Load(init_reader)); + auto id_reader = reader.getIdentifier(); + auto identifier = dynamic_cast(storage.Load(id_reader)); + auto list_reader = reader.getList(); + auto list = dynamic_cast(storage.Load(list_reader)); + auto expr_reader = reader.getExpression(); + auto expression = dynamic_cast(storage.Load(expr_reader)); + return storage.Create(accumulator, initializer, identifier, list, + expression); +} + +// Single +void Single::Save(capnp::Expression::Builder &expr_builder) { + Expression::Save(expr_builder); + auto builder = expr_builder.initSingle(); + Save(builder); +} + +void Single::Save(capnp::Single::Builder &builder) { + auto where_builder = builder.initWhere(); + where_->Save(where_builder); + auto id_builder = builder.initIdentifier(); + identifier_->Save(id_builder); + auto expr_builder = builder.initListExpression(); + list_expression_->Save(expr_builder); +} + +Single *Single::Construct(capnp::Single::Reader &reader, + AstTreeStorage &storage) { + auto id_reader = reader.getIdentifier(); + auto identifier = dynamic_cast(storage.Load(id_reader)); + auto list_reader = reader.getListExpression(); + auto list_expression = dynamic_cast(storage.Load(list_reader)); + auto where_reader = reader.getWhere(); + auto where = dynamic_cast(storage.Load(where_reader)); + return storage.Create(identifier, list_expression, where); +} + +// Where +void Where::Save(capnp::Tree::Builder &tree_builder) { + Tree::Save(tree_builder); + auto builder = tree_builder.initWhere(); + Save(builder); +} + +void Where::Save(capnp::Where::Builder &builder) { + if (expression_) { + auto expr_builder = builder.initExpression(); + expression_->Save(expr_builder); + } +} + +Where *Where::Construct(capnp::Where::Reader &reader, AstTreeStorage &storage) { + Expression *expression = nullptr; + if (reader.hasExpression()) { + auto expr_reader = reader.getExpression(); + expression = dynamic_cast(storage.Load(expr_reader)); + } + return storage.Create(expression); +} + +// Clause. +void Clause::Save(capnp::Tree::Builder &tree_builder) { + Tree::Save(tree_builder); + auto clause_builder = tree_builder.initClause(); + Save(clause_builder); +} + +Clause *Clause::Construct(capnp::Clause::Reader &reader, + AstTreeStorage &storage) { + switch (reader.which()) { + case capnp::Clause::CREATE: { + auto create_reader = reader.getCreate(); + return Create::Construct(create_reader, storage); + } + case capnp::Clause::CREATE_INDEX: { + auto ci_reader = reader.getCreateIndex(); + return CreateIndex::Construct(ci_reader, storage); + } + case capnp::Clause::DELETE: { + auto del_reader = reader.getDelete(); + return Delete::Construct(del_reader, storage); + } + case capnp::Clause::MATCH: { + auto match_reader = reader.getMatch(); + return Match::Construct(match_reader, storage); + } + case capnp::Clause::MERGE: { + auto merge_reader = reader.getMerge(); + return Merge::Construct(merge_reader, storage); + } + case capnp::Clause::REMOVE_LABELS: { + auto rl_reader = reader.getRemoveLabels(); + return RemoveLabels::Construct(rl_reader, storage); + } + case capnp::Clause::REMOVE_PROPERTY: { + auto rp_reader = reader.getRemoveProperty(); + return RemoveProperty::Construct(rp_reader, storage); + } + case capnp::Clause::RETURN: { + auto ret_reader = reader.getReturn(); + return Return::Construct(ret_reader, storage); + } + case capnp::Clause::SET_LABELS: { + auto sl_reader = reader.getSetLabels(); + return SetLabels::Construct(sl_reader, storage); + break; + } + case capnp::Clause::SET_PROPERTY: { + auto sp_reader = reader.getSetProperty(); + return SetProperty::Construct(sp_reader, storage); + } + case capnp::Clause::SET_PROPERTIES: { + auto sp_reader = reader.getSetProperties(); + return SetProperties::Construct(sp_reader, storage); + } + case capnp::Clause::UNWIND: { + auto unwind_reader = reader.getUnwind(); + return Unwind::Construct(unwind_reader, storage); + } + case capnp::Clause::WITH: { + auto with_reader = reader.getWith(); + return With::Construct(with_reader, storage); + } + } +} + +// Create. +void Create::Save(capnp::Clause::Builder &builder) { + Clause::Save(builder); + auto create_builder = builder.initCreate(); + Create::Save(create_builder); +} + +void Create::Save(capnp::Create::Builder &builder) { + ::capnp::List::Builder tree_builders = + builder.initPatterns(patterns_.size()); + for (size_t i = 0; i < patterns_.size(); ++i) { + auto tree_builder = tree_builders[i]; + patterns_[i]->Save(tree_builder); + } +} + +Create *Create::Construct(capnp::Create::Reader &reader, + AstTreeStorage &storage) { + std::vector patterns; + for (auto tree_reader : reader.getPatterns()) { + auto tree = storage.Load(tree_reader); + patterns.push_back(dynamic_cast(tree)); + } + return storage.Create(patterns); +} + +// CreateIndex. +void CreateIndex::Save(capnp::Clause::Builder &builder) { + Clause::Save(builder); + auto create_builder = builder.initCreateIndex(); + CreateIndex::Save(create_builder); +} + +void CreateIndex::Save(capnp::CreateIndex::Builder &builder) { + auto label_builder = builder.getLabel(); + label_.Save(label_builder); + auto property_builder = builder.getProperty(); + property_.Save(property_builder); +} + +CreateIndex *CreateIndex::Construct(capnp::CreateIndex::Reader &reader, + AstTreeStorage &storage) { + auto label_reader = reader.getLabel(); + storage::Label label; + label.Load(label_reader); + auto property_reader = reader.getProperty(); + storage::Property property; + property.Load(property_reader); + return storage.Create(label, property); +} + +// Delete. +void Delete::Save(capnp::Clause::Builder &builder) { + Clause::Save(builder); + auto del_builder = builder.initDelete(); + Delete::Save(del_builder); +} + +void Delete::Save(capnp::Delete::Builder &builder) { + ::capnp::List::Builder tree_builders = + builder.initExpressions(expressions_.size()); + for (size_t i = 0; i < expressions_.size(); ++i) { + auto tree_builder = tree_builders[i]; + expressions_[i]->Save(tree_builder); + } + builder.setDetach(detach_); +} + +Delete *Delete::Construct(capnp::Delete::Reader &reader, + AstTreeStorage &storage) { + std::vector expressions; + for (auto tree_reader : reader.getExpressions()) { + auto tree = storage.Load(tree_reader); + expressions.push_back(dynamic_cast(tree)); + } + auto detach = reader.getDetach(); + return storage.Create(detach, expressions); +} + +// Match. +void Match::Save(capnp::Clause::Builder &clause_builder) { + Clause::Save(clause_builder); + auto builder = clause_builder.initMatch(); + Match::Save(builder); +} + +void Match::Save(capnp::Match::Builder &builder) { + ::capnp::List::Builder tree_builders = + builder.initPatterns(patterns_.size()); + for (size_t i = 0; i < patterns_.size(); ++i) { + auto tree_builder = tree_builders[i]; + patterns_[i]->Save(tree_builder); + } + + if (where_) { + auto where_builder = builder.initWhere(); + where_->Save(where_builder); + } + builder.setOptional(optional_); +} + +Match *Match::Construct(capnp::Match::Reader &reader, AstTreeStorage &storage) { + std::vector patterns; + for (auto tree_reader : reader.getPatterns()) { + auto tree = storage.Load(tree_reader); + patterns.push_back(dynamic_cast(tree)); + } + Where *where = nullptr; + if (reader.hasWhere()) { + auto where_reader = reader.getWhere(); + where = dynamic_cast(storage.Load(where_reader)); + } + auto optional = reader.getOptional(); + return storage.Create(optional, where, patterns); +} + +// Merge. +void Merge::Save(capnp::Clause::Builder &clause_builder) { + Clause::Save(clause_builder); + auto builder = clause_builder.initMerge(); + Merge::Save(builder); +} + +void Merge::Save(capnp::Merge::Builder &builder) { + ::capnp::List::Builder match_builder = + builder.initOnMatch(on_match_.size()); + for (size_t i = 0; i < on_match_.size(); ++i) { + auto tree_builder = match_builder[i]; + on_match_[i]->Save(tree_builder); + } + + ::capnp::List::Builder create_builder = + builder.initOnCreate(on_create_.size()); + for (size_t i = 0; i < on_create_.size(); ++i) { + auto tree_builder = create_builder[i]; + on_create_[i]->Save(tree_builder); + } + + if (pattern_) { + auto pattern_builder = builder.getPattern(); + pattern_->Save(pattern_builder); + } +} + +Merge *Merge::Construct(capnp::Merge::Reader &reader, AstTreeStorage &storage) { + std::vector on_match; + for (auto tree_reader : reader.getOnMatch()) { + auto tree = storage.Load(tree_reader); + on_match.push_back(dynamic_cast(tree)); + } + + std::vector on_create; + for (auto tree_reader : reader.getOnCreate()) { + auto tree = storage.Load(tree_reader); + on_create.push_back(dynamic_cast(tree)); + } + Pattern *pattern = nullptr; + if (reader.hasPattern()) { + auto pattern_reader = reader.getPattern(); + pattern = dynamic_cast(storage.Load(pattern_reader)); + } + return storage.Create(pattern, on_match, on_create); +} + +// RemoveLabels. +void RemoveLabels::Save(capnp::Clause::Builder &clause_builder) { + Clause::Save(clause_builder); + auto builder = clause_builder.initRemoveLabels(); + RemoveLabels::Save(builder); +} + +void RemoveLabels::Save(capnp::RemoveLabels::Builder &builder) { + if (identifier_) { + auto id_builder = builder.getIdentifier(); + identifier_->Save(id_builder); + } + ::capnp::List::Builder 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); + } +} + +RemoveLabels *RemoveLabels::Construct(capnp::RemoveLabels::Reader &reader, + AstTreeStorage &storage) { + Identifier *identifier = nullptr; + if (reader.hasIdentifier()) { + auto id_reader = reader.getIdentifier(); + identifier = dynamic_cast(storage.Load(id_reader)); + } + std::vector labels; + for (auto label_reader : reader.getLabels()) { + storage::Label label; + label.Load(label_reader); + labels.push_back(label); + } + return storage.Create(identifier, labels); +} + +// RemoveProperty. +void RemoveProperty::Save(capnp::Clause::Builder &clause_builder) { + Clause::Save(clause_builder); + auto builder = clause_builder.initRemoveProperty(); + RemoveProperty::Save(builder); +} + +void RemoveProperty::Save(capnp::RemoveProperty::Builder &builder) { + if (property_lookup_) { + auto pl_builder = builder.getPropertyLookup(); + property_lookup_->Save(pl_builder); + } +} + +RemoveProperty *RemoveProperty::Construct(capnp::RemoveProperty::Reader &reader, + AstTreeStorage &storage) { + PropertyLookup *property_lookup; + if (reader.hasPropertyLookup()) { + auto pl_reader = reader.getPropertyLookup(); + property_lookup = dynamic_cast(storage.Load(pl_reader)); + } + return storage.Create(property_lookup); +} + +// Return. +void Return::Save(capnp::Clause::Builder &clause_builder) { + Clause::Save(clause_builder); + auto builder = clause_builder.initReturn(); + Return::Save(builder); +} + +void SaveReturnBody(capnp::ReturnBody::Builder &rb_builder, ReturnBody &body) { + rb_builder.setDistinct(body.distinct); + rb_builder.setAllIdentifiers(body.all_identifiers); + + ::capnp::List::Builder named_expressions = + rb_builder.initNamedExpressions(body.named_expressions.size()); + for (size_t i = 0; i < body.named_expressions.size(); ++i) { + auto tree_builder = named_expressions[i]; + body.named_expressions[i]->Save(tree_builder); + } + + ::capnp::List::Builder order_by = + rb_builder.initOrderBy(body.order_by.size()); + for (size_t i = 0; i < body.order_by.size(); ++i) { + auto pair_builder = order_by[i]; + auto ordering = body.order_by[i].first == Ordering::ASC + ? capnp::Ordering::ASC + : capnp::Ordering::DESC; + pair_builder.setOrdering(ordering); + auto tree_builder = pair_builder.getExpression(); + body.order_by[i].second->Save(tree_builder); + } + + if (body.skip) { + auto skip_builder = rb_builder.getSkip(); + body.skip->Save(skip_builder); + } + if (body.limit) { + auto limit_builder = rb_builder.getLimit(); + body.limit->Save(limit_builder); + } +} + +void Return::Save(capnp::Return::Builder &builder) { + auto rb_builder = builder.initReturnBody(); + SaveReturnBody(rb_builder, body_); +} + +void LoadReturnBody(capnp::ReturnBody::Reader &rb_reader, ReturnBody &body, + AstTreeStorage &storage) { + body.distinct = rb_reader.getDistinct(); + body.all_identifiers = rb_reader.getAllIdentifiers(); + + for (auto tree_reader : rb_reader.getNamedExpressions()) { + auto tree = storage.Load(tree_reader); + body.named_expressions.push_back(dynamic_cast(tree)); + } + + for (auto pair_reader : rb_reader.getOrderBy()) { + auto ordering = pair_reader.getOrdering() == capnp::Ordering::ASC + ? Ordering::ASC + : Ordering::DESC; + auto tree_reader = pair_reader.getExpression(); + // TODO Check if expression is null? + auto tree = dynamic_cast(storage.Load(tree_reader)); + body.order_by.push_back(std::make_pair(ordering, tree)); + } + + if (rb_reader.hasSkip()) { + auto skip_reader = rb_reader.getSkip(); + body.skip = dynamic_cast(storage.Load(skip_reader)); + } + if (rb_reader.hasLimit()) { + auto limit_reader = rb_reader.getLimit(); + body.limit = dynamic_cast(storage.Load(limit_reader)); + } +} + +Return *Return::Construct(capnp::Return::Reader &reader, + AstTreeStorage &storage) { + auto rb_reader = reader.getReturnBody(); + ReturnBody body; + LoadReturnBody(rb_reader, body, storage); + return storage.Create(body); +} + +// SetLabels. +void SetLabels::Save(capnp::Clause::Builder &clause_builder) { + Clause::Save(clause_builder); + auto builder = clause_builder.initSetLabels(); + SetLabels::Save(builder); +} + +void SetLabels::Save(capnp::SetLabels::Builder &builder) { + if (identifier_) { + auto id_builder = builder.getIdentifier(); + identifier_->Save(id_builder); + } + ::capnp::List::Builder 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); + } +} + +SetLabels *SetLabels::Construct(capnp::SetLabels::Reader &reader, + AstTreeStorage &storage) { + Identifier *identifier = nullptr; + if (reader.hasIdentifier()) { + auto id_reader = reader.getIdentifier(); + identifier = dynamic_cast(storage.Load(id_reader)); + } + std::vector labels; + for (auto label_reader : reader.getLabels()) { + storage::Label label; + label.Load(label_reader); + labels.push_back(label); + } + return storage.Create(identifier, labels); +} + +// SetProperty. +void SetProperty::Save(capnp::Clause::Builder &clause_builder) { + Clause::Save(clause_builder); + auto builder = clause_builder.initSetProperty(); + SetProperty::Save(builder); +} + +void SetProperty::Save(capnp::SetProperty::Builder &builder) { + if (property_lookup_) { + auto pl_builder = builder.getPropertyLookup(); + property_lookup_->Save(pl_builder); + } + if (expression_) { + auto expr_builder = builder.getExpression(); + expression_->Save(expr_builder); + } +} + +SetProperty *SetProperty::Construct(capnp::SetProperty::Reader &reader, + AstTreeStorage &storage) { + PropertyLookup *property_lookup = nullptr; + if (reader.hasPropertyLookup()) { + auto pl_reader = reader.getPropertyLookup(); + property_lookup = dynamic_cast(storage.Load(pl_reader)); + } + Expression *expression; + if (reader.hasExpression()) { + auto expr_reader = reader.getExpression(); + expression = dynamic_cast(storage.Load(expr_reader)); + } + return storage.Create(property_lookup, expression); +} + +// SetProperties. +void SetProperties::Save(capnp::Clause::Builder &clause_builder) { + Clause::Save(clause_builder); + auto builder = clause_builder.initSetProperties(); + SetProperties::Save(builder); +} + +void SetProperties::Save(capnp::SetProperties::Builder &builder) { + if (identifier_) { + auto id_builder = builder.getIdentifier(); + identifier_->Save(id_builder); + } + if (expression_) { + auto expr_builder = builder.getExpression(); + expression_->Save(expr_builder); + } + builder.setUpdate(update_); +} + +SetProperties *SetProperties::Construct(capnp::SetProperties::Reader &reader, + AstTreeStorage &storage) { + Identifier *identifier = nullptr; + if (reader.hasIdentifier()) { + auto id_reader = reader.getIdentifier(); + identifier = dynamic_cast(storage.Load(id_reader)); + } + Expression *expression = nullptr; + if (reader.hasExpression()) { + auto expr_reader = reader.getExpression(); + expression = dynamic_cast(storage.Load(expr_reader)); + } + auto update = reader.getUpdate(); + return storage.Create(identifier, expression, update); +} + +// Unwind. +void Unwind::Save(capnp::Clause::Builder &clause_builder) { + Clause::Save(clause_builder); + auto builder = clause_builder.initUnwind(); + Unwind::Save(builder); +} + +void Unwind::Save(capnp::Unwind::Builder &builder) { + if (named_expression_) { + auto expr_builder = builder.getNamedExpression(); + named_expression_->Save(expr_builder); + } +} + +Unwind *Unwind::Construct(capnp::Unwind::Reader &reader, + AstTreeStorage &storage) { + NamedExpression *expression = nullptr; + if (reader.hasNamedExpression()) { + auto expr_reader = reader.getNamedExpression(); + expression = dynamic_cast(storage.Load(expr_reader)); + } + return storage.Create(expression); +} + +// With. +void With::Save(capnp::Clause::Builder &clause_builder) { + Clause::Save(clause_builder); + auto builder = clause_builder.initWith(); + With::Save(builder); +} + +void With::Save(capnp::With::Builder &builder) { + if (where_) { + auto where_builder = builder.getWhere(); + where_->Save(where_builder); + } + auto rb_builder = builder.initReturnBody(); + SaveReturnBody(rb_builder, body_); +} + +With *With::Construct(capnp::With::Reader &reader, AstTreeStorage &storage) { + Where *where = nullptr; + if (reader.hasWhere()) { + auto where_reader = reader.getWhere(); + where = dynamic_cast(storage.Load(where_reader)); + } + auto rb_reader = reader.getReturnBody(); + ReturnBody body; + LoadReturnBody(rb_reader, body, storage); + return storage.Create(body, where); +} + +// CypherUnion +void CypherUnion::Save(capnp::Tree::Builder &tree_builder) { + Tree::Save(tree_builder); + auto builder = tree_builder.initCypherUnion(); + Save(builder); +} + +void CypherUnion::Save(capnp::CypherUnion::Builder &builder) { + if (single_query_) { + auto sq_builder = builder.initSingleQuery(); + single_query_->Save(sq_builder); + } + builder.setDistinct(distinct_); + ::capnp::List::Builder 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); + } +} + +CypherUnion *CypherUnion::Construct(capnp::CypherUnion::Reader &reader, + AstTreeStorage &storage) { + SingleQuery *single_query = nullptr; + if (reader.hasSingleQuery()) { + auto sq_reader = reader.getSingleQuery(); + single_query = dynamic_cast(storage.Load(sq_reader)); + } + auto distinct = reader.getDistinct(); + std::vector symbols; + for (auto symbol_reader : reader.getUnionSymbols()) { + Symbol symbol; + symbol.Load(symbol_reader); + symbols.push_back(symbol); + } + return storage.Create(distinct, single_query, symbols); +} + +// NamedExpression +void NamedExpression::Save(capnp::Tree::Builder &tree_builder) { + Tree::Save(tree_builder); + auto builder = tree_builder.initNamedExpression(); + Save(builder); +} + +void NamedExpression::Save(capnp::NamedExpression::Builder &builder) { + builder.setName(name_); + builder.setTokenPosition(token_position_); + if (expression_) { + auto expr_builder = builder.getExpression(); + expression_->Save(expr_builder); + } +} + +NamedExpression *NamedExpression::Construct( + capnp::NamedExpression::Reader &reader, AstTreeStorage &storage) { + auto name = reader.getName().cStr(); + auto token_position = reader.getTokenPosition(); + Expression *expression = nullptr; + if (reader.hasExpression()) { + auto expr_reader = reader.getExpression(); + expression = dynamic_cast(storage.Load(expr_reader)); + } + return storage.Create(name, expression, token_position); +} + +// Pattern +void Pattern::Save(capnp::Tree::Builder &tree_builder) { + Tree::Save(tree_builder); + auto builder = tree_builder.initPattern(); + Save(builder); +} + +void Pattern::Save(capnp::Pattern::Builder &builder) { + if (identifier_) { + auto id_builder = builder.getIdentifier(); + identifier_->Save(id_builder); + } + ::capnp::List::Builder tree_builders = + builder.initAtoms(atoms_.size()); + for (size_t i = 0; i < atoms_.size(); ++i) { + auto tree_builder = tree_builders[i]; + atoms_[i]->Save(tree_builder); + } +} + +Pattern *Pattern::Construct(capnp::Pattern::Reader &reader, + AstTreeStorage &storage) { + auto pattern = storage.Create(); + if (reader.hasIdentifier()) { + auto id_reader = reader.getIdentifier(); + pattern->identifier_ = dynamic_cast(storage.Load(id_reader)); + } + for (auto tree_reader : reader.getAtoms()) { + auto tree = storage.Load(tree_reader); + pattern->atoms_.push_back(dynamic_cast(tree)); + } + return pattern; +} + +// PatternAtom. +void PatternAtom::Save(capnp::Tree::Builder &tree_builder) { + Tree::Save(tree_builder); + auto pattern_builder = tree_builder.initPatternAtom(); + Save(pattern_builder); +} + +void PatternAtom::Save(capnp::PatternAtom::Builder &builder) { + if (identifier_) { + auto id_builder = builder.getIdentifier(); + identifier_->Save(id_builder); + } +} + +PatternAtom *PatternAtom::Construct(capnp::PatternAtom::Reader &reader, + AstTreeStorage &storage) { + switch (reader.which()) { + case capnp::PatternAtom::EDGE_ATOM: { + auto edge_reader = reader.getEdgeAtom(); + return EdgeAtom::Construct(edge_reader, storage); + } + case capnp::PatternAtom::NODE_ATOM: { + auto node_reader = reader.getNodeAtom(); + return NodeAtom::Construct(node_reader, storage); + } + } +} + +void PatternAtom::Load(capnp::Tree::Reader &reader, AstTreeStorage &storage) { + Tree::Load(reader, storage); + auto pa_reader = reader.getPatternAtom(); + if (pa_reader.hasIdentifier()) { + auto id_reader = pa_reader.getIdentifier(); + identifier_ = dynamic_cast(storage.Load(id_reader)); + } +} + +// NodeAtom +void NodeAtom::Save(capnp::PatternAtom::Builder &pattern_builder) { + PatternAtom::Save(pattern_builder); + auto builder = pattern_builder.initNodeAtom(); + Save(builder); +} + +void NodeAtom::Save(capnp::NodeAtom::Builder &builder) { + ::capnp::List::Builder map_builder = + builder.initProperties(properties_.size()); + size_t i = 0; + for (auto &entry : properties_) { + auto entry_builder = map_builder[i]; + 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); + auto value_builder = entry_builder.getValue(); + if (entry.second) entry.second->Save(value_builder); + ++i; + } + ::capnp::List::Builder 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); + } +} + +NodeAtom *NodeAtom::Construct(capnp::NodeAtom::Reader &reader, + AstTreeStorage &storage) { + auto *atom = storage.Create(); + for (auto entry_reader : reader.getProperties()) { + auto key_pair_reader = entry_reader.getKey(); + auto key_first = key_pair_reader.getFirst().cStr(); + auto storage_property_reader = key_pair_reader.getSecond(); + storage::Property property; + property.Load(storage_property_reader); + auto value_reader = entry_reader.getValue(); + auto value = storage.Load(value_reader); + auto key = std::make_pair(key_first, property); + // TODO Maybe check if expression is nullptr? + atom->properties_.emplace(key, dynamic_cast(value)); + } + for (auto label_reader : reader.getLabels()) { + storage::Label label; + label.Load(label_reader); + atom->labels_.push_back(label); + } + return atom; +} + +// EdgeAtom +void EdgeAtom::Save(capnp::PatternAtom::Builder &pattern_builder) { + PatternAtom::Save(pattern_builder); + auto builder = pattern_builder.initEdgeAtom(); + Save(builder); +} + +void SaveLambda(query::EdgeAtom::Lambda &lambda, + capnp::EdgeAtom::Lambda::Builder &builder) { + if (lambda.inner_edge) { + auto ie_builder = builder.getInnerEdge(); + lambda.inner_edge->Save(ie_builder); + } + if (lambda.inner_node) { + auto in_builder = builder.getInnerNode(); + lambda.inner_node->Save(in_builder); + } + if (lambda.expression) { + auto expr_builder = builder.getExpression(); + lambda.expression->Save(expr_builder); + } +} + +void EdgeAtom::Save(capnp::EdgeAtom::Builder &builder) { + switch (type_) { + case Type::BREADTH_FIRST: + builder.setType(capnp::EdgeAtom::Type::BREADTH_FIRST); + break; + case Type::DEPTH_FIRST: + builder.setType(capnp::EdgeAtom::Type::DEPTH_FIRST); + break; + case Type::SINGLE: + builder.setType(capnp::EdgeAtom::Type::SINGLE); + break; + case Type::WEIGHTED_SHORTEST_PATH: + builder.setType(capnp::EdgeAtom::Type::WEIGHTED_SHORTEST_PATH); + break; + } + + switch (direction_) { + case Direction::BOTH: + builder.setDirection(capnp::EdgeAtom::Direction::BOTH); + break; + case Direction::IN: + builder.setDirection(capnp::EdgeAtom::Direction::IN); + break; + case Direction::OUT: + builder.setDirection(capnp::EdgeAtom::Direction::OUT); + break; + } + + ::capnp::List::Builder 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); + } + + ::capnp::List::Builder map_builder = + builder.initProperties(properties_.size()); + size_t i = 0; + for (auto &entry : properties_) { + auto entry_builder = map_builder[i]; + 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); + auto value_builder = entry_builder.getValue(); + if (entry.second) entry.second->Save(value_builder); + ++i; + } + + if (lower_bound_) { + auto lb_builder = builder.getLowerBound(); + lower_bound_->Save(lb_builder); + } + if (upper_bound_) { + auto ub_builder = builder.getUpperBound(); + upper_bound_->Save(ub_builder); + } + + auto filter_builder = builder.initFilterLambda(); + SaveLambda(filter_lambda_, filter_builder); + auto weight_builder = builder.initWeightLambda(); + SaveLambda(weight_lambda_, weight_builder); + + if (total_weight_) { + auto total_weight_builder = builder.getTotalWeight(); + total_weight_->Save(total_weight_builder); + } +} + +void LoadLambda(capnp::EdgeAtom::Lambda::Reader &reader, + query::EdgeAtom::Lambda &lambda, AstTreeStorage &storage) { + if (reader.hasInnerEdge()) { + auto ie_reader = reader.getInnerEdge(); + lambda.inner_edge = dynamic_cast(storage.Load(ie_reader)); + } + if (reader.hasInnerNode()) { + auto in_reader = reader.getInnerNode(); + lambda.inner_node = dynamic_cast(storage.Load(in_reader)); + } + if (reader.hasExpression()) { + auto expr_reader = reader.getExpression(); + lambda.expression = dynamic_cast(storage.Load(expr_reader)); + } +} + +EdgeAtom *EdgeAtom::Construct(capnp::EdgeAtom::Reader &reader, + AstTreeStorage &storage) { + auto *atom = storage.Create(); + + switch (reader.getType()) { + case capnp::EdgeAtom::Type::BREADTH_FIRST: + atom->type_ = Type::BREADTH_FIRST; + break; + case capnp::EdgeAtom::Type::DEPTH_FIRST: + atom->type_ = Type::DEPTH_FIRST; + break; + case capnp::EdgeAtom::Type::SINGLE: + atom->type_ = Type::SINGLE; + break; + case capnp::EdgeAtom::Type::WEIGHTED_SHORTEST_PATH: + atom->type_ = Type::WEIGHTED_SHORTEST_PATH; + break; + } + + switch (reader.getDirection()) { + case capnp::EdgeAtom::Direction::BOTH: + atom->direction_ = Direction::BOTH; + break; + case capnp::EdgeAtom::Direction::IN: + atom->direction_ = Direction::IN; + break; + case capnp::EdgeAtom::Direction::OUT: + atom->direction_ = Direction::OUT; + break; + } + + if (reader.hasTotalWeight()) { + auto id_reader = reader.getTotalWeight(); + atom->total_weight_ = dynamic_cast(storage.Load(id_reader)); + } + if (reader.hasLowerBound()) { + auto lb_reader = reader.getLowerBound(); + atom->lower_bound_ = dynamic_cast(storage.Load(lb_reader)); + } + if (reader.hasUpperBound()) { + auto ub_reader = reader.getUpperBound(); + atom->upper_bound_ = dynamic_cast(storage.Load(ub_reader)); + } + auto filter_reader = reader.getFilterLambda(); + LoadLambda(filter_reader, atom->filter_lambda_, storage); + auto weight_reader = reader.getWeightLambda(); + LoadLambda(weight_reader, atom->weight_lambda_, storage); + + for (auto entry_reader : reader.getProperties()) { + auto key_pair_reader = entry_reader.getKey(); + auto key_first = key_pair_reader.getFirst().cStr(); + auto storage_property_reader = key_pair_reader.getSecond(); + storage::Property property; + property.Load(storage_property_reader); + auto value_reader = entry_reader.getValue(); + auto value = storage.Load(value_reader); + auto key = std::make_pair(key_first, property); + // TODO Check if expression is null? + atom->properties_.emplace(key, dynamic_cast(value)); + } + + for (auto edge_type_reader : reader.getEdgeTypes()) { + storage::EdgeType edge_type; + edge_type.Load(edge_type_reader); + atom->edge_types_.push_back(edge_type); + } + return atom; +} + +// Query +void Query::Save(capnp::Tree::Builder &tree_builder) { + Tree::Save(tree_builder); + auto builder = tree_builder.initQuery(); + Save(builder); +} + +void Query::Save(capnp::Query::Builder &builder) { + if (single_query_) { + auto sq_builder = builder.initSingleQuery(); + single_query_->Save(sq_builder); + } + ::capnp::List::Builder tree_builders = + builder.initCypherUnions(cypher_unions_.size()); + for (size_t i = 0; i < cypher_unions_.size(); ++i) { + auto tree_builder = tree_builders[i]; + cypher_unions_[i]->Save(tree_builder); + } +} + +Query *Query::Construct(capnp::Query::Reader &reader, AstTreeStorage &storage) { + auto query = storage.query(); + if (reader.hasSingleQuery()) { + auto sq_reader = reader.getSingleQuery(); + query->single_query_ = dynamic_cast(storage.Load(sq_reader)); + } + for (auto tree_reader : reader.getCypherUnions()) { + auto tree = storage.Load(tree_reader); + query->cypher_unions_.push_back(dynamic_cast(tree)); + } + return query; +} + +// SingleQuery +void SingleQuery::Save(capnp::Tree::Builder &tree_builder) { + Tree::Save(tree_builder); + auto builder = tree_builder.initSingleQuery(); + Save(builder); +} + +void SingleQuery::Save(capnp::SingleQuery::Builder &builder) { + ::capnp::List::Builder tree_builders = + builder.initClauses(clauses_.size()); + for (size_t i = 0; i < clauses_.size(); ++i) { + auto tree_builder = tree_builders[i]; + clauses_[i]->Save(tree_builder); + } +} + +SingleQuery *SingleQuery::Construct(capnp::SingleQuery::Reader &reader, + AstTreeStorage &storage) { + auto query = storage.Create(); + for (auto tree_reader : reader.getClauses()) { + auto tree = storage.Load(tree_reader); + query->clauses_.push_back(dynamic_cast(tree)); + } + return query; +} } // namespace query BOOST_CLASS_EXPORT_IMPLEMENT(query::Query); diff --git a/src/query/frontend/ast/ast.hpp b/src/query/frontend/ast/ast.hpp index 049edec2f..9e9929d71 100644 --- a/src/query/frontend/ast/ast.hpp +++ b/src/query/frontend/ast/ast.hpp @@ -17,6 +17,8 @@ #include "storage/types.hpp" #include "utils/serialization.hpp" +#include "ast.capnp.h" + // Hash function for the key in pattern atom property maps. namespace std { template <> @@ -101,6 +103,8 @@ class AstTreeStorage { Load(ar, *query()); } + Tree *Load(capnp::Tree::Reader &tree); + private: int next_uid_ = 0; std::vector> storage_; @@ -165,10 +169,13 @@ class Tree : public ::utils::Visitable, int uid() const { return uid_; } virtual Tree *Clone(AstTreeStorage &storage) const = 0; + virtual void Save(capnp::Tree::Builder &builder); protected: explicit Tree(int uid) : uid_(uid) {} + virtual void Load(capnp::Tree::Reader &reader, AstTreeStorage &storage); + private: int uid_; @@ -187,10 +194,16 @@ class Expression : public Tree { public: Expression *Clone(AstTreeStorage &storage) const override = 0; + static Expression *Construct(capnp::Expression::Reader &reader, + AstTreeStorage &storage); + + void Save(capnp::Tree::Builder &builder) override; protected: explicit Expression(int uid) : Tree(uid) {} + virtual void Save(capnp::Expression::Builder &) {} + private: friend class boost::serialization::access; SERIALIZE_USING_BASE(Tree); @@ -212,12 +225,19 @@ class Where : public Tree { return storage.Create(expression_->Clone(storage)); } + static Where *Construct(capnp::Where::Reader &reader, + AstTreeStorage &storage); + + void Save(capnp::Tree::Builder &builder) override; + Expression *expression_ = nullptr; protected: explicit Where(int uid) : Tree(uid) {} Where(int uid, Expression *expression) : Tree(uid), expression_(expression) {} + virtual void Save(capnp::Where::Builder &); + private: friend class boost::serialization::access; @@ -248,12 +268,19 @@ class BinaryOperator : public Expression { Expression *expression2_ = nullptr; BinaryOperator *Clone(AstTreeStorage &storage) const override = 0; + static BinaryOperator *Construct(capnp::BinaryOperator::Reader &reader, + AstTreeStorage &storage); protected: explicit BinaryOperator(int uid) : Expression(uid) {} BinaryOperator(int uid, Expression *expression1, Expression *expression2) : Expression(uid), expression1_(expression1), expression2_(expression2) {} + void Save(capnp::Expression::Builder &builder) override; + using Expression::Save; + virtual void Save(capnp::BinaryOperator::Builder &builder); + void Load(capnp::Tree::Reader &reader, AstTreeStorage &storage) override; + private: friend class boost::serialization::access; @@ -281,12 +308,19 @@ class UnaryOperator : public Expression { Expression *expression_ = nullptr; UnaryOperator *Clone(AstTreeStorage &storage) const override = 0; + static UnaryOperator *Construct(capnp::UnaryOperator::Reader &reader, + AstTreeStorage &storage); protected: explicit UnaryOperator(int uid) : Expression(uid) {} UnaryOperator(int uid, Expression *expression) : Expression(uid), expression_(expression) {} + void Save(capnp::Expression::Builder &) override; + using Expression::Save; + virtual void Save(capnp::UnaryOperator::Builder &builder); + void Load(capnp::Tree::Reader &reader, AstTreeStorage &storage) override; + private: friend class boost::serialization::access; @@ -318,8 +352,12 @@ class OrOperator : public BinaryOperator { } CLONE_BINARY_EXPRESSION; + static OrOperator *Construct(capnp::OrOperator::Reader &reader, + AstTreeStorage &storage); + protected: using BinaryOperator::BinaryOperator; + void Save(capnp::BinaryOperator::Builder &builder) override; private: friend class boost::serialization::access; @@ -342,9 +380,12 @@ class XorOperator : public BinaryOperator { return visitor.PostVisit(*this); } CLONE_BINARY_EXPRESSION; + static XorOperator *Construct(capnp::XorOperator::Reader &reader, + AstTreeStorage &storage); protected: using BinaryOperator::BinaryOperator; + void Save(capnp::BinaryOperator::Builder &builder) override; private: friend class boost::serialization::access; @@ -367,9 +408,12 @@ class AndOperator : public BinaryOperator { return visitor.PostVisit(*this); } CLONE_BINARY_EXPRESSION; + static AndOperator *Construct(capnp::AndOperator::Reader &reader, + AstTreeStorage &storage); protected: using BinaryOperator::BinaryOperator; + void Save(capnp::BinaryOperator::Builder &builder) override; private: friend class boost::serialization::access; @@ -392,9 +436,12 @@ class AdditionOperator : public BinaryOperator { return visitor.PostVisit(*this); } CLONE_BINARY_EXPRESSION; + static AdditionOperator *Construct(capnp::AdditionOperator::Reader &reader, + AstTreeStorage &storage); protected: using BinaryOperator::BinaryOperator; + void Save(capnp::BinaryOperator::Builder &builder) override; private: friend class boost::serialization::access; @@ -417,9 +464,12 @@ class SubtractionOperator : public BinaryOperator { return visitor.PostVisit(*this); } CLONE_BINARY_EXPRESSION; + static SubtractionOperator *Construct( + capnp::SubtractionOperator::Reader &reader, AstTreeStorage &storage); protected: using BinaryOperator::BinaryOperator; + void Save(capnp::BinaryOperator::Builder &builder) override; private: friend class boost::serialization::access; @@ -442,9 +492,12 @@ class MultiplicationOperator : public BinaryOperator { return visitor.PostVisit(*this); } CLONE_BINARY_EXPRESSION; + static MultiplicationOperator *Construct( + capnp::MultiplicationOperator::Reader &reader, AstTreeStorage &storage); protected: using BinaryOperator::BinaryOperator; + void Save(capnp::BinaryOperator::Builder &builder) override; private: friend class boost::serialization::access; @@ -466,9 +519,12 @@ class DivisionOperator : public BinaryOperator { return visitor.PostVisit(*this); } CLONE_BINARY_EXPRESSION; + static DivisionOperator *Construct(capnp::DivisionOperator::Reader &reader, + AstTreeStorage &storage); protected: using BinaryOperator::BinaryOperator; + void Save(capnp::BinaryOperator::Builder &builder) override; private: friend class boost::serialization::access; @@ -491,9 +547,12 @@ class ModOperator : public BinaryOperator { return visitor.PostVisit(*this); } CLONE_BINARY_EXPRESSION; + static ModOperator *Construct(capnp::ModOperator::Reader &reader, + AstTreeStorage &storage); protected: using BinaryOperator::BinaryOperator; + void Save(capnp::BinaryOperator::Builder &builder) override; private: friend class boost::serialization::access; @@ -516,9 +575,12 @@ class NotEqualOperator : public BinaryOperator { return visitor.PostVisit(*this); } CLONE_BINARY_EXPRESSION; + static NotEqualOperator *Construct(capnp::NotEqualOperator::Reader &reader, + AstTreeStorage &storage); protected: using BinaryOperator::BinaryOperator; + void Save(capnp::BinaryOperator::Builder &builder) override; private: friend class boost::serialization::access; @@ -541,9 +603,12 @@ class EqualOperator : public BinaryOperator { return visitor.PostVisit(*this); } CLONE_BINARY_EXPRESSION; + static EqualOperator *Construct(capnp::EqualOperator::Reader &reader, + AstTreeStorage &storage); protected: using BinaryOperator::BinaryOperator; + void Save(capnp::BinaryOperator::Builder &builder) override; private: friend class boost::serialization::access; @@ -566,9 +631,12 @@ class LessOperator : public BinaryOperator { return visitor.PostVisit(*this); } CLONE_BINARY_EXPRESSION; + static LessOperator *Construct(capnp::LessOperator::Reader &reader, + AstTreeStorage &storage); protected: using BinaryOperator::BinaryOperator; + void Save(capnp::BinaryOperator::Builder &builder) override; private: friend class boost::serialization::access; @@ -591,9 +659,12 @@ class GreaterOperator : public BinaryOperator { return visitor.PostVisit(*this); } CLONE_BINARY_EXPRESSION; + static GreaterOperator *Construct(capnp::GreaterOperator::Reader &reader, + AstTreeStorage &storage); protected: using BinaryOperator::BinaryOperator; + void Save(capnp::BinaryOperator::Builder &builder) override; private: friend class boost::serialization::access; @@ -616,9 +687,12 @@ class LessEqualOperator : public BinaryOperator { return visitor.PostVisit(*this); } CLONE_BINARY_EXPRESSION; + static LessEqualOperator *Construct(capnp::LessEqualOperator::Reader &reader, + AstTreeStorage &storage); protected: using BinaryOperator::BinaryOperator; + void Save(capnp::BinaryOperator::Builder &builder) override; private: friend class boost::serialization::access; @@ -641,9 +715,12 @@ class GreaterEqualOperator : public BinaryOperator { return visitor.PostVisit(*this); } CLONE_BINARY_EXPRESSION; + static GreaterEqualOperator *Construct( + capnp::GreaterEqualOperator::Reader &reader, AstTreeStorage &storage); protected: using BinaryOperator::BinaryOperator; + void Save(capnp::BinaryOperator::Builder &builder) override; private: friend class boost::serialization::access; @@ -666,9 +743,12 @@ class InListOperator : public BinaryOperator { return visitor.PostVisit(*this); } CLONE_BINARY_EXPRESSION; + static InListOperator *Construct(capnp::InListOperator::Reader &reader, + AstTreeStorage &storage); protected: using BinaryOperator::BinaryOperator; + void Save(capnp::BinaryOperator::Builder &builder) override; private: friend class boost::serialization::access; @@ -691,9 +771,12 @@ class ListMapIndexingOperator : public BinaryOperator { return visitor.PostVisit(*this); } CLONE_BINARY_EXPRESSION; + static ListMapIndexingOperator *Construct( + capnp::ListMapIndexingOperator::Reader &reader, AstTreeStorage &storage); protected: using BinaryOperator::BinaryOperator; + void Save(capnp::BinaryOperator::Builder &builder) override; private: friend class boost::serialization::access; @@ -728,6 +811,9 @@ class ListSlicingOperator : public Expression { upper_bound_ ? upper_bound_->Clone(storage) : nullptr); } + static ListSlicingOperator *Construct( + capnp::ListSlicingOperator::Reader &reader, AstTreeStorage &storage); + Expression *list_ = nullptr; Expression *lower_bound_ = nullptr; Expression *upper_bound_ = nullptr; @@ -740,6 +826,10 @@ class ListSlicingOperator : public Expression { lower_bound_(lower_bound), upper_bound_(upper_bound) {} + void Save(capnp::Expression::Builder &builder) override; + using Expression::Save; + virtual void Save(capnp::ListSlicingOperator::Builder &builder); + private: friend class boost::serialization::access; @@ -786,6 +876,8 @@ class IfOperator : public Expression { else_expression_->Clone(storage)); } + static IfOperator *Construct(capnp::IfOperator::Reader &reader, + AstTreeStorage &storage); // None of the expressions should be nullptrs. If there is no else_expression // you probably want to make it NULL PrimitiveLiteral. Expression *condition_; @@ -800,6 +892,10 @@ class IfOperator : public Expression { then_expression_(then_expression), else_expression_(else_expression) {} + void Save(capnp::Expression::Builder &builder) override; + using Expression::Save; + virtual void Save(capnp::IfOperator::Builder &builder); + private: friend class boost::serialization::access; @@ -839,9 +935,12 @@ class NotOperator : public UnaryOperator { return visitor.PostVisit(*this); } CLONE_UNARY_EXPRESSION; + static NotOperator *Construct(capnp::NotOperator::Reader &reader, + AstTreeStorage &storage); protected: using UnaryOperator::UnaryOperator; + void Save(capnp::UnaryOperator::Builder &builder) override; private: friend class boost::serialization::access; @@ -864,9 +963,12 @@ class UnaryPlusOperator : public UnaryOperator { return visitor.PostVisit(*this); } CLONE_UNARY_EXPRESSION; + static UnaryPlusOperator *Construct(capnp::UnaryPlusOperator::Reader &reader, + AstTreeStorage &storage); protected: using UnaryOperator::UnaryOperator; + void Save(capnp::UnaryOperator::Builder &builder) override; private: friend class boost::serialization::access; @@ -889,9 +991,12 @@ class UnaryMinusOperator : public UnaryOperator { return visitor.PostVisit(*this); } CLONE_UNARY_EXPRESSION; + static UnaryMinusOperator *Construct( + capnp::UnaryMinusOperator::Reader &reader, AstTreeStorage &storage); protected: using UnaryOperator::UnaryOperator; + void Save(capnp::UnaryOperator::Builder &builder) override; private: friend class boost::serialization::access; @@ -914,9 +1019,12 @@ class IsNullOperator : public UnaryOperator { return visitor.PostVisit(*this); } CLONE_UNARY_EXPRESSION; + static IsNullOperator *Construct(capnp::IsNullOperator::Reader &reader, + AstTreeStorage &storage); protected: using UnaryOperator::UnaryOperator; + void Save(capnp::UnaryOperator::Builder &builder) override; private: friend class boost::serialization::access; @@ -932,10 +1040,16 @@ class BaseLiteral : public Expression { public: BaseLiteral *Clone(AstTreeStorage &storage) const override = 0; + static BaseLiteral *Construct(capnp::BaseLiteral::Reader &reader, + AstTreeStorage &storage); protected: explicit BaseLiteral(int uid) : Expression(uid) {} + void Save(capnp::Expression::Builder &builder) override; + using Expression::Save; + virtual void Save(capnp::BaseLiteral::Builder &) {} + private: friend class boost::serialization::access; SERIALIZE_USING_BASE(Expression); @@ -952,6 +1066,9 @@ class PrimitiveLiteral : public BaseLiteral { return storage.Create(value_, token_position_); } + static PrimitiveLiteral *Construct(capnp::PrimitiveLiteral::Reader &reader, + AstTreeStorage &storage); + TypedValue value_; // This field contains token position of literal used to create // PrimitiveLiteral object. If PrimitiveLiteral object is not created from @@ -966,6 +1083,8 @@ class PrimitiveLiteral : public BaseLiteral { PrimitiveLiteral(int uid, T value, int token_position) : BaseLiteral(uid), value_(value), token_position_(token_position) {} + void Save(capnp::BaseLiteral::Builder &builder) override; + private: friend class boost::serialization::access; @@ -1012,6 +1131,9 @@ class ListLiteral : public BaseLiteral { return list; } + static ListLiteral *Construct(capnp::ListLiteral::Reader &reader, + AstTreeStorage &storage); + std::vector elements_; protected: @@ -1019,6 +1141,8 @@ class ListLiteral : public BaseLiteral { ListLiteral(int uid, const std::vector &elements) : BaseLiteral(uid), elements_(elements) {} + void Save(capnp::BaseLiteral::Builder &builder) override; + private: friend class boost::serialization::access; @@ -1062,6 +1186,9 @@ class MapLiteral : public BaseLiteral { return map; } + static MapLiteral *Construct(capnp::MapLiteral::Reader &reader, + AstTreeStorage &storage); + // maps (property_name, property) to expressions std::unordered_map, Expression *> elements_; @@ -1073,6 +1200,8 @@ class MapLiteral : public BaseLiteral { Expression *> &elements) : BaseLiteral(uid), elements_(elements) {} + void Save(capnp::BaseLiteral::Builder &builder) override; + private: friend class boost::serialization::access; @@ -1123,6 +1252,10 @@ class Identifier : public Expression { return storage.Create(name_, user_declared_); } + static Identifier *Construct(capnp::Identifier::Reader &reader, + AstTreeStorage &storage); + using Expression::Save; + std::string name_; bool user_declared_ = true; @@ -1131,6 +1264,9 @@ class Identifier : public Expression { Identifier(int uid, const std::string &name, bool user_declared) : Expression(uid), name_(name), user_declared_(user_declared) {} + void Save(capnp::Expression::Builder &builder) override; + virtual void Save(capnp::Identifier::Builder &builder); + private: friend class boost::serialization::access; @@ -1164,6 +1300,10 @@ class PropertyLookup : public Expression { property_name_, property_); } + static PropertyLookup *Construct(capnp::PropertyLookup::Reader &reader, + AstTreeStorage &storage); + using Expression::Save; + Expression *expression_ = nullptr; std::string property_name_; storage::Property property_; @@ -1182,6 +1322,9 @@ class PropertyLookup : public Expression { property_name_(property.first), property_(property.second) {} + void Save(capnp::Expression::Builder &builder) override; + virtual void Save(capnp::PropertyLookup::Builder &builder); + private: friend class boost::serialization::access; @@ -1225,6 +1368,10 @@ class LabelsTest : public Expression { return storage.Create(expression_->Clone(storage), labels_); } + static LabelsTest *Construct(capnp::LabelsTest::Reader &reader, + AstTreeStorage &storage); + using Expression::Save; + Expression *expression_ = nullptr; std::vector labels_; @@ -1233,6 +1380,9 @@ class LabelsTest : public Expression { const std::vector &labels) : Expression(uid), expression_(expression), labels_(labels) {} + void Save(capnp::Expression::Builder &builder) override; + virtual void Save(capnp::LabelsTest::Builder &builder); + private: friend class boost::serialization::access; @@ -1280,6 +1430,9 @@ class Function : public Expression { return storage.Create(function_name_, arguments); } + static Function *Construct(capnp::Function::Reader &reader, + AstTreeStorage &storage); + const auto &function() const { return function_; } const auto &function_name() const { return function_name_; } std::vector arguments_; @@ -1295,6 +1448,9 @@ class Function : public Expression { function_(NameToFunction(function_name_)) { DCHECK(function_) << "Unexpected missing function: " << function_name_; } + void Save(capnp::Expression::Builder &builder) override; + using Expression::Save; + virtual void Save(capnp::Function::Builder &builder); private: std::string function_name_; @@ -1361,8 +1517,13 @@ class Aggregation : public BinaryOperator { } Op op_; + static Aggregation *Construct(capnp::Aggregation::Reader &, + AstTreeStorage &storage); protected: + // Use only for serialization. + Aggregation(int uid, Op op) : BinaryOperator(uid), op_(op) {} + /// Aggregation's first expression is the value being aggregated. The second /// expression is the key used only in COLLECT_MAP. Aggregation(int uid, Expression *expression1, Expression *expression2, Op op) @@ -1375,6 +1536,8 @@ class Aggregation : public BinaryOperator { "invalid otherwise"; } + void Save(capnp::BinaryOperator::Builder &builder) override; + private: friend class boost::serialization::access; @@ -1410,6 +1573,11 @@ class Reduce : public Expression { identifier_->Clone(storage), list_->Clone(storage), expression_->Clone(storage)); } + + static Reduce *Construct(capnp::Reduce::Reader &reader, + AstTreeStorage &storage); + using Expression::Save; + // None of these should be nullptr after construction. /// Identifier for the accumulating variable @@ -1434,6 +1602,9 @@ class Reduce : public Expression { list_(list), expression_(expression) {} + void Save(capnp::Expression::Builder &builder) override; + virtual void Save(capnp::Reduce::Builder &builder); + private: friend class boost::serialization::access; @@ -1484,6 +1655,8 @@ class All : public Expression { where_->Clone(storage)); } + static All *Construct(capnp::All::Reader &reader, AstTreeStorage &storage); + // None of these should be nullptr after construction. Identifier *identifier_ = nullptr; Expression *list_expression_ = nullptr; @@ -1497,6 +1670,10 @@ class All : public Expression { list_expression_(list_expression), where_(where) {} + void Save(capnp::Expression::Builder &builder) override; + using Expression::Save; + virtual void Save(capnp::All::Builder &builder); + private: friend class boost::serialization::access; @@ -1523,9 +1700,9 @@ class All : public Expression { const unsigned int); }; -// TODO: This is pretty much copy pasted from All. Consider merging Reduce, All, -// Any and Single into something like a higher-order function call which takes a -// list argument and a function which is applied on list elements. +// TODO: This is pretty much copy pasted from All. Consider merging Reduce, +// All, Any and Single into something like a higher-order function call which +// takes a list argument and a function which is applied on list elements. class Single : public Expression { friend class AstTreeStorage; @@ -1545,6 +1722,10 @@ class Single : public Expression { where_->Clone(storage)); } + static Single *Construct(capnp::Single::Reader &reader, + AstTreeStorage &storage); + using Expression::Save; + // None of these should be nullptr after construction. Identifier *identifier_ = nullptr; Expression *list_expression_ = nullptr; @@ -1558,6 +1739,9 @@ class Single : public Expression { list_expression_(list_expression), where_(where) {} + void Save(capnp::Expression::Builder &builder) override; + virtual void Save(capnp::Single::Builder &builder); + private: friend class boost::serialization::access; @@ -1595,6 +1779,10 @@ class ParameterLookup : public Expression { return storage.Create(token_position_); } + static ParameterLookup *Construct(capnp::ParameterLookup::Reader &reader, + AstTreeStorage &storage); + using Expression::Save; + // This field contains token position of *literal* used to create // ParameterLookup object. If ParameterLookup object is not created from // a literal leave this value at -1. @@ -1605,6 +1793,9 @@ class ParameterLookup : public Expression { ParameterLookup(int uid, int token_position) : Expression(uid), token_position_(token_position) {} + void Save(capnp::Expression::Builder &builder) override; + virtual void Save(capnp::ParameterLookup::Builder &builder); + friend class boost::serialization::access; template @@ -1636,6 +1827,10 @@ class NamedExpression : public Tree { token_position_); } + static NamedExpression *Construct(capnp::NamedExpression::Reader &reader, + AstTreeStorage &storage); + void Save(capnp::Tree::Builder &builder) override; + std::string name_; Expression *expression_ = nullptr; // This field contains token position of first token in named expression @@ -1655,6 +1850,8 @@ class NamedExpression : public Tree { expression_(expression), token_position_(token_position) {} + virtual void Save(capnp::NamedExpression::Builder &); + private: friend class boost::serialization::access; @@ -1692,11 +1889,18 @@ class PatternAtom : public Tree { PatternAtom *Clone(AstTreeStorage &storage) const override = 0; + static PatternAtom *Construct(capnp::PatternAtom::Reader &reader, + AstTreeStorage &storage); + void Save(capnp::Tree::Builder &builder) override; + protected: explicit PatternAtom(int uid) : Tree(uid) {} PatternAtom(int uid, Identifier *identifier) : Tree(uid), identifier_(identifier) {} + virtual void Save(capnp::PatternAtom::Builder &); + void Load(capnp::Tree::Reader &reader, AstTreeStorage &storage) override; + private: friend class boost::serialization::access; @@ -1741,6 +1945,10 @@ class NodeAtom : public PatternAtom { return node_atom; } + static NodeAtom *Construct(capnp::NodeAtom::Reader &reader, + AstTreeStorage &storage); + using PatternAtom::Save; + std::vector labels_; // maps (property_name, property) to an expression std::unordered_map, Expression *> @@ -1749,6 +1957,9 @@ class NodeAtom : public PatternAtom { protected: using PatternAtom::PatternAtom; + void Save(capnp::PatternAtom::Builder &builder) override; + virtual void Save(capnp::NodeAtom::Builder &builder); + private: friend class boost::serialization::access; @@ -1870,6 +2081,10 @@ class EdgeAtom : public PatternAtom { } } + static EdgeAtom *Construct(capnp::EdgeAtom::Reader &reader, + AstTreeStorage &storage); + using PatternAtom::Save; + Type type_ = Type::SINGLE; Direction direction_ = Direction::BOTH; std::vector edge_types_; @@ -1887,8 +2102,8 @@ class EdgeAtom : public PatternAtom { /// optimization pass may inline other expressions into this lambda. Lambda filter_lambda_; /// Used in weighted shortest path. - /// It must have valid expressions and identifiers. In all other expand types, - /// it is empty. + /// It must have valid expressions and identifiers. In all other expand + /// types, it is empty. Lambda weight_lambda_; /// Variable where the total weight for weighted shortest path will be stored. Identifier *total_weight_ = nullptr; @@ -1906,6 +2121,9 @@ class EdgeAtom : public PatternAtom { direction_(direction), edge_types_(edge_types) {} + void Save(capnp::PatternAtom::Builder &builder) override; + virtual void Save(capnp::EdgeAtom::Builder &builder); + private: friend class boost::serialization::access; @@ -1996,12 +2214,18 @@ class Pattern : public Tree { return pattern; } + static Pattern *Construct(capnp::Pattern::Reader &reader, + AstTreeStorage &storage); + void Save(capnp::Tree::Builder &builder) override; + Identifier *identifier_ = nullptr; std::vector atoms_; protected: explicit Pattern(int uid) : Tree(uid) {} + virtual void Save(capnp::Pattern::Builder &); + private: friend class boost::serialization::access; @@ -2036,6 +2260,14 @@ class Clause : public Tree { Clause *Clone(AstTreeStorage &storage) const override = 0; + static Clause *Construct(capnp::Clause::Reader &reader, + AstTreeStorage &storage); + + void Save(capnp::Tree::Builder &builder) override; + + protected: + virtual void Save(capnp::Clause::Builder &) {} + private: friend class boost::serialization::access; SERIALIZE_USING_BASE(Tree); @@ -2065,11 +2297,18 @@ class SingleQuery : public Tree { return single_query; } + static SingleQuery *Construct(capnp::SingleQuery::Reader &reader, + AstTreeStorage &storage); + + void Save(capnp::Tree::Builder &builder) override; + std::vector clauses_; protected: explicit SingleQuery(int uid) : Tree(uid) {} + virtual void Save(capnp::SingleQuery::Builder &); + private: friend class boost::serialization::access; @@ -2114,6 +2353,10 @@ class CypherUnion : public Tree { return cypher_union; } + static CypherUnion *Construct(capnp::CypherUnion::Reader &reader, + AstTreeStorage &storage); + void Save(capnp::Tree::Builder &builder) override; + SingleQuery *single_query_ = nullptr; bool distinct_ = false; /// Holds symbols that are created during symbol generation phase. @@ -2123,6 +2366,14 @@ class CypherUnion : public Tree { protected: explicit CypherUnion(int uid) : Tree(uid) {} CypherUnion(int uid, bool distinct) : Tree(uid), distinct_(distinct) {} + CypherUnion(int uid, bool distinct, SingleQuery *single_query, + std::vector union_symbols) + : Tree(uid), + single_query_(single_query), + distinct_(distinct), + union_symbols_(union_symbols) {} + + virtual void Save(capnp::CypherUnion::Builder &); private: friend class boost::serialization::access; @@ -2180,12 +2431,18 @@ class Query : public Tree { return query; } + static Query *Construct(capnp::Query::Reader &reader, + AstTreeStorage &storage); + void Save(capnp::Tree::Builder &builder) override; + SingleQuery *single_query_ = nullptr; std::vector cypher_unions_; protected: explicit Query(int uid) : Tree(uid) {} + virtual void Save(capnp::Query::Builder &); + private: friend class boost::serialization::access; @@ -2234,10 +2491,19 @@ class Create : public Clause { return create; } + static Create *Construct(capnp::Create::Reader &reader, + AstTreeStorage &storage); + using Clause::Save; + std::vector patterns_; protected: explicit Create(int uid) : Clause(uid) {} + Create(int uid, std::vector patterns) + : Clause(uid), patterns_(patterns) {} + + void Save(capnp::Clause::Builder &builder) override; + virtual void Save(capnp::Create::Builder &builder); private: friend class boost::serialization::access; @@ -2291,6 +2557,10 @@ class Match : public Clause { return match; } + using Clause::Save; + static Match *Construct(capnp::Match::Reader &reader, + AstTreeStorage &storage); + std::vector patterns_; Where *where_ = nullptr; bool optional_ = false; @@ -2298,6 +2568,11 @@ class Match : public Clause { protected: explicit Match(int uid) : Clause(uid) {} Match(int uid, bool optional) : Clause(uid), optional_(optional) {} + Match(int uid, bool optional, Where *where, std::vector patterns) + : Clause(uid), patterns_(patterns), where_(where), optional_(optional) {} + + void Save(capnp::Clause::Builder &builder) override; + virtual void Save(capnp::Match::Builder &builder); private: friend class boost::serialization::access; @@ -2421,10 +2696,18 @@ class Return : public Clause { return ret; } + using Clause::Save; + static Return *Construct(capnp::Return::Reader &reader, + AstTreeStorage &storage); + ReturnBody body_; protected: explicit Return(int uid) : Clause(uid) {} + Return(int uid, ReturnBody &body) : Clause(uid), body_(body) {} + + void Save(capnp::Clause::Builder &builder) override; + virtual void Save(capnp::Return::Builder &builder); private: friend class boost::serialization::access; @@ -2476,11 +2759,19 @@ class With : public Clause { return with; } + using Clause::Save; + static With *Construct(capnp::With::Reader &reader, AstTreeStorage &storage); + ReturnBody body_; Where *where_ = nullptr; protected: explicit With(int uid) : Clause(uid) {} + With(int uid, ReturnBody &body, Where *where) + : Clause(uid), body_(body), where_(where) {} + + void Save(capnp::Clause::Builder &builder) override; + virtual void Save(capnp::With::Builder &builder); private: friend class boost::serialization::access; @@ -2529,11 +2820,21 @@ class Delete : public Clause { return del; } + using Clause::Save; + static Delete *Construct(capnp::Delete::Reader &reader, + AstTreeStorage &storage); + std::vector expressions_; + bool detach_ = false; protected: explicit Delete(int uid) : Clause(uid) {} + Delete(int uid, bool detach, std::vector expressions) + : Clause(uid), expressions_(expressions), detach_(detach) {} + + void Save(capnp::Clause::Builder &builder) override; + virtual void Save(capnp::Delete::Builder &builder); private: friend class boost::serialization::access; @@ -2576,6 +2877,10 @@ class SetProperty : public Clause { expression_->Clone(storage)); } + using Clause::Save; + static SetProperty *Construct(capnp::SetProperty::Reader &reader, + AstTreeStorage &storage); + PropertyLookup *property_lookup_ = nullptr; Expression *expression_ = nullptr; @@ -2586,6 +2891,9 @@ class SetProperty : public Clause { property_lookup_(property_lookup), expression_(expression) {} + void Save(capnp::Clause::Builder &builder) override; + virtual void Save(capnp::SetProperty::Builder &builder); + private: friend class boost::serialization::access; @@ -2628,6 +2936,10 @@ class SetProperties : public Clause { expression_->Clone(storage), update_); } + using Clause::Save; + static SetProperties *Construct(capnp::SetProperties::Reader &reader, + AstTreeStorage &storage); + Identifier *identifier_ = nullptr; Expression *expression_ = nullptr; bool update_ = false; @@ -2641,6 +2953,9 @@ class SetProperties : public Clause { expression_(expression), update_(update) {} + void Save(capnp::Clause::Builder &builder) override; + virtual void Save(capnp::SetProperties::Builder &builder); + private: friend class boost::serialization::access; @@ -2684,6 +2999,10 @@ class SetLabels : public Clause { return storage.Create(identifier_->Clone(storage), labels_); } + using Clause::Save; + static SetLabels *Construct(capnp::SetLabels::Reader &reader, + AstTreeStorage &storage); + Identifier *identifier_ = nullptr; std::vector labels_; @@ -2693,6 +3012,9 @@ class SetLabels : public Clause { const std::vector &labels) : Clause(uid), identifier_(identifier), labels_(labels) {} + void Save(capnp::Clause::Builder &builder) override; + virtual void Save(capnp::SetLabels::Builder &builder); + private: friend class boost::serialization::access; @@ -2733,6 +3055,10 @@ class RemoveProperty : public Clause { return storage.Create(property_lookup_->Clone(storage)); } + using Clause::Save; + static RemoveProperty *Construct(capnp::RemoveProperty::Reader &reader, + AstTreeStorage &storage); + PropertyLookup *property_lookup_ = nullptr; protected: @@ -2740,6 +3066,9 @@ class RemoveProperty : public Clause { RemoveProperty(int uid, PropertyLookup *property_lookup) : Clause(uid), property_lookup_(property_lookup) {} + void Save(capnp::Clause::Builder &builder) override; + virtual void Save(capnp::RemoveProperty::Builder &builder); + private: friend class boost::serialization::access; @@ -2779,6 +3108,10 @@ class RemoveLabels : public Clause { return storage.Create(identifier_->Clone(storage), labels_); } + using Clause::Save; + static RemoveLabels *Construct(capnp::RemoveLabels::Reader &reader, + AstTreeStorage &storage); + Identifier *identifier_ = nullptr; std::vector labels_; @@ -2788,6 +3121,9 @@ class RemoveLabels : public Clause { const std::vector &labels) : Clause(uid), identifier_(identifier), labels_(labels) {} + void Save(capnp::Clause::Builder &builder) override; + virtual void Save(capnp::RemoveLabels::Builder &builder); + private: friend class boost::serialization::access; @@ -2853,12 +3189,25 @@ class Merge : public Clause { return merge; } + using Clause::Save; + static Merge *Construct(capnp::Merge::Reader &reader, + AstTreeStorage &storage); + Pattern *pattern_ = nullptr; std::vector on_match_; std::vector on_create_; protected: explicit Merge(int uid) : Clause(uid) {} + Merge(int uid, Pattern *pattern, std::vector on_match, + std::vector on_create) + : Clause(uid), + pattern_(pattern), + on_match_(on_match), + on_create_(on_create) {} + + void Save(capnp::Clause::Builder &builder) override; + virtual void Save(capnp::Merge::Builder &builder); private: friend class boost::serialization::access; @@ -2902,6 +3251,10 @@ class Unwind : public Clause { return storage.Create(named_expression_->Clone(storage)); } + using Clause::Save; + static Unwind *Construct(capnp::Unwind::Reader &reader, + AstTreeStorage &storage); + NamedExpression *named_expression_ = nullptr; protected: @@ -2913,6 +3266,9 @@ class Unwind : public Clause { << "Unwind cannot take nullptr for named_expression"; } + void Save(capnp::Clause::Builder &builder) override; + virtual void Save(capnp::Unwind::Builder &builder); + private: friend class boost::serialization::access; @@ -2946,6 +3302,10 @@ class CreateIndex : public Clause { return storage.Create(label_, property_); } + static CreateIndex *Construct(capnp::CreateIndex::Reader &reader, + AstTreeStorage &storage); + using Clause::Save; + storage::Label label_; storage::Property property_; @@ -2954,6 +3314,9 @@ class CreateIndex : public Clause { CreateIndex(int uid, storage::Label label, storage::Property property) : Clause(uid), label_(label), property_(property) {} + void Save(capnp::Clause::Builder &builder) override; + virtual void Save(capnp::CreateIndex::Builder &builder); + private: friend class boost::serialization::access; @@ -2975,7 +3338,6 @@ class CreateIndex : public Clause { #undef SERIALIZE_USING_BASE } // namespace query - // All of the serialization cruft follows #define LOAD_AND_CONSTRUCT(DerivedClass, ...) \ diff --git a/src/query/frontend/semantic/symbol.hpp b/src/query/frontend/semantic/symbol.hpp index a6becfd19..4620e46a6 100644 --- a/src/query/frontend/semantic/symbol.hpp +++ b/src/query/frontend/semantic/symbol.hpp @@ -5,6 +5,8 @@ #include "boost/serialization/serialization.hpp" #include "boost/serialization/string.hpp" +#include "symbol.capnp.h" + namespace query { class Symbol { @@ -40,6 +42,60 @@ 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_); + switch (type_) { + case Type::Any: + builder.setType(capnp::Symbol::Type::ANY); + break; + case Type::Edge: + builder.setType(capnp::Symbol::Type::EDGE); + break; + case Type::EdgeList: + builder.setType(capnp::Symbol::Type::EDGE_LIST); + break; + case Type::Number: + builder.setType(capnp::Symbol::Type::NUMBER); + break; + case Type::Path: + builder.setType(capnp::Symbol::Type::PATH); + break; + case Type::Vertex: + builder.setType(capnp::Symbol::Type::VERTEX); + break; + } + } + + void Load(const capnp::Symbol::Reader &reader) { + name_ = reader.getName(); + position_ = reader.getPosition(); + user_declared_ = reader.getUserDeclared(); + token_position_ = reader.getTokenPosition(); + switch (reader.getType()) { + case capnp::Symbol::Type::ANY: + type_ = Type::Any; + break; + case capnp::Symbol::Type::EDGE: + type_ = Type::Edge; + break; + case capnp::Symbol::Type::EDGE_LIST: + type_ = Type::EdgeList; + break; + case capnp::Symbol::Type::NUMBER: + type_ = Type::Number; + break; + case capnp::Symbol::Type::PATH: + type_ = Type::Path; + break; + case capnp::Symbol::Type::VERTEX: + type_ = Type::Vertex; + break; + } + } + private: std::string name_; int position_; diff --git a/src/storage/types.capnp b/src/storage/types.capnp new file mode 100644 index 000000000..08b81673c --- /dev/null +++ b/src/storage/types.capnp @@ -0,0 +1,17 @@ +@0x8678c6a8817808d9; + +using Cxx = import "/capnp/c++.capnp"; +$Cxx.namespace("storage::capnp"); + +struct Common { + storage @0 :UInt16; + union { + label @1 :Label; + edgeType @2 :EdgeType; + property @3 :Property; + } +} + +struct Label {} +struct EdgeType {} +struct Property {} diff --git a/src/storage/types.hpp b/src/storage/types.hpp index f97f93d09..5b4007719 100644 --- a/src/storage/types.hpp +++ b/src/storage/types.hpp @@ -4,6 +4,7 @@ #include #include "boost/serialization/base_object.hpp" +#include "types.capnp.h" #include "utils/total_ordering.hpp" @@ -32,6 +33,14 @@ class Common : public utils::TotalOrdering { size_t operator()(const TSpecificType &t) const { return hash(t.storage_); } }; + virtual void Save(capnp::Common::Builder &builder) const { + builder.setStorage(storage_); + } + + virtual void Load(capnp::Common::Reader &reader) { + storage_ = reader.getStorage(); + } + private: friend class boost::serialization::access; @@ -46,6 +55,7 @@ class Common : public utils::TotalOrdering { class Label : public Common