diff --git a/cmake/functions.cmake b/cmake/functions.cmake index 4971b08fa..02c191f66 100644 --- a/cmake/functions.cmake +++ b/cmake/functions.cmake @@ -128,20 +128,17 @@ set(lcp_src_files ${CMAKE_SOURCE_DIR}/src/lisp/lcp.lisp ${lcp_exe}) # file through `add_capnp` function. To generate the use `capnp id` # invocation, and specify it here. This preserves correct id information across # multiple schema generations. If this wasn't the case, wrong typeId -# information will break RPC between different compilations of memgraph. -# Instead of CAPNP_SCHEMA, you may pass the CAPNP_DECLARATION option. This will -# generate serialization declarations but not the implementation. +# information will break serialization between different compilations of memgraph. macro(define_add_lcp name main_src_files generated_lcp_files) function(${name} lcp_file) - set(options CAPNP_DECLARATION) set(one_value_kwargs CAPNP_SCHEMA) set(multi_value_kwargs DEPENDS) # NOTE: ${${}ARGN} syntax escapes evaluating macro's ARGN variable; see: # https://stackoverflow.com/questions/50365544/how-to-access-enclosing-functions-arguments-from-within-a-macro - cmake_parse_arguments(KW "${options}" "${one_value_kwargs}" "${multi_value_kwargs}" ${${}ARGN}) + cmake_parse_arguments(KW "" "${one_value_kwargs}" "${multi_value_kwargs}" ${${}ARGN}) string(REGEX REPLACE "\.lcp$" ".hpp" h_file "${CMAKE_CURRENT_SOURCE_DIR}/${lcp_file}") - if (KW_CAPNP_SCHEMA AND NOT KW_CAPNP_DECLARATION) + if (KW_CAPNP_SCHEMA) string(REGEX REPLACE "\.lcp$" ".capnp" capnp_file "${CMAKE_CURRENT_SOURCE_DIR}/${lcp_file}") set(capnp_id ${KW_CAPNP_SCHEMA}) @@ -150,9 +147,6 @@ macro(define_add_lcp name main_src_files generated_lcp_files) # Update *global* main_src_files set(${main_src_files} ${${main_src_files}} ${cpp_file} PARENT_SCOPE) endif() - if (KW_CAPNP_DECLARATION) - set(capnp_id "--capnp-declaration") - endif() add_custom_command(OUTPUT ${h_file} ${cpp_file} ${capnp_file} COMMAND ${lcp_exe} ${lcp_file} ${capnp_id} VERBATIM diff --git a/docs/dev/lcp.md b/docs/dev/lcp.md index bc21b6847..8fa3a8137 100644 --- a/docs/dev/lcp.md +++ b/docs/dev/lcp.md @@ -384,7 +384,7 @@ to perform the registration manually. For example: rpc_server.Register( [](const auto &req_reader, auto *res_builder) { QueryResultReq request; - request.Load(req_reader); + Load(&request, req_reader); // process the request and send the response QueryResultRes response(values_for_response); Save(response, res_builder); @@ -421,7 +421,7 @@ To specify a class or structure for serialization, you may pass a For example: ```lisp -(lcp:define-class my-class () +(lcp:define-struct my-struct () ((member :int64_t)) (:serialize :capnp)) ``` @@ -431,11 +431,9 @@ it in the `.capnp` file. C++ code will be generated for saving and loading members: ```cpp -// Top level function -void Save(const MyClass &instance, capnp::MyClass::Builder *builder); - -// Member function -void MyClass::Load(const capnp::MyClass::Reader &reader); +// Top level functions +void Save(const MyStruct &self, capnp::MyStruct::Builder *builder); +void Load(MyStruct *self, const capnp::MyStruct::Reader &reader); ``` Since we use top level functions, the class needs to have some sort of public @@ -454,31 +452,26 @@ For example: ```lisp (lcp:define-class base () - ((base-member "std::vector")) + ((base-member "std::vector" :scope :public)) (:serialize :capnp)) (lcp:define-class derived (base) - ((derived-member :bool)) + ((derived-member :bool :scope :public)) (:serialize :capnp)) ``` Note that all classes need to have the `:serialize` option set. Signatures of `Save` and `Load` functions are changed to accept reader and builder to the -base class. And a `Construct` function is added which will instantiate a -concrete type from a base reader. +base class. The `Load` function now takes a `std::unique_ptr *` which is +used to take ownership of a concrete type. This approach transfers the +responsibility of type allocation and construction from the user of `Load` to +`Load` itself. ```cpp -void Save(const Derived &derived, capnp::Base *builder); - -class Derived { - ... - static std::unique_ptr Construct(const capnp::Base &reader); - - virtual void Load(const capnp::Base &reader); +void Save(const Derived &self, capnp::Base::Builder *builder); +void Load(std::unique_ptr *self, const capnp::Base::Reader &reader); ``` -With polymorphic types, you need to call `Base::Construct` followed by `Load`. - #### Multiple Inheritance Cap'n Proto does not support any form of inheritance, instead we are @@ -615,8 +608,8 @@ You will rarely need to use the 3rd argument, so it should be ignored in most cases. It is usually needed when you set `:capnp-init nil`, so that you can correctly initialize the builder. -Similarly, `:capnp-load` expects a function taking a reader and a member, then -returns a C++ block. +Similarly, `:capnp-load` expects a function taking a reader, C++ member and +Cap'n Proto member, then returns a C++ block. Example: @@ -630,7 +623,8 @@ Example: auto my_builder = ${builder}.init${capnp-name}(); my_builder.setData(data); cpp<#) - :capnp-load (lambda (reader member) + :capnp-load (lambda (reader member capnp-name) + (declare (ignore capnp-name)) #>cpp auto data = ${reader}.getData(); ${member}.LoadFromData(data); diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 4ee0f108a..3e102cf65 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -115,9 +115,9 @@ add_capnp(distributed/updates_rpc_messages.capnp) add_lcp(distributed/dynamic_worker_rpc_messages.lcp CAPNP_SCHEMA @0x8c53f6c9a0c71b05) add_capnp(distributed/dynamic_worker_rpc_messages.capnp) -# distributed_ops.lcp is leading the capnp code generation, so we only want -# function declarations in generated operator.hpp -add_lcp(query/plan/operator.lcp CAPNP_DECLARATION) +# distributed_ops.lcp is leading the capnp code generation, so we don't need +# to generate any capnp for operator.lcp +add_lcp(query/plan/operator.lcp) add_lcp(query/plan/distributed_ops.lcp CAPNP_SCHEMA @0xe5cae8d045d30c42 DEPENDS query/plan/operator.lcp) add_capnp(query/plan/distributed_ops.capnp) diff --git a/src/communication/rpc/client.hpp b/src/communication/rpc/client.hpp index b5f93d1fe..d5949885a 100644 --- a/src/communication/rpc/client.hpp +++ b/src/communication/rpc/client.hpp @@ -36,7 +36,7 @@ class Client { return CallWithLoad( [](const auto &reader) { typename TRequestResponse::Response response; - response.Load(reader); + Load(&response, reader); return response; }, std::forward(args)...); diff --git a/src/database/state_delta.lcp b/src/database/state_delta.lcp index 4bd4c4007..6b7c41dea 100644 --- a/src/database/state_delta.lcp +++ b/src/database/state_delta.lcp @@ -59,7 +59,8 @@ cpp<# storage::SaveCapnpPropertyValue(${member}, &${builder}); cpp<#) :capnp-load - (lambda (reader member) + (lambda (reader member capnp-name) + (declare (ignore capnp-name)) #>cpp storage::LoadCapnpPropertyValue(${reader}, &${member}); cpp<#)) diff --git a/src/database/storage_gc_master.hpp b/src/database/storage_gc_master.hpp index ad9de25cd..9b2ceac7e 100644 --- a/src/database/storage_gc_master.hpp +++ b/src/database/storage_gc_master.hpp @@ -21,7 +21,7 @@ class StorageGcMaster : public StorageGc { rpc_server_.Register( [this](const auto &req_reader, auto *res_builder) { distributed::RanLocalGcReq req; - req.Load(req_reader); + Load(&req, req_reader); std::unique_lock lock(worker_safe_transaction_mutex_); worker_safe_transaction_[req.worker_id] = req.local_oldest_active; }); diff --git a/src/distributed/bfs_rpc_clients.cpp b/src/distributed/bfs_rpc_clients.cpp index 5aeace05a..aaec6924d 100644 --- a/src/distributed/bfs_rpc_clients.cpp +++ b/src/distributed/bfs_rpc_clients.cpp @@ -88,7 +88,7 @@ std::experimental::optional BfsRpcClients::Pull( auto res = coordination_->GetClientPool(worker_id)->CallWithLoad( [this, dba](const auto &reader) { SubcursorPullRes res; - res.Load(reader, dba, this->data_manager_); + Load(&res, reader, dba, this->data_manager_); return res; }, subcursor_id); @@ -152,7 +152,7 @@ PathSegment BfsRpcClients::ReconstructPath( coordination_->GetClientPool(worker_id)->CallWithLoad( [this, dba](const auto &reader) { ReconstructPathRes res; - res.Load(reader, dba, this->data_manager_); + Load(&res, reader, dba, this->data_manager_); return res; }, subcursor_ids.at(worker_id), vertex); @@ -171,7 +171,7 @@ PathSegment BfsRpcClients::ReconstructPath( coordination_->GetClientPool(worker_id)->CallWithLoad( [this, dba](const auto &reader) { ReconstructPathRes res; - res.Load(reader, dba, this->data_manager_); + Load(&res, reader, dba, this->data_manager_); return res; }, subcursor_ids.at(worker_id), edge); diff --git a/src/distributed/bfs_rpc_messages.lcp b/src/distributed/bfs_rpc_messages.lcp index 99463762d..f458911a0 100644 --- a/src/distributed/bfs_rpc_messages.lcp +++ b/src/distributed/bfs_rpc_messages.lcp @@ -65,7 +65,8 @@ cpp<# }); cpp<#) :capnp-load - (lambda (reader member) + (lambda (reader member capnp-name) + (declare (ignore capnp-name)) #>cpp utils::LoadMap( &${member}, ${reader}, diff --git a/src/distributed/bfs_rpc_server.hpp b/src/distributed/bfs_rpc_server.hpp index 8657b04e2..4a4be0295 100644 --- a/src/distributed/bfs_rpc_server.hpp +++ b/src/distributed/bfs_rpc_server.hpp @@ -24,7 +24,7 @@ class BfsRpcServer { server_->Register( [this](const auto &req_reader, auto *res_builder) { CreateBfsSubcursorReq req; - req.Load(req_reader); + Load(&req, req_reader); CreateBfsSubcursorRes res(subcursor_storage_->Create( req.tx_id, req.direction, req.edge_types, req.graph_view)); Save(res, res_builder); @@ -33,7 +33,7 @@ class BfsRpcServer { server_->Register( [this](const auto &req_reader, auto *res_builder) { RegisterSubcursorsReq req; - req.Load(req_reader); + Load(&req, req_reader); subcursor_storage_->Get(req.subcursor_ids.at(db_->WorkerId())) ->RegisterSubcursors(req.subcursor_ids); RegisterSubcursorsRes res; @@ -43,7 +43,7 @@ class BfsRpcServer { server_->Register( [this](const auto &req_reader, auto *res_builder) { ResetSubcursorReq req; - req.Load(req_reader); + Load(&req, req_reader); subcursor_storage_->Get(req.subcursor_id)->Reset(); ResetSubcursorRes res; Save(res, res_builder); @@ -52,7 +52,7 @@ class BfsRpcServer { server_->Register( [this](const auto &req_reader, auto *res_builder) { RemoveBfsSubcursorReq req; - req.Load(req_reader); + Load(&req, req_reader); subcursor_storage_->Erase(req.member); RemoveBfsSubcursorRes res; Save(res, res_builder); @@ -61,7 +61,7 @@ class BfsRpcServer { server_->Register( [this](const auto &req_reader, auto *res_builder) { SetSourceReq req; - req.Load(req_reader); + Load(&req, req_reader); subcursor_storage_->Get(req.subcursor_id)->SetSource(req.source); SetSourceRes res; Save(res, res_builder); @@ -70,7 +70,7 @@ class BfsRpcServer { server_->Register([this](const auto &req_reader, auto *res_builder) { ExpandLevelReq req; - req.Load(req_reader); + Load(&req, req_reader); ExpandLevelRes res(subcursor_storage_->Get(req.member)->ExpandLevel()); Save(res, res_builder); }); @@ -78,7 +78,7 @@ class BfsRpcServer { server_->Register( [this](const auto &req_reader, auto *res_builder) { SubcursorPullReq req; - req.Load(req_reader); + Load(&req, req_reader); auto vertex = subcursor_storage_->Get(req.member)->Pull(); SubcursorPullRes res(vertex); Save(res, res_builder, db_->WorkerId()); @@ -87,7 +87,7 @@ class BfsRpcServer { server_->Register( [this](const auto &req_reader, auto *res_builder) { ExpandToRemoteVertexReq req; - req.Load(req_reader); + Load(&req, req_reader); ExpandToRemoteVertexRes res( subcursor_storage_->Get(req.subcursor_id) ->ExpandToLocalVertex(req.edge, req.vertex)); @@ -97,7 +97,7 @@ class BfsRpcServer { server_->Register([this](const auto &req_reader, auto *res_builder) { ReconstructPathReq req; - req.Load(req_reader); + Load(&req, req_reader); auto subcursor = subcursor_storage_->Get(req.subcursor_id); PathSegment result; if (req.vertex) { @@ -114,7 +114,7 @@ class BfsRpcServer { server_->Register([this](const auto &req_reader, auto *res_builder) { PrepareForExpandReq req; - req.Load(req_reader); + Load(&req, req_reader); subcursor_storage_->Get(req.subcursor_id)->PrepareForExpand(req.clear); PrepareForExpandRes res; Save(res, res_builder); diff --git a/src/distributed/cluster_discovery_master.cpp b/src/distributed/cluster_discovery_master.cpp index 88fb02ad0..e712dbe93 100644 --- a/src/distributed/cluster_discovery_master.cpp +++ b/src/distributed/cluster_discovery_master.cpp @@ -24,7 +24,7 @@ ClusterDiscoveryMaster::ClusterDiscoveryMaster( bool durability_error = false; RegisterWorkerReq req; - req.Load(req_reader); + Load(&req, req_reader); // Compose the worker's endpoint from its connecting address and its // advertised port. @@ -83,7 +83,7 @@ ClusterDiscoveryMaster::ClusterDiscoveryMaster( server_->Register([this](const auto &req_reader, auto *res_builder) { NotifyWorkerRecoveredReq req; - req.Load(req_reader); + Load(&req, req_reader); coordination_->WorkerRecoveredSnapshot(req.worker_id, req.recovery_info); }); } diff --git a/src/distributed/cluster_discovery_worker.cpp b/src/distributed/cluster_discovery_worker.cpp index 1da621897..165c1bb4d 100644 --- a/src/distributed/cluster_discovery_worker.cpp +++ b/src/distributed/cluster_discovery_worker.cpp @@ -15,7 +15,7 @@ ClusterDiscoveryWorker::ClusterDiscoveryWorker( server_.Register( [this](const auto &req_reader, auto *res_builder) { ClusterDiscoveryReq req; - req.Load(req_reader); + Load(&req, req_reader); this->coordination_.RegisterWorker(req.worker_id, req.endpoint); }); } diff --git a/src/distributed/coordination_rpc_messages.lcp b/src/distributed/coordination_rpc_messages.lcp index 43743ebf4..c6e9891b2 100644 --- a/src/distributed/coordination_rpc_messages.lcp +++ b/src/distributed/coordination_rpc_messages.lcp @@ -42,7 +42,8 @@ cpp<# }); cpp<#) :capnp-load - (lambda (reader member) + (lambda (reader member capnp-name) + (declare (ignore capnp-name)) #>cpp ${member} = utils::LoadOptional, std::pair>( ${reader}, [](auto reader){ @@ -64,12 +65,13 @@ cpp<# }); cpp<#) :capnp-load - (lambda (reader member) + (lambda (reader member capnp-name) + (declare (ignore capnp-name)) #>cpp utils::LoadMap(&${member}, ${reader}, [](const auto &reader) { io::network::Endpoint value; - value.Load(reader.getValue()); + Load(&value, reader.getValue()); return std::make_pair( reader.getKey().getValue(), value); }); diff --git a/src/distributed/data_rpc_messages.lcp b/src/distributed/data_rpc_messages.lcp index 8b2e470fd..c04e2ce90 100644 --- a/src/distributed/data_rpc_messages.lcp +++ b/src/distributed/data_rpc_messages.lcp @@ -38,10 +38,10 @@ cpp<# storage::SaveVertex(*${member}, &${builder}, self.worker_id); cpp<#) :capnp-load - (lambda (reader member) - (declare (ignore member)) + (lambda (reader member capnp-name) + (declare (ignore member capnp-name)) #>cpp - vertex_output = storage::LoadVertex(${reader}); + self->vertex_output = storage::LoadVertex(${reader}); cpp<#)) (worker-id :int64_t :capnp-save :dont-save) (vertex-output "std::unique_ptr" :initarg nil @@ -60,10 +60,10 @@ cpp<# storage::SaveEdge(*${member}, &${builder}, self.worker_id); cpp<#) :capnp-load - (lambda (reader member) - (declare (ignore member)) + (lambda (reader member capnp-name) + (declare (ignore member capnp-name)) #>cpp - edge_output = storage::LoadEdge(${reader}); + self->edge_output = storage::LoadEdge(${reader}); cpp<#)) (worker-id :int64_t :capnp-save :dont-save) (edge-output "std::unique_ptr" :initarg nil diff --git a/src/distributed/data_rpc_server.cpp b/src/distributed/data_rpc_server.cpp index 80c4ee813..b433d0c74 100644 --- a/src/distributed/data_rpc_server.cpp +++ b/src/distributed/data_rpc_server.cpp @@ -33,7 +33,7 @@ DataRpcServer::DataRpcServer(database::DistributedGraphDb *db, rpc_server_->Register( [this](const auto &req_reader, auto *res_builder) { VertexCountReq req; - req.Load(req_reader); + Load(&req, req_reader); auto dba = db_->Access(req.member); int64_t size = 0; for (auto vertex : dba->Vertices(false)) ++size; diff --git a/src/distributed/durability_rpc_worker.cpp b/src/distributed/durability_rpc_worker.cpp index f8c464b78..217e3f0f6 100644 --- a/src/distributed/durability_rpc_worker.cpp +++ b/src/distributed/durability_rpc_worker.cpp @@ -19,7 +19,7 @@ DurabilityRpcWorker::DurabilityRpcWorker(database::Worker *db, rpc_server_->Register( [this](const auto &req_reader, auto *res_builder) { durability::RecoveryData recovery_data; - recovery_data.Load(req_reader.getMember()); + durability::Load(&recovery_data, req_reader.getMember()); this->db_->RecoverWalAndIndexes(&recovery_data); }); } diff --git a/src/distributed/dynamic_worker.cpp b/src/distributed/dynamic_worker.cpp index bf0e9dd1e..7771f538a 100644 --- a/src/distributed/dynamic_worker.cpp +++ b/src/distributed/dynamic_worker.cpp @@ -13,7 +13,7 @@ DynamicWorkerAddition::DynamicWorkerAddition(database::DistributedGraphDb *db, server_->Register( [this](const auto &req_reader, auto *res_builder) { DynamicWorkerReq req; - req.Load(req_reader); + Load(&req, req_reader); DynamicWorkerRes res(this->GetIndicesToCreate()); Save(res, res_builder); }); diff --git a/src/distributed/dynamic_worker_rpc_messages.lcp b/src/distributed/dynamic_worker_rpc_messages.lcp index aff153ec5..ea1b59511 100644 --- a/src/distributed/dynamic_worker_rpc_messages.lcp +++ b/src/distributed/dynamic_worker_rpc_messages.lcp @@ -31,7 +31,8 @@ cpp<# }); cpp<#) :capnp-load - (lambda (reader member) + (lambda (reader member capnp-name) + (declare (ignore capnp-name)) #>cpp utils::LoadVector, std::pair>( diff --git a/src/distributed/index_rpc_server.cpp b/src/distributed/index_rpc_server.cpp index 349f3c392..b867b284e 100644 --- a/src/distributed/index_rpc_server.cpp +++ b/src/distributed/index_rpc_server.cpp @@ -13,7 +13,7 @@ IndexRpcServer::IndexRpcServer(database::GraphDb &db, rpc_server_.Register( [this](const auto &req_reader, auto *res_builder) { CreateIndexReq req; - req.Load(req_reader); + Load(&req, req_reader); database::LabelPropertyIndex::Key key{req.label, req.property}; db_.storage().label_property_index_.CreateIndex(key); }); @@ -21,7 +21,7 @@ IndexRpcServer::IndexRpcServer(database::GraphDb &db, rpc_server_.Register( [this](const auto &req_reader, auto *res_builder) { PopulateIndexReq req; - req.Load(req_reader); + Load(&req, req_reader); database::LabelPropertyIndex::Key key{req.label, req.property}; auto dba = db_.Access(req.tx_id); dba->PopulateIndex(key); diff --git a/src/distributed/plan_consumer.cpp b/src/distributed/plan_consumer.cpp index adac0a17e..23fafde7c 100644 --- a/src/distributed/plan_consumer.cpp +++ b/src/distributed/plan_consumer.cpp @@ -7,7 +7,7 @@ PlanConsumer::PlanConsumer(communication::rpc::Server &server) server_.Register( [this](const auto &req_reader, auto *res_builder) { DispatchPlanReq req; - req.Load(req_reader); + Load(&req, req_reader); plan_cache_.access().insert( req.plan_id, std::make_unique(req.plan, req.symbol_table, std::move(req.storage))); diff --git a/src/distributed/plan_rpc_messages.lcp b/src/distributed/plan_rpc_messages.lcp index 3531dbc9e..7e3ec8ae0 100644 --- a/src/distributed/plan_rpc_messages.lcp +++ b/src/distributed/plan_rpc_messages.lcp @@ -17,16 +17,17 @@ cpp<# (lcp:capnp-import 'plan "/query/plan/distributed_ops.capnp") (lcp:capnp-import 'sem "/query/frontend/semantic/symbol.capnp") -(defun load-plan (reader member) +(defun load-plan (reader member capnp-name) + (declare (ignore capnp-name)) #>cpp query::plan::LogicalOperator::LoadHelper helper; ${member} = utils::LoadSharedPtr( ${reader}, [&helper](const auto &reader) { - auto op = query::plan::LogicalOperator::Construct(reader); - op->Load(reader, &helper); + std::unique_ptr op; + query::plan::Load(&op, reader, &helper); return op.release(); }, &helper.loaded_ops); - storage = std::move(helper.ast_storage); + self->storage = std::move(helper.ast_storage); cpp<#) (defun save-plan (builder member capnp-name) diff --git a/src/distributed/produce_rpc_server.cpp b/src/distributed/produce_rpc_server.cpp index d61929371..3909d5803 100644 --- a/src/distributed/produce_rpc_server.cpp +++ b/src/distributed/produce_rpc_server.cpp @@ -110,7 +110,7 @@ ProduceRpcServer::ProduceRpcServer(database::Worker *db, produce_rpc_server_.Register( [this](const auto &req_reader, auto *res_builder) { PullReq req; - req.Load(req_reader); + Load(&req, req_reader); PullRes res(Pull(req)); Save(res, res_builder); }); @@ -118,7 +118,7 @@ ProduceRpcServer::ProduceRpcServer(database::Worker *db, produce_rpc_server_.Register( [this](const auto &req_reader, auto *res_builder) { ResetCursorReq req; - req.Load(req_reader); + Load(&req, req_reader); Reset(req); ResetCursorRes res; Save(res, res_builder); @@ -129,7 +129,7 @@ ProduceRpcServer::ProduceRpcServer(database::Worker *db, produce_rpc_server_.Register( [this, data_manager](const auto &req_reader, auto *res_builder) { TransactionCommandAdvancedReq req; - req.Load(req_reader); + Load(&req, req_reader); tx_engine_->UpdateCommand(req.member); data_manager->ClearCacheForSingleTransaction(req.member); TransactionCommandAdvancedRes res; diff --git a/src/distributed/pull_produce_rpc_messages.lcp b/src/distributed/pull_produce_rpc_messages.lcp index c0492b812..0acf077e6 100644 --- a/src/distributed/pull_produce_rpc_messages.lcp +++ b/src/distributed/pull_produce_rpc_messages.lcp @@ -86,7 +86,8 @@ the relevant parts of the response, ready for use.")) } cpp<#) :capnp-load - (lambda (reader member) + (lambda (reader member capnp-name) + (declare (ignore capnp-name)) #>cpp ${member}.reserve(${reader}.size()); for (const auto &frame_reader : ${reader}) { @@ -192,28 +193,29 @@ to the appropriate value. Not used on side that generates the response.") (lambda (builder member capnp-name) (declare (ignore capnp-name)) #>cpp - ${builder}.setTimestamp(${member}.timestamp); - auto params_builder = ${builder}.initParams().initEntries(${member}.parameters.size()); - size_t i = 0; - for (auto &entry : ${member}.parameters) { - auto builder = params_builder[i]; - auto key_builder = builder.initKey(); - key_builder.setValue(entry.first); - auto value_builder = builder.initValue(); - storage::SaveCapnpPropertyValue(entry.second, &value_builder); - ++i; - } - cpp<#) - :capnp-load - (lambda (reader member) - #>cpp - ${member}.timestamp = ${reader}.getTimestamp(); - for (const auto &entry_reader : ${reader}.getParams().getEntries()) { - PropertyValue value; - storage::LoadCapnpPropertyValue(entry_reader.getValue(), &value); - ${member}.parameters.Add(entry_reader.getKey().getValue(), value); - } - cpp<#)) + ${builder}.setTimestamp(${member}.timestamp); + auto params_builder = ${builder}.initParams().initEntries(${member}.parameters.size()); + size_t i = 0; + for (auto &entry : ${member}.parameters) { + auto builder = params_builder[i]; + auto key_builder = builder.initKey(); + key_builder.setValue(entry.first); + auto value_builder = builder.initValue(); + storage::SaveCapnpPropertyValue(entry.second, &value_builder); + ++i; + } + cpp<#) + :capnp-load + (lambda (reader member capnp-name) + (declare (ignore capnp-name)) + #>cpp + ${member}.timestamp = ${reader}.getTimestamp(); + for (const auto &entry_reader : ${reader}.getParams().getEntries()) { + PropertyValue value; + storage::LoadCapnpPropertyValue(entry_reader.getValue(), &value); + ${member}.parameters.Add(entry_reader.getKey().getValue(), value); + } + cpp<#)) (symbols "std::vector" :capnp-type "List(Sem.Symbol)") (accumulate :bool) (batch-size :int64_t) diff --git a/src/distributed/pull_rpc_clients.cpp b/src/distributed/pull_rpc_clients.cpp index ce18970f6..da9455cae 100644 --- a/src/distributed/pull_rpc_clients.cpp +++ b/src/distributed/pull_rpc_clients.cpp @@ -18,7 +18,7 @@ utils::Future PullRpcClients::Pull( ](int worker_id, ClientPool &client_pool) { auto load_pull_res = [data_manager, dba](const auto &res_reader) { PullRes res; - res.Load(res_reader, dba, data_manager); + Load(&res, res_reader, dba, data_manager); return res; }; auto result = client_pool.CallWithLoad( diff --git a/src/distributed/updates_rpc_messages.lcp b/src/distributed/updates_rpc_messages.lcp index a6dcf0f3b..9b30b5ae8 100644 --- a/src/distributed/updates_rpc_messages.lcp +++ b/src/distributed/updates_rpc_messages.lcp @@ -72,13 +72,14 @@ cpp<# }); cpp<#) :capnp-load - (lambda (reader member) + (lambda (reader member capnp-name) + (declare (ignore capnp-name)) #>cpp utils::LoadMap( &${member}, ${reader}, [](const auto &reader) { storage::Property prop; - prop.Load(reader.getKey()); + storage::Load(&prop, reader.getKey()); PropertyValue value; storage::LoadCapnpPropertyValue(reader.getValue(), &value); return std::make_pair(prop, value); @@ -96,9 +97,10 @@ cpp<# }); cpp<#) :capnp-load - (lambda (reader member) + (lambda (reader member capnp-name) + (declare (ignore capnp-name)) #>cpp - cypher_id = utils::LoadOptional( + ${member} = utils::LoadOptional( ${reader}, [](const auto &reader) { return reader.getValue(); }); @@ -126,9 +128,10 @@ cpp<# }); cpp<#) :capnp-load - (lambda (reader member) + (lambda (reader member capnp-name) + (declare (ignore capnp-name)) #>cpp - cypher_id = utils::LoadOptional( + ${member} = utils::LoadOptional( ${reader}, [](const auto &reader) { return reader.getValue(); }); diff --git a/src/distributed/updates_rpc_server.cpp b/src/distributed/updates_rpc_server.cpp index b6ca5c118..28aef7e05 100644 --- a/src/distributed/updates_rpc_server.cpp +++ b/src/distributed/updates_rpc_server.cpp @@ -182,7 +182,7 @@ UpdatesRpcServer::UpdatesRpcServer(database::DistributedGraphDb *db, server->Register([this](const auto &req_reader, auto *res_builder) { UpdateReq req; - req.Load(req_reader); + Load(&req, req_reader); using DeltaType = database::StateDelta::Type; auto &delta = req.member; switch (delta.type) { @@ -211,7 +211,7 @@ UpdatesRpcServer::UpdatesRpcServer(database::DistributedGraphDb *db, server->Register( [this](const auto &req_reader, auto *res_builder) { UpdateApplyReq req; - req.Load(req_reader); + Load(&req, req_reader); UpdateApplyRes res(Apply(req.member)); Save(res, res_builder); }); @@ -219,7 +219,7 @@ UpdatesRpcServer::UpdatesRpcServer(database::DistributedGraphDb *db, server->Register([this](const auto &req_reader, auto *res_builder) { CreateVertexReq req; - req.Load(req_reader); + Load(&req, req_reader); auto result = GetUpdates(vertex_updates_, req.member.tx_id) .CreateVertex(req.member.labels, req.member.properties, req.member.cypher_id); @@ -231,7 +231,7 @@ UpdatesRpcServer::UpdatesRpcServer(database::DistributedGraphDb *db, server->Register( [this](const auto &req_reader, auto *res_builder) { CreateEdgeReq req; - req.Load(req_reader); + Load(&req, req_reader); auto data = req.member; auto creation_result = CreateEdge(data); @@ -253,7 +253,7 @@ UpdatesRpcServer::UpdatesRpcServer(database::DistributedGraphDb *db, server->Register( [this](const auto &req_reader, auto *res_builder) { AddInEdgeReq req; - req.Load(req_reader); + Load(&req, req_reader); auto to_delta = database::StateDelta::AddInEdge( req.member.tx_id, req.member.to, req.member.from, req.member.edge_address, req.member.edge_type); @@ -266,7 +266,7 @@ UpdatesRpcServer::UpdatesRpcServer(database::DistributedGraphDb *db, server->Register( [this](const auto &req_reader, auto *res_builder) { RemoveVertexReq req; - req.Load(req_reader); + Load(&req, req_reader); auto to_delta = database::StateDelta::RemoveVertex( req.member.tx_id, req.member.gid, req.member.check_empty); auto result = @@ -278,7 +278,7 @@ UpdatesRpcServer::UpdatesRpcServer(database::DistributedGraphDb *db, server->Register( [this](const auto &req_reader, auto *res_builder) { RemoveEdgeReq req; - req.Load(req_reader); + Load(&req, req_reader); RemoveEdgeRes res(RemoveEdge(req.member)); Save(res, res_builder); }); @@ -286,7 +286,7 @@ UpdatesRpcServer::UpdatesRpcServer(database::DistributedGraphDb *db, server->Register([this](const auto &req_reader, auto *res_builder) { RemoveInEdgeReq req; - req.Load(req_reader); + Load(&req, req_reader); auto data = req.member; RemoveInEdgeRes res(GetUpdates(vertex_updates_, data.tx_id) .Emplace(database::StateDelta::RemoveInEdge( diff --git a/src/durability/recovery.hpp b/src/durability/recovery.hpp index 163713999..31ff50860 100644 --- a/src/durability/recovery.hpp +++ b/src/durability/recovery.hpp @@ -34,13 +34,6 @@ struct RecoveryInfo { wal_recovered == other.wal_recovered; } bool operator!=(const RecoveryInfo &other) const { return !(*this == other); } - - void Load(const capnp::RecoveryInfo::Reader &reader) { - durability_version = reader.getDurabilityVersion(); - snapshot_tx_id = reader.getSnapshotTxId(); - auto list_reader = reader.getWalRecovered(); - utils::LoadVector(&wal_recovered, list_reader); - } }; inline void Save(const RecoveryInfo &info, @@ -51,6 +44,14 @@ inline void Save(const RecoveryInfo &info, utils::SaveVector(info.wal_recovered, &list_builder); } +inline void Load(RecoveryInfo *info, + const capnp::RecoveryInfo::Reader &reader) { + info->durability_version = reader.getDurabilityVersion(); + info->snapshot_tx_id = reader.getSnapshotTxId(); + auto list_reader = reader.getWalRecovered(); + utils::LoadVector(&info->wal_recovered, list_reader); +} + // A data structure for exchanging info between main recovery function and // snapshot and WAL recovery functions. struct RecoveryData { @@ -66,26 +67,6 @@ struct RecoveryData { snapshooter_tx_snapshot.clear(); indexes.clear(); } - - void Load(const capnp::RecoveryData::Reader &reader) { - snapshooter_tx_id = reader.getSnapshooterTxId(); - { - auto list_reader = reader.getWalTxToRecover(); - utils::LoadVector(&wal_tx_to_recover, list_reader); - } - { - auto list_reader = reader.getSnapshooterTxSnapshot(); - utils::LoadVector(&snapshooter_tx_snapshot, list_reader); - } - { - auto list_reader = reader.getIndexes(); - utils::LoadVector, - std::pair>( - &indexes, list_reader, [](const auto &reader) { - return std::make_pair(reader.getFirst(), reader.getSecond()); - }); - } - } }; inline void Save(const RecoveryData &data, @@ -112,6 +93,27 @@ inline void Save(const RecoveryData &data, } } +inline void Load(RecoveryData *data, + const capnp::RecoveryData::Reader &reader) { + data->snapshooter_tx_id = reader.getSnapshooterTxId(); + { + auto list_reader = reader.getWalTxToRecover(); + utils::LoadVector(&data->wal_tx_to_recover, list_reader); + } + { + auto list_reader = reader.getSnapshooterTxSnapshot(); + utils::LoadVector(&data->snapshooter_tx_snapshot, list_reader); + } + { + auto list_reader = reader.getIndexes(); + utils::LoadVector, + std::pair>( + &data->indexes, list_reader, [](const auto &reader) { + return std::make_pair(reader.getFirst(), reader.getSecond()); + }); + } +} + /** Reads snapshot metadata from the end of the file without messing up the * hash. */ bool ReadSnapshotSummary(HashedFileReader &buffer, int64_t &vertex_count, diff --git a/src/io/network/endpoint.cpp b/src/io/network/endpoint.cpp index e03922cb8..5514c13da 100644 --- a/src/io/network/endpoint.cpp +++ b/src/io/network/endpoint.cpp @@ -30,10 +30,10 @@ void Save(const Endpoint &endpoint, capnp::Endpoint::Builder *builder) { builder->setFamily(endpoint.family()); } -void Endpoint::Load(const capnp::Endpoint::Reader &reader) { - address_ = reader.getAddress(); - port_ = reader.getPort(); - family_ = reader.getFamily(); +void Load(Endpoint *endpoint, const capnp::Endpoint::Reader &reader) { + endpoint->address_ = reader.getAddress(); + endpoint->port_ = reader.getPort(); + endpoint->family_ = reader.getFamily(); } bool Endpoint::operator==(const Endpoint &other) const { diff --git a/src/io/network/endpoint.hpp b/src/io/network/endpoint.hpp index 76e7b8f53..5e5b4f970 100644 --- a/src/io/network/endpoint.hpp +++ b/src/io/network/endpoint.hpp @@ -20,6 +20,7 @@ class Endpoint { Endpoint(); Endpoint(const std::string &address, uint16_t port); + // TODO: Remove these since members are public std::string address() const { return address_; } uint16_t port() const { return port_; } unsigned char family() const { return family_; } @@ -27,9 +28,6 @@ class Endpoint { bool operator==(const Endpoint &other) const; friend std::ostream &operator<<(std::ostream &os, const Endpoint &endpoint); - void Load(const capnp::Endpoint::Reader &reader); - - private: std::string address_; uint16_t port_{0}; unsigned char family_{0}; @@ -37,4 +35,6 @@ class Endpoint { void Save(const Endpoint &endpoint, capnp::Endpoint::Builder *builder); +void Load(Endpoint *endpoint, const capnp::Endpoint::Reader &reader); + } // namespace io::network diff --git a/src/lisp/lcp.lisp b/src/lisp/lcp.lisp index eefb9c738..d8d46c4aa 100644 --- a/src/lisp/lcp.lisp +++ b/src/lisp/lcp.lisp @@ -346,15 +346,31 @@ produces: (let ((cpp-name (cpp-variable-name (cpp-member-symbol cpp-member)))) (if struct cpp-name (format nil "~A_" cpp-name)))) +(defun call-with-cpp-block-output (out fun &key semicolonp name) + "Surround the invocation of FUN by emitting '{' and '}' to OUT. If +SEMICOLONP is set, the closing '}' is suffixed with ';'. NAME is used to +prepend the starting block with a name, for example \"class MyClass\"." + (if name + (format out "~A {~%" name) + (write-line "{" out)) + (funcall fun) + (if semicolonp (write-line "};" out) (write-line "}" out))) + +(defmacro with-cpp-block-output ((out &rest rest &key semicolonp name) &body body) + "Surround BODY with emitting '{' and '}' to OUT. For additional arguments, +see `CALL-WITH-CPP-BLOCK-OUTPUT' documentation." + (declare (ignorable semicolonp name)) + `(call-with-cpp-block-output ,out (lambda () ,@body) ,@rest)) + (defun cpp-enum-definition (cpp-enum) "Get C++ style `CPP-ENUM' definition as a string." (declare (type cpp-enum cpp-enum)) (with-output-to-string (s) (when (cpp-type-documentation cpp-enum) (write-line (cpp-documentation (cpp-type-documentation cpp-enum)) s)) - (format s "enum class ~A {~%" (cpp-type-name cpp-enum)) - (format s "~{ ~A~^,~%~}~%" (mapcar #'cpp-constant-name (cpp-enum-values cpp-enum))) - (write-line "};" s))) + (with-cpp-block-output (s :name (format nil "enum class ~A" (cpp-type-name cpp-enum)) + :semicolonp t) + (format s "~{ ~A~^,~%~}~%" (mapcar #'cpp-constant-name (cpp-enum-values cpp-enum)))))) (defun cpp-member-declaration (cpp-member &key struct) "Get C++ style `CPP-MEMBER' declaration as a string." @@ -403,32 +419,26 @@ NIL, returns a string." (when (cpp-class-super-classes cpp-class) (format s " : ~{public ~A~^, ~}" (mapcar #'cpp-type-name (cpp-class-super-classes cpp-class)))) - (write-line " {" s) - (let ((reader-members (remove-if (complement #'cpp-member-reader) - (cpp-class-members cpp-class)))) - (when (or (cpp-class-public cpp-class) (cpp-class-members-scoped :public) reader-members) - (unless (cpp-class-structp cpp-class) - (write-line " public:" s)) - (format s "~{~A~%~}" (mapcar #'cpp-code (cpp-class-public cpp-class))) - (format s "~{~%~A~}~%" (mapcar #'cpp-member-reader-definition reader-members)) + (with-cpp-block-output (s :semicolonp t) + (let ((reader-members (remove-if (complement #'cpp-member-reader) + (cpp-class-members cpp-class)))) + (when (or (cpp-class-public cpp-class) (cpp-class-members-scoped :public) reader-members) + (unless (cpp-class-structp cpp-class) + (write-line " public:" s)) + (format s "~{~A~%~}" (mapcar #'cpp-code (cpp-class-public cpp-class))) + (format s "~{~%~A~}~%" (mapcar #'cpp-member-reader-definition reader-members)) + (format s "~{ ~%~A~}~%" + (mapcar #'member-declaration (cpp-class-members-scoped :public))))) + (when (or (cpp-class-protected cpp-class) (cpp-class-members-scoped :protected)) + (write-line " protected:" s) + (format s "~{~A~%~}" (mapcar #'cpp-code (cpp-class-protected cpp-class))) (format s "~{ ~%~A~}~%" - (mapcar #'member-declaration (cpp-class-members-scoped :public))))) - (when (cpp-class-capnp-opts cpp-class) - (let ((construct (capnp-construct-declaration cpp-class)) - (load (capnp-load-declaration cpp-class))) - (when construct (format s " ~A;~2%" construct)) - (when load (format s " ~A;~2%" load)))) - (when (or (cpp-class-protected cpp-class) (cpp-class-members-scoped :protected)) - (write-line " protected:" s) - (format s "~{~A~%~}" (mapcar #'cpp-code (cpp-class-protected cpp-class))) - (format s "~{ ~%~A~}~%" - (mapcar #'member-declaration (cpp-class-members-scoped :protected)))) - (when (or (cpp-class-private cpp-class) (cpp-class-members-scoped :private)) - (write-line " private:" s) - (format s "~{~A~%~}" (mapcar #'cpp-code (cpp-class-private cpp-class))) - (format s "~{ ~%~A~}~%" - (mapcar #'member-declaration (cpp-class-members-scoped :private)))) - (write-line "};" s)))) + (mapcar #'member-declaration (cpp-class-members-scoped :protected)))) + (when (or (cpp-class-private cpp-class) (cpp-class-members-scoped :private)) + (write-line " private:" s) + (format s "~{~A~%~}" (mapcar #'cpp-code (cpp-class-private cpp-class))) + (format s "~{ ~%~A~}~%" + (mapcar #'member-declaration (cpp-class-members-scoped :private)))))))) (defun cpp-function-declaration (name &key args (returns "void") type-params) "Generate a C++ top level function declaration named NAME as a string. ARGS @@ -680,12 +690,11 @@ encoded as union inheritance in Cap'n Proto." "Generate Cap'n Proto serialization schema for CPP-ENUM" (declare (type cpp-enum cpp-enum)) (with-output-to-string (s) - (format s "enum ~A {~%" (cpp-type-name cpp-enum)) - (loop for val in (cpp-enum-values cpp-enum) and field-number from 0 - do (format s " ~A @~A;~%" - (string-downcase (cpp-type-name val) :end 1) - field-number)) - (write-line "}" s))) + (with-cpp-block-output (s :name (format nil "enum ~A" (cpp-type-name cpp-enum))) + (loop for val in (cpp-enum-values cpp-enum) and field-number from 0 + do (format s " ~A @~A;~%" + (string-downcase (cpp-type-name val) :end 1) + field-number))))) (defun capnp-schema (cpp-class) "Generate Cap'n Proto serialiation schema for CPP-CLASS" @@ -715,57 +724,53 @@ encoded as union inheritance in Cap'n Proto." (error "Class ~A has multiple inheritance. Use :inherit-compose for remaining parents." class-name)) (with-output-to-string (s) - (format s "struct ~A {~%" (cpp-type-name class-name)) - (dolist (compose compose-parents) - (format s " ~A @~A :~A;~%" - (field-name<-symbol compose) - field-number - (capnp-type<-cpp-type compose)) - (incf field-number)) - (when capnp-type-args - (write-line " union {" s) - (dolist (type-arg capnp-type-args) - (format s " ~A @~A :Void;~%" (field-name<-symbol type-arg) field-number) - (incf field-number)) - (write-line " }" s)) - (dolist (member members) - (unless (eq :dont-save (cpp-member-capnp-save member)) - (let ((capnp-type (capnp-type-of-member member)) - (field-name (field-name<-symbol (cpp-member-symbol member)))) - (if (stringp capnp-type) - (progn - (format s " ~A @~A :~A;~%" - field-name field-number capnp-type) - (incf field-number)) - ;; capnp-type is a list specifying a union type - (progn - (format s " ~A :union {~%" field-name) - (dolist (union-member capnp-type) - (format s " ~A @~A :~A;~%" - (field-name<-symbol (first union-member)) - field-number (second union-member)) - (incf field-number)) - (write-line " }" s)))))) - (dolist (inner inner-types) - (when (or (and (typep inner 'cpp-class) (cpp-class-capnp-opts inner)) - (and (typep inner 'cpp-enum) (cpp-enum-capnp-schema inner))) - (write-line (capnp-schema inner) s))) - (when union-subclasses - (write-line " union {" s) - (when union-parents - ;; Allow instantiating classes in the middle of inheritance - ;; hierarchy. - (format s " ~A @~A :Void;~%" - (field-name<-symbol class-name) field-number) - (incf field-number)) - (dolist (subclass union-subclasses) - (format s " ~A @~A :~A;~%" - (field-name<-symbol (cpp-type-base-name subclass)) + (with-cpp-block-output (s :name (format nil "struct ~A" (cpp-type-name class-name))) + (dolist (compose compose-parents) + (format s " ~A @~A :~A;~%" + (field-name<-symbol compose) field-number - (capnp-type<-cpp-type (cpp-type-base-name subclass))) + (capnp-type<-cpp-type compose)) (incf field-number)) - (write-line " }" s)) - (write-line "}" s)))))) + (when capnp-type-args + (with-cpp-block-output (s :name "union") + (dolist (type-arg capnp-type-args) + (format s " ~A @~A :Void;~%" (field-name<-symbol type-arg) field-number) + (incf field-number)))) + (dolist (member members) + (unless (eq :dont-save (cpp-member-capnp-save member)) + (let ((capnp-type (capnp-type-of-member member)) + (field-name (field-name<-symbol (cpp-member-symbol member)))) + (if (stringp capnp-type) + (progn + (format s " ~A @~A :~A;~%" + field-name field-number capnp-type) + (incf field-number)) + ;; capnp-type is a list specifying a union type + (progn + (with-cpp-block-output (s :name (format nil " ~A :union" field-name)) + (dolist (union-member capnp-type) + (format s " ~A @~A :~A;~%" + (field-name<-symbol (first union-member)) + field-number (second union-member)) + (incf field-number)))))))) + (dolist (inner inner-types) + (when (or (and (typep inner 'cpp-class) (cpp-class-capnp-opts inner)) + (and (typep inner 'cpp-enum) (cpp-enum-capnp-schema inner))) + (write-line (capnp-schema inner) s))) + (when union-subclasses + (with-cpp-block-output (s :name "union") + (when union-parents + ;; Allow instantiating classes in the middle of inheritance + ;; hierarchy. + (format s " ~A @~A :Void;~%" + (field-name<-symbol class-name) field-number) + (incf field-number)) + (dolist (subclass union-subclasses) + (format s " ~A @~A :~A;~%" + (field-name<-symbol (cpp-type-base-name subclass)) + field-number + (capnp-type<-cpp-type (cpp-type-base-name subclass))) + (incf field-number)))))))))) ;;; Capnp C++ serialization code generation ;;; @@ -951,25 +956,25 @@ Proto schema." (capnp-primitive-type-p (capnp-type-of-member member))) (format s " builder->set~A(~A);~%" capnp-name member-access)) (t - (write-line "{" s) ;; Enclose larger save code in new scope - (let ((size (if (string= "vector" (cpp-type-base-name - (parse-cpp-type-declaration - (cpp-member-type member)))) - (format nil "~A.size()" member-access) - ""))) - (if (and (cpp-member-capnp-init member) - (not (find-cpp-enum (cpp-member-type member)))) - (format s " auto ~A = builder->init~A(~A);~%" - member-builder capnp-name size) - (setf member-builder "builder"))) - (if (cpp-member-capnp-save member) - (format s " ~A~%" - (cpp-code (funcall (cpp-member-capnp-save member) - member-builder member-access capnp-name))) - (write-line (capnp-save-default member-access (cpp-member-type member) - member-builder capnp-name) - s)) - (write-line "}" s)))))))) + ;; Enclose larger save code in new scope + (with-cpp-block-output (s) + (let ((size (if (string= "vector" (cpp-type-base-name + (parse-cpp-type-declaration + (cpp-member-type member)))) + (format nil "~A.size()" member-access) + ""))) + (if (and (cpp-member-capnp-init member) + (not (find-cpp-enum (cpp-member-type member)))) + (format s " auto ~A = builder->init~A(~A);~%" + member-builder capnp-name size) + (setf member-builder "builder"))) + (if (cpp-member-capnp-save member) + (format s " ~A~%" + (cpp-code (funcall (cpp-member-capnp-save member) + member-builder member-access capnp-name))) + (write-line (capnp-save-default member-access (cpp-member-type member) + member-builder capnp-name) + s)))))))))) (defun capnp-save-parents (cpp-class save-parent) "Generate Cap'n Proto code for serializing parent classes of CPP-CLASS. @@ -985,8 +990,7 @@ It takes a parent class symbol." (let ((parents (capnp-union-parents-rec cpp-class))) (when parents (let ((first-parent (first parents))) - (write-line - (funcall save-parent first-parent) s)) + (write-line (funcall save-parent first-parent) s)) (if (or compose-parents (cpp-class-members cpp-class)) (progn (format s " auto ~A_builder = base_builder->~{get~A().~}init~A();~%" @@ -1004,12 +1008,11 @@ It takes a parent class symbol." (format s " builder->set~A();" (cpp-type-name cpp-class))))) ;; Now handle composite inheritance calls. (dolist (parent compose-parents) - (write-line "{" s) - (let* ((builder (format nil "~A_builder" (cpp-variable-name parent)))) - (format s " auto ~A = builder->init~A();~%" builder (cpp-type-name parent)) - (format s " auto *builder = &~A;~%" builder) - (write-line (funcall save-parent parent) s)) - (write-line "}" s))))) + (with-cpp-block-output (s) + (let* ((builder (format nil "~A_builder" (cpp-variable-name parent)))) + (format s " auto ~A = builder->init~A();~%" builder (cpp-type-name parent)) + (format s " auto *builder = &~A;~%" builder) + (write-line (funcall save-parent parent) s))))))) (defun capnp-save-function-code (cpp-class) "Generate Cap'n Proto save code for CPP-CLASS." @@ -1037,10 +1040,9 @@ It takes a parent class symbol." "Generate serialization code for parent class." (let ((cpp-class (find-cpp-class parent))) (with-output-to-string (s) - (write-line "{" s) - (format s "// Save base class ~A~%" (cpp-type-name parent)) - (save-class cpp-class s) - (write-line "}" s))))) + (with-cpp-block-output (s) + (format s "// Save base class ~A~%" (cpp-type-name parent)) + (save-class cpp-class s)))))) (with-output-to-string (cpp-out) (let ((subclasses (direct-subclasses-of cpp-class))) (when subclasses @@ -1082,84 +1084,59 @@ It takes a parent class symbol." "Generate Cap'n Proto save function." (declare (type cpp-class cpp-class)) (with-output-to-string (cpp-out) - (format cpp-out "~A {~%" (capnp-save-function-declaration cpp-class)) - (write-line (capnp-save-function-code cpp-class) cpp-out) - (write-line "}" cpp-out))) + (with-cpp-block-output (cpp-out :name (capnp-save-function-declaration cpp-class)) + (write-line (capnp-save-function-code cpp-class) cpp-out)))) ;;; Capnp C++ deserialization code generation ;;; ;;; This is almost the same as serialization, but with a special case for ;;; handling serialized pointers to base classes. ;;; -;;; We need to generate a static Construct function, which dispatches on the -;;; union of the Capnp struct schema. This needs to recursively traverse -;;; unions to instantiate a concrete C++ class. +;;; The usual function signature for data types with no inheritance is: ;;; -;;; When loading such a pointer, first we call Construct and then follow it -;;; with calling Load on the constructed instance. +;;; void Load(Data *self, const capnp::Data::Reader &, ) +;;; +;;; The function expects that the `Data` type is already allocated and can be +;;; modified via pointer. This way the user can allocate `Data` any way they +;;; see fit. +;;; +;;; With inheritance, the user doesn't know the concrete type to allocate. +;;; Therefore, the signature is changed so that the `Load` can heap allocate +;;; and construct the correct type. The downside of this approach is that the +;;; user of the `Load` function has no control over the allocation. The +;;; signature for loading types with inheritance is: +;;; +;;; void Load(std::unique_ptr *self, const capnp::Data::Reader &, +;;; ) +;;; +;;; The user can now only provide a pointer to unique_ptr which should take +;;; the ownership of the concrete type. -(defun capnp-construct-declaration (cpp-class &key (inline t)) - "Generate Cap'n Proto construct function declaration for CPP-CLASS. If -INLINE is NIL, the declaration is namespaced for the class so that it can be -used for outside definition." +(defun capnp-load-function-declaration (cpp-class) + "Generate Cap'n Proto load function declaration for CPP-CLASS." (declare (type cpp-class cpp-class)) - ;; Don't generate Construct if this class is only inherited as composite. - (when (and (not (capnp-union-subclasses cpp-class)) - (direct-subclasses-of cpp-class)) - (return-from capnp-construct-declaration)) - (let ((reader-type (format nil "const capnp::~A::Reader &" - (cpp-type-decl cpp-class :type-args nil :namespace nil)))) - (cpp-method-declaration - cpp-class "Construct" :args (list (list 'reader reader-type)) - :returns (format nil "std::unique_ptr<~A>" (cpp-type-decl cpp-class :namespace nil)) - :inline inline :static t))) + (let* ((parents (capnp-union-parents-rec cpp-class)) + (top-parent-class (if parents + (cpp-type-decl (find-cpp-class (car (last parents))) :type-args nil :namespace nil) + (cpp-type-decl cpp-class :type-args nil :namespace nil))) + (reader-arg (list (if (or parents (capnp-union-subclasses cpp-class)) + 'base-reader + 'reader) + (format nil "const capnp::~A::Reader &" top-parent-class))) + (out-arg (list 'self + (if (or parents (direct-subclasses-of cpp-class)) + (format nil "std::unique_ptr<~A> *" (cpp-type-decl cpp-class :namespace nil)) + (format nil "~A *" (cpp-type-decl cpp-class :namespace nil)))))) + (cpp-function-declaration + "Load" + :args (cons out-arg (cons reader-arg (capnp-extra-args cpp-class :load))) + :returns "void" + :type-params (cpp-type-type-params cpp-class)))) -(defun capnp-construct-code (cpp-class) - "Generate Cap'n Proto construct code for CPP-CLASS" - (declare (type cpp-class cpp-class)) - (let ((construct-declaration (capnp-construct-declaration cpp-class :inline nil))) - (unless construct-declaration - (return-from capnp-construct-code)) - (let ((class-name (cpp-type-base-name cpp-class)) - (union-subclasses (capnp-union-subclasses cpp-class))) - (with-output-to-string (s) - (format s "~A {~%" construct-declaration) - (if (not union-subclasses) - ;; No inheritance, just instantiate the concrete class. - (format s " return std::unique_ptr<~A>(new ~A());~%" - (cpp-type-name class-name) (cpp-type-name class-name)) - ;; Inheritance, so forward the Construct. - (progn - (write-line " switch (reader.which()) {" s) - (when (capnp-union-and-compose-parents cpp-class) - ;; We are in the middle of the hierarchy, so allow - ;; constructing us. - (format s " case capnp::~A::~A: return std::unique_ptr<~A>(new ~A());~%" - (cpp-type-name class-name) (cpp-constant-name class-name) - (cpp-type-name class-name) (cpp-type-name class-name))) - (dolist (subclass union-subclasses) - (format s " case capnp::~A::~A:~%" - (cpp-type-name class-name) - (cpp-constant-name (cpp-type-base-name subclass))) - (let ((subclass-name (cpp-type-name (cpp-type-base-name subclass)))) - (if (capnp-opts-type-args (cpp-class-capnp-opts subclass)) - ;; Handle template instantiation - (progn - (format s " switch (reader.get~A().which()) {~%" subclass-name) - (dolist (type-arg (capnp-opts-type-args (cpp-class-capnp-opts subclass))) - (format s " case capnp::~A::~A: return ~A<~A>::Construct(reader.get~A());~%" - subclass-name (cpp-constant-name type-arg) - subclass-name (cpp-type-name type-arg) - subclass-name)) - (write-line " }" s)) - ;; Just forward the construct normally. - (format s " return ~A::Construct(reader.get~A());~%" - subclass-name subclass-name)))) - (write-line " }" s))) ;; close switch - (write-line "}" s))))) ;; close function - -(defun capnp-load-default (member-name member-type member-reader) - "Generate default load call for member." +(defun capnp-load-default (member-name member-type member-reader capnp-name) + "Generate default load call for member. MEMBER-NAME and MEMBER-TYPE are +strings describing the member being loaded. MEMBER-READER is the name of the +reader variable. CAPNP-NAME is the name of the member in Cap'n Proto schema." (declare (type string member-name member-type member-reader)) (let* ((type (parse-cpp-type-declaration member-type)) (type-name (cpp-type-base-name type)) @@ -1168,8 +1145,8 @@ used for outside definition." (cpp-enum (funcall (capnp-load-enum (cpp-type-decl (capnp-cpp-type<-cpp-type cpp-enum)) - member-type (cpp-enum-values cpp-enum)) - member-reader member-name)) + (cpp-type-decl cpp-enum) (cpp-enum-values cpp-enum)) + member-reader member-name capnp-name)) ((string= "vector" type-name) (let* ((elem-type (car (cpp-type-type-args type))) (capnp-cpp-type (capnp-cpp-type<-cpp-type elem-type))) @@ -1180,7 +1157,7 @@ used for outside definition." cpp<#) (raw-cpp-string (funcall (capnp-load-vector (cpp-type-decl capnp-cpp-type) (cpp-type-decl elem-type)) - member-reader member-name))))) + member-reader member-name capnp-name))))) ((string= "optional" type-name) (let* ((elem-type (car (cpp-type-type-args type))) (capnp-cpp-type (capnp-cpp-type<-cpp-type elem-type :boxp t)) @@ -1189,7 +1166,7 @@ used for outside definition." (raw-cpp-string (funcall (capnp-load-optional (cpp-type-decl capnp-cpp-type) (cpp-type-decl elem-type) lambda-code) - member-reader member-name)))) + member-reader member-name capnp-name)))) ((member type-name '("unique_ptr" "shared_ptr" "vector") :test #'string=) (error "Use a custom :capnp-load function for ~A ~A" type-name member-name)) (t @@ -1198,81 +1175,148 @@ used for outside definition." (mapcar (lambda (name-and-type) (cpp-variable-name (first name-and-type))) (capnp-extra-args cpp-class :load))))) - (format nil "~A.Load(~A~{, ~A~});" + (format nil "Load(&~A, ~A~{, ~A~});" member-name member-reader extra-args)))))) -(defun capnp-load-declaration (cpp-class &key (inline t)) - "Generate Cap'n Proto load function declaration for CPP-CLASS. If -INLINE is NIL, the declaration is namespaced for the class so that it can be -used for outside definition." - (declare (type cpp-class cpp-class)) - (let* ((parents (capnp-union-parents-rec cpp-class)) - (top-parent-class (if parents - (cpp-type-decl (find-cpp-class (car (last parents))) :type-args nil :namespace nil) - (cpp-type-decl cpp-class :type-args nil :namespace nil))) - (reader-arg - (list (if parents 'base-reader 'reader) - (format nil "const capnp::~A::Reader &" top-parent-class)))) - (cpp-method-declaration - cpp-class "Load" :args (cons reader-arg (capnp-extra-args cpp-class :load)) - :virtual (and (not parents) (capnp-union-subclasses cpp-class)) - :override parents :inline inline))) - -(defun capnp-load-code (cpp-class) - "Generate Cap'n Proto loading code for CPP-CLASS" +(defun capnp-load-members (cpp-class &key instance-access) + "Generate Cap'n Proto loading code for members of CPP-CLASS. +INSTANCE-ACCESS is a C++ string which will be prefixed to member access. For +example, INSTANCE-ACCESS could be `my_struct->`" (declare (type cpp-class cpp-class)) + (declare (type string instance-access)) (with-output-to-string (s) - (format s "~A {~%" (capnp-load-declaration cpp-class :inline nil)) - (flet ((parent-args (parent) - (mapcar (lambda (name-and-type) - (cpp-variable-name (first name-and-type))) - (capnp-extra-args (find-cpp-class parent) :load)))) - (multiple-value-bind (direct-union-parents compose-parents) - (capnp-union-and-compose-parents cpp-class) - (declare (ignore direct-union-parents)) - ;; Handle the union inheritance calls first. - (let ((parents (capnp-union-parents-rec cpp-class))) - (when parents - (let ((first-parent (first parents))) - (format s " ~A::Load(base_reader~{, ~A~});~%" - (cpp-type-name first-parent) (parent-args first-parent))) - (when (or compose-parents (cpp-class-members cpp-class)) - (format s " auto reader = base_reader.~{get~A().~}get~A();~%" - (mapcar #'cpp-type-name (cdr (reverse parents))) - (cpp-type-name cpp-class))) - ;; Now handle composite inheritance calls. - (dolist (parent compose-parents) - (write-line "{" s) - (format s " auto ~A_reader = reader.get~A();~%" - (cpp-variable-name parent) (cpp-type-name parent)) - (format s " ~A::Load(~A_reader~{, ~A~});~%" - (cpp-type-name parent) (cpp-variable-name parent) (parent-args parent)) - (write-line "}" s)))))) (dolist (member (cpp-class-members cpp-class)) (unless (and (eq :dont-save (cpp-member-capnp-save member)) (not (cpp-member-capnp-load member))) - (let ((member-name (cpp-member-name member :struct (cpp-class-structp cpp-class))) + (let ((member-access + (concatenate 'string instance-access + (cpp-member-name member :struct (cpp-class-structp cpp-class)))) (member-reader (format nil "~A_reader" (cpp-member-name member :struct t))) (capnp-name (cpp-type-name (cpp-member-symbol member)))) (cond ((and (not (cpp-member-capnp-load member)) (capnp-primitive-type-p (capnp-type-of-member member))) - (format s " ~A = reader.get~A();~%" member-name capnp-name)) + (format s " ~A = reader.get~A();~%" member-access capnp-name)) (t - (write-line "{" s) ;; Enclose larger load code in new scope - (if (and (cpp-member-capnp-init member) - (not (find-cpp-enum (cpp-member-type member)))) - (format s " auto ~A = reader.get~A();~%" member-reader capnp-name) - (setf member-reader "reader")) - (if (cpp-member-capnp-load member) - (format s " ~A~%" - (cpp-code (funcall (cpp-member-capnp-load member) - member-reader member-name))) - (write-line (capnp-load-default member-name - (cpp-member-type member) - member-reader) s)) - (write-line "}" s)))))) - (write-line "}" s))) + ;; Enclose larger load code in new scope + (with-cpp-block-output (s) + (if (and (cpp-member-capnp-init member) + (not (find-cpp-enum (cpp-member-type member)))) + (format s " auto ~A = reader.get~A();~%" member-reader capnp-name) + (setf member-reader "reader")) + (if (cpp-member-capnp-load member) + (format s " ~A~%" + (cpp-code (funcall (cpp-member-capnp-load member) + member-reader member-access capnp-name))) + (write-line (capnp-load-default member-access + (cpp-member-type member) + member-reader capnp-name) s)))))))))) + +(defun capnp-load-parents (cpp-class load-parent) + "Generate Cap'n Proto code for loading parent classes of CPP-CLASS. +LOAD-PARENT is a function which generates the code for loading parent members. +It takes a parent class symbol." + (declare (type cpp-class cpp-class)) + (declare (type (function (symbol) string) load-parent)) + (with-output-to-string (s) + (multiple-value-bind (direct-union-parents compose-parents) + (capnp-union-and-compose-parents cpp-class) + (declare (ignore direct-union-parents)) + ;; Handle the union inheritance calls first. + (let ((parents (capnp-union-parents-rec cpp-class))) + (when parents + (let ((first-parent (first parents))) + (write-line (funcall load-parent first-parent) s)) + (when (or compose-parents (cpp-class-members cpp-class)) + (format s " auto reader = base_reader.~{get~A().~}get~A();~%" + (mapcar #'cpp-type-name (cdr (reverse parents))) + (cpp-type-name cpp-class))) + ;; Now handle composite inheritance calls. + (dolist (parent compose-parents) + (with-cpp-block-output (s) + (let ((reader (format nil "~A_reader" (cpp-variable-name parent)))) + (format s " auto ~A = reader.get~A();~%" reader (cpp-type-name parent)) + (format s " const auto &reader = ~A;" reader) + (write-line (funcall load-parent parent) s))))))))) + +(defun capnp-load-function-code (cpp-class) + "Generate Cap'n Proto loadd code for CPP-CLASS." + (declare (type cpp-class cpp-class)) + (let ((instance-access (if (or (direct-subclasses-of cpp-class) + (capnp-union-parents-rec cpp-class)) + "self->get()->" + "self->"))) + (labels ((load-class (cpp-class) + (with-output-to-string (s) + (write-line (capnp-load-parents cpp-class #'load-parent) s) + (write-line (capnp-load-members cpp-class :instance-access instance-access) s))) + (load-parent (parent) + (with-output-to-string (s) + (with-cpp-block-output (s) + (format s "// Load base class ~A~%" (cpp-type-name parent)) + (write-line (load-class (find-cpp-class parent)) s))))) + (with-output-to-string (s) + (cond + ((and (capnp-union-and-compose-parents cpp-class) + (not (direct-subclasses-of cpp-class))) + ;; CPP-CLASS is the most derived class, so construct and load. + (format s "*self = std::make_unique<~A>();~%" (cpp-type-decl cpp-class :namespace nil)) + (write-line (load-class cpp-class) s)) + ((capnp-union-subclasses cpp-class) + ;; Forward the load to most derived class by switching on reader.which() + (let ((parents (capnp-union-parents-rec cpp-class))) + (if parents + (format s "switch (base_reader.~{get~A().~}get~A().which()) " + (mapcar #'cpp-type-name (cdr (reverse parents))) + (cpp-type-name cpp-class)) + (write-string "switch (base_reader.which()) " s))) + (with-cpp-block-output (s) + (dolist (subclass (capnp-union-subclasses cpp-class)) + (format s " case capnp::~A::~A: " + (cpp-type-name cpp-class) + (cpp-constant-name (cpp-type-base-name subclass))) + (flet ((load-derived (derived-type-name) + (with-cpp-block-output (s) + (format s "std::unique_ptr<~A> derived;~%" derived-type-name) + (format s "Load(&derived, base_reader~{, ~A~});~%" + (mapcar (lambda (name-and-type) + (cpp-variable-name (first name-and-type))) + (capnp-extra-args cpp-class :load))) + (write-line "*self = std::move(derived);" s)))) + (if (capnp-opts-type-args (cpp-class-capnp-opts subclass)) + ;; Handle template instantiation + (progn + (format s "switch (base_reader.get~A().which()) " (cpp-type-name subclass)) + (with-cpp-block-output (s) + (dolist (type-arg (capnp-opts-type-args (cpp-class-capnp-opts subclass))) + (format s " case capnp::~A::~A: " + (cpp-type-name subclass) (cpp-constant-name type-arg)) + (load-derived (format nil "~A<~A>" + (cpp-type-name subclass) + (cpp-type-name type-arg)))))) + ;; Regular forward to derived + (load-derived (cpp-type-name subclass)))) + (write-line "break;" s)) + (when (capnp-union-and-compose-parents cpp-class) + ;; We are in the middle of the hierarchy, so allow constructing and loading us. + (with-cpp-block-output (s :name (format nil "case capnp::~A::~A:" + (cpp-type-name cpp-class) + (cpp-constant-name (cpp-type-base-name cpp-class)))) + (format s "*self = std::make_unique<~A>();~%" + (cpp-type-decl cpp-class :namespace nil)) + (write-line (load-class cpp-class) s))))) + (t + ;; Regular load for absolutely no inheritance class + (assert (not (capnp-union-subclasses cpp-class))) + (assert (not (capnp-union-and-compose-parents cpp-class))) + (write-line (load-class cpp-class) s))))))) + +(defun capnp-load-function-definition (cpp-class) + "Generate Cap'n Proto load function." + (declare (type cpp-class cpp-class)) + (with-output-to-string (cpp-out) + (with-cpp-block-output (cpp-out :name (capnp-load-function-declaration cpp-class)) + (write-line (capnp-load-function-code cpp-class) cpp-out)))) (defvar *capnp-imports* nil "List of pairs (namespace, import-file), which will be imported in Cap'n @@ -1318,12 +1362,15 @@ are passed as template parameters, while the optional LAMBDA-CODE is used to load the value of std::optional." (declare (type string capnp-type cpp-type) (type (or null string) lambda-code)) - (let ((lambda-code (if lambda-code + (let* ((namespace (format nil "~{~A::~}" + (cpp-type-namespace (parse-cpp-type-declaration cpp-type)))) + (lambda-code (if lambda-code lambda-code (format nil - "[](const auto &reader) { ~A val; val.Load(reader); return val; }" - cpp-type)))) - (lambda (reader member) + "[](const auto &reader) { ~A val; ~ALoad(&val, reader); return val; }" + cpp-type namespace)))) + (lambda (reader member capnp-name) + (declare (ignore capnp-name)) #>cpp ${member} = utils::LoadOptional<${capnp-type}, ${cpp-type}>(${reader}, ${lambda-code}); cpp<#))) @@ -1354,12 +1401,15 @@ are passed as template parameters, while LAMBDA-CODE is used to load each element." (declare (type string capnp-type cpp-type) (type (or null string) lambda-code)) - (let ((lambda-code (if lambda-code + (let* ((namespace (format nil "~{~A::~}" + (cpp-type-namespace (parse-cpp-type-declaration cpp-type)))) + (lambda-code (if lambda-code lambda-code (format nil - "[](const auto &reader) { ~A val; val.Load(reader); return val; }" - cpp-type)))) - (lambda (reader member-name) + "[](const auto &reader) { ~A val; ~ALoad(&val, reader); return val; }" + cpp-type namespace)))) + (lambda (reader member-name capnp-name) + (declare (ignore capnp-name)) #>cpp utils::LoadVector<${capnp-type}, ${cpp-type}>(&${member-name}, ${reader}, ${lambda-code}); cpp<#))) @@ -1390,11 +1440,10 @@ the values from CAPNP-TYPE. If ENUM-VALUES are not specified, tries to find the CPP-TYPE among defined enums." (declare (type string capnp-type) (type (or symbol string) cpp-type)) - (lambda (reader member) + (lambda (reader member capnp-name) (let* ((enum-values (if enum-values enum-values (cpp-enum-values (find-cpp-enum cpp-type)))) - (member-getter (remove #\_ (string-capitalize member))) (cases (mapcar (lambda (value-symbol) (let ((value (cl-ppcre:regex-replace-all "-" (string value-symbol) "_"))) #>cpp @@ -1404,7 +1453,7 @@ CPP-TYPE among defined enums." cpp<#)) enum-values))) (format nil "switch (~A.get~A()) {~%~{~A~%~}}" - reader member-getter (mapcar #'raw-cpp-string cases))))) + reader capnp-name (mapcar #'raw-cpp-string cases))))) (defvar *cpp-namespaces* nil "Stack of C++ namespaces we are generating the code in.") @@ -1730,13 +1779,9 @@ code generation." (format cpp-out "// Serialize code for ~A~2%" (cpp-type-name cpp-class)) ;; Top level functions (write-line (capnp-save-function-definition cpp-class) cpp-out) - ;; Member functions - (let ((construct-code (capnp-construct-code cpp-class)) - (load-code (capnp-load-code cpp-class))) - (when construct-code (write-line construct-code cpp-out)) - (when load-code (write-line load-code cpp-out)))))) + (write-line (capnp-load-function-definition cpp-class) cpp-out)))) -(defun process-file (lcp-file &key capnp-id capnp-declaration) +(defun process-file (lcp-file &key capnp-id) "Process a LCP-FILE and write the output to .hpp file in the same directory. If CAPNP-ID is passed, generates the Cap'n Proto schema to .capnp file in the same directory, while the loading code is generated in LCP-FILE.cpp source @@ -1750,7 +1795,7 @@ file." (cpp-file (concatenate 'string lcp-file ".cpp")) (capnp-file (concatenate 'string filename ".capnp")) ;; Reset globals - (*capnp-serialize-p* (or capnp-id capnp-declaration)) + (*capnp-serialize-p* capnp-id) (*capnp-namespace* nil) (*capnp-imports* nil) (*capnp-type-converters* nil) @@ -1784,7 +1829,8 @@ file." (dolist (type-for-capnp types-for-capnp) (when (typep type-for-capnp 'cpp-class) (open-namespace (cpp-type-namespace type-for-capnp)) - (format out "~A;~%" (capnp-save-function-declaration type-for-capnp)))))) + (format out "~A;~%" (capnp-save-function-declaration type-for-capnp)) + (format out "~A;~%" (capnp-load-function-declaration type-for-capnp)))))) ;; When we have either capnp or C++ code for the .cpp file, generate the .cpp file (when (or *cpp-impl* types-for-capnp) (with-open-file (out cpp-file :direction :output :if-exists :supersede) diff --git a/src/query/common.cpp b/src/query/common.cpp index 48a17ffb3..7702c77bc 100644 --- a/src/query/common.cpp +++ b/src/query/common.cpp @@ -284,16 +284,6 @@ bool TypedValueVectorCompare::operator()( return (c1_it == c1.end()) && (c2_it != c2.end()); } -void TypedValueVectorCompare::Save( - capnp::TypedValueVectorCompare::Builder *builder) const { - auto ordering_builder = builder->initOrdering(ordering_.size()); - for (size_t i = 0; i < ordering_.size(); ++i) { - ordering_builder.set(i, ordering_[i] == Ordering::ASC - ? capnp::Ordering::ASC - : capnp::Ordering::DESC); - } -} - void Save(const TypedValueVectorCompare &comparator, capnp::TypedValueVectorCompare::Builder *builder) { auto ordering_builder = builder->initOrdering(comparator.ordering().size()); @@ -304,8 +294,8 @@ void Save(const TypedValueVectorCompare &comparator, } } -void TypedValueVectorCompare::Load( - const capnp::TypedValueVectorCompare::Reader &reader) { +void Load(TypedValueVectorCompare *comparator, + const capnp::TypedValueVectorCompare::Reader &reader) { std::vector ordering; ordering.reserve(reader.getOrdering().size()); for (auto ordering_reader : reader.getOrdering()) { @@ -313,7 +303,7 @@ void TypedValueVectorCompare::Load( ? Ordering::ASC : Ordering::DESC); } - ordering_ = ordering; + comparator->ordering_ = ordering; } template diff --git a/src/query/common.hpp b/src/query/common.hpp index 5c6edd98c..dd2388223 100644 --- a/src/query/common.hpp +++ b/src/query/common.hpp @@ -44,18 +44,18 @@ class TypedValueVectorCompare final { bool operator()(const std::vector &c1, const std::vector &c2) const; + // TODO: Remove this, member is public const auto &ordering() const { return ordering_; } - void Save(capnp::TypedValueVectorCompare::Builder *builder) const; - void Load(const capnp::TypedValueVectorCompare::Reader &reader); - - private: std::vector ordering_; }; void Save(const TypedValueVectorCompare &comparator, capnp::TypedValueVectorCompare::Builder *builder); +void Load(TypedValueVectorCompare *comparator, + const capnp::TypedValueVectorCompare::Reader &reader); + /// Switch the given [Vertex/Edge]Accessor to the desired state. template void SwitchAccessor(TAccessor &accessor, GraphView graph_view); diff --git a/src/query/frontend/ast/ast.cpp b/src/query/frontend/ast/ast.cpp index 7eb5550e2..f335b3d7b 100644 --- a/src/query/frontend/ast/ast.cpp +++ b/src/query/frontend/ast/ast.cpp @@ -315,7 +315,7 @@ void MapLiteral::Load(const capnp::Tree::Reader &base_reader, 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); + storage::Load(&key_second, storage_property_reader); const auto value_reader = entry_reader.getValue(); auto value = storage->Load(value_reader, loaded_uids); auto key = std::make_pair(key_first, key_second); @@ -982,7 +982,7 @@ void LabelsTest::Load(const capnp::Tree::Reader &base_reader, } for (auto label_reader : reader.getLabels()) { storage::Label label; - label.Load(label_reader); + storage::Load(&label, label_reader); labels_.push_back(label); } } @@ -1041,7 +1041,7 @@ void PropertyLookup::Load(const capnp::Tree::Reader &base_reader, } property_name_ = reader.getPropertyName().cStr(); auto storage_property_reader = reader.getProperty(); - property_.Load(storage_property_reader); + storage::Load(&property_, storage_property_reader); } PropertyLookup *PropertyLookup::Construct( @@ -1356,10 +1356,10 @@ CreateIndex *CreateIndex::Construct(const capnp::CreateIndex::Reader &reader, AstStorage *storage) { auto label_reader = reader.getLabel(); storage::Label label; - label.Load(label_reader); + storage::Load(&label, label_reader); auto property_reader = reader.getProperty(); storage::Property property; - property.Load(property_reader); + storage::Load(&property, property_reader); return storage->Create(label, property); } @@ -1740,7 +1740,7 @@ void RemoveLabels::Load(const capnp::Tree::Reader &base_reader, } for (auto label_reader : reader.getLabels()) { storage::Label label; - label.Load(label_reader); + storage::Load(&label, label_reader); labels_.push_back(label); } } @@ -1908,7 +1908,7 @@ void SetLabels::Load(const capnp::Tree::Reader &base_reader, } for (auto label_reader : reader.getLabels()) { storage::Label label; - label.Load(label_reader); + storage::Load(&label, label_reader); labels_.push_back(label); } } @@ -2301,7 +2301,7 @@ void CypherUnion::Load(const capnp::Tree::Reader &base_reader, distinct_ = reader.getDistinct(); for (auto symbol_reader : reader.getUnionSymbols()) { Symbol symbol; - symbol.Load(symbol_reader); + query::Load(&symbol, symbol_reader); union_symbols_.push_back(symbol); } } @@ -2481,7 +2481,7 @@ void NodeAtom::Load(const capnp::Tree::Reader &base_reader, AstStorage *storage, auto key_first = key_pair_reader.getFirst().cStr(); auto storage_property_reader = key_pair_reader.getSecond(); storage::Property property; - property.Load(storage_property_reader); + storage::Load(&property, storage_property_reader); const auto value_reader = entry_reader.getValue(); auto value = storage->Load(value_reader, loaded_uids); auto key = std::make_pair(key_first, property); @@ -2490,7 +2490,7 @@ void NodeAtom::Load(const capnp::Tree::Reader &base_reader, AstStorage *storage, } for (auto label_reader : reader.getLabels()) { storage::Label label; - label.Load(label_reader); + storage::Load(&label, label_reader); labels_.push_back(label); } } @@ -2670,7 +2670,7 @@ void EdgeAtom::Load(const capnp::Tree::Reader &base_reader, AstStorage *storage, auto key_first = key_pair_reader.getFirst().cStr(); auto storage_property_reader = key_pair_reader.getSecond(); storage::Property property; - property.Load(storage_property_reader); + storage::Load(&property, storage_property_reader); const auto value_reader = entry_reader.getValue(); auto value = storage->Load(value_reader, loaded_uids); auto key = std::make_pair(key_first, property); @@ -2680,7 +2680,7 @@ void EdgeAtom::Load(const capnp::Tree::Reader &base_reader, AstStorage *storage, for (auto edge_type_reader : reader.getEdgeTypes()) { storage::EdgeType edge_type; - edge_type.Load(edge_type_reader); + storage::Load(&edge_type, edge_type_reader); edge_types_.push_back(edge_type); } } diff --git a/src/query/frontend/semantic/symbol.hpp b/src/query/frontend/semantic/symbol.hpp index d12d0e17e..892790293 100644 --- a/src/query/frontend/semantic/symbol.hpp +++ b/src/query/frontend/semantic/symbol.hpp @@ -33,40 +33,13 @@ class Symbol { } bool operator!=(const Symbol &other) const { return !operator==(other); } + // TODO: Remove these since members are public const auto &name() const { return name_; } int position() const { return position_; } Type type() const { return type_; } bool user_declared() const { return user_declared_; } int token_position() const { return token_position_; } - 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_; bool user_declared_ = true; @@ -101,6 +74,33 @@ inline void Save(const Symbol &symbol, capnp::Symbol::Builder *builder) { } } +inline void Load(Symbol *symbol, const capnp::Symbol::Reader &reader) { + symbol->name_ = reader.getName(); + symbol->position_ = reader.getPosition(); + symbol->user_declared_ = reader.getUserDeclared(); + symbol->token_position_ = reader.getTokenPosition(); + switch (reader.getType()) { + case capnp::Symbol::Type::ANY: + symbol->type_ = Symbol::Type::Any; + break; + case capnp::Symbol::Type::EDGE: + symbol->type_ = Symbol::Type::Edge; + break; + case capnp::Symbol::Type::EDGE_LIST: + symbol->type_ = Symbol::Type::EdgeList; + break; + case capnp::Symbol::Type::NUMBER: + symbol->type_ = Symbol::Type::Number; + break; + case capnp::Symbol::Type::PATH: + symbol->type_ = Symbol::Type::Path; + break; + case capnp::Symbol::Type::VERTEX: + symbol->type_ = Symbol::Type::Vertex; + break; + } +} + } // namespace query namespace std { diff --git a/src/query/frontend/semantic/symbol_table.hpp b/src/query/frontend/semantic/symbol_table.hpp index ba9368bc8..f5b08cd6b 100644 --- a/src/query/frontend/semantic/symbol_table.hpp +++ b/src/query/frontend/semantic/symbol_table.hpp @@ -24,22 +24,11 @@ class SymbolTable final { Symbol &at(const Tree &tree) { return table_.at(tree.uid()); } const Symbol &at(const Tree &tree) const { return table_.at(tree.uid()); } + // TODO: Remove these since members are public int max_position() const { return position_; } const auto &table() const { return table_; } - void Load(const capnp::SymbolTable::Reader &reader) { - position_ = reader.getPosition(); - table_.clear(); - for (const auto &entry_reader : reader.getTable()) { - int key = entry_reader.getKey(); - Symbol val; - val.Load(entry_reader.getVal()); - table_[key] = val; - } - } - - private: int position_{0}; std::map table_; }; @@ -57,4 +46,16 @@ inline void Save(const SymbolTable &symbol_table, } } +inline void Load(SymbolTable *symbol_table, + const capnp::SymbolTable::Reader &reader) { + symbol_table->position_ = reader.getPosition(); + symbol_table->table_.clear(); + for (const auto &entry_reader : reader.getTable()) { + int key = entry_reader.getKey(); + Symbol val; + Load(&val, entry_reader.getVal()); + symbol_table->table_[key] = val; + } +} + } // namespace query diff --git a/src/query/plan/cost_estimator.hpp b/src/query/plan/cost_estimator.hpp index eff495b07..5971090dc 100644 --- a/src/query/plan/cost_estimator.hpp +++ b/src/query/plan/cost_estimator.hpp @@ -76,7 +76,7 @@ class CostEstimator : public HierarchicalLogicalOperatorVisitor { } bool PostVisit(ScanAllByLabel &scan_all_by_label) override { - cardinality_ *= db_accessor_.VerticesCount(scan_all_by_label.label()); + cardinality_ *= db_accessor_.VerticesCount(scan_all_by_label.label_); // ScanAll performs some work for every element that is produced IncrementCost(CostParam::kScanAllByLabel); return true; @@ -86,16 +86,16 @@ class CostEstimator : public HierarchicalLogicalOperatorVisitor { // This cardinality estimation depends on the property value (expression). // If it's a constant, we can evaluate cardinality exactly, otherwise // we estimate - auto property_value = ConstPropertyValue(logical_op.expression()); + auto property_value = ConstPropertyValue(logical_op.expression_); double factor = 1.0; if (property_value) // get the exact influence based on ScanAll(label, property, value) factor = db_accessor_.VerticesCount( - logical_op.label(), logical_op.property(), property_value.value()); + logical_op.label_, logical_op.property_, property_value.value()); else // estimate the influence as ScanAll(label, property) * filtering - factor = db_accessor_.VerticesCount(logical_op.label(), - logical_op.property()) * + factor = db_accessor_.VerticesCount(logical_op.label_, + logical_op.property_) * CardParam::kFilter; cardinality_ *= factor; @@ -108,23 +108,23 @@ class CostEstimator : public HierarchicalLogicalOperatorVisitor { bool PostVisit(ScanAllByLabelPropertyRange &logical_op) override { // this cardinality estimation depends on Bound expressions. // if they are literals we can evaluate cardinality properly - auto lower = BoundToPropertyValue(logical_op.lower_bound()); - auto upper = BoundToPropertyValue(logical_op.upper_bound()); + auto lower = BoundToPropertyValue(logical_op.lower_bound_); + auto upper = BoundToPropertyValue(logical_op.upper_bound_); int64_t factor = 1; if (upper || lower) // if we have either Bound, use the value index - factor = db_accessor_.VerticesCount(logical_op.label(), - logical_op.property(), lower, upper); + factor = db_accessor_.VerticesCount(logical_op.label_, + logical_op.property_, lower, upper); else // no values, but we still have the label factor = - db_accessor_.VerticesCount(logical_op.label(), logical_op.property()); + db_accessor_.VerticesCount(logical_op.label_, logical_op.property_); // if we failed to take either bound from the op into account, then apply // the filtering constant to the factor - if ((logical_op.upper_bound() && !upper) || - (logical_op.lower_bound() && !lower)) + if ((logical_op.upper_bound_ && !upper) || + (logical_op.lower_bound_ && !lower)) factor *= CardParam::kFilter; cardinality_ *= factor; @@ -174,7 +174,7 @@ class CostEstimator : public HierarchicalLogicalOperatorVisitor { // exactly, otherwise we approximate int unwind_value; if (auto literal = - dynamic_cast(unwind.input_expression())) + dynamic_cast(unwind.input_expression_)) unwind_value = literal->elements_.size(); else unwind_value = MiscParam::kUnwindNoLiteral; diff --git a/src/query/plan/distributed.cpp b/src/query/plan/distributed.cpp index 08b26626a..75a2f4ab9 100644 --- a/src/query/plan/distributed.cpp +++ b/src/query/plan/distributed.cpp @@ -26,9 +26,9 @@ std::pair, AstStorage> Clone( Save(original_plan, &builder, &helper); } auto reader = message.getRoot(); - auto plan_copy = LogicalOperator::Construct(reader); + std::unique_ptr plan_copy; LogicalOperator::LoadHelper helper; - plan_copy->Load(reader, &helper); + Load(&plan_copy, reader, &helper); return std::make_pair(std::move(plan_copy), std::move(helper.ast_storage)); } @@ -139,9 +139,9 @@ class IndependentSubtreeFinder : public DistributedOperatorVisitor { maybe_bound->value()->Accept(collector); return this->ContainsForbidden(collector.symbols_); }; - CHECK(scan.lower_bound() || scan.upper_bound()); - auto lower_depends = find_forbidden(scan.lower_bound()); - auto upper_depends = find_forbidden(scan.upper_bound()); + CHECK(scan.lower_bound_ || scan.upper_bound_); + auto lower_depends = find_forbidden(scan.lower_bound_); + auto upper_depends = find_forbidden(scan.upper_bound_); if (!lower_depends && !upper_depends) return true; // Since we have dependencies, we need to extract them as a Filter. There @@ -155,45 +155,45 @@ class IndependentSubtreeFinder : public DistributedOperatorVisitor { auto make_prop_lookup = [&]() { auto ident = storage_->Create( - scan.output_symbol().name(), scan.output_symbol().user_declared()); - (*symbol_table_)[*ident] = scan.output_symbol(); - return storage_->Create(ident, "", scan.property()); + scan.output_symbol_.name(), scan.output_symbol_.user_declared()); + (*symbol_table_)[*ident] = scan.output_symbol_; + return storage_->Create(ident, "", scan.property_); }; Expression *extracted_filter = nullptr; std::shared_ptr new_scan; if (lower_depends) { // Extract the filtering expression auto prop_lookup = make_prop_lookup(); - if (scan.lower_bound()->IsInclusive()) { + if (scan.lower_bound_->IsInclusive()) { extracted_filter = storage_->Create( - prop_lookup, scan.lower_bound()->value()); + prop_lookup, scan.lower_bound_->value()); } else { extracted_filter = storage_->Create( - prop_lookup, scan.lower_bound()->value()); + prop_lookup, scan.lower_bound_->value()); } // Choose new scan operation branch_.depends_on = lower_depends; - if (upper_depends || !scan.upper_bound()) { + if (upper_depends || !scan.upper_bound_) { // Cases 2) and 1.b) new_scan = - std::make_shared(scan.input(), scan.output_symbol(), - scan.label(), scan.graph_view()); + std::make_shared(scan.input(), scan.output_symbol_, + scan.label_, scan.graph_view_); } else { // Case 1.a) new_scan = std::make_shared( - scan.input(), scan.output_symbol(), scan.label(), scan.property(), - std::experimental::nullopt, scan.upper_bound(), scan.graph_view()); + scan.input(), scan.output_symbol_, scan.label_, scan.property_, + std::experimental::nullopt, scan.upper_bound_, scan.graph_view_); } } if (upper_depends) { Expression *filter; auto prop_lookup = make_prop_lookup(); - if (scan.upper_bound()->IsInclusive()) { + if (scan.upper_bound_->IsInclusive()) { filter = storage_->Create( - prop_lookup, scan.upper_bound()->value()); + prop_lookup, scan.upper_bound_->value()); } else { filter = storage_->Create(prop_lookup, - scan.upper_bound()->value()); + scan.upper_bound_->value()); } if (lower_depends) { CHECK(extracted_filter); @@ -207,17 +207,17 @@ class IndependentSubtreeFinder : public DistributedOperatorVisitor { CHECK(!branch_.depends_on); branch_.depends_on = upper_depends; extracted_filter = filter; - if (scan.lower_bound()) { + if (scan.lower_bound_) { // Case 1.a) new_scan = std::make_shared( - scan.input(), scan.output_symbol(), scan.label(), scan.property(), - scan.lower_bound(), std::experimental::nullopt, - scan.graph_view()); + scan.input(), scan.output_symbol_, scan.label_, scan.property_, + scan.lower_bound_, std::experimental::nullopt, + scan.graph_view_); } else { // Case 1.b) new_scan = std::make_shared( - scan.input(), scan.output_symbol(), scan.label(), - scan.graph_view()); + scan.input(), scan.output_symbol_, scan.label_, + scan.graph_view_); } } } @@ -244,18 +244,18 @@ class IndependentSubtreeFinder : public DistributedOperatorVisitor { prev_ops_.pop_back(); if (branch_.subtree) return true; UsedSymbolsCollector collector(*symbol_table_); - scan.expression()->Accept(collector); + scan.expression_->Accept(collector); if (auto found = ContainsForbidden(collector.symbols_)) { // Split to ScanAllByLabel + Filter on property auto subtree = std::make_shared( - scan.input(), scan.output_symbol(), scan.label(), scan.graph_view()); + scan.input(), scan.output_symbol_, scan.label_, scan.graph_view_); auto ident = storage_->Create( - scan.output_symbol().name(), scan.output_symbol().user_declared()); - (*symbol_table_)[*ident] = scan.output_symbol(); + scan.output_symbol_.name(), scan.output_symbol_.user_declared()); + (*symbol_table_)[*ident] = scan.output_symbol_; auto prop_lookup = - storage_->Create(ident, "", scan.property()); + storage_->Create(ident, "", scan.property_); auto prop_equal = - storage_->Create(prop_lookup, scan.expression()); + storage_->Create(prop_lookup, scan.expression_); auto parent = std::make_shared(subtree, prop_equal); SetBranch(subtree, parent.get(), *found); if (prev_ops_.empty()) { @@ -274,15 +274,15 @@ class IndependentSubtreeFinder : public DistributedOperatorVisitor { bool PostVisit(DistributedExpand &exp) override { prev_ops_.pop_back(); if (branch_.subtree) return true; - if (auto found = FindForbidden(exp.input_symbol())) { + if (auto found = FindForbidden(exp.input_symbol_)) { SetBranch(exp.input(), &exp, *found); } - if (exp.existing_node()) { - if (auto found = FindForbidden(exp.node_symbol())) { + if (exp.existing_node_) { + if (auto found = FindForbidden(exp.node_symbol_)) { SetBranch(exp.input(), &exp, *found); } } - CHECK(!FindForbidden(exp.edge_symbol())) + CHECK(!FindForbidden(exp.edge_symbol_)) << "Expand uses an already used edge symbol."; return true; } @@ -294,44 +294,44 @@ class IndependentSubtreeFinder : public DistributedOperatorVisitor { bool PostVisit(ExpandVariable &exp) override { prev_ops_.pop_back(); if (branch_.subtree) return true; - if (auto found = FindForbidden(exp.input_symbol())) { + if (auto found = FindForbidden(exp.input_symbol_)) { SetBranch(exp.input(), &exp, *found); } - if (exp.existing_node()) { - if (auto found = FindForbidden(exp.node_symbol())) { + if (exp.existing_node_) { + if (auto found = FindForbidden(exp.node_symbol_)) { SetBranch(exp.input(), &exp, *found); } } - CHECK(!FindForbidden(exp.edge_symbol())) + CHECK(!FindForbidden(exp.edge_symbol_)) << "Expand uses an already used edge symbol."; // Check for bounding expressions. - if (exp.lower_bound()) { + if (exp.lower_bound_) { UsedSymbolsCollector collector(*symbol_table_); - exp.lower_bound()->Accept(collector); + exp.lower_bound_->Accept(collector); if (auto found = ContainsForbidden(collector.symbols_)) { SetBranch(exp.input(), &exp, *found); } } - if (exp.upper_bound()) { + if (exp.upper_bound_) { UsedSymbolsCollector collector(*symbol_table_); - exp.upper_bound()->Accept(collector); + exp.upper_bound_->Accept(collector); if (auto found = ContainsForbidden(collector.symbols_)) { SetBranch(exp.input(), &exp, *found); } } // Check for lambda expressions - if (exp.filter_lambda().expression) { + if (exp.filter_lambda_.expression) { UsedSymbolsCollector collector(*symbol_table_); - exp.filter_lambda().expression->Accept(collector); + exp.filter_lambda_.expression->Accept(collector); if (auto found = ContainsForbidden(collector.symbols_)) { SetBranch(exp.input(), &exp, *found); } } - if (exp.weight_lambda()) { - CHECK(exp.weight_lambda()->expression) + if (exp.weight_lambda_) { + CHECK(exp.weight_lambda_->expression) << "Unexpected nullptr expression in lambda"; UsedSymbolsCollector collector(*symbol_table_); - exp.weight_lambda()->expression->Accept(collector); + exp.weight_lambda_->expression->Accept(collector); if (auto found = ContainsForbidden(collector.symbols_)) { SetBranch(exp.input(), &exp, *found); } @@ -346,35 +346,35 @@ class IndependentSubtreeFinder : public DistributedOperatorVisitor { bool PostVisit(DistributedExpandBfs &exp) override { prev_ops_.pop_back(); if (branch_.subtree) return true; - if (auto found = FindForbidden(exp.input_symbol())) { + if (auto found = FindForbidden(exp.input_symbol_)) { SetBranch(exp.input(), &exp, *found); } - if (exp.existing_node()) { - if (auto found = FindForbidden(exp.node_symbol())) { + if (exp.existing_node_) { + if (auto found = FindForbidden(exp.node_symbol_)) { SetBranch(exp.input(), &exp, *found); } } - CHECK(!FindForbidden(exp.edge_symbol())) + CHECK(!FindForbidden(exp.edge_symbol_)) << "Expand uses an already used edge symbol."; // Check for bounding expressions. - if (exp.lower_bound()) { + if (exp.lower_bound_) { UsedSymbolsCollector collector(*symbol_table_); - exp.lower_bound()->Accept(collector); + exp.lower_bound_->Accept(collector); if (auto found = ContainsForbidden(collector.symbols_)) { SetBranch(exp.input(), &exp, *found); } } - if (exp.upper_bound()) { + if (exp.upper_bound_) { UsedSymbolsCollector collector(*symbol_table_); - exp.upper_bound()->Accept(collector); + exp.upper_bound_->Accept(collector); if (auto found = ContainsForbidden(collector.symbols_)) { SetBranch(exp.input(), &exp, *found); } } // Check for lambda expressions - if (exp.filter_lambda().expression) { + if (exp.filter_lambda_.expression) { UsedSymbolsCollector collector(*symbol_table_); - exp.filter_lambda().expression->Accept(collector); + exp.filter_lambda_.expression->Accept(collector); if (auto found = ContainsForbidden(collector.symbols_)) { SetBranch(exp.input(), &exp, *found); } @@ -389,10 +389,10 @@ class IndependentSubtreeFinder : public DistributedOperatorVisitor { bool PostVisit(ExpandUniquenessFilter &op) override { prev_ops_.pop_back(); if (branch_.subtree) return true; - if (auto found = FindForbidden(op.expand_symbol())) { + if (auto found = FindForbidden(op.expand_symbol_)) { SetBranch(op.input(), &op, *found); } - if (auto found = ContainsForbidden(op.previous_symbols())) { + if (auto found = ContainsForbidden(op.previous_symbols_)) { SetBranch(op.input(), &op, *found); } return true; @@ -405,7 +405,7 @@ class IndependentSubtreeFinder : public DistributedOperatorVisitor { bool PostVisit(ConstructNamedPath &op) override { prev_ops_.pop_back(); if (branch_.subtree) return true; - if (auto found = ContainsForbidden(op.path_elements())) { + if (auto found = ContainsForbidden(op.path_elements_)) { SetBranch(op.input(), &op, *found); } return true; @@ -419,7 +419,7 @@ class IndependentSubtreeFinder : public DistributedOperatorVisitor { prev_ops_.pop_back(); if (branch_.subtree) return true; UsedSymbolsCollector collector(*symbol_table_); - op.expression()->Accept(collector); + op.expression_->Accept(collector); if (auto found = ContainsForbidden(collector.symbols_)) { SetBranch(op.input(), &op, *found); } @@ -433,7 +433,7 @@ class IndependentSubtreeFinder : public DistributedOperatorVisitor { bool PostVisit(Produce &produce) override { prev_ops_.pop_back(); if (branch_.subtree) return true; - for (auto *named_expr : produce.named_expressions()) { + for (auto *named_expr : produce.named_expressions_) { UsedSymbolsCollector collector(*symbol_table_); named_expr->expression_->Accept(collector); if (auto found = ContainsForbidden(collector.symbols_)) { @@ -453,7 +453,7 @@ class IndependentSubtreeFinder : public DistributedOperatorVisitor { prev_ops_.pop_back(); if (branch_.subtree) return true; auto optional_branch = FindIndependentSubtree( - optional.optional(), forbidden_symbols_, symbol_table_, storage_); + optional.optional_, forbidden_symbols_, symbol_table_, storage_); if (optional_branch.depends_on) { SetBranch(optional.input(), &optional, *optional_branch.depends_on); } @@ -468,7 +468,7 @@ class IndependentSubtreeFinder : public DistributedOperatorVisitor { prev_ops_.pop_back(); if (branch_.subtree) return true; UsedSymbolsCollector collector(*symbol_table_); - unwind.input_expression()->Accept(collector); + unwind.input_expression_->Accept(collector); if (auto found = ContainsForbidden(collector.symbols_)) { SetBranch(unwind.input(), &unwind, *found); } @@ -485,8 +485,8 @@ class IndependentSubtreeFinder : public DistributedOperatorVisitor { } bool PostVisit(DistributedCreateNode &op) override { prev_ops_.pop_back(); - CHECK(!FindForbidden(symbol_table_->at(*(op.node_atom()->identifier_)))); - for (auto &kv : op.node_atom()->properties_) { + CHECK(!FindForbidden(symbol_table_->at(*(op.node_atom_->identifier_)))); + for (auto &kv : op.node_atom_->properties_) { UsedSymbolsCollector collector(*symbol_table_); kv.second->Accept(collector); CHECK(!ContainsForbidden(collector.symbols_)); @@ -500,15 +500,15 @@ class IndependentSubtreeFinder : public DistributedOperatorVisitor { } bool PostVisit(DistributedCreateExpand &op) override { prev_ops_.pop_back(); - CHECK(!FindForbidden(op.input_symbol())); - CHECK(!FindForbidden(symbol_table_->at(*(op.node_atom()->identifier_)))); - CHECK(!FindForbidden(symbol_table_->at(*(op.edge_atom()->identifier_)))); - for (auto &kv : op.node_atom()->properties_) { + CHECK(!FindForbidden(op.input_symbol_)); + CHECK(!FindForbidden(symbol_table_->at(*(op.node_atom_->identifier_)))); + CHECK(!FindForbidden(symbol_table_->at(*(op.edge_atom_->identifier_)))); + for (auto &kv : op.node_atom_->properties_) { UsedSymbolsCollector collector(*symbol_table_); kv.second->Accept(collector); CHECK(!ContainsForbidden(collector.symbols_)); } - for (auto &kv : op.edge_atom()->properties_) { + for (auto &kv : op.edge_atom_->properties_) { UsedSymbolsCollector collector(*symbol_table_); kv.second->Accept(collector); CHECK(!ContainsForbidden(collector.symbols_)); @@ -522,7 +522,7 @@ class IndependentSubtreeFinder : public DistributedOperatorVisitor { } bool PostVisit(Delete &op) override { prev_ops_.pop_back(); - for (auto *expr : op.expressions()) { + for (auto *expr : op.expressions_) { UsedSymbolsCollector collector(*symbol_table_); expr->Accept(collector); CHECK(!ContainsForbidden(collector.symbols_)); @@ -537,8 +537,8 @@ class IndependentSubtreeFinder : public DistributedOperatorVisitor { bool PostVisit(SetProperty &op) override { prev_ops_.pop_back(); UsedSymbolsCollector collector(*symbol_table_); - op.lhs()->Accept(collector); - op.rhs()->Accept(collector); + op.lhs_->Accept(collector); + op.rhs_->Accept(collector); CHECK(!ContainsForbidden(collector.symbols_)); return true; } @@ -549,9 +549,9 @@ class IndependentSubtreeFinder : public DistributedOperatorVisitor { } bool PostVisit(SetProperties &op) override { prev_ops_.pop_back(); - CHECK(!FindForbidden(op.input_symbol())); + CHECK(!FindForbidden(op.input_symbol_)); UsedSymbolsCollector collector(*symbol_table_); - op.rhs()->Accept(collector); + op.rhs_->Accept(collector); CHECK(!ContainsForbidden(collector.symbols_)); return true; } @@ -562,7 +562,7 @@ class IndependentSubtreeFinder : public DistributedOperatorVisitor { } bool PostVisit(SetLabels &op) override { prev_ops_.pop_back(); - CHECK(!FindForbidden(op.input_symbol())); + CHECK(!FindForbidden(op.input_symbol_)); return true; } @@ -573,7 +573,7 @@ class IndependentSubtreeFinder : public DistributedOperatorVisitor { bool PostVisit(RemoveProperty &op) override { prev_ops_.pop_back(); UsedSymbolsCollector collector(*symbol_table_); - op.lhs()->Accept(collector); + op.lhs_->Accept(collector); CHECK(!ContainsForbidden(collector.symbols_)); return true; } @@ -584,7 +584,7 @@ class IndependentSubtreeFinder : public DistributedOperatorVisitor { } bool PostVisit(RemoveLabels &op) override { prev_ops_.pop_back(); - CHECK(!FindForbidden(op.input_symbol())); + CHECK(!FindForbidden(op.input_symbol_)); return true; } @@ -594,14 +594,14 @@ class IndependentSubtreeFinder : public DistributedOperatorVisitor { } bool PostVisit(Aggregate &aggr) override { prev_ops_.pop_back(); - CHECK(!ContainsForbidden(aggr.remember())); - for (auto &elem : aggr.aggregations()) { + CHECK(!ContainsForbidden(aggr.remember_)); + for (auto &elem : aggr.aggregations_) { UsedSymbolsCollector collector(*symbol_table_); if (elem.value) elem.value->Accept(collector); if (elem.key) elem.key->Accept(collector); CHECK(!ContainsForbidden(collector.symbols_)); } - for (auto *expr : aggr.group_by()) { + for (auto *expr : aggr.group_by_) { UsedSymbolsCollector collector(*symbol_table_); expr->Accept(collector); CHECK(!ContainsForbidden(collector.symbols_)); @@ -616,7 +616,7 @@ class IndependentSubtreeFinder : public DistributedOperatorVisitor { bool PostVisit(Skip &skip) override { prev_ops_.pop_back(); UsedSymbolsCollector collector(*symbol_table_); - skip.expression()->Accept(collector); + skip.expression_->Accept(collector); CHECK(!ContainsForbidden(collector.symbols_)); return true; } @@ -628,7 +628,7 @@ class IndependentSubtreeFinder : public DistributedOperatorVisitor { bool PostVisit(Limit &limit) override { prev_ops_.pop_back(); UsedSymbolsCollector collector(*symbol_table_); - limit.expression()->Accept(collector); + limit.expression_->Accept(collector); CHECK(!ContainsForbidden(collector.symbols_)); return true; } @@ -639,8 +639,8 @@ class IndependentSubtreeFinder : public DistributedOperatorVisitor { } bool PostVisit(OrderBy &order_by) override { prev_ops_.pop_back(); - CHECK(!ContainsForbidden(order_by.output_symbols())); - for (auto *expr : order_by.order_by()) { + CHECK(!ContainsForbidden(order_by.output_symbols_)); + for (auto *expr : order_by.order_by_) { UsedSymbolsCollector collector(*symbol_table_); expr->Accept(collector); CHECK(!ContainsForbidden(collector.symbols_)); @@ -654,7 +654,7 @@ class IndependentSubtreeFinder : public DistributedOperatorVisitor { } bool PostVisit(Distinct &distinct) override { prev_ops_.pop_back(); - CHECK(!ContainsForbidden(distinct.value_symbols())); + CHECK(!ContainsForbidden(distinct.value_symbols_)); return true; } @@ -664,8 +664,8 @@ class IndependentSubtreeFinder : public DistributedOperatorVisitor { } bool PostVisit(Cartesian &cart) override { prev_ops_.pop_back(); - CHECK(!ContainsForbidden(cart.left_symbols()) && - !ContainsForbidden(cart.right_symbols())); + CHECK(!ContainsForbidden(cart.left_symbols_) && + !ContainsForbidden(cart.right_symbols_)); return true; } @@ -684,7 +684,7 @@ class IndependentSubtreeFinder : public DistributedOperatorVisitor { } bool PostVisit(PullRemote &pull) override { prev_ops_.pop_back(); - CHECK(!ContainsForbidden(pull.symbols())); + CHECK(!ContainsForbidden(pull.symbols_)); return true; } @@ -694,8 +694,8 @@ class IndependentSubtreeFinder : public DistributedOperatorVisitor { } bool PostVisit(PullRemoteOrderBy &pull) override { prev_ops_.pop_back(); - CHECK(!ContainsForbidden(pull.symbols())); - for (auto *expr : pull.order_by()) { + CHECK(!ContainsForbidden(pull.symbols_)); + for (auto *expr : pull.order_by_) { UsedSymbolsCollector collector(*symbol_table_); expr->Accept(collector); CHECK(!ContainsForbidden(collector.symbols_)); @@ -978,8 +978,8 @@ class DistributedPlanner : public HierarchicalLogicalOperatorVisitor { bool PostVisit(Expand &exp) override { prev_ops_.pop_back(); auto distributed_expand = std::make_unique( - exp.node_symbol(), exp.edge_symbol(), exp.direction(), exp.edge_types(), - exp.input(), exp.input_symbol(), exp.existing_node(), exp.graph_view()); + exp.node_symbol_, exp.edge_symbol_, exp.direction_, exp.edge_types_, + exp.input(), exp.input_symbol_, exp.existing_node_, exp.graph_view_); SetOnPrevious(std::move(distributed_expand)); return true; } @@ -990,12 +990,12 @@ class DistributedPlanner : public HierarchicalLogicalOperatorVisitor { } bool PostVisit(ExpandVariable &exp) override { prev_ops_.pop_back(); - if (exp.type() == EdgeAtom::Type::BREADTH_FIRST) { + if (exp.type_ == EdgeAtom::Type::BREADTH_FIRST) { auto distributed_bfs = std::make_unique( - exp.node_symbol(), exp.edge_symbol(), exp.direction(), - exp.edge_types(), exp.input(), exp.input_symbol(), - exp.existing_node(), exp.graph_view(), exp.lower_bound(), - exp.upper_bound(), exp.filter_lambda()); + exp.node_symbol_, exp.edge_symbol_, exp.direction_, + exp.edge_types_, exp.input(), exp.input_symbol_, + exp.existing_node_, exp.graph_view_, exp.lower_bound_, + exp.upper_bound_, exp.filter_lambda_); SetOnPrevious(std::move(distributed_bfs)); } return true; @@ -1046,7 +1046,7 @@ class DistributedPlanner : public HierarchicalLogicalOperatorVisitor { // Use dummy produce to simulate an end of the query, thus forcing merge // points to be planned (like Cartesian). optional_plan.master_plan = std::make_unique( - op.optional(), std::vector{}); + op.optional_, std::vector{}); // Temporary transfer symbol table and storage optional_plan.symbol_table = std::move(distributed_plan_.symbol_table); optional_plan.ast_storage = std::move(distributed_plan_.ast_storage); @@ -1070,7 +1070,7 @@ class DistributedPlanner : public HierarchicalLogicalOperatorVisitor { // we continue as normal. SetOnPrevious(std::make_unique( op.input(), optional_plan.master_plan->input(), - op.optional_symbols())); + op.optional_symbols_)); return true; } // Case 2) @@ -1095,7 +1095,7 @@ class DistributedPlanner : public HierarchicalLogicalOperatorVisitor { // on LHS symbols should have been taken care of. SetOnPrevious(std::make_unique( op.input(), optional_plan.master_plan->input(), - op.optional_symbols())); + op.optional_symbols_)); return true; } CHECK(optional_planner.ShouldSplit()); @@ -1116,7 +1116,7 @@ class DistributedPlanner : public HierarchicalLogicalOperatorVisitor { new_opt = branch.parent_start; } SetOnPrevious( - std::make_unique(op.input(), new_opt, op.optional_symbols())); + std::make_unique(op.input(), new_opt, op.optional_symbols_)); return true; } @@ -1197,8 +1197,8 @@ class DistributedPlanner : public HierarchicalLogicalOperatorVisitor { prev_ops_.pop_back(); // TODO: Associative combination of OrderBy if (ShouldSplit()) { - std::unordered_set pull_symbols(order_by.output_symbols().begin(), - order_by.output_symbols().end()); + std::unordered_set pull_symbols(order_by.output_symbols_.begin(), + order_by.output_symbols_.end()); // Pull symbols need to also include those used in order by expressions. // For example, `RETURN n AS m ORDER BY n.prop`, output symbols will // contain `m`, while we also need to pull `n`. @@ -1206,7 +1206,7 @@ class DistributedPlanner : public HierarchicalLogicalOperatorVisitor { // and sending them instead. It's possible that the evaluated expression // requires less network traffic than sending the value of the used symbol // `n` itself. - for (const auto &expr : order_by.order_by()) { + for (const auto &expr : order_by.order_by_) { UsedSymbolsCollector collector(distributed_plan_.symbol_table); expr->Accept(collector); pull_symbols.insert(collector.symbols_.begin(), @@ -1215,10 +1215,10 @@ class DistributedPlanner : public HierarchicalLogicalOperatorVisitor { // Create a copy of OrderBy but with added symbols used in expressions, so // that they can be pulled. std::vector> ordering; - ordering.reserve(order_by.order_by().size()); - for (int i = 0; i < order_by.order_by().size(); ++i) { - ordering.emplace_back(order_by.compare().ordering()[i], - order_by.order_by()[i]); + ordering.reserve(order_by.order_by_.size()); + for (int i = 0; i < order_by.order_by_.size(); ++i) { + ordering.emplace_back(order_by.compare_.ordering()[i], + order_by.order_by_[i]); } auto worker_plan = std::make_shared( order_by.input(), ordering, @@ -1281,7 +1281,7 @@ class DistributedPlanner : public HierarchicalLogicalOperatorVisitor { return true; } auto is_associative = [&aggr_op]() { - for (const auto &aggr : aggr_op.aggregations()) { + for (const auto &aggr : aggr_op.aggregations_) { switch (aggr.op) { case Aggregation::Op::COUNT: case Aggregation::Op::MIN: @@ -1298,9 +1298,9 @@ class DistributedPlanner : public HierarchicalLogicalOperatorVisitor { if (!is_associative()) { auto input = aggr_op.input(); auto pull_id = AddWorkerPlan(input); - std::unordered_set pull_symbols(aggr_op.remember().begin(), - aggr_op.remember().end()); - for (const auto &elem : aggr_op.aggregations()) { + std::unordered_set pull_symbols(aggr_op.remember_.begin(), + aggr_op.remember_.end()); + for (const auto &elem : aggr_op.aggregations_) { UsedSymbolsCollector collector(distributed_plan_.symbol_table); elem.value->Accept(collector); if (elem.key) elem.key->Accept(collector); @@ -1337,15 +1337,15 @@ class DistributedPlanner : public HierarchicalLogicalOperatorVisitor { // Aggregate uses associative operation(s), so split the work across master // and workers. std::vector master_aggrs; - master_aggrs.reserve(aggr_op.aggregations().size()); + master_aggrs.reserve(aggr_op.aggregations_.size()); std::vector worker_aggrs; - worker_aggrs.reserve(aggr_op.aggregations().size()); + worker_aggrs.reserve(aggr_op.aggregations_.size()); // We will need to create a Produce operator which moves the final results // from new (merge) symbols into old aggregation symbols, because // expressions following the aggregation expect the result in old symbols. std::vector produce_exprs; - produce_exprs.reserve(aggr_op.aggregations().size()); - for (const auto &aggr : aggr_op.aggregations()) { + produce_exprs.reserve(aggr_op.aggregations_.size()); + for (const auto &aggr : aggr_op.aggregations_) { switch (aggr.op) { // Count, like sum, only needs to sum all of the results on master. case Aggregation::Op::COUNT: @@ -1406,17 +1406,17 @@ class DistributedPlanner : public HierarchicalLogicalOperatorVisitor { } // Rewire master/worker aggregation. auto worker_plan = std::make_shared( - aggr_op.input(), worker_aggrs, aggr_op.group_by(), aggr_op.remember()); + aggr_op.input(), worker_aggrs, aggr_op.group_by_, aggr_op.remember_); auto pull_id = AddWorkerPlan(worker_plan); std::vector pull_symbols; - pull_symbols.reserve(worker_aggrs.size() + aggr_op.remember().size()); + pull_symbols.reserve(worker_aggrs.size() + aggr_op.remember_.size()); for (const auto &aggr : worker_aggrs) pull_symbols.push_back(aggr.output_sym); - for (const auto &sym : aggr_op.remember()) pull_symbols.push_back(sym); + for (const auto &sym : aggr_op.remember_) pull_symbols.push_back(sym); auto pull_op = std::make_shared(worker_plan, pull_id, pull_symbols); auto master_aggr_op = std::make_shared( - pull_op, master_aggrs, aggr_op.group_by(), aggr_op.remember()); + pull_op, master_aggrs, aggr_op.group_by_, aggr_op.remember_); // Make our master Aggregate into Produce + Aggregate auto master_plan = std::make_unique(master_aggr_op, produce_exprs); SplitOnPrevious(std::move(master_plan)); @@ -1484,10 +1484,10 @@ class DistributedPlanner : public HierarchicalLogicalOperatorVisitor { if (ShouldSplit()) { auto pull_id = AddWorkerPlan(acc.input()); pull_remote = - std::make_shared(nullptr, pull_id, acc.symbols()); + std::make_shared(nullptr, pull_id, acc.symbols_); } auto sync = std::make_unique(acc.input(), pull_remote, - acc.advance_command()); + acc.advance_command_); SetOnPrevious(std::move(sync)); on_master_ = true; needs_synchronize_ = false; @@ -1509,7 +1509,7 @@ class DistributedPlanner : public HierarchicalLogicalOperatorVisitor { // node creation to workers. bool create_on_random_worker = !ShouldSplit(); auto distributed_create = std::make_unique( - op.input(), op.node_atom(), create_on_random_worker); + op.input(), op.node_atom_, create_on_random_worker); if (prev_ops_.empty()) distributed_plan_.master_plan = std::move(distributed_create); else @@ -1528,8 +1528,8 @@ class DistributedPlanner : public HierarchicalLogicalOperatorVisitor { Split(op, PlanCartesian(op.input())); } auto distributed_create = std::make_unique( - op.node_atom(), op.edge_atom(), op.input(), op.input_symbol(), - op.existing_node()); + op.node_atom_, op.edge_atom_, op.input(), op.input_symbol_, + op.existing_node_); if (prev_ops_.empty()) distributed_plan_.master_plan = std::move(distributed_create); else diff --git a/src/query/plan/distributed_ops.cpp b/src/query/plan/distributed_ops.cpp index df165ba65..a766da6f2 100644 --- a/src/query/plan/distributed_ops.cpp +++ b/src/query/plan/distributed_ops.cpp @@ -113,8 +113,8 @@ ACCEPT_WITH_INPUT(DistributedExpand); std::vector DistributedExpand::ModifiedSymbols( const SymbolTable &table) const { auto symbols = input_->ModifiedSymbols(table); - symbols.emplace_back(node_symbol()); - symbols.emplace_back(edge_symbol()); + symbols.emplace_back(node_symbol_); + symbols.emplace_back(edge_symbol_); return symbols; } @@ -135,8 +135,8 @@ ACCEPT_WITH_INPUT(DistributedExpandBfs); std::vector DistributedExpandBfs::ModifiedSymbols( const SymbolTable &table) const { auto symbols = input_->ModifiedSymbols(table); - symbols.emplace_back(node_symbol()); - symbols.emplace_back(edge_symbol()); + symbols.emplace_back(node_symbol_); + symbols.emplace_back(edge_symbol_); return symbols; } @@ -367,7 +367,7 @@ class PullRemoteCursor : public Cursor { remote_puller_( // TODO: Pass in a Master GraphDb. &dynamic_cast(&db.db())->pull_clients(), db, - self.symbols(), self.plan_id(), command_id_) {} + self.symbols_, self.plan_id_, command_id_) {} bool Pull(Frame &frame, Context &context) override { if (context.db_accessor_.should_abort()) throw HintedAbortError(); @@ -403,14 +403,14 @@ class PullRemoteCursor : public Cursor { if (input_cursor_ && input_cursor_->Pull(frame, context)) { VLOG(10) << "[PullRemoteCursor] [" << context.db_accessor_.transaction_id() << "] [" - << self_.plan_id() << "] [" << command_id_ + << self_.plan_id_ << "] [" << command_id_ << "] producing local results "; return true; } VLOG(10) << "[PullRemoteCursor] [" << context.db_accessor_.transaction_id() << "] [" - << self_.plan_id() << "] [" << command_id_ + << self_.plan_id_ << "] [" << command_id_ << "] no results available, sleeping "; // If there aren't any local/remote results available, sleep. std::this_thread::sleep_for( @@ -423,7 +423,7 @@ class PullRemoteCursor : public Cursor { if (input_cursor_ && input_cursor_->Pull(frame, context)) { VLOG(10) << "[PullRemoteCursor] [" << context.db_accessor_.transaction_id() << "] [" - << self_.plan_id() << "] [" << command_id_ + << self_.plan_id_ << "] [" << command_id_ << "] producing local results "; return true; } @@ -434,11 +434,11 @@ class PullRemoteCursor : public Cursor { int worker_id = remote_puller_.GetWorkerId(last_pulled_worker_id_index_); VLOG(10) << "[PullRemoteCursor] [" << context.db_accessor_.transaction_id() << "] [" - << self_.plan_id() << "] [" << command_id_ + << self_.plan_id_ << "] [" << command_id_ << "] producing results from worker " << worker_id; auto result = remote_puller_.PopResultFromWorker(worker_id); - for (size_t i = 0; i < self_.symbols().size(); ++i) { - frame[self_.symbols()[i]] = std::move(result[i]); + for (size_t i = 0; i < self_.symbols_.size(); ++i) { + frame[self_.symbols_[i]] = std::move(result[i]); } } return true; @@ -478,7 +478,7 @@ class SynchronizeCursor : public Cursor { &dynamic_cast(&db.db())->updates_server()), input_cursor_(self.input()->MakeCursor(db)), pull_remote_cursor_( - self.pull_remote() ? self.pull_remote()->MakeCursor(db) : nullptr), + self.pull_remote_ ? self.pull_remote_->MakeCursor(db) : nullptr), command_id_(db.transaction().cid()), master_id_( // TODO: Pass in a Master GraphDb. @@ -496,7 +496,7 @@ class SynchronizeCursor : public Cursor { << "] producing local results"; auto &result = local_frames_.back(); for (size_t i = 0; i < frame.elems().size(); ++i) { - if (self_.advance_command()) { + if (self_.advance_command_) { query::ReconstructTypedValue(result[i]); } frame.elems()[i] = std::move(result[i]); @@ -550,9 +550,9 @@ class SynchronizeCursor : public Cursor { for (auto worker_id : pull_clients_->GetWorkerIds()) { if (worker_id == master_id_) continue; worker_accumulations.emplace_back(pull_clients_->Pull( - &context.db_accessor_, worker_id, self_.pull_remote()->plan_id(), + &context.db_accessor_, worker_id, self_.pull_remote_->plan_id_, command_id_, context.evaluation_context_, - self_.pull_remote()->symbols(), true, 0)); + self_.pull_remote_->symbols_, true, 0)); } } @@ -601,7 +601,7 @@ class SynchronizeCursor : public Cursor { } } - if (self_.advance_command()) { + if (self_.advance_command_) { context.db_accessor_.AdvanceCommand(); } @@ -628,7 +628,7 @@ class SynchronizeCursor : public Cursor { } // If the command advanced, let the workers know. - if (self_.advance_command()) { + if (self_.advance_command_) { auto futures = pull_clients_->NotifyAllTransactionCommandAdvanced(tx_id); for (auto &future : futures) future.get(); } @@ -645,7 +645,7 @@ class PullRemoteOrderByCursor : public Cursor { remote_puller_( // TODO: Pass in a Master GraphDb. &dynamic_cast(&db.db())->pull_clients(), db, - self.symbols(), self.plan_id(), command_id_) {} + self.symbols_, self.plan_id_, command_id_) {} bool Pull(Frame &frame, Context &context) override { if (context.db_accessor_.should_abort()) throw HintedAbortError(); @@ -655,8 +655,8 @@ class PullRemoteOrderByCursor : public Cursor { auto evaluate_result = [this, &evaluator]() { std::vector order_by; - order_by.reserve(self_.order_by().size()); - for (auto expression_ptr : self_.order_by()) { + order_by.reserve(self_.order_by_.size()); + for (auto expression_ptr : self_.order_by_) { order_by.emplace_back(expression_ptr->Accept(evaluator)); } return order_by; @@ -665,14 +665,14 @@ class PullRemoteOrderByCursor : public Cursor { auto restore_frame = [&frame, this](const std::vector &restore_from) { for (size_t i = 0; i < restore_from.size(); ++i) { - frame[self_.symbols()[i]] = restore_from[i]; + frame[self_.symbols_[i]] = restore_from[i]; } }; if (!merge_initialized_) { VLOG(10) << "[PullRemoteOrderBy] [" << context.db_accessor_.transaction_id() << "] [" - << self_.plan_id() << "] [" << command_id_ << "] initialize"; + << self_.plan_id_ << "] [" << command_id_ << "] initialize"; remote_puller_.Initialize(context); missing_results_from_ = remote_puller_.Workers(); missing_master_result_ = true; @@ -682,8 +682,8 @@ class PullRemoteOrderByCursor : public Cursor { if (missing_master_result_) { if (input_->Pull(frame, context)) { std::vector output; - output.reserve(self_.symbols().size()); - for (const Symbol &symbol : self_.symbols()) { + output.reserve(self_.symbols_.size()); + for (const Symbol &symbol : self_.symbols_) { output.emplace_back(frame[symbol]); } @@ -709,7 +709,7 @@ class PullRemoteOrderByCursor : public Cursor { if (!has_all_result) { VLOG(10) << "[PullRemoteOrderByCursor] [" << context.db_accessor_.transaction_id() << "] [" - << self_.plan_id() << "] [" << command_id_ + << self_.plan_id_ << "] [" << command_id_ << "] missing results, sleep"; // If we don't have results from all workers, sleep before continuing. std::this_thread::sleep_for( @@ -734,7 +734,7 @@ class PullRemoteOrderByCursor : public Cursor { auto result_it = std::min_element( merge_.begin(), merge_.end(), [this](const auto &lhs, const auto &rhs) { - return self_.compare()(lhs.order_by, rhs.order_by); + return self_.compare_(lhs.order_by, rhs.order_by); }); restore_frame(result_it->remote_result); @@ -742,14 +742,14 @@ class PullRemoteOrderByCursor : public Cursor { if (result_it->worker_id) { VLOG(10) << "[PullRemoteOrderByCursor] [" << context.db_accessor_.transaction_id() << "] [" - << self_.plan_id() << "] [" << command_id_ + << self_.plan_id_ << "] [" << command_id_ << "] producing results from worker " << result_it->worker_id.value(); missing_results_from_.push_back(result_it->worker_id.value()); } else { VLOG(10) << "[PullRemoteOrderByCursor] [" << context.db_accessor_.transaction_id() << "] [" - << self_.plan_id() << "] [" << command_id_ + << self_.plan_id_ << "] [" << command_id_ << "] producing local results"; missing_master_result_ = true; } @@ -799,13 +799,13 @@ class DistributedExpandCursor : public query::plan::Cursor { // A helper function for expanding a node from an edge. auto pull_node = [this, &frame](const EdgeAccessor &new_edge, EdgeAtom::Direction direction) { - if (self_->existing_node()) return; + if (self_->existing_node_) return; switch (direction) { case EdgeAtom::Direction::IN: - frame[self_->node_symbol()] = new_edge.from(); + frame[self_->node_symbol_] = new_edge.from(); break; case EdgeAtom::Direction::OUT: - frame[self_->node_symbol()] = new_edge.to(); + frame[self_->node_symbol_] = new_edge.to(); break; case EdgeAtom::Direction::BOTH: LOG(FATAL) << "Must indicate exact expansion direction here"; @@ -833,8 +833,8 @@ class DistributedExpandCursor : public query::plan::Cursor { auto put_future_edge_on_frame = [this, &frame](auto &future) { auto edge_to = future.edge_to.get(); frame.elems() = future.frame_elems; - frame[self_->edge_symbol()] = edge_to.first; - frame[self_->node_symbol()] = edge_to.second; + frame[self_->edge_symbol_] = edge_to.first; + frame[self_->node_symbol_] = edge_to.second; }; while (true) { @@ -863,8 +863,8 @@ class DistributedExpandCursor : public query::plan::Cursor { // attempt to get a value from the incoming edges if (in_edges_ && *in_edges_it_ != in_edges_->end()) { auto edge = *(*in_edges_it_)++; - if (edge.address().is_local() || self_->existing_node()) { - frame[self_->edge_symbol()] = edge; + if (edge.address().is_local() || self_->existing_node_) { + frame[self_->edge_symbol_] = edge; pull_node(edge, EdgeAtom::Direction::IN); return true; } else { @@ -879,10 +879,10 @@ class DistributedExpandCursor : public query::plan::Cursor { // when expanding in EdgeAtom::Direction::BOTH directions // we should do only one expansion for cycles, and it was // already done in the block above - if (self_->direction() == EdgeAtom::Direction::BOTH && edge.is_cycle()) + if (self_->direction_ == EdgeAtom::Direction::BOTH && edge.is_cycle()) continue; - if (edge.address().is_local() || self_->existing_node()) { - frame[self_->edge_symbol()] = edge; + if (edge.address().is_local() || self_->existing_node_) { + frame[self_->edge_symbol_] = edge; pull_node(edge, EdgeAtom::Direction::OUT); return true; } else { @@ -945,46 +945,46 @@ class DistributedExpandCursor : public query::plan::Cursor { // In those cases we skip that input pull and continue with the next. while (true) { if (!input_cursor_->Pull(frame, context)) return false; - TypedValue &vertex_value = frame[self_->input_symbol()]; + TypedValue &vertex_value = frame[self_->input_symbol_]; // Null check due to possible failed optional match. if (vertex_value.IsNull()) continue; - ExpectType(self_->input_symbol(), vertex_value, TypedValue::Type::Vertex); + ExpectType(self_->input_symbol_, vertex_value, TypedValue::Type::Vertex); auto &vertex = vertex_value.Value(); - SwitchAccessor(vertex, self_->graph_view()); + SwitchAccessor(vertex, self_->graph_view_); - auto direction = self_->direction(); + auto direction = self_->direction_; if (direction == EdgeAtom::Direction::IN || direction == EdgeAtom::Direction::BOTH) { - if (self_->existing_node()) { - TypedValue &existing_node = frame[self_->node_symbol()]; + if (self_->existing_node_) { + TypedValue &existing_node = frame[self_->node_symbol_]; // old_node_value may be Null when using optional matching if (!existing_node.IsNull()) { - ExpectType(self_->node_symbol(), existing_node, + ExpectType(self_->node_symbol_, existing_node, TypedValue::Type::Vertex); in_edges_.emplace( - vertex.in(existing_node.ValueVertex(), &self_->edge_types())); + vertex.in(existing_node.ValueVertex(), &self_->edge_types_)); } } else { - in_edges_.emplace(vertex.in(&self_->edge_types())); + in_edges_.emplace(vertex.in(&self_->edge_types_)); } in_edges_it_.emplace(in_edges_->begin()); } if (direction == EdgeAtom::Direction::OUT || direction == EdgeAtom::Direction::BOTH) { - if (self_->existing_node()) { - TypedValue &existing_node = frame[self_->node_symbol()]; + if (self_->existing_node_) { + TypedValue &existing_node = frame[self_->node_symbol_]; // old_node_value may be Null when using optional matching if (!existing_node.IsNull()) { - ExpectType(self_->node_symbol(), existing_node, + ExpectType(self_->node_symbol_, existing_node, TypedValue::Type::Vertex); out_edges_.emplace( - vertex.out(existing_node.ValueVertex(), &self_->edge_types())); + vertex.out(existing_node.ValueVertex(), &self_->edge_types_)); } } else { - out_edges_.emplace(vertex.out(&self_->edge_types())); + out_edges_.emplace(vertex.out(&self_->edge_types_)); } out_edges_it_.emplace(out_edges_->begin()); } @@ -1030,8 +1030,8 @@ class DistributedExpandBfsCursor : public query::plan::Cursor { } CHECK(bfs_subcursor_clients_); subcursor_ids_ = bfs_subcursor_clients_->CreateBfsSubcursors( - db_.transaction_id(), self_.direction(), self_.edge_types(), - self_.graph_view()); + db_.transaction_id(), self_.direction_, self_.edge_types_, + self_.graph_view_); bfs_subcursor_clients_->RegisterSubcursors(subcursor_ids_); VLOG(10) << "BFS subcursors initialized"; pull_pos_ = subcursor_ids_.end(); @@ -1044,14 +1044,14 @@ class DistributedExpandBfsCursor : public query::plan::Cursor { bool Pull(Frame &frame, Context &context) override { // TODO(mtomic): lambda filtering in distributed - if (self_.filter_lambda().expression) { + if (self_.filter_lambda_.expression) { throw utils::NotYetImplemented("lambda filtering in distributed BFS"); } // Evaluator for the filtering condition and expansion depth. ExpressionEvaluator evaluator(&frame, context.symbol_table_, context.evaluation_context_, - &context.db_accessor_, self_.graph_view()); + &context.db_accessor_, self_.graph_view_); while (true) { if (context.db_accessor_.should_abort()) throw HintedAbortError(); @@ -1064,7 +1064,7 @@ class DistributedExpandBfsCursor : public query::plan::Cursor { pull_pos_->second, &db_); if (vertex) { last_vertex = *vertex; - SwitchAccessor(last_vertex.ValueVertex(), self_.graph_view()); + SwitchAccessor(last_vertex.ValueVertex(), self_.graph_view_); break; } VLOG(10) << "Nothing to pull from " << pull_pos_->first; @@ -1073,15 +1073,15 @@ class DistributedExpandBfsCursor : public query::plan::Cursor { if (last_vertex.IsVertex()) { // Handle existence flag - if (self_.existing_node()) { - TypedValue &node = frame[self_.node_symbol()]; + if (self_.existing_node_) { + TypedValue &node = frame[self_.node_symbol_]; // Due to optional matching the existing node could be null if (node.IsNull() || (node != last_vertex).ValueBool()) continue; // There is no point in traversing the rest of the graph because BFS // can find only one path to a certain node. skip_rest_ = true; } else { - frame[self_.node_symbol()] = last_vertex; + frame[self_.node_symbol_] = last_vertex; } VLOG(10) << "Expanded to vertex: " << last_vertex; @@ -1116,8 +1116,8 @@ class DistributedExpandBfsCursor : public query::plan::Cursor { } std::reverse(edges.begin(), edges.end()); for (auto &edge : edges) - SwitchAccessor(edge.ValueEdge(), self_.graph_view()); - frame[self_.edge_symbol()] = std::move(edges); + SwitchAccessor(edge.ValueEdge(), self_.graph_view_); + frame[self_.edge_symbol_] = std::move(edges); return true; } @@ -1139,18 +1139,18 @@ class DistributedExpandBfsCursor : public query::plan::Cursor { // We're done with this source, try getting a new one if (!input_cursor_->Pull(frame, context)) return false; - auto vertex_value = frame[self_.input_symbol()]; + auto vertex_value = frame[self_.input_symbol_]; // It is possible that the vertex is Null due to optional matching. if (vertex_value.IsNull()) continue; auto vertex = vertex_value.ValueVertex(); - lower_bound_ = self_.lower_bound() - ? EvaluateInt(&evaluator, self_.lower_bound(), + lower_bound_ = self_.lower_bound_ + ? EvaluateInt(&evaluator, self_.lower_bound_, "Min depth in breadth-first expansion") : 1; - upper_bound_ = self_.upper_bound() - ? EvaluateInt(&evaluator, self_.upper_bound(), + upper_bound_ = self_.upper_bound_ + ? EvaluateInt(&evaluator, self_.upper_bound_, "Max depth in breadth-first expansion") : std::numeric_limits::max(); skip_rest_ = false; @@ -1257,8 +1257,8 @@ class DistributedCreateNodeCursor : public query::plan::Cursor { : input_cursor_(self->input()->MakeCursor(*dba)), // TODO: Replace this with some other mechanism db_(dynamic_cast(&dba->db())), - node_atom_(self->node_atom()), - on_random_worker_(self->on_random_worker()) { + node_atom_(self->node_atom_), + on_random_worker_(self->on_random_worker_) { CHECK(db_); CHECK(node_atom_); } @@ -1301,8 +1301,8 @@ class DistributedCreateExpandCursor : public query::plan::Cursor { if (!input_cursor_->Pull(frame, context)) return false; // get the origin vertex - TypedValue &vertex_value = frame[self_->input_symbol()]; - ExpectType(self_->input_symbol(), vertex_value, TypedValue::Type::Vertex); + TypedValue &vertex_value = frame[self_->input_symbol_]; + ExpectType(self_->input_symbol_, vertex_value, TypedValue::Type::Vertex); auto &v1 = vertex_value.Value(); // Similarly to CreateNode, newly created edges and nodes should use the @@ -1319,7 +1319,7 @@ class DistributedCreateExpandCursor : public query::plan::Cursor { auto *dba = &context.db_accessor_; // create an edge between the two nodes - switch (self_->edge_atom()->direction_) { + switch (self_->edge_atom_->direction_) { case EdgeAtom::Direction::IN: CreateEdge(&v2, &v1, &frame, context.symbol_table_, &evaluator, dba); break; @@ -1342,14 +1342,14 @@ class DistributedCreateExpandCursor : public query::plan::Cursor { void Reset() override { input_cursor_->Reset(); } VertexAccessor &OtherVertex(int worker_id, Frame &frame, Context &context) { - if (self_->existing_node()) { + if (self_->existing_node_) { const auto &dest_node_symbol = - context.symbol_table_.at(*self_->node_atom()->identifier_); + context.symbol_table_.at(*self_->node_atom_->identifier_); TypedValue &dest_node_value = frame[dest_node_symbol]; ExpectType(dest_node_symbol, dest_node_value, TypedValue::Type::Vertex); return dest_node_value.Value(); } else { - return CreateVertexOnWorker(worker_id, self_->node_atom(), frame, + return CreateVertexOnWorker(worker_id, self_->node_atom_, frame, context); } } @@ -1359,10 +1359,10 @@ class DistributedCreateExpandCursor : public query::plan::Cursor { ExpressionEvaluator *evaluator, database::GraphDbAccessor *dba) { EdgeAccessor edge = - dba->InsertEdge(*from, *to, self_->edge_atom()->edge_types_[0]); - for (auto kv : self_->edge_atom()->properties_) + dba->InsertEdge(*from, *to, self_->edge_atom_->edge_types_[0]); + for (auto kv : self_->edge_atom_->properties_) PropsSetChecked(&edge, kv.first.second, kv.second->Accept(*evaluator)); - (*frame)[symbol_table.at(*self_->edge_atom()->identifier_)] = edge; + (*frame)[symbol_table.at(*self_->edge_atom_->identifier_)] = edge; } private: diff --git a/src/query/plan/distributed_ops.lcp b/src/query/plan/distributed_ops.lcp index c4fc76bd4..0e725ee45 100644 --- a/src/query/plan/distributed_ops.lcp +++ b/src/query/plan/distributed_ops.lcp @@ -3,7 +3,9 @@ #pragma once +#include "query/plan/distributed_ops.capnp.h" #include "query/plan/operator.hpp" + cpp<# (load "query/plan/operator.lcp") @@ -46,11 +48,11 @@ class DistributedOperatorVisitor : public virtual HierarchicalLogicalOperatorVis cpp<# (lcp:define-class pull-remote (logical-operator) - ((input "std::shared_ptr" + ((input "std::shared_ptr" :scope :public :capnp-save #'save-operator-pointer :capnp-load #'load-operator-pointer) - (plan-id :int64_t :initval 0 :reader t) - (symbols "std::vector" :reader t + (plan-id :int64_t :initval 0 :scope :public) + (symbols "std::vector" :scope :public :capnp-save (lcp:capnp-save-vector "::query::capnp::Symbol" "Symbol") :capnp-load (lcp:capnp-load-vector "::query::capnp::Symbol" "Symbol"))) (:documentation @@ -62,6 +64,7 @@ This operator aims to yield results as fast as possible and lose minimal time on data transfer. It gives no guarantees on result order.") (:public #>cpp + PullRemote() {} PullRemote(const std::shared_ptr &input, int64_t plan_id, const std::vector &symbols) : input_(input), plan_id_(plan_id), symbols_(symbols) {} @@ -77,28 +80,28 @@ time on data transfer. It gives no guarantees on result order.") input_ = input; } cpp<#) - (:private #>cpp PullRemote() {} cpp<#) (:serialize :capnp)) -(defun load-pull-remote (reader member-name) +(defun load-pull-remote (reader member-name capnp-name) + (declare (ignore capnp-name)) #>cpp ${member-name} = std::static_pointer_cast( utils::LoadSharedPtr(${reader}, [helper](const auto &reader) { - auto op = LogicalOperator::Construct(reader); - op->Load(reader, helper); + std::unique_ptr op; + Load(&op, reader, helper); return op.release(); }, &helper->loaded_ops)); cpp<#) (lcp:define-class synchronize (logical-operator) - ((input "std::shared_ptr" + ((input "std::shared_ptr" :scope :public :capnp-save #'save-operator-pointer :capnp-load #'load-operator-pointer) - (pull-remote "std::shared_ptr" :reader t + (pull-remote "std::shared_ptr" :scope :public :capnp-save #'save-operator-pointer :capnp-load #'load-pull-remote) - (advance-command :bool :initval "false" :reader t)) + (advance-command :bool :initval "false" :scope :public)) (:documentation "Operator used to synchronize stages of plan execution between the master and all the workers. Synchronization is necessary in queries that update that @@ -119,6 +122,7 @@ Logic of the synchronize operator is: 8. Yield all the results, first local, then from Pull if available.") (:public #>cpp + Synchronize() {} Synchronize(const std::shared_ptr &input, const std::shared_ptr &pull_remote, bool advance_command) @@ -141,22 +145,21 @@ Logic of the synchronize operator is: input_ = input; } cpp<#) - (:private #>cpp Synchronize() {} cpp<#) (:serialize :capnp)) (lcp:define-class pull-remote-order-by (logical-operator) - ((input "std::shared_ptr" + ((input "std::shared_ptr" :scope :public :capnp-save #'save-operator-pointer :capnp-load #'load-operator-pointer) - (plan-id :int64_t :initval 0 :reader t) - (symbols "std::vector" :reader t + (plan-id :int64_t :initval 0 :scope :public) + (symbols "std::vector" :scope :public :capnp-save (lcp:capnp-save-vector "::query::capnp::Symbol" "Symbol") :capnp-load (lcp:capnp-load-vector "::query::capnp::Symbol" "Symbol")) - (order-by "std::vector" :reader t + (order-by "std::vector" :scope :public :capnp-type "List(Ast.Tree)" :capnp-save (save-ast-vector "Expression *") :capnp-load (load-ast-vector "Expression *")) - (compare "TypedValueVectorCompare" :reader t + (compare "TypedValueVectorCompare" :scope :public :capnp-type "Common.TypedValueVectorCompare")) (:documentation "Operator that merges distributed OrderBy operators. @@ -166,24 +169,24 @@ have the master rely on the fact that the results are ordered and merge them by having only one result from each worker.") (:public #>cpp - PullRemoteOrderBy( - const std::shared_ptr &input, int64_t plan_id, - const std::vector> &order_by, - const std::vector &symbols); - bool Accept(HierarchicalLogicalOperatorVisitor &visitor) override; - std::unique_ptr MakeCursor( - database::GraphDbAccessor &db) const override; + PullRemoteOrderBy() {} + PullRemoteOrderBy( + const std::shared_ptr &input, int64_t plan_id, + const std::vector> &order_by, + const std::vector &symbols); + bool Accept(HierarchicalLogicalOperatorVisitor &visitor) override; + std::unique_ptr MakeCursor( + database::GraphDbAccessor &db) const override; - std::vector ModifiedSymbols(const SymbolTable &) const override; - std::vector OutputSymbols(const SymbolTable &) const override; + std::vector ModifiedSymbols(const SymbolTable &) const override; + std::vector OutputSymbols(const SymbolTable &) const override; - bool HasSingleInput() const override { return true; } - std::shared_ptr input() const override { return input_; } - void set_input(std::shared_ptr input) override { - input_ = input; - } - cpp<#) - (:private #>cpp PullRemoteOrderBy() {} cpp<#) + bool HasSingleInput() const override { return true; } + std::shared_ptr input() const override { return input_; } + void set_input(std::shared_ptr input) override { + input_ = input; + } + cpp<#) (:serialize :capnp)) (lcp:define-class distributed-expand (logical-operator expand-common) @@ -207,22 +210,23 @@ by having only one result from each worker.") (:serialize :capnp :inherit-compose '(expand-common))) (lcp:define-class distributed-expand-bfs (logical-operator expand-common) - ((lower-bound "Expression *" :reader t + ((lower-bound "Expression *" :scope :public :documentation "Optional lower bound, default is 1" :capnp-type "Ast.Tree" :capnp-init nil :capnp-save #'save-ast-pointer :capnp-load (load-ast-pointer "Expression *")) - (upper-bound "Expression *" :reader t + (upper-bound "Expression *" :scope :public :documentation "Optional upper bound, default is infinity" :capnp-type "Ast.Tree" :capnp-init nil :capnp-save #'save-ast-pointer :capnp-load (load-ast-pointer "Expression *")) - (filter-lambda "ExpandVariable::Lambda" :reader t + (filter-lambda "ExpandVariable::Lambda" :scope :public :documentation "Filter that must be satisfied for expansion to succeed." :capnp-type "ExpandVariable.Lambda")) (:documentation "BFS expansion operator suited for distributed execution.") (:public #>cpp + DistributedExpandBfs() {} DistributedExpandBfs(Symbol node_symbol, Symbol edge_symbol, EdgeAtom::Direction direction, const std::vector &edge_types, @@ -243,20 +247,20 @@ by having only one result from each worker.") input_ = input; } cpp<#) - (:private #>cpp DistributedExpandBfs() {} cpp<#) (:serialize :capnp :inherit-compose '(expand-common))) (lcp:define-class distributed-create-node (logical-operator) - ((input "std::shared_ptr" + ((input "std::shared_ptr" :scope :public :capnp-save #'save-operator-pointer :capnp-load #'load-operator-pointer) - (node-atom "NodeAtom *" :initval "nullptr" :reader t + (node-atom "NodeAtom *" :initval "nullptr" :scope :public :capnp-type "Ast.Tree" :capnp-init nil :capnp-save #'save-ast-pointer :capnp-load (load-ast-pointer "NodeAtom *")) - (on-random-worker :bool :initval "false" :reader t)) + (on-random-worker :bool :initval "false" :scope :public)) (:documentation "Create nodes in distributed environment.") (:public #>cpp + DistributedCreateNode() {} DistributedCreateNode(const std::shared_ptr &input, NodeAtom *node_atom, bool on_random_worker); @@ -271,24 +275,24 @@ by having only one result from each worker.") input_ = input; } cpp<#) - (:private #>cpp DistributedCreateNode() {} cpp<#) (:serialize :capnp)) (lcp:define-class distributed-create-expand (logical-operator) - ((node-atom "NodeAtom *" :reader t + ((node-atom "NodeAtom *" :scope :public :capnp-type "Ast.Tree" :capnp-init nil :capnp-save #'save-ast-pointer :capnp-load (load-ast-pointer "NodeAtom *")) - (edge-atom "EdgeAtom *" :reader t + (edge-atom "EdgeAtom *" :scope :public :capnp-type "Ast.Tree" :capnp-init nil :capnp-save #'save-ast-pointer :capnp-load (load-ast-pointer "EdgeAtom *")) - (input "std::shared_ptr" + (input "std::shared_ptr" :scope :public :capnp-save #'save-operator-pointer :capnp-load #'load-operator-pointer) - (input-symbol "Symbol" :reader t) - (existing-node :bool :reader t)) + (input-symbol "Symbol" :scope :public) + (existing-node :bool :scope :public)) (:documentation "Distributed version of CreateExpand") (:public #>cpp + DistributedCreateExpand() {} DistributedCreateExpand(NodeAtom *node_atom, EdgeAtom *edge_atom, const std::shared_ptr &input, Symbol input_symbol, bool existing_node); @@ -303,7 +307,6 @@ by having only one result from each worker.") input_ = input; } cpp<#) - (:private #>cpp DistributedCreateExpand() {} cpp<#) (:serialize :capnp)) (lcp:pop-namespace) diff --git a/src/query/plan/distributed_pretty_print.cpp b/src/query/plan/distributed_pretty_print.cpp index 566b52947..ad2d640c6 100644 --- a/src/query/plan/distributed_pretty_print.cpp +++ b/src/query/plan/distributed_pretty_print.cpp @@ -20,8 +20,8 @@ bool DistributedPlanPrinter::PreVisit(query::plan::DistributedExpandBfs &op) { bool DistributedPlanPrinter::PreVisit(query::plan::PullRemote &op) { WithPrintLn([&op](auto &out) { - out << "* PullRemote [" << op.plan_id() << "] {"; - utils::PrintIterable(out, op.symbols(), ", ", + out << "* PullRemote [" << op.plan_id_ << "] {"; + utils::PrintIterable(out, op.symbols_, ", ", [](auto &out, const auto &sym) { out << sym.name(); }); out << "}"; }); @@ -35,7 +35,7 @@ bool DistributedPlanPrinter::PreVisit(query::plan::PullRemote &op) { bool DistributedPlanPrinter::PreVisit(query::plan::PullRemoteOrderBy &op) { WithPrintLn([&op](auto &out) { out << "* PullRemoteOrderBy {"; - utils::PrintIterable(out, op.symbols(), ", ", + utils::PrintIterable(out, op.symbols_, ", ", [](auto &out, const auto &sym) { out << sym.name(); }); out << "}"; }); @@ -61,10 +61,10 @@ PRE_VISIT(DistributedCreateExpand); bool DistributedPlanPrinter::PreVisit(query::plan::Synchronize &op) { WithPrintLn([&op](auto &out) { out << "* Synchronize"; - if (op.advance_command()) out << " (ADV CMD)"; + if (op.advance_command_) out << " (ADV CMD)"; }); - if (op.pull_remote()) Branch(*op.pull_remote()); - op.input()->Accept(*this); + if (op.pull_remote_) Branch(*op.pull_remote_); + op.input_->Accept(*this); return false; } diff --git a/src/query/plan/operator.cpp b/src/query/plan/operator.cpp index 18df6f35e..7914866d8 100644 --- a/src/query/plan/operator.cpp +++ b/src/query/plan/operator.cpp @@ -223,7 +223,7 @@ VertexAccessor &CreateExpand::CreateExpandCursor::OtherVertex( ExpectType(dest_node_symbol, dest_node_value, TypedValue::Type::Vertex); return dest_node_value.Value(); } else { - return CreateLocalVertex(self_.node_atom(), frame, context); + return CreateLocalVertex(self_.node_atom_, frame, context); } } @@ -365,8 +365,8 @@ std::unique_ptr ScanAllByLabelPropertyRange::MakeCursor( value.type()); } }; - auto maybe_lower = convert(lower_bound()); - auto maybe_upper = convert(upper_bound()); + auto maybe_lower = convert(lower_bound_); + auto maybe_upper = convert(upper_bound_); // If any bound is null, then the comparison would result in nulls. This // is treated as not satisfying the filter, so return no vertices. if (maybe_lower && maybe_lower->value().IsNull()) @@ -454,8 +454,8 @@ std::unique_ptr Expand::MakeCursor( std::vector Expand::ModifiedSymbols(const SymbolTable &table) const { auto symbols = input_->ModifiedSymbols(table); - symbols.emplace_back(node_symbol()); - symbols.emplace_back(edge_symbol()); + symbols.emplace_back(node_symbol_); + symbols.emplace_back(edge_symbol_); return symbols; } @@ -549,10 +549,10 @@ bool Expand::ExpandCursor::InitEdges(Frame &frame, Context &context) { ExpectType(self_.node_symbol_, existing_node, TypedValue::Type::Vertex); in_edges_.emplace( - vertex.in(existing_node.ValueVertex(), &self_.edge_types())); + vertex.in(existing_node.ValueVertex(), &self_.edge_types_)); } } else { - in_edges_.emplace(vertex.in(&self_.edge_types())); + in_edges_.emplace(vertex.in(&self_.edge_types_)); } in_edges_it_.emplace(in_edges_->begin()); } @@ -566,10 +566,10 @@ bool Expand::ExpandCursor::InitEdges(Frame &frame, Context &context) { ExpectType(self_.node_symbol_, existing_node, TypedValue::Type::Vertex); out_edges_.emplace( - vertex.out(existing_node.ValueVertex(), &self_.edge_types())); + vertex.out(existing_node.ValueVertex(), &self_.edge_types_)); } } else { - out_edges_.emplace(vertex.out(&self_.edge_types())); + out_edges_.emplace(vertex.out(&self_.edge_types_)); } out_edges_it_.emplace(out_edges_->begin()); } @@ -610,8 +610,8 @@ ACCEPT_WITH_INPUT(ExpandVariable) std::vector ExpandVariable::ModifiedSymbols( const SymbolTable &table) const { auto symbols = input_->ModifiedSymbols(table); - symbols.emplace_back(node_symbol()); - symbols.emplace_back(edge_symbol()); + symbols.emplace_back(node_symbol_); + symbols.emplace_back(edge_symbol_); return symbols; } @@ -895,11 +895,11 @@ class STShortestPathCursor : public query::plan::Cursor { STShortestPathCursor(const ExpandVariable &self, database::GraphDbAccessor &dba) : self_(self), input_cursor_(self_.input()->MakeCursor(dba)) { - CHECK(self_.graph_view() == GraphView::OLD) + CHECK(self_.graph_view_ == GraphView::OLD) << "ExpandVariable should only be planned with GraphView::OLD"; - CHECK(self_.existing_node()) << "s-t shortest path algorithm should only " - "be used when `existing_node` flag is " - "set!"; + CHECK(self_.existing_node_) << "s-t shortest path algorithm should only " + "be used when `existing_node` flag is " + "set!"; } bool Pull(Frame &frame, Context &context) override { @@ -907,8 +907,8 @@ class STShortestPathCursor : public query::plan::Cursor { context.evaluation_context_, &context.db_accessor_, GraphView::OLD); while (input_cursor_->Pull(frame, context)) { - auto source_tv = frame[self_.input_symbol()]; - auto sink_tv = frame[self_.node_symbol()]; + auto source_tv = frame[self_.input_symbol_]; + auto sink_tv = frame[self_.node_symbol_]; // It is possible that source or sink vertex is Null due to optional // matching. @@ -918,13 +918,13 @@ class STShortestPathCursor : public query::plan::Cursor { auto sink = sink_tv.ValueVertex(); int64_t lower_bound = - self_.lower_bound() - ? EvaluateInt(&evaluator, self_.lower_bound(), + self_.lower_bound_ + ? EvaluateInt(&evaluator, self_.lower_bound_, "Min depth in breadth-first expansion") : 1; int64_t upper_bound = - self_.upper_bound() - ? EvaluateInt(&evaluator, self_.upper_bound(), + self_.upper_bound_ + ? EvaluateInt(&evaluator, self_.upper_bound_, "Max depth in breadth-first expansion") : std::numeric_limits::max(); @@ -971,17 +971,17 @@ class STShortestPathCursor : public query::plan::Cursor { last_edge->from_is(last_vertex) ? last_edge->to() : last_edge->from(); result.emplace_back(*last_edge); } - frame->at(self_.edge_symbol()) = std::move(result); + frame->at(self_.edge_symbol_) = std::move(result); } bool ShouldExpand(const VertexAccessor &vertex, const EdgeAccessor &edge, Frame *frame, ExpressionEvaluator *evaluator) { - if (!self_.filter_lambda().expression) return true; + if (!self_.filter_lambda_.expression) return true; - frame->at(self_.filter_lambda().inner_node_symbol) = vertex; - frame->at(self_.filter_lambda().inner_edge_symbol) = edge; + frame->at(self_.filter_lambda_.inner_node_symbol) = vertex; + frame->at(self_.filter_lambda_.inner_edge_symbol) = edge; - TypedValue result = self_.filter_lambda().expression->Accept(*evaluator); + TypedValue result = self_.filter_lambda_.expression->Accept(*evaluator); if (result.IsNull()) return false; if (result.IsBool()) return result.ValueBool(); @@ -1031,8 +1031,8 @@ class STShortestPathCursor : public query::plan::Cursor { if (current_length > upper_bound) return false; for (const auto &vertex : source_frontier) { - if (self_.direction() != EdgeAtom::Direction::IN) { - for (const auto &edge : vertex.out(&self_.edge_types())) { + if (self_.direction_ != EdgeAtom::Direction::IN) { + for (const auto &edge : vertex.out(&self_.edge_types_)) { if (ShouldExpand(edge.to(), edge, frame, evaluator) && !Contains(in_edge, edge.to())) { in_edge.emplace(edge.to(), edge); @@ -1048,8 +1048,8 @@ class STShortestPathCursor : public query::plan::Cursor { } } } - if (self_.direction() != EdgeAtom::Direction::OUT) { - for (const auto &edge : vertex.in(&self_.edge_types())) { + if (self_.direction_ != EdgeAtom::Direction::OUT) { + for (const auto &edge : vertex.in(&self_.edge_types_)) { if (ShouldExpand(edge.from(), edge, frame, evaluator) && !Contains(in_edge, edge.from())) { in_edge.emplace(edge.from(), edge); @@ -1079,8 +1079,8 @@ class STShortestPathCursor : public query::plan::Cursor { // endpoint we pass to `should_expand`, because everything is // reversed. for (const auto &vertex : sink_frontier) { - if (self_.direction() != EdgeAtom::Direction::OUT) { - for (const auto &edge : vertex.out(&self_.edge_types())) { + if (self_.direction_ != EdgeAtom::Direction::OUT) { + for (const auto &edge : vertex.out(&self_.edge_types_)) { if (ShouldExpand(vertex, edge, frame, evaluator) && !Contains(out_edge, edge.to())) { out_edge.emplace(edge.to(), edge); @@ -1096,8 +1096,8 @@ class STShortestPathCursor : public query::plan::Cursor { } } } - if (self_.direction() != EdgeAtom::Direction::IN) { - for (const auto &edge : vertex.in(&self_.edge_types())) { + if (self_.direction_ != EdgeAtom::Direction::IN) { + for (const auto &edge : vertex.in(&self_.edge_types_)) { if (ShouldExpand(vertex, edge, frame, evaluator) && !Contains(out_edge, edge.from())) { out_edge.emplace(edge.from(), edge); @@ -1127,9 +1127,9 @@ class SingleSourceShortestPathCursor : public query::plan::Cursor { SingleSourceShortestPathCursor(const ExpandVariable &self, database::GraphDbAccessor &db) : self_(self), input_cursor_(self_.input()->MakeCursor(db)) { - CHECK(self_.graph_view() == GraphView::OLD) + CHECK(self_.graph_view_ == GraphView::OLD) << "ExpandVariable should only be planned with GraphView::OLD"; - CHECK(!self_.existing_node()) << "Single source shortest path algorithm " + CHECK(!self_.existing_node_) << "Single source shortest path algorithm " "should not be used when `existing_node` " "flag is set, s-t shortest path algorithm " "should be used instead!"; @@ -1147,11 +1147,11 @@ class SingleSourceShortestPathCursor : public query::plan::Cursor { // if we already processed the given vertex it doesn't get expanded if (processed_.find(vertex) != processed_.end()) return; - frame[self_.filter_lambda().inner_edge_symbol] = edge; - frame[self_.filter_lambda().inner_node_symbol] = vertex; + frame[self_.filter_lambda_.inner_edge_symbol] = edge; + frame[self_.filter_lambda_.inner_node_symbol] = vertex; - if (self_.filter_lambda().expression) { - TypedValue result = self_.filter_lambda().expression->Accept(evaluator); + if (self_.filter_lambda_.expression) { + TypedValue result = self_.filter_lambda_.expression->Accept(evaluator); switch (result.type()) { case TypedValue::Type::Null: return; @@ -1171,12 +1171,12 @@ class SingleSourceShortestPathCursor : public query::plan::Cursor { // from the given vertex. skips expansions that don't satisfy // the "where" condition. auto expand_from_vertex = [this, &expand_pair](VertexAccessor &vertex) { - if (self_.direction() != EdgeAtom::Direction::IN) { - for (const EdgeAccessor &edge : vertex.out(&self_.edge_types())) + if (self_.direction_ != EdgeAtom::Direction::IN) { + for (const EdgeAccessor &edge : vertex.out(&self_.edge_types_)) expand_pair(edge, edge.to()); } - if (self_.direction() != EdgeAtom::Direction::OUT) { - for (const EdgeAccessor &edge : vertex.in(&self_.edge_types())) + if (self_.direction_ != EdgeAtom::Direction::OUT) { + for (const EdgeAccessor &edge : vertex.in(&self_.edge_types_)) expand_pair(edge, edge.from()); } }; @@ -1195,18 +1195,18 @@ class SingleSourceShortestPathCursor : public query::plan::Cursor { to_visit_next_.clear(); processed_.clear(); - auto vertex_value = frame[self_.input_symbol()]; + auto vertex_value = frame[self_.input_symbol_]; // it is possible that the vertex is Null due to optional matching if (vertex_value.IsNull()) continue; auto vertex = vertex_value.Value(); processed_.emplace(vertex, std::experimental::nullopt); expand_from_vertex(vertex); - lower_bound_ = self_.lower_bound() - ? EvaluateInt(&evaluator, self_.lower_bound(), + lower_bound_ = self_.lower_bound_ + ? EvaluateInt(&evaluator, self_.lower_bound_, "Min depth in breadth-first expansion") : 1; - upper_bound_ = self_.upper_bound() - ? EvaluateInt(&evaluator, self_.upper_bound(), + upper_bound_ = self_.upper_bound_ + ? EvaluateInt(&evaluator, self_.upper_bound_, "Max depth in breadth-first expansion") : std::numeric_limits::max(); if (upper_bound_ < 1) @@ -1242,11 +1242,11 @@ class SingleSourceShortestPathCursor : public query::plan::Cursor { if (static_cast(edge_list.size()) < lower_bound_) continue; - frame[self_.node_symbol()] = expansion.second; + frame[self_.node_symbol_] = expansion.second; // place edges on the frame in the correct order std::reverse(edge_list.begin(), edge_list.end()); - frame[self_.edge_symbol()] = std::move(edge_list); + frame[self_.edge_symbol_] = std::move(edge_list); return true; } @@ -1549,15 +1549,15 @@ class ConstructNamedPathCursor : public Cursor { bool Pull(Frame &frame, Context &context) override { if (!input_cursor_->Pull(frame, context)) return false; - auto symbol_it = self_.path_elements().begin(); - DCHECK(symbol_it != self_.path_elements().end()) + auto symbol_it = self_.path_elements_.begin(); + DCHECK(symbol_it != self_.path_elements_.end()) << "Named path must contain at least one node"; TypedValue start_vertex = frame[*symbol_it++]; // In an OPTIONAL MATCH everything could be Null. if (start_vertex.IsNull()) { - frame[self_.path_symbol()] = TypedValue::Null; + frame[self_.path_symbol_] = TypedValue::Null; return true; } @@ -1571,13 +1571,13 @@ class ConstructNamedPathCursor : public Cursor { // expansion already did it. bool last_was_edge_list = false; - for (; symbol_it != self_.path_elements().end(); symbol_it++) { + for (; symbol_it != self_.path_elements_.end(); symbol_it++) { TypedValue expansion = frame[*symbol_it]; // We can have Null (OPTIONAL MATCH), a vertex, an edge, or an edge // list (variable expand or BFS). switch (expansion.type()) { case TypedValue::Type::Null: - frame[self_.path_symbol()] = TypedValue::Null; + frame[self_.path_symbol_] = TypedValue::Null; return true; case TypedValue::Type::Vertex: if (!last_was_edge_list) path.Expand(expansion.ValueVertex()); @@ -1608,7 +1608,7 @@ class ConstructNamedPathCursor : public Cursor { } } - frame[self_.path_symbol()] = path; + frame[self_.path_symbol_] = path; return true; } @@ -3037,7 +3037,7 @@ class CreateIndexCursor : public Cursor { throw IndexInMulticommandTxException(); } try { - db_.BuildIndex(self_.label(), self_.property()); + db_.BuildIndex(self_.label_, self_.property_); } catch (const database::IndexExistsException &) { // Ignore creating an existing index. } @@ -3155,8 +3155,8 @@ class CartesianCursor : public Cursor { public: CartesianCursor(const Cartesian &self, database::GraphDbAccessor &db) : self_(self), - left_op_cursor_(self.left_op()->MakeCursor(db)), - right_op_cursor_(self_.right_op()->MakeCursor(db)) { + left_op_cursor_(self.left_op_->MakeCursor(db)), + right_op_cursor_(self_.right_op_->MakeCursor(db)) { CHECK(left_op_cursor_ != nullptr) << "CartesianCursor: Missing left operator cursor."; CHECK(right_op_cursor_ != nullptr) @@ -3204,12 +3204,12 @@ class CartesianCursor : public Cursor { left_op_frames_it_ = left_op_frames_.begin(); } else { // Make sure right_op_cursor last pulled results are on frame. - restore_frame(self_.right_symbols(), right_op_frame_); + restore_frame(self_.right_symbols_, right_op_frame_); } if (context.db_accessor_.should_abort()) throw HintedAbortError(); - restore_frame(self_.left_symbols(), *left_op_frames_it_); + restore_frame(self_.left_symbols_, *left_op_frames_it_); left_op_frames_it_++; return true; } @@ -3301,7 +3301,7 @@ class AuthHandlerCursor : public Cursor { std::vector GetAuthPermissions() { std::vector ret; - for (const auto &privilege : self_.privileges()) { + for (const auto &privilege : self_.privileges_) { ret.push_back(glue::PrivilegeToPermission(privilege)); } return ret; @@ -3368,8 +3368,8 @@ class AuthHandlerCursor : public Cursor { ctx.evaluation_context_, &ctx.db_accessor_, GraphView::OLD); std::experimental::optional password; - if (self_.password()) { - auto password_tv = self_.password()->Accept(evaluator); + if (self_.password_) { + auto password_tv = self_.password_->Accept(evaluator); if (!password_tv.IsString() && !password_tv.IsNull()) { throw QueryRuntimeException( "Expected string or null for password, got {}.", @@ -3382,35 +3382,35 @@ class AuthHandlerCursor : public Cursor { auto &auth = *ctx.auth_; - switch (self_.action()) { + switch (self_.action_) { case AuthQuery::Action::CREATE_USER: { std::lock_guard lock(auth.WithLock()); - auto user = auth.AddUser(self_.user(), password); + auto user = auth.AddUser(self_.user_, password); if (!user) { throw QueryRuntimeException("User or role '{}' already exists.", - self_.user()); + self_.user_); } return false; } case AuthQuery::Action::DROP_USER: { std::lock_guard lock(auth.WithLock()); - auto user = auth.GetUser(self_.user()); + auto user = auth.GetUser(self_.user_); if (!user) { - throw QueryRuntimeException("User '{}' doesn't exist.", self_.user()); + throw QueryRuntimeException("User '{}' doesn't exist.", self_.user_); } - if (!auth.RemoveUser(self_.user())) { + if (!auth.RemoveUser(self_.user_)) { throw QueryRuntimeException("Couldn't remove user '{}'.", - self_.user()); + self_.user_); } return false; } case AuthQuery::Action::SET_PASSWORD: { std::lock_guard lock(auth.WithLock()); - auto user = auth.GetUser(self_.user()); + auto user = auth.GetUser(self_.user_); if (!user) { - throw QueryRuntimeException("User '{}' doesn't exist.", self_.user()); + throw QueryRuntimeException("User '{}' doesn't exist.", self_.user_); } user->UpdatePassword(password); auth.SaveUser(*user); @@ -3419,23 +3419,23 @@ class AuthHandlerCursor : public Cursor { case AuthQuery::Action::CREATE_ROLE: { std::lock_guard lock(auth.WithLock()); - auto role = auth.AddRole(self_.role()); + auto role = auth.AddRole(self_.role_); if (!role) { throw QueryRuntimeException("User or role '{}' already exists.", - self_.role()); + self_.role_); } return false; } case AuthQuery::Action::DROP_ROLE: { std::lock_guard lock(auth.WithLock()); - auto role = auth.GetRole(self_.role()); + auto role = auth.GetRole(self_.role_); if (!role) { - throw QueryRuntimeException("Role '{}' doesn't exist.", self_.role()); + throw QueryRuntimeException("Role '{}' doesn't exist.", self_.role_); } - if (!auth.RemoveRole(self_.role())) { + if (!auth.RemoveRole(self_.role_)) { throw QueryRuntimeException("Couldn't remove role '{}'.", - self_.role()); + self_.role_); } return false; } @@ -3449,7 +3449,7 @@ class AuthHandlerCursor : public Cursor { if (users_it_ == users_->end()) return false; - frame[self_.user_symbol()] = users_it_->username(); + frame[self_.user_symbol_] = users_it_->username(); users_it_++; return true; @@ -3464,7 +3464,7 @@ class AuthHandlerCursor : public Cursor { if (roles_it_ == roles_->end()) return false; - frame[self_.role_symbol()] = roles_it_->rolename(); + frame[self_.role_symbol_] = roles_it_->rolename(); roles_it_++; return true; @@ -3472,17 +3472,17 @@ class AuthHandlerCursor : public Cursor { case AuthQuery::Action::SET_ROLE: { std::lock_guard lock(auth.WithLock()); - auto user = auth.GetUser(self_.user()); + auto user = auth.GetUser(self_.user_); if (!user) { - throw QueryRuntimeException("User '{}' doesn't exist.", self_.user()); + throw QueryRuntimeException("User '{}' doesn't exist.", self_.user_); } - auto role = auth.GetRole(self_.role()); + auto role = auth.GetRole(self_.role_); if (!role) { - throw QueryRuntimeException("Role '{}' doesn't exist.", self_.role()); + throw QueryRuntimeException("Role '{}' doesn't exist.", self_.role_); } if (user->role()) { throw QueryRuntimeException( - "User '{}' is already a member of role '{}'.", self_.user(), + "User '{}' is already a member of role '{}'.", self_.user_, user->role()->rolename()); } user->SetRole(*role); @@ -3492,9 +3492,9 @@ class AuthHandlerCursor : public Cursor { case AuthQuery::Action::CLEAR_ROLE: { std::lock_guard lock(auth.WithLock()); - auto user = auth.GetUser(self_.user()); + auto user = auth.GetUser(self_.user_); if (!user) { - throw QueryRuntimeException("User '{}' doesn't exist.", self_.user()); + throw QueryRuntimeException("User '{}' doesn't exist.", self_.user_); } user->ClearRole(); auth.SaveUser(*user); @@ -3505,11 +3505,11 @@ class AuthHandlerCursor : public Cursor { case AuthQuery::Action::DENY_PRIVILEGE: case AuthQuery::Action::REVOKE_PRIVILEGE: { std::lock_guard lock(auth.WithLock()); - auto user = auth.GetUser(self_.user_or_role()); - auto role = auth.GetRole(self_.user_or_role()); + auto user = auth.GetUser(self_.user_or_role_); + auto role = auth.GetRole(self_.user_or_role_); if (!user && !role) { throw QueryRuntimeException("User or role '{}' doesn't exist.", - self_.user_or_role()); + self_.user_or_role_); } auto permissions = GetAuthPermissions(); if (user) { @@ -3517,9 +3517,9 @@ class AuthHandlerCursor : public Cursor { // TODO (mferencevic): should we first check that the privilege // is granted/denied/revoked before unconditionally // granting/denying/revoking it? - if (self_.action() == AuthQuery::Action::GRANT_PRIVILEGE) { + if (self_.action_ == AuthQuery::Action::GRANT_PRIVILEGE) { user->permissions().Grant(permission); - } else if (self_.action() == AuthQuery::Action::DENY_PRIVILEGE) { + } else if (self_.action_ == AuthQuery::Action::DENY_PRIVILEGE) { user->permissions().Deny(permission); } else { user->permissions().Revoke(permission); @@ -3531,9 +3531,9 @@ class AuthHandlerCursor : public Cursor { // TODO (mferencevic): should we first check that the privilege // is granted/denied/revoked before unconditionally // granting/denying/revoking it? - if (self_.action() == AuthQuery::Action::GRANT_PRIVILEGE) { + if (self_.action_ == AuthQuery::Action::GRANT_PRIVILEGE) { role->permissions().Grant(permission); - } else if (self_.action() == AuthQuery::Action::DENY_PRIVILEGE) { + } else if (self_.action_ == AuthQuery::Action::DENY_PRIVILEGE) { role->permissions().Deny(permission); } else { role->permissions().Revoke(permission); @@ -3547,11 +3547,11 @@ class AuthHandlerCursor : public Cursor { case AuthQuery::Action::SHOW_PRIVILEGES: { if (!grants_) { std::lock_guard lock(auth.WithLock()); - auto user = auth.GetUser(self_.user_or_role()); - auto role = auth.GetRole(self_.user_or_role()); + auto user = auth.GetUser(self_.user_or_role_); + auto role = auth.GetRole(self_.user_or_role_); if (!user && !role) { throw QueryRuntimeException("User or role '{}' doesn't exist.", - self_.user_or_role()); + self_.user_or_role_); } if (user) { grants_.emplace(GetGrantsForAuthUser(*user)); @@ -3563,9 +3563,9 @@ class AuthHandlerCursor : public Cursor { if (grants_it_ == grants_->end()) return false; - frame[self_.privilege_symbol()] = std::get<0>(*grants_it_); - frame[self_.effective_symbol()] = std::get<1>(*grants_it_); - frame[self_.details_symbol()] = std::get<2>(*grants_it_); + frame[self_.privilege_symbol_] = std::get<0>(*grants_it_); + frame[self_.effective_symbol_] = std::get<1>(*grants_it_); + frame[self_.details_symbol_] = std::get<2>(*grants_it_); grants_it_++; return true; @@ -3574,14 +3574,14 @@ class AuthHandlerCursor : public Cursor { case AuthQuery::Action::SHOW_ROLE_FOR_USER: { if (returned_role_for_user_) return false; std::lock_guard lock(auth.WithLock()); - auto user = auth.GetUser(self_.user()); + auto user = auth.GetUser(self_.user_); if (!user) { - throw QueryRuntimeException("User '{}' doesn't exist.", self_.user()); + throw QueryRuntimeException("User '{}' doesn't exist.", self_.user_); } if (user->role()) { - frame[self_.role_symbol()] = user->role()->rolename(); + frame[self_.role_symbol_] = user->role()->rolename(); } else { - frame[self_.role_symbol()] = TypedValue::Null; + frame[self_.role_symbol_] = TypedValue::Null; } returned_role_for_user_ = true; return true; @@ -3590,18 +3590,18 @@ class AuthHandlerCursor : public Cursor { case AuthQuery::Action::SHOW_USERS_FOR_ROLE: { if (!users_) { std::lock_guard lock(auth.WithLock()); - auto role = auth.GetRole(self_.role()); + auto role = auth.GetRole(self_.role_); if (!role) { throw QueryRuntimeException("Role '{}' doesn't exist.", - self_.role()); + self_.role_); } - users_.emplace(auth.AllUsersForRole(self_.role())); + users_.emplace(auth.AllUsersForRole(self_.role_)); users_it_ = users_->begin(); } if (users_it_ == users_->end()) return false; - frame[self_.user_symbol()] = users_it_->username(); + frame[self_.user_symbol_] = users_it_->username(); users_it_++; return true; @@ -3664,23 +3664,23 @@ class CreateStreamCursor : public Cursor { ctx.evaluation_context_, &ctx.db_accessor_, GraphView::OLD); - TypedValue stream_uri = self_.stream_uri()->Accept(evaluator); - TypedValue stream_topic = self_.stream_topic()->Accept(evaluator); - TypedValue transform_uri = self_.transform_uri()->Accept(evaluator); + TypedValue stream_uri = self_.stream_uri_->Accept(evaluator); + TypedValue stream_topic = self_.stream_topic_->Accept(evaluator); + TypedValue transform_uri = self_.transform_uri_->Accept(evaluator); std::experimental::optional batch_interval_in_ms, batch_size; - if (self_.batch_interval_in_ms()) { + if (self_.batch_interval_in_ms_) { batch_interval_in_ms = - self_.batch_interval_in_ms()->Accept(evaluator).Value(); + self_.batch_interval_in_ms_->Accept(evaluator).Value(); } - if (self_.batch_size()) { - batch_size = self_.batch_size()->Accept(evaluator).Value(); + if (self_.batch_size_) { + batch_size = self_.batch_size_->Accept(evaluator).Value(); } try { StreamInfo info; - info.stream_name = self_.stream_name(); + info.stream_name = self_.stream_name_; info.stream_uri = stream_uri.Value(); info.stream_topic = stream_topic.Value(); info.transform_uri = transform_uri.Value(); @@ -3724,7 +3724,7 @@ class DropStreamCursor : public Cursor { } try { - ctx.kafka_streams_->Drop(self_.stream_name()); + ctx.kafka_streams_->Drop(self_.stream_name_); } catch (const integrations::kafka::KafkaStreamException &e) { throw QueryRuntimeException(e.what()); } @@ -3778,11 +3778,11 @@ class ShowStreamsCursor : public Cursor { if (streams_it_ == streams_.end()) return false; - frame[self_.name_symbol()] = streams_it_->stream_name; - frame[self_.uri_symbol()] = streams_it_->stream_uri; - frame[self_.topic_symbol()] = streams_it_->stream_topic; - frame[self_.transform_symbol()] = streams_it_->transform_uri; - frame[self_.status_symbol()] = streams_it_->stream_status; + frame[self_.name_symbol_] = streams_it_->stream_name; + frame[self_.uri_symbol_] = streams_it_->stream_uri; + frame[self_.topic_symbol_] = streams_it_->stream_topic; + frame[self_.transform_symbol_] = streams_it_->transform_uri; + frame[self_.status_symbol_] = streams_it_->stream_status; streams_it_++; @@ -3831,15 +3831,15 @@ class StartStopStreamCursor : public Cursor { GraphView::OLD); std::experimental::optional limit_batches; - if (self_.limit_batches()) { - limit_batches = self_.limit_batches()->Accept(evaluator).Value(); + if (self_.limit_batches_) { + limit_batches = self_.limit_batches_->Accept(evaluator).Value(); } try { - if (self_.is_start()) { - ctx.kafka_streams_->Start(self_.stream_name(), limit_batches); + if (self_.is_start_) { + ctx.kafka_streams_->Start(self_.stream_name_, limit_batches); } else { - ctx.kafka_streams_->Stop(self_.stream_name()); + ctx.kafka_streams_->Stop(self_.stream_name_); } } catch (const integrations::kafka::KafkaStreamException &e) { throw QueryRuntimeException(e.what()); @@ -3877,7 +3877,7 @@ class StartStopAllStreamsCursor : public Cursor { } try { - if (self_.is_start()) { + if (self_.is_start_) { ctx.kafka_streams_->StartAll(); } else { ctx.kafka_streams_->StopAll(); @@ -3933,14 +3933,14 @@ class TestStreamCursor : public Cursor { GraphView::OLD); std::experimental::optional limit_batches; - if (self_.limit_batches()) { + if (self_.limit_batches_) { limit_batches = - self_.limit_batches()->Accept(evaluator).Value(); + self_.limit_batches_->Accept(evaluator).Value(); } try { auto results = - ctx.kafka_streams_->Test(self_.stream_name(), limit_batches); + ctx.kafka_streams_->Test(self_.stream_name_, limit_batches); for (const auto &result : results) { std::map params_tv; for (const auto &kv : result.second) { @@ -3957,8 +3957,8 @@ class TestStreamCursor : public Cursor { if (results_it_ == results_.end()) return false; - frame[self_.query_symbol()] = results_it_->first; - frame[self_.params_symbol()] = results_it_->second; + frame[self_.query_symbol_] = results_it_->first; + frame[self_.params_symbol_] = results_it_->second; results_it_++; return true; @@ -3986,9 +3986,9 @@ Explain::Explain( const std::shared_ptr &input, const Symbol &output_symbol, const std::function &pretty_print) - : pretty_print_(pretty_print), - input_(input), - output_symbol_(output_symbol) {} + : input_(input), + output_symbol_(output_symbol), + pretty_print_(pretty_print) {} ACCEPT_WITH_INPUT(Explain); diff --git a/src/query/plan/operator.lcp b/src/query/plan/operator.lcp index c64d74738..5f87c08da 100644 --- a/src/query/plan/operator.lcp +++ b/src/query/plan/operator.lcp @@ -20,14 +20,6 @@ #include "utils/hashing/fnv.hpp" #include "utils/visitor.hpp" -// TODO: It makes no sense for this file to include distributed_ops Cap'n -// Proto schema. Unfortunately, forward declares of nested capnp types do not -// work, so we cannot use that mechanism. Perhaps we want to generate -// serialization code based only on type info, similarly to RPCs. This -// requires rework of LCP and we will need to have a sort of 'register' -// mechanism to fill the table of (type info -> operator constructor). -#include "query/plan/distributed_ops.capnp.h" - namespace database { class GraphDbAccessor; } @@ -251,14 +243,13 @@ can serve as inputs to others and thus a sequence of operations is formed.") cpp<#) (defun load-ast-pointer (ast-type) - (lambda (reader member) - (let ((member-getter (remove #\_ (string-capitalize member)))) - #>cpp - if (${reader}.has${member-getter}()) - ${member} = static_cast<${ast-type}>(helper->ast_storage.Load(${reader}.get${member-getter}(), &helper->loaded_ast_uids)); - else - ${member} = nullptr; - cpp<#))) + (lambda (reader member capnp-name) + #>cpp + if (${reader}.has${capnp-name}()) + ${member} = static_cast<${ast-type}>(helper->ast_storage.Load(${reader}.get${capnp-name}(), &helper->loaded_ast_uids)); + else + ${member} = nullptr; + cpp<#)) (defun save-ast-vector (ast-type) (lcp:capnp-save-vector "::query::capnp::Tree" ast-type @@ -276,6 +267,7 @@ can serve as inputs to others and thus a sequence of operations is formed.") }" ast-type))) (defun save-operator-pointer (builder member-name capnp-name) + (declare (ignore capnp-name)) #>cpp utils::SaveSharedPtr(${member-name}, &${builder}, [helper](auto *builder, const auto &val) { @@ -283,12 +275,13 @@ can serve as inputs to others and thus a sequence of operations is formed.") }, &helper->saved_ops); cpp<#) -(defun load-operator-pointer (reader member-name) +(defun load-operator-pointer (reader member-name capnp-name) + (declare (ignore capnp-name)) #>cpp ${member-name} = utils::LoadSharedPtr(${reader}, [helper](const auto &reader) { - auto op = LogicalOperator::Construct(reader); - op->Load(reader, helper); + std::unique_ptr op; + Load(&op, reader, helper); return op.release(); }, &helper->loaded_ops); cpp<#) @@ -327,10 +320,10 @@ and false on every following Pull.") (:serialize :capnp)) (lcp:define-class create-node (logical-operator) - ((input "std::shared_ptr" + ((input "std::shared_ptr" :scope :public :capnp-save #'save-operator-pointer :capnp-load #'load-operator-pointer) - (node-atom "NodeAtom *" :initval "nullptr" :reader t + (node-atom "NodeAtom *" :initval "nullptr" :scope :public :capnp-type "Ast.Tree" :capnp-init nil :capnp-save #'save-ast-pointer :capnp-load (load-ast-pointer "NodeAtom *"))) (:documentation @@ -343,6 +336,8 @@ a preceeding `MATCH`), or multiple nodes (`MATCH ... CREATE` or @sa CreateExpand") (:public #>cpp + CreateNode() {} + /** * @param input Optional. If @c nullptr, then a single node will be * created (a single successful @c Cursor::Pull from this op's @c Cursor). @@ -366,8 +361,6 @@ a preceeding `MATCH`), or multiple nodes (`MATCH ... CREATE` or cpp<#) (:private #>cpp - CreateNode() {} - class CreateNodeCursor : public Cursor { public: CreateNodeCursor(const CreateNode &self, database::GraphDbAccessor &db); @@ -385,19 +378,19 @@ a preceeding `MATCH`), or multiple nodes (`MATCH ... CREATE` or (lcp:define-class create-expand (logical-operator) ( ;; info on what's getting expanded - (node-atom "NodeAtom *" :reader t + (node-atom "NodeAtom *" :scope :public :capnp-type "Ast.Tree" :capnp-init nil :capnp-save #'save-ast-pointer :capnp-load (load-ast-pointer "NodeAtom *")) - (edge-atom "EdgeAtom *" :reader t + (edge-atom "EdgeAtom *" :scope :public :capnp-type "Ast.Tree" :capnp-init nil :capnp-save #'save-ast-pointer :capnp-load (load-ast-pointer "EdgeAtom *")) ;; the input op and the symbol under which the op's result ;; can be found in the frame - (input "std::shared_ptr" + (input "std::shared_ptr" :scope :public :capnp-save #'save-operator-pointer :capnp-load #'load-operator-pointer) - (input-symbol "Symbol" :reader t) - (existing-node :bool :reader t :documentation + (input-symbol "Symbol" :scope :public) + (existing-node :bool :scope :public :documentation "if the given node atom refers to an existing node (either matched or created)")) (:documentation "Operator for creating edges and destination nodes. @@ -414,6 +407,8 @@ chained in cases when longer paths need creating. @sa CreateNode") (:public #>cpp + CreateExpand() {} + /** @brief Construct @c CreateExpand. * * @param node_atom @c NodeAtom at the end of the edge. Used to create a node, @@ -442,8 +437,6 @@ chained in cases when longer paths need creating. cpp<#) (:private #>cpp - CreateExpand() {} - class CreateExpandCursor : public Cursor { public: CreateExpandCursor(const CreateExpand &self, database::GraphDbAccessor &db); @@ -475,11 +468,11 @@ chained in cases when longer paths need creating. (:serialize :capnp)) (lcp:define-class scan-all (logical-operator) - ((input "std::shared_ptr" :scope :protected + ((input "std::shared_ptr" :scope :public :capnp-save #'save-operator-pointer :capnp-load #'load-operator-pointer) - (output-symbol "Symbol" :reader t :scope :protected) - (graph-view "GraphView" :reader t :scope :protected + (output-symbol "Symbol" :scope :public) + (graph-view "GraphView" :scope :public :capnp-init nil :capnp-save (lcp:capnp-save-enum "::query::capnp::GraphView" "GraphView" '(old new)) @@ -510,6 +503,7 @@ with a constructor argument. @sa ScanAllByLabelPropertyValue") (:public #>cpp + ScanAll() {} ScanAll(const std::shared_ptr &input, Symbol output_symbol, GraphView graph_view = GraphView::OLD); bool Accept(HierarchicalLogicalOperatorVisitor &visitor) override; @@ -523,11 +517,10 @@ with a constructor argument. input_ = input; } cpp<#) - (:protected #>cpp ScanAll() {} cpp<#) (:serialize :capnp)) (lcp:define-class scan-all-by-label (scan-all) - ((label "storage::Label" :reader t)) + ((label "storage::Label" :scope :public)) (:documentation "Behaves like @c ScanAll, but this operator produces only vertices with given label. @@ -537,6 +530,7 @@ given label. @sa ScanAllByLabelPropertyValue") (:public #>cpp + ScanAllByLabel() {} ScanAllByLabel(const std::shared_ptr &input, Symbol output_symbol, storage::Label label, GraphView graph_view = GraphView::OLD); @@ -544,7 +538,6 @@ given label. std::unique_ptr MakeCursor( database::GraphDbAccessor &db) const override; cpp<#) - (:private #>cpp ScanAllByLabel() {} cpp<#) (:serialize :capnp)) (defun save-optional-bound (builder member capnp-name) @@ -561,25 +554,26 @@ given label. save-bound) builder member capnp-name))) -(defun load-optional-bound (reader member) +(defun load-optional-bound (reader member capnp-name) (let ((load-bound "[helper](const auto &reader) { auto type = reader.getType() == ::utils::capnp::Bound<::query::capnp::Tree>::Type::INCLUSIVE - ? Bound::Type::INCLUSIVE : Bound::Type::EXCLUSIVE; + ? utils::BoundType::INCLUSIVE : utils::BoundType::EXCLUSIVE; auto *value = static_cast(helper->ast_storage.Load(reader.getValue(), &helper->loaded_ast_uids)); - return Bound(value, type); + return utils::Bound(value, type); }")) - (funcall (lcp:capnp-load-optional "::utils::capnp::Bound<::query::capnp::Tree>" "Bound" + (funcall (lcp:capnp-load-optional "::utils::capnp::Bound<::query::capnp::Tree>" + "utils::Bound" load-bound) - reader member))) + reader member capnp-name))) (lcp:define-class scan-all-by-label-property-range (scan-all) - ((label "storage::Label" :reader t) - (property "storage::Property" :reader t) - (lower-bound "std::experimental::optional" :reader t + ((label "storage::Label" :scope :public) + (property "storage::Property" :scope :public) + (lower-bound "std::experimental::optional" :scope :public :capnp-type "Utils.Optional(Utils.Bound(Ast.Tree))" :capnp-save #'save-optional-bound :capnp-load #'load-optional-bound) - (upper-bound "std::experimental::optional" :reader t + (upper-bound "std::experimental::optional" :scope :public :capnp-save #'save-optional-bound :capnp-load #'load-optional-bound :capnp-type "Utils.Optional(Utils.Bound(Ast.Tree))")) (:documentation @@ -593,6 +587,7 @@ property value which is inside a range (inclusive or exlusive). #>cpp /** Bound with expression which when evaluated produces the bound value. */ using Bound = utils::Bound; + ScanAllByLabelPropertyRange() {} /** * Constructs the operator for given label and property value in range * (inclusive). @@ -618,13 +613,12 @@ property value which is inside a range (inclusive or exlusive). std::unique_ptr MakeCursor( database::GraphDbAccessor &db) const override; cpp<#) - (:private #>cpp ScanAllByLabelPropertyRange() {} cpp<#) (:serialize :capnp)) (lcp:define-class scan-all-by-label-property-value (scan-all) - ((label "storage::Label" :reader t) - (property "storage::Property" :reader t) - (expression "Expression *" :reader t + ((label "storage::Label" :scope :public) + (property "storage::Property" :scope :public) + (expression "Expression *" :scope :public :capnp-type "Ast.Tree" :capnp-init nil :capnp-save #'save-ast-pointer :capnp-load (load-ast-pointer "Expression *"))) (:documentation @@ -636,6 +630,7 @@ property value. @sa ScanAllByLabelPropertyRange") (:public #>cpp + ScanAllByLabelPropertyValue() {} /** * Constructs the operator for given label and property value. * @@ -656,33 +651,32 @@ property value. std::unique_ptr MakeCursor( database::GraphDbAccessor &db) const override; cpp<#) - (:private #>cpp ScanAllByLabelPropertyValue() {} cpp<#) (:serialize :capnp)) (lcp:define-class expand-common () ( ;; info on what's getting expanded - (node-symbol "Symbol" :reader t :scope :protected) - (edge-symbol "Symbol" :reader t :scope :protected) - (direction "EdgeAtom::Direction" :reader t :scope :protected + (node-symbol "Symbol" :scope :public) + (edge-symbol "Symbol" :scope :public) + (direction "EdgeAtom::Direction" :scope :public :capnp-type "Ast.EdgeAtom.Direction" :capnp-init nil :capnp-save (lcp:capnp-save-enum "::query::capnp::EdgeAtom::Direction" "EdgeAtom::Direction" '(in out both)) :capnp-load (lcp:capnp-load-enum "::query::capnp::EdgeAtom::Direction" "EdgeAtom::Direction" '(in out both))) - (edge-types "std::vector" :reader t :scope :protected + (edge-types "std::vector" :scope :public :capnp-save (lcp:capnp-save-vector "::storage::capnp::Common" "storage::EdgeType") :capnp-load (lcp:capnp-load-vector "::storage::capnp::Common" "storage::EdgeType")) ;; the input op and the symbol under which the op's result ;; can be found in the frame - (input "std::shared_ptr" :scope :protected :reader t + (input "std::shared_ptr" :scope :public :capnp-save #'save-operator-pointer :capnp-load #'load-operator-pointer) - (input-symbol "Symbol" :reader t :scope :protected) - (existing-node :bool :reader t :scope :protected :documentation + (input-symbol "Symbol" :scope :public) + (existing-node :bool :scope :public :documentation "If the given node atom refer to a symbol that has already been expanded and should be just validated in the frame.") - (graph-view "GraphView" :reader t :scope :protected + (graph-view "GraphView" :scope :public :capnp-init nil :capnp-save (lcp:capnp-save-enum "::query::capnp::GraphView" "GraphView" '(old new)) @@ -817,31 +811,31 @@ pulled.") (:serialize :capnp :inherit-compose '(expand-common))) (lcp:define-class expand-variable (logical-operator expand-common) - ((type "EdgeAtom::Type" :reader t :capnp-type "Ast.EdgeAtom.Type" + ((type "EdgeAtom::Type" :scope :public :capnp-type "Ast.EdgeAtom.Type" :capnp-init nil :capnp-save (lcp:capnp-save-enum "::query::capnp::EdgeAtom::Type" "EdgeAtom::Type" '(single depth-first breadth-first weighted-shortest-path)) :capnp-load (lcp:capnp-load-enum "::query::capnp::EdgeAtom::Type" "EdgeAtom::Type" '(single depth-first breadth-first weighted-shortest-path))) - (is-reverse :bool :reader t :documentation + (is-reverse :bool :scope :public :documentation "True if the path should be written as expanding from node_symbol to input_symbol.") - (lower-bound "Expression *" :reader t + (lower-bound "Expression *" :scope :public :capnp-type "Ast.Tree" :capnp-init nil :capnp-save #'save-ast-pointer :capnp-load (load-ast-pointer "Expression *") :documentation "Optional lower bound of the variable length expansion, defaults are (1, inf)") - (upper-bound "Expression *" :reader t + (upper-bound "Expression *" :scope :public :capnp-type "Ast.Tree" :capnp-init nil :capnp-save #'save-ast-pointer :capnp-load (load-ast-pointer "Expression *") :documentation "Optional upper bound of the variable length expansion, defaults are (1, inf)") - (filter-lambda "Lambda" :reader t) - (weight-lambda "std::experimental::optional" :reader t + (filter-lambda "Lambda" :scope :public) + (weight-lambda "std::experimental::optional" :scope :public :capnp-save (lcp:capnp-save-optional "capnp::ExpandVariable::Lambda" "ExpandVariable::Lambda" "[helper](auto *builder, const auto &val) { Save(val, builder, helper); }") :capnp-load (lcp:capnp-load-optional "capnp::ExpandVariable::Lambda" "ExpandVariable::Lambda" - "[helper](const auto &reader) { Lambda val; val.Load(reader, helper); return val; }")) - (total-weight "std::experimental::optional" :reader t + "[helper](const auto &reader) { ExpandVariable::Lambda val; Load(&val, reader, helper); return val; }")) + (total-weight "std::experimental::optional" :scope :public :capnp-save (lcp:capnp-save-optional "::query::capnp::Symbol" "Symbol") :capnp-load (lcp:capnp-load-optional "::query::capnp::Symbol" "Symbol"))) (:documentation @@ -872,6 +866,8 @@ pulled.") :save-args '((helper "LogicalOperator::SaveHelper *")) :load-args '((helper "LogicalOperator::LoadHelper *")))) #>cpp + ExpandVariable() {} + /** * Creates a variable-length expansion. Most params are forwarded * to the @c ExpandCommon constructor, and are documented there. @@ -924,23 +920,22 @@ pulled.") // that should be inaccessible (private class function won't compile) friend class ExpandVariableCursor; friend class ExpandWeightedShortestPathCursor; - - ExpandVariable() {} cpp<#) (:serialize :capnp :inherit-compose '(expand-common))) (lcp:define-class construct-named-path (logical-operator) - ((input "std::shared_ptr" + ((input "std::shared_ptr" :scope :public :capnp-save #'save-operator-pointer :capnp-load #'load-operator-pointer) - (path-symbol "Symbol" :reader t) - (path-elements "std::vector" :reader t + (path-symbol "Symbol" :scope :public) + (path-elements "std::vector" :scope :public :capnp-save (lcp:capnp-save-vector "::query::capnp::Symbol" "Symbol") :capnp-load (lcp:capnp-load-vector "::query::capnp::Symbol" "Symbol"))) (:documentation "Constructs a named path from it's elements and places it on the frame.") (:public #>cpp + ConstructNamedPath() {} ConstructNamedPath(const std::shared_ptr &input, Symbol path_symbol, const std::vector &path_elements) @@ -958,15 +953,13 @@ pulled.") input_ = input; } cpp<#) - (:private - #>cpp ConstructNamedPath() {} cpp<#) (:serialize :capnp)) (lcp:define-class filter (logical-operator) - ((input "std::shared_ptr" + ((input "std::shared_ptr" :scope :public :capnp-save #'save-operator-pointer :capnp-load #'load-operator-pointer) - (expression "Expression *" :reader t + (expression "Expression *" :scope :public :capnp-type "Ast.Tree" :capnp-init nil :capnp-save #'save-ast-pointer :capnp-load (load-ast-pointer "Expression *"))) (:documentation @@ -977,6 +970,8 @@ The given expression is assumed to return either NULL (treated as false) or a boolean value.") (:public #>cpp + Filter() {} + Filter(const std::shared_ptr &input_, Expression *expression_); bool Accept(HierarchicalLogicalOperatorVisitor &visitor) override; @@ -992,8 +987,6 @@ a boolean value.") cpp<#) (:private #>cpp - Filter() {} - class FilterCursor : public Cursor { public: FilterCursor(const Filter &self, database::GraphDbAccessor &db); @@ -1009,10 +1002,10 @@ a boolean value.") (:serialize :capnp)) (lcp:define-class produce (logical-operator) - ((input "std::shared_ptr" + ((input "std::shared_ptr" :scope :public :capnp-save #'save-operator-pointer :capnp-load #'load-operator-pointer) - (named-expressions "std::vector" :reader t + (named-expressions "std::vector" :scope :public :capnp-type "List(Ast.Tree)" :capnp-save (save-ast-vector "NamedExpression *") :capnp-load (load-ast-vector "NamedExpression *"))) @@ -1028,6 +1021,8 @@ When the input is not provided (typically a standalone RETURN clause) the Produce's pull succeeds exactly once.") (:public #>cpp + Produce() {} + Produce(const std::shared_ptr &input, const std::vector &named_expressions); bool Accept(HierarchicalLogicalOperatorVisitor &visitor) override; @@ -1055,20 +1050,18 @@ RETURN clause) the Produce's pull succeeds exactly once.") const Produce &self_; const std::unique_ptr input_cursor_; }; - - Produce() {} cpp<#) (:serialize :capnp)) (lcp:define-class delete (logical-operator) - ((input "std::shared_ptr" + ((input "std::shared_ptr" :scope :public :capnp-save #'save-operator-pointer :capnp-load #'load-operator-pointer) - (expressions "std::vector" :reader t + (expressions "std::vector" :scope :public :capnp-type "List(Ast.Tree)" :capnp-save (save-ast-vector "Expression *") :capnp-load (load-ast-vector "Expression *")) - (detach :bool :reader t :documentation + (detach :bool :scope :public :documentation "if the vertex should be detached before deletion if not detached, and has connections, an error is raised ignored when deleting edges")) (:documentation @@ -1077,6 +1070,8 @@ RETURN clause) the Produce's pull succeeds exactly once.") Has a flag for using DETACH DELETE when deleting vertices.") (:public #>cpp + Delete() {} + Delete(const std::shared_ptr &input_, const std::vector &expressions, bool detach_); bool Accept(HierarchicalLogicalOperatorVisitor &visitor) override; @@ -1092,8 +1087,6 @@ Has a flag for using DETACH DELETE when deleting vertices.") cpp<#) (:private #>cpp - Delete() {} - class DeleteCursor : public Cursor { public: DeleteCursor(const Delete &self, database::GraphDbAccessor &db); @@ -1110,13 +1103,13 @@ Has a flag for using DETACH DELETE when deleting vertices.") (:serialize :capnp)) (lcp:define-class set-property (logical-operator) - ((input "std::shared_ptr" + ((input "std::shared_ptr" :scope :public :capnp-save #'save-operator-pointer :capnp-load #'load-operator-pointer) - (lhs "PropertyLookup *" :reader t + (lhs "PropertyLookup *" :scope :public :capnp-type "Ast.Tree" :capnp-init nil :capnp-save #'save-ast-pointer :capnp-load (load-ast-pointer "PropertyLookup *")) - (rhs "Expression *" :reader t + (rhs "Expression *" :scope :public :capnp-type "Ast.Tree" :capnp-init nil :capnp-save #'save-ast-pointer :capnp-load (load-ast-pointer "Expression *"))) (:documentation @@ -1126,6 +1119,8 @@ The property value is an expression that must evaluate to some type that can be stored (a TypedValue that can be converted to PropertyValue).") (:public #>cpp + SetProperty() {} + SetProperty(const std::shared_ptr &input, PropertyLookup *lhs, Expression *rhs); bool Accept(HierarchicalLogicalOperatorVisitor &visitor) override; @@ -1141,8 +1136,6 @@ can be stored (a TypedValue that can be converted to PropertyValue).") cpp<#) (:private #>cpp - SetProperty() {} - class SetPropertyCursor : public Cursor { public: SetPropertyCursor(const SetProperty &self, database::GraphDbAccessor &db); @@ -1158,14 +1151,14 @@ can be stored (a TypedValue that can be converted to PropertyValue).") (:serialize :capnp)) (lcp:define-class set-properties (logical-operator) - ((input "std::shared_ptr" + ((input "std::shared_ptr" :scope :public :capnp-save #'save-operator-pointer :capnp-load #'load-operator-pointer) - (input-symbol "Symbol" :reader t) - (rhs "Expression *" :reader t + (input-symbol "Symbol" :scope :public) + (rhs "Expression *" :scope :public :capnp-type "Ast.Tree" :capnp-init nil :capnp-save #'save-ast-pointer :capnp-load (load-ast-pointer "Expression *")) - (op "Op" :reader t)) + (op "Op" :scope :public)) (:documentation "Logical op for setting the whole properties set on a vertex or an edge. @@ -1185,6 +1178,8 @@ that the old props are discarded and replaced with new ones.") (:serialize :capnp)) #>cpp + SetProperties() {} + SetProperties(const std::shared_ptr &input, Symbol input_symbol, Expression *rhs, Op op); bool Accept(HierarchicalLogicalOperatorVisitor &visitor) override; @@ -1200,8 +1195,6 @@ that the old props are discarded and replaced with new ones.") cpp<#) (:private #>cpp - SetProperties() {} - class SetPropertiesCursor : public Cursor { public: SetPropertiesCursor(const SetProperties &self, @@ -1227,11 +1220,11 @@ that the old props are discarded and replaced with new ones.") (:serialize :capnp)) (lcp:define-class set-labels (logical-operator) - ((input "std::shared_ptr" + ((input "std::shared_ptr" :scope :public :capnp-save #'save-operator-pointer :capnp-load #'load-operator-pointer) - (input-symbol "Symbol" :reader t) - (labels "std::vector" :reader t + (input-symbol "Symbol" :scope :public) + (labels "std::vector" :scope :public :capnp-save (lcp:capnp-save-vector "::storage::capnp::Common" "storage::Label") :capnp-load (lcp:capnp-load-vector "::storage::capnp::Common" "storage::Label"))) (:documentation @@ -1240,6 +1233,8 @@ that the old props are discarded and replaced with new ones.") It does NOT remove labels that are already set on that Vertex.") (:public #>cpp + SetLabels() {} + SetLabels(const std::shared_ptr &input, Symbol input_symbol, const std::vector &labels); bool Accept(HierarchicalLogicalOperatorVisitor &visitor) override; @@ -1255,8 +1250,6 @@ It does NOT remove labels that are already set on that Vertex.") cpp<#) (:private #>cpp - SetLabels() {} - class SetLabelsCursor : public Cursor { public: SetLabelsCursor(const SetLabels &self, database::GraphDbAccessor &db); @@ -1272,16 +1265,18 @@ It does NOT remove labels that are already set on that Vertex.") (:serialize :capnp)) (lcp:define-class remove-property (logical-operator) - ((input "std::shared_ptr" + ((input "std::shared_ptr" :scope :public :capnp-save #'save-operator-pointer :capnp-load #'load-operator-pointer) - (lhs "PropertyLookup *" :reader t + (lhs "PropertyLookup *" :scope :public :capnp-type "Ast.Tree" :capnp-init nil :capnp-save #'save-ast-pointer :capnp-load (load-ast-pointer "PropertyLookup *"))) (:documentation "Logical op for removing a property from an edge or a vertex.") (:public #>cpp + RemoveProperty() {} + RemoveProperty(const std::shared_ptr &input, PropertyLookup *lhs); bool Accept(HierarchicalLogicalOperatorVisitor &visitor) override; @@ -1297,8 +1292,6 @@ It does NOT remove labels that are already set on that Vertex.") cpp<#) (:private #>cpp - RemoveProperty() {} - class RemovePropertyCursor : public Cursor { public: RemovePropertyCursor(const RemoveProperty &self, @@ -1315,11 +1308,11 @@ It does NOT remove labels that are already set on that Vertex.") (:serialize :capnp)) (lcp:define-class remove-labels (logical-operator) - ((input "std::shared_ptr" + ((input "std::shared_ptr" :scope :public :capnp-save #'save-operator-pointer :capnp-load #'load-operator-pointer) - (input-symbol "Symbol" :reader t) - (labels "std::vector" :reader t + (input-symbol "Symbol" :scope :public) + (labels "std::vector" :scope :public :capnp-save (lcp:capnp-save-vector "::storage::capnp::Common" "storage::Label") :capnp-load (lcp:capnp-load-vector "::storage::capnp::Common" "storage::Label"))) (:documentation @@ -1328,6 +1321,8 @@ It does NOT remove labels that are already set on that Vertex.") If a label does not exist on a Vertex, nothing happens.") (:public #>cpp + RemoveLabels() {} + RemoveLabels(const std::shared_ptr &input, Symbol input_symbol, const std::vector &labels); bool Accept(HierarchicalLogicalOperatorVisitor &visitor) override; @@ -1343,8 +1338,6 @@ If a label does not exist on a Vertex, nothing happens.") cpp<#) (:private #>cpp - RemoveLabels() {} - class RemoveLabelsCursor : public Cursor { public: RemoveLabelsCursor(const RemoveLabels &self, database::GraphDbAccessor &db); @@ -1360,11 +1353,11 @@ If a label does not exist on a Vertex, nothing happens.") (:serialize :capnp)) (lcp:define-class (expand-uniqueness-filter t-accessor) (logical-operator) - ((input "std::shared_ptr" + ((input "std::shared_ptr" :scope :public :capnp-save #'save-operator-pointer :capnp-load #'load-operator-pointer) - (expand-symbol "Symbol" :reader t) - (previous-symbols "std::vector" :reader t + (expand-symbol "Symbol" :scope :public) + (previous-symbols "std::vector" :scope :public :capnp-save (lcp:capnp-save-vector "::query::capnp::Symbol" "Symbol") :capnp-load (lcp:capnp-load-vector "::query::capnp::Symbol" "Symbol"))) (:documentation @@ -1391,6 +1384,8 @@ Supports variable-length-edges (uniqueness comparisons between edges and an edge lists).") (:public #>cpp + ExpandUniquenessFilter() {} + ExpandUniquenessFilter(const std::shared_ptr &input, Symbol expand_symbol, const std::vector &previous_symbols); @@ -1407,8 +1402,6 @@ between edges and an edge lists).") cpp<#) (:private #>cpp - ExpandUniquenessFilter() {} - class ExpandUniquenessFilterCursor : public Cursor { public: ExpandUniquenessFilterCursor(const ExpandUniquenessFilter &self, @@ -1425,13 +1418,13 @@ between edges and an edge lists).") (:serialize :capnp :type-args '(vertex-accessor edge-accessor))) (lcp:define-class accumulate (logical-operator) - ((input "std::shared_ptr" + ((input "std::shared_ptr" :scope :public :capnp-save #'save-operator-pointer :capnp-load #'load-operator-pointer) - (symbols "std::vector" :reader t + (symbols "std::vector" :scope :public :capnp-save (lcp:capnp-save-vector "::query::capnp::Symbol" "Symbol") :capnp-load (lcp:capnp-load-vector "::query::capnp::Symbol" "Symbol")) - (advance-command :bool :reader t)) + (advance-command :bool :scope :public)) (:documentation "Pulls everything from the input before passing it through. Optionally advances the command after accumulation and before emitting. @@ -1461,6 +1454,8 @@ has been cached will be reconstructed before Pull returns. and exposed to the next op.") (:public #>cpp + Accumulate() {} + Accumulate(const std::shared_ptr &input, const std::vector &symbols, bool advance_command = false); bool Accept(HierarchicalLogicalOperatorVisitor &visitor) override; @@ -1476,8 +1471,6 @@ has been cached will be reconstructed before Pull returns. cpp<#) (:private #>cpp - Accumulate() {} - class AccumulateCursor : public Cursor { public: AccumulateCursor(const Accumulate &self, database::GraphDbAccessor &db); @@ -1508,21 +1501,21 @@ struct TypedValueVectorEqual { cpp<# (lcp:define-class aggregate (logical-operator) - ((input "std::shared_ptr" + ((input "std::shared_ptr" :scope :public :capnp-save #'save-operator-pointer :capnp-load #'load-operator-pointer) - (aggregations "std::vector" :reader t + (aggregations "std::vector" :scope :public :capnp-save (lcp:capnp-save-vector "capnp::Aggregate::Element" "Aggregate::Element" "[helper](auto *builder, const auto &val) { Save(val, builder, helper); }") :capnp-load (lcp:capnp-load-vector - "capnp::Aggregate::Element" "Element" - "[helper](const auto &reader) { Element val; val.Load(reader, helper); return val; }")) - (group-by "std::vector" :reader t + "capnp::Aggregate::Element" "Aggregate::Element" + "[helper](const auto &reader) { Aggregate::Element val; Load(&val, reader, helper); return val; }")) + (group-by "std::vector" :scope :public :capnp-type "List(Ast.Tree)" :capnp-save (save-ast-vector "Expression *") :capnp-load (load-ast-vector "Expression *")) - (remember "std::vector" :reader t + (remember "std::vector" :scope :public :capnp-save (lcp:capnp-save-vector "::query::capnp::Symbol" "Symbol") :capnp-load (lcp:capnp-load-vector "::query::capnp::Symbol" "Symbol"))) (:documentation @@ -1561,6 +1554,7 @@ elements are in an undefined state after aggregation.") :save-args '((helper "LogicalOperator::SaveHelper *")) :load-args '((helper "LogicalOperator::LoadHelper *")))) #>cpp + Aggregate() = default; Aggregate(const std::shared_ptr &input, const std::vector &aggregations, const std::vector &group_by, @@ -1578,8 +1572,6 @@ elements are in an undefined state after aggregation.") cpp<#) (:private #>cpp - Aggregate() {} - class AggregateCursor : public Cursor { public: AggregateCursor(const Aggregate &self, database::GraphDbAccessor &db); @@ -1663,10 +1655,10 @@ elements are in an undefined state after aggregation.") (:serialize :capnp)) (lcp:define-class skip (logical-operator) - ((input "std::shared_ptr" + ((input "std::shared_ptr" :scope :public :capnp-save #'save-operator-pointer :capnp-load #'load-operator-pointer) - (expression "Expression *" :reader t + (expression "Expression *" :scope :public :capnp-type "Ast.Tree" :capnp-init nil :capnp-save #'save-ast-pointer :capnp-load (load-ast-pointer "Expression *"))) (:documentation @@ -1683,6 +1675,8 @@ to contain identifiers, and neither does Memgraph, but this operator's implementation does not expect this.") (:public #>cpp + Skip() {} + Skip(const std::shared_ptr &input, Expression *expression); bool Accept(HierarchicalLogicalOperatorVisitor &visitor) override; std::unique_ptr MakeCursor( @@ -1698,8 +1692,6 @@ operator's implementation does not expect this.") cpp<#) (:private #>cpp - Skip() {} - class SkipCursor : public Cursor { public: SkipCursor(const Skip &self, database::GraphDbAccessor &db); @@ -1719,10 +1711,10 @@ operator's implementation does not expect this.") (:serialize :capnp)) (lcp:define-class limit (logical-operator) - ((input "std::shared_ptr" + ((input "std::shared_ptr" :scope :public :capnp-save #'save-operator-pointer :capnp-load #'load-operator-pointer) - (expression "Expression *" :reader t + (expression "Expression *" :scope :public :capnp-type "Ast.Tree" :capnp-init nil :capnp-save #'save-ast-pointer :capnp-load (load-ast-pointer "Expression *"))) (:documentation @@ -1742,6 +1734,8 @@ when limit evaluates to 0 (because 0 Pulls from the input should be performed).") (:public #>cpp + Limit() {} + Limit(const std::shared_ptr &input, Expression *expression); bool Accept(HierarchicalLogicalOperatorVisitor &visitor) override; std::unique_ptr MakeCursor( @@ -1757,8 +1751,6 @@ input should be performed).") cpp<#) (:private #>cpp - Limit() {} - class LimitCursor : public Cursor { public: LimitCursor(const Limit &self, database::GraphDbAccessor &db); @@ -1778,16 +1770,16 @@ input should be performed).") (:serialize :capnp)) (lcp:define-class order-by (logical-operator) - ((input "std::shared_ptr" + ((input "std::shared_ptr" :scope :public :capnp-save #'save-operator-pointer :capnp-load #'load-operator-pointer) - (compare "TypedValueVectorCompare" :reader t + (compare "TypedValueVectorCompare" :scope :public :capnp-type "Common.TypedValueVectorCompare") - (order-by "std::vector" :reader t + (order-by "std::vector" :scope :public :capnp-type "List(Ast.Tree)" :capnp-save (save-ast-vector "Expression *") :capnp-load (load-ast-vector "Expression *")) - (output-symbols "std::vector" :reader t + (output-symbols "std::vector" :scope :public :capnp-save (lcp:capnp-save-vector "::query::capnp::Symbol" "Symbol") :capnp-load (lcp:capnp-load-vector "::query::capnp::Symbol" "Symbol"))) (:documentation @@ -1803,6 +1795,8 @@ remembered. Only these elements (defined by their Symbols) are valid for usage after the OrderBy operator.") (:public #>cpp + OrderBy() {} + OrderBy(const std::shared_ptr &input, const std::vector> &order_by, const std::vector &output_symbols); @@ -1820,8 +1814,6 @@ are valid for usage after the OrderBy operator.") cpp<#) (:private #>cpp - OrderBy() {} - class OrderByCursor : public Cursor { public: OrderByCursor(const OrderBy &self, database::GraphDbAccessor &db); @@ -1846,13 +1838,13 @@ are valid for usage after the OrderBy operator.") (:serialize :capnp)) (lcp:define-class merge (logical-operator) - ((input "std::shared_ptr" + ((input "std::shared_ptr" :scope :public :capnp-save #'save-operator-pointer :capnp-load #'load-operator-pointer) - (merge-match "std::shared_ptr" :reader t + (merge-match "std::shared_ptr" :scope :public :capnp-save #'save-operator-pointer :capnp-load #'load-operator-pointer) - (merge-create "std::shared_ptr" :reader t + (merge-create "std::shared_ptr" :scope :public :capnp-save #'save-operator-pointer :capnp-load #'load-operator-pointer)) (:documentation @@ -1869,6 +1861,8 @@ For an argumentation of this implementation see the wiki documentation.") (:public #>cpp + Merge() {} + Merge(const std::shared_ptr &input, const std::shared_ptr &merge_match, const std::shared_ptr &merge_create); @@ -1888,8 +1882,6 @@ documentation.") cpp<#) (:private #>cpp - Merge() {} - class MergeCursor : public Cursor { public: MergeCursor(const Merge &self, database::GraphDbAccessor &db); @@ -1913,13 +1905,13 @@ documentation.") (:serialize :capnp)) (lcp:define-class optional (logical-operator) - ((input "std::shared_ptr" + ((input "std::shared_ptr" :scope :public :capnp-save #'save-operator-pointer :capnp-load #'load-operator-pointer) - (optional "std::shared_ptr" :reader t + (optional "std::shared_ptr" :scope :public :capnp-save #'save-operator-pointer :capnp-load #'load-operator-pointer) - (optional-symbols "std::vector" :reader t + (optional-symbols "std::vector" :scope :public :capnp-save (lcp:capnp-save-vector "::query::capnp::Symbol" "Symbol") :capnp-load (lcp:capnp-load-vector "::query::capnp::Symbol" "Symbol"))) (:documentation @@ -1931,6 +1923,8 @@ sets the optional symbols to TypedValue::Null on the Frame and returns true, once.") (:public #>cpp + Optional() {} + Optional(const std::shared_ptr &input, const std::shared_ptr &optional, const std::vector &optional_symbols); @@ -1947,8 +1941,6 @@ and returns true, once.") cpp<#) (:private #>cpp - Optional() {} - class OptionalCursor : public Cursor { public: OptionalCursor(const Optional &self, database::GraphDbAccessor &db); @@ -1971,7 +1963,7 @@ and returns true, once.") (:serialize :capnp)) (lcp:define-class auth-handler (logical-operator) - ((action "AuthQuery::Action" :reader t + ((action "AuthQuery::Action" :scope :public :capnp-init nil :capnp-type "Ast.AuthQuery.Action" :capnp-save (lcp:capnp-save-enum "::query::capnp::AuthQuery::Action" @@ -1992,92 +1984,95 @@ and returns true, once.") deny-privilege revoke-privilege show-privileges show-role-for-user show-users-for-role))) - (user "std::string" :reader t) - (role "std::string" :reader t) - (user-or-role "std::string" :reader t) - (password "Expression *" :reader t + (user "std::string" :scope :public) + (role "std::string" :scope :public) + (user-or-role "std::string" :scope :public) + (password "Expression *" :scope :public :capnp-type "Ast.Tree" :capnp-init nil :capnp-save #'save-ast-pointer :capnp-load (load-ast-pointer "Expression *")) - (privileges "std::vector" :reader t + (privileges "std::vector" :scope :public :capnp-type "List(Ast.AuthQuery.Privilege)" :capnp-save - (lambda (builder member capnp-name) - #>cpp - for (size_t i = 0; i < ${member}.size(); ++i) { - switch (${member}[i]) { - case AuthQuery::Privilege::CREATE: - ${builder}.set(i, query::capnp::AuthQuery::Privilege::CREATE); - break; - case AuthQuery::Privilege::DELETE: - ${builder}.set(i, query::capnp::AuthQuery::Privilege::DELETE); - break; - case AuthQuery::Privilege::MATCH: - ${builder}.set(i, query::capnp::AuthQuery::Privilege::MATCH); - break; - case AuthQuery::Privilege::MERGE: - ${builder}.set(i, query::capnp::AuthQuery::Privilege::MERGE); - break; - case AuthQuery::Privilege::SET: - ${builder}.set(i, query::capnp::AuthQuery::Privilege::SET); - break; - case AuthQuery::Privilege::REMOVE: - ${builder}.set(i, query::capnp::AuthQuery::Privilege::REMOVE); - break; - case AuthQuery::Privilege::INDEX: - ${builder}.set(i, query::capnp::AuthQuery::Privilege::INDEX); - break; - case AuthQuery::Privilege::AUTH: - ${builder}.set(i, query::capnp::AuthQuery::Privilege::AUTH); - break; - case AuthQuery::Privilege::STREAM: - ${builder}.set(i, query::capnp::AuthQuery::Privilege::STREAM); - break; - } - } - cpp<#) - :capnp-load - (lambda (reader member-name) - #>cpp - for (auto privilege : ${reader}) { - switch (privilege) { - case query::capnp::AuthQuery::Privilege::CREATE: - ${member-name}.push_back(AuthQuery::Privilege::CREATE); - break; - case query::capnp::AuthQuery::Privilege::DELETE: - ${member-name}.push_back(AuthQuery::Privilege::DELETE); - break; - case query::capnp::AuthQuery::Privilege::MATCH: - ${member-name}.push_back(AuthQuery::Privilege::MATCH); - break; - case query::capnp::AuthQuery::Privilege::MERGE: - ${member-name}.push_back(AuthQuery::Privilege::MERGE); - break; - case query::capnp::AuthQuery::Privilege::SET: - ${member-name}.push_back(AuthQuery::Privilege::SET); - break; - case query::capnp::AuthQuery::Privilege::REMOVE: - ${member-name}.push_back(AuthQuery::Privilege::REMOVE); - break; - case query::capnp::AuthQuery::Privilege::INDEX: - ${member-name}.push_back(AuthQuery::Privilege::INDEX); - break; - case query::capnp::AuthQuery::Privilege::AUTH: - ${member-name}.push_back(AuthQuery::Privilege::AUTH); - break; - case query::capnp::AuthQuery::Privilege::STREAM: - ${member-name}.push_back(AuthQuery::Privilege::STREAM); - break; - } + (lambda (builder member capnp-name) + (declare (ignore capnp-name)) + #>cpp + for (size_t i = 0; i < ${member}.size(); ++i) { + switch (${member}[i]) { + case AuthQuery::Privilege::CREATE: + ${builder}.set(i, query::capnp::AuthQuery::Privilege::CREATE); + break; + case AuthQuery::Privilege::DELETE: + ${builder}.set(i, query::capnp::AuthQuery::Privilege::DELETE); + break; + case AuthQuery::Privilege::MATCH: + ${builder}.set(i, query::capnp::AuthQuery::Privilege::MATCH); + break; + case AuthQuery::Privilege::MERGE: + ${builder}.set(i, query::capnp::AuthQuery::Privilege::MERGE); + break; + case AuthQuery::Privilege::SET: + ${builder}.set(i, query::capnp::AuthQuery::Privilege::SET); + break; + case AuthQuery::Privilege::REMOVE: + ${builder}.set(i, query::capnp::AuthQuery::Privilege::REMOVE); + break; + case AuthQuery::Privilege::INDEX: + ${builder}.set(i, query::capnp::AuthQuery::Privilege::INDEX); + break; + case AuthQuery::Privilege::AUTH: + ${builder}.set(i, query::capnp::AuthQuery::Privilege::AUTH); + break; + case AuthQuery::Privilege::STREAM: + ${builder}.set(i, query::capnp::AuthQuery::Privilege::STREAM); + break; } - cpp<#)) - (user-symbol "Symbol" :reader t) - (role-symbol "Symbol" :reader t) - (privilege-symbol "Symbol" :reader t) - (effective-symbol "Symbol" :reader t) - (details-symbol "Symbol" :reader t)) + } + cpp<#) + :capnp-load + (lambda (reader member-name capnp-name) + (declare (ignore capnp-name)) + #>cpp + for (auto privilege : ${reader}) { + switch (privilege) { + case query::capnp::AuthQuery::Privilege::CREATE: + ${member-name}.push_back(AuthQuery::Privilege::CREATE); + break; + case query::capnp::AuthQuery::Privilege::DELETE: + ${member-name}.push_back(AuthQuery::Privilege::DELETE); + break; + case query::capnp::AuthQuery::Privilege::MATCH: + ${member-name}.push_back(AuthQuery::Privilege::MATCH); + break; + case query::capnp::AuthQuery::Privilege::MERGE: + ${member-name}.push_back(AuthQuery::Privilege::MERGE); + break; + case query::capnp::AuthQuery::Privilege::SET: + ${member-name}.push_back(AuthQuery::Privilege::SET); + break; + case query::capnp::AuthQuery::Privilege::REMOVE: + ${member-name}.push_back(AuthQuery::Privilege::REMOVE); + break; + case query::capnp::AuthQuery::Privilege::INDEX: + ${member-name}.push_back(AuthQuery::Privilege::INDEX); + break; + case query::capnp::AuthQuery::Privilege::AUTH: + ${member-name}.push_back(AuthQuery::Privilege::AUTH); + break; + case query::capnp::AuthQuery::Privilege::STREAM: + ${member-name}.push_back(AuthQuery::Privilege::STREAM); + break; + } + } + cpp<#)) + (user-symbol "Symbol" :scope :public) + (role-symbol "Symbol" :scope :public) + (privilege-symbol "Symbol" :scope :public) + (effective-symbol "Symbol" :scope :public) + (details-symbol "Symbol" :scope :public)) (:public #>cpp + AuthHandler() {} AuthHandler(AuthQuery::Action action, std::string user, std::string role, std::string user_or_role, Expression * password, std::vector privileges, @@ -2096,17 +2091,16 @@ and returns true, once.") std::shared_ptr input() const override; void set_input(std::shared_ptr) override; cpp<#) - (:protected #>cpp AuthHandler() {} cpp<#) (:serialize :capnp)) (lcp:define-class unwind (logical-operator) - ((input "std::shared_ptr" + ((input "std::shared_ptr" :scope :public :capnp-save #'save-operator-pointer :capnp-load #'load-operator-pointer) - (input-expression "Expression *" :reader t + (input-expression "Expression *" :scope :public :capnp-type "Ast.Tree" :capnp-init nil :capnp-save #'save-ast-pointer :capnp-load (load-ast-pointer "Expression *")) - (output-symbol "Symbol" :reader t)) + (output-symbol "Symbol" :scope :public)) (:documentation "Takes a list TypedValue as it's input and yields each element as it's output. @@ -2114,6 +2108,8 @@ element as it's output. Input is optional (unwind can be the first clause in a query).") (:public #>cpp + Unwind() {} + Unwind(const std::shared_ptr &input, Expression *input_expression_, Symbol output_symbol); bool Accept(HierarchicalLogicalOperatorVisitor &visitor) override; @@ -2131,8 +2127,6 @@ Input is optional (unwind can be the first clause in a query).") cpp<#) (:private #>cpp - Unwind() {} - class UnwindCursor : public Cursor { public: UnwindCursor(const Unwind &self, database::GraphDbAccessor &db); @@ -2153,10 +2147,10 @@ Input is optional (unwind can be the first clause in a query).") (:serialize :capnp)) (lcp:define-class distinct (logical-operator) - ((input "std::shared_ptr" + ((input "std::shared_ptr" :scope :public :capnp-save #'save-operator-pointer :capnp-load #'load-operator-pointer) - (value-symbols "std::vector" :reader t + (value-symbols "std::vector" :scope :public :capnp-save (lcp:capnp-save-vector "::query::capnp::Symbol" "Symbol") :capnp-load (lcp:capnp-load-vector "::query::capnp::Symbol" "Symbol"))) (:documentation @@ -2168,6 +2162,8 @@ for use in operators following Distinct. This implementation maintains input ordering.") (:public #>cpp + Distinct() {} + Distinct(const std::shared_ptr &input, const std::vector &value_symbols); bool Accept(HierarchicalLogicalOperatorVisitor &visitor) override; @@ -2184,8 +2180,6 @@ This implementation maintains input ordering.") cpp<#) (:private #>cpp - Distinct() {} - class DistinctCursor : public Cursor { public: DistinctCursor(const Distinct &self, database::GraphDbAccessor &db); @@ -2210,8 +2204,8 @@ This implementation maintains input ordering.") (:serialize :capnp)) (lcp:define-class create-index (logical-operator) - ((label "storage::Label" :reader t) - (property "storage::Property" :reader t)) + ((label "storage::Label" :scope :public) + (property "storage::Property" :scope :public)) (:documentation "Creates an index for a combination of label and a property. @@ -2221,6 +2215,7 @@ the database for the vertices which have the given label and property. In case the index already exists, nothing happens.") (:public #>cpp + CreateIndex() {} CreateIndex(storage::Label label, storage::Property property); bool Accept(HierarchicalLogicalOperatorVisitor &visitor) override; std::unique_ptr MakeCursor( @@ -2233,23 +2228,22 @@ case the index already exists, nothing happens.") std::shared_ptr input() const override; void set_input(std::shared_ptr) override; cpp<#) - (:private #>cpp CreateIndex() {} cpp<#) (:serialize :capnp)) (lcp:define-class union (logical-operator) - ((left-op "std::shared_ptr" :reader t + ((left-op "std::shared_ptr" :scope :public :capnp-save #'save-operator-pointer :capnp-load #'load-operator-pointer) - (right-op "std::shared_ptr" :reader t + (right-op "std::shared_ptr" :scope :public :capnp-save #'save-operator-pointer :capnp-load #'load-operator-pointer) - (union-symbols "std::vector" :reader t + (union-symbols "std::vector" :scope :public :capnp-save (lcp:capnp-save-vector "::query::capnp::Symbol" "Symbol") :capnp-load (lcp:capnp-load-vector "::query::capnp::Symbol" "Symbol")) - (left-symbols "std::vector" :reader t + (left-symbols "std::vector" :scope :public :capnp-save (lcp:capnp-save-vector "::query::capnp::Symbol" "Symbol") :capnp-load (lcp:capnp-load-vector "::query::capnp::Symbol" "Symbol")) - (right-symbols "std::vector" :reader t + (right-symbols "std::vector" :scope :public :capnp-save (lcp:capnp-save-vector "::query::capnp::Symbol" "Symbol") :capnp-load (lcp:capnp-load-vector "::query::capnp::Symbol" "Symbol"))) (:documentation @@ -2260,6 +2254,8 @@ This operator takes two inputs, a vector of symbols for the result, and vectors of symbols used by each of the inputs.") (:public #>cpp + Union() {} + Union(const std::shared_ptr &left_op, const std::shared_ptr &right_op, const std::vector &union_symbols, @@ -2277,8 +2273,6 @@ vectors of symbols used by each of the inputs.") cpp<#) (:private #>cpp - Union() {} - class UnionCursor : public Cursor { public: UnionCursor(const Union &self, database::GraphDbAccessor &db); @@ -2296,22 +2290,23 @@ vectors of symbols used by each of the inputs.") ;; TODO: We should probably output this operator in regular planner, not just ;; distributed planner. (lcp:define-class cartesian (logical-operator) - ((left-op "std::shared_ptr" :reader t + ((left-op "std::shared_ptr" :scope :public :capnp-save #'save-operator-pointer :capnp-load #'load-operator-pointer) - (left-symbols "std::vector" :reader t + (left-symbols "std::vector" :scope :public :capnp-save (lcp:capnp-save-vector "::query::capnp::Symbol" "Symbol") :capnp-load (lcp:capnp-load-vector "::query::capnp::Symbol" "Symbol")) - (right-op "std::shared_ptr" :reader t + (right-op "std::shared_ptr" :scope :public :capnp-save #'save-operator-pointer :capnp-load #'load-operator-pointer) - (right-symbols "std::vector" :reader t + (right-symbols "std::vector" :scope :public :capnp-save (lcp:capnp-save-vector "::query::capnp::Symbol" "Symbol") :capnp-load (lcp:capnp-load-vector "::query::capnp::Symbol" "Symbol"))) (:documentation "Operator for producing a Cartesian product from 2 input branches") (:public #>cpp + Cartesian() {} /** Construct the operator with left input branch and right input branch. */ Cartesian(const std::shared_ptr &left_op, const std::vector &left_symbols, @@ -2331,38 +2326,37 @@ vectors of symbols used by each of the inputs.") std::shared_ptr input() const override; void set_input(std::shared_ptr) override; cpp<#) - (:private #>cpp Cartesian() {} cpp<#) (:serialize :capnp)) ;;; KAFKA STREAM OPERATORS (lcp:define-class create-stream (logical-operator) - ((stream-name "std::string" :reader t) + ((stream-name "std::string" :scope :public) (stream-uri "Expression *" - :reader t + :scope :public :capnp-type "Ast.Tree" :capnp-init nil :capnp-save #'save-ast-pointer :capnp-load (load-ast-pointer "Expression *")) (stream-topic "Expression *" - :reader t + :scope :public :capnp-type "Ast.Tree" :capnp-init nil :capnp-save #'save-ast-pointer :capnp-load (load-ast-pointer "Expression *")) (transform-uri "Expression *" - :reader t + :scope :public :capnp-type "Ast.Tree" :capnp-init nil :capnp-save #'save-ast-pointer :capnp-load (load-ast-pointer "Expression *")) (batch-interval-in-ms "Expression *" - :reader t + :scope :public :capnp-type "Ast.Tree" :capnp-init nil :capnp-save #'save-ast-pointer :capnp-load (load-ast-pointer "Expression *")) (batch-size "Expression *" - :reader t + :scope :public :capnp-type "Ast.Tree" :capnp-init nil :capnp-save #'save-ast-pointer @@ -2371,6 +2365,7 @@ vectors of symbols used by each of the inputs.") "Creates a new stream with given parameters that imports data.") (:public #>cpp + CreateStream() {} CreateStream(std::string stream_name, Expression *stream_uri, Expression *stream_topic, Expression *transform_uri, Expression *batch_interval_in_ms, Expression *batch_size); @@ -2385,16 +2380,15 @@ vectors of symbols used by each of the inputs.") std::shared_ptr input() const override; void set_input(std::shared_ptr) override; cpp<#) - (:private - #>cpp CreateStream() {} cpp<#) (:serialize :capnp)) (lcp:define-class drop-stream (logical-operator) - ((stream-name "std::string" :reader t)) + ((stream-name "std::string" :scope :public)) (:documentation "Stops and deletes a stream if it exists.") (:public #>cpp + DropStream() {} explicit DropStream(std::string stream_name); DEFVISITABLE(HierarchicalLogicalOperatorVisitor); std::unique_ptr MakeCursor( @@ -2407,20 +2401,19 @@ vectors of symbols used by each of the inputs.") std::shared_ptr input() const override; void set_input(std::shared_ptr) override; cpp<#) - (:private - #>cpp DropStream() {} cpp<#) (:serialize :capnp)) (lcp:define-class show-streams (logical-operator) - ((name-symbol "Symbol" :reader t) - (uri-symbol "Symbol" :reader t) - (topic-symbol "Symbol" :reader t) - (transform-symbol "Symbol" :reader t) - (status-symbol "Symbol" :reader t)) + ((name-symbol "Symbol" :scope :public) + (uri-symbol "Symbol" :scope :public) + (topic-symbol "Symbol" :scope :public) + (transform-symbol "Symbol" :scope :public) + (status-symbol "Symbol" :scope :public)) (:documentation "Shows all streams, started and stopped, that were configured.") (:public #>cpp + ShowStreams() {} ShowStreams(Symbol name_symbol, Symbol endpoint_symbol, Symbol topic_symbol, Symbol transform_symbol, Symbol status_symbol); DEFVISITABLE(HierarchicalLogicalOperatorVisitor); @@ -2435,15 +2428,13 @@ vectors of symbols used by each of the inputs.") std::shared_ptr input() const override; void set_input(std::shared_ptr) override; cpp<#) - (:private - #>cpp ShowStreams() {} cpp<#) (:serialize :capnp)) (lcp:define-class start-stop-stream (logical-operator) - ((stream-name "std::string" :reader t) - (is-start :bool :reader t) + ((stream-name "std::string" :scope :public) + (is-start :bool :scope :public) (limit-batches "Expression *" - :reader t + :scope :public :capnp-type "Ast.Tree" :capnp-init nil :capnp-save #'save-ast-pointer @@ -2455,6 +2446,7 @@ If a stream is already running, it wont limit the number of batches that this stream is importing.") (:public #>cpp + StartStopStream() {} StartStopStream(std::string stream_name, bool is_start, Expression *limit_batches); DEFVISITABLE(HierarchicalLogicalOperatorVisitor); @@ -2468,17 +2460,16 @@ stream is importing.") std::shared_ptr input() const override; void set_input(std::shared_ptr) override; cpp<#) - (:private - #>cpp StartStopStream() {} cpp<#) (:serialize :capnp)) (lcp:define-class start-stop-all-streams (logical-operator) - ((stream-name "std::string" :reader t) - (is-start :bool :reader t)) + ((stream-name "std::string" :scope :public) + (is-start :bool :scope :public)) (:documentation "Starts or stops all stream.") (:public #>cpp + StartStopAllStreams() {} explicit StartStopAllStreams(bool is_start); DEFVISITABLE(HierarchicalLogicalOperatorVisitor); std::unique_ptr MakeCursor( @@ -2491,25 +2482,24 @@ stream is importing.") std::shared_ptr input() const override; void set_input(std::shared_ptr) override; cpp<#) - (:private - #>cpp StartStopAllStreams() {} cpp<#) (:serialize :capnp)) (lcp:define-class test-stream (logical-operator) - ((stream-name "std::string" :reader t) + ((stream-name "std::string" :scope :public) (limit-batches "Expression *" - :reader t + :scope :public :capnp-type "Ast.Tree" :capnp-init nil :capnp-save #'save-ast-pointer :capnp-load (load-ast-pointer "Expression *")) - (query-symbol "Symbol" :reader t) - (params-symbol "Symbol" :reader t)) + (query-symbol "Symbol" :scope :public) + (params-symbol "Symbol" :scope :public)) (:documentation "Test a stream. This will start consuming messages but wont insert anything in the db.") (:public #>cpp + TestStream() {} TestStream(std::string stream_name, Expression *limit_batches, Symbol query_symbol, Symbol params_symbol); DEFVISITABLE(HierarchicalLogicalOperatorVisitor); @@ -2524,17 +2514,15 @@ in the db.") std::shared_ptr input() const override; void set_input(std::shared_ptr) override; cpp<#) - (:private - #>cpp TestStream() {} cpp<#) (:serialize :capnp)) ;;; END KAFKA STREAM OPERATORS (lcp:define-class explain (logical-operator) - ((input "std::shared_ptr" + ((input "std::shared_ptr" :scope :public :capnp-save #'save-operator-pointer :capnp-load #'load-operator-pointer) - (output-symbol "Symbol" :reader t) + (output-symbol "Symbol" :scope :public) (pretty-print "std::function" :scope :public :documentation "Pretty printer function" @@ -2542,6 +2530,7 @@ in the db.") (:documentation "Pretty print a LogicalOperator plan") (:public #>cpp + Explain() {} Explain( const std::shared_ptr &input, const Symbol &output_symbol, const std::functioncpp Explain () {} cpp<#) (:serialize :capnp)) (lcp:pop-namespace) ;; plan diff --git a/src/query/plan/pretty_print.cpp b/src/query/plan/pretty_print.cpp index c0d516e58..eee3d7d30 100644 --- a/src/query/plan/pretty_print.cpp +++ b/src/query/plan/pretty_print.cpp @@ -21,7 +21,7 @@ PRE_VISIT(Delete); bool PlanPrinter::PreVisit(query::plan::ScanAll &op) { WithPrintLn([&](auto &out) { out << "* ScanAll" - << " (" << op.output_symbol().name() << ")"; + << " (" << op.output_symbol_.name() << ")"; }); return true; } @@ -29,8 +29,8 @@ bool PlanPrinter::PreVisit(query::plan::ScanAll &op) { bool PlanPrinter::PreVisit(query::plan::ScanAllByLabel &op) { WithPrintLn([&](auto &out) { out << "* ScanAllByLabel" - << " (" << op.output_symbol().name() << " :" - << dba_->LabelName(op.label()) << ")"; + << " (" << op.output_symbol_.name() << " :" + << dba_->LabelName(op.label_) << ")"; }); return true; } @@ -38,9 +38,9 @@ bool PlanPrinter::PreVisit(query::plan::ScanAllByLabel &op) { bool PlanPrinter::PreVisit(query::plan::ScanAllByLabelPropertyValue &op) { WithPrintLn([&](auto &out) { out << "* ScanAllByLabelPropertyValue" - << " (" << op.output_symbol().name() << " :" - << dba_->LabelName(op.label()) << " {" - << dba_->PropertyName(op.property()) << "})"; + << " (" << op.output_symbol_.name() << " :" + << dba_->LabelName(op.label_) << " {" + << dba_->PropertyName(op.property_) << "})"; }); return true; } @@ -48,9 +48,9 @@ bool PlanPrinter::PreVisit(query::plan::ScanAllByLabelPropertyValue &op) { bool PlanPrinter::PreVisit(query::plan::ScanAllByLabelPropertyRange &op) { WithPrintLn([&](auto &out) { out << "* ScanAllByLabelPropertyRange" - << " (" << op.output_symbol().name() << " :" - << dba_->LabelName(op.label()) << " {" - << dba_->PropertyName(op.property()) << "})"; + << " (" << op.output_symbol_.name() << " :" + << dba_->LabelName(op.label_) << " {" + << dba_->PropertyName(op.property_) << "})"; }); return true; } @@ -75,7 +75,7 @@ bool PlanPrinter::PreVisit(query::plan::Produce &op) { WithPrintLn([&](auto &out) { out << "* Produce {"; utils::PrintIterable( - out, op.named_expressions(), ", ", + out, op.named_expressions_, ", ", [](auto &out, const auto &nexpr) { out << nexpr->name_; }); out << "}"; }); @@ -97,10 +97,10 @@ bool PlanPrinter::PreVisit(query::plan::Aggregate &op) { WithPrintLn([&](auto &out) { out << "* Aggregate {"; utils::PrintIterable( - out, op.aggregations(), ", ", + out, op.aggregations_, ", ", [](auto &out, const auto &aggr) { out << aggr.output_sym.name(); }); out << "} {"; - utils::PrintIterable(out, op.remember(), ", ", + utils::PrintIterable(out, op.remember_, ", ", [](auto &out, const auto &sym) { out << sym.name(); }); out << "}"; }); @@ -113,7 +113,7 @@ PRE_VISIT(Limit); bool PlanPrinter::PreVisit(query::plan::OrderBy &op) { WithPrintLn([&op](auto &out) { out << "* OrderBy {"; - utils::PrintIterable(out, op.output_symbols(), ", ", + utils::PrintIterable(out, op.output_symbols_, ", ", [](auto &out, const auto &sym) { out << sym.name(); }); out << "}"; }); @@ -122,16 +122,16 @@ bool PlanPrinter::PreVisit(query::plan::OrderBy &op) { bool PlanPrinter::PreVisit(query::plan::Merge &op) { WithPrintLn([](auto &out) { out << "* Merge"; }); - Branch(*op.merge_match(), "On Match"); - Branch(*op.merge_create(), "On Create"); - op.input()->Accept(*this); + Branch(*op.merge_match_, "On Match"); + Branch(*op.merge_create_, "On Create"); + op.input_->Accept(*this); return false; } bool PlanPrinter::PreVisit(query::plan::Optional &op) { WithPrintLn([](auto &out) { out << "* Optional"; }); - Branch(*op.optional()); - op.input()->Accept(*this); + Branch(*op.optional_); + op.input_->Accept(*this); return false; } @@ -185,7 +185,7 @@ bool PlanPrinter::Visit(query::plan::TestStream &op) { bool PlanPrinter::PreVisit(query::plan::Explain &explain) { WithPrintLn([&explain](auto &out) { - out << "* Explain {" << explain.output_symbol().name() << "}"; + out << "* Explain {" << explain.output_symbol_.name() << "}"; }); return true; } @@ -193,15 +193,15 @@ bool PlanPrinter::PreVisit(query::plan::Explain &explain) { bool PlanPrinter::PreVisit(query::plan::Cartesian &op) { WithPrintLn([&op](auto &out) { out << "* Cartesian {"; - utils::PrintIterable(out, op.left_symbols(), ", ", + utils::PrintIterable(out, op.left_symbols_, ", ", [](auto &out, const auto &sym) { out << sym.name(); }); out << " : "; - utils::PrintIterable(out, op.right_symbols(), ", ", + utils::PrintIterable(out, op.right_symbols_, ", ", [](auto &out, const auto &sym) { out << sym.name(); }); out << "}"; }); - Branch(*op.right_op()); - op.left_op()->Accept(*this); + Branch(*op.right_op_); + op.left_op_->Accept(*this); return false; } @@ -221,11 +221,11 @@ void PlanPrinter::Branch(query::plan::LogicalOperator &op, } void PlanPrinter::PrintExpand(const query::plan::ExpandCommon &op) { - *out_ << " (" << op.input_symbol().name() << ")" - << (op.direction() == query::EdgeAtom::Direction::IN ? "<-" : "-") - << "[" << op.edge_symbol().name() << "]" - << (op.direction() == query::EdgeAtom::Direction::OUT ? "->" : "-") - << "(" << op.node_symbol().name() << ")"; + *out_ << " (" << op.input_symbol_.name() << ")" + << (op.direction_ == query::EdgeAtom::Direction::IN ? "<-" : "-") << "[" + << op.edge_symbol_.name() << "]" + << (op.direction_ == query::EdgeAtom::Direction::OUT ? "->" : "-") + << "(" << op.node_symbol_.name() << ")"; } void PrettyPrint(const database::GraphDbAccessor &dba, diff --git a/src/storage/address.hpp b/src/storage/address.hpp index 506e6a9f3..6a3ab83f6 100644 --- a/src/storage/address.hpp +++ b/src/storage/address.hpp @@ -89,11 +89,6 @@ class Address { return storage_ == other.storage_; } - void Load(const capnp::Address::Reader &reader) { - storage_ = reader.getStorage(); - } - - private: StorageT storage_{0}; }; @@ -103,8 +98,8 @@ void Save(const Address &address, capnp::Address::Builder *builder) { } template -Address Load(const capnp::Address::Reader &reader) { - return Address(reader.getStorage()); +void Load(Address *address, const capnp::Address::Reader &reader) { + address->storage_ = reader.getStorage(); } } // namespace storage diff --git a/src/storage/concurrent_id_mapper_master.cpp b/src/storage/concurrent_id_mapper_master.cpp index 10d11bb47..7fb6c17b8 100644 --- a/src/storage/concurrent_id_mapper_master.cpp +++ b/src/storage/concurrent_id_mapper_master.cpp @@ -17,14 +17,14 @@ void RegisterRpc(MasterConcurrentIdMapper &mapper, rpc_server.Register( \ [&mapper](const auto &req_reader, auto *res_builder) { \ type##IdReq req; \ - req.Load(req_reader); \ + Load(&req, req_reader); \ type##IdRes res(mapper.value_to_id(req.member)); \ Save(res, res_builder); \ }); \ rpc_server.Register( \ [&mapper](const auto &req_reader, auto *res_builder) { \ Id##type##Req req; \ - req.Load(req_reader); \ + Load(&req, req_reader); \ Id##type##Res res(mapper.id_to_value(req.member)); \ Save(res, res_builder); \ }); \ diff --git a/src/storage/serialization.cpp b/src/storage/serialization.cpp index 041c0ebea..e02d4bd2c 100644 --- a/src/storage/serialization.cpp +++ b/src/storage/serialization.cpp @@ -107,7 +107,7 @@ void LoadProperties(const capnp::PropertyValueStore::Reader &reader, auto props_reader = reader.getProperties(); for (const auto &kv_reader : props_reader) { storage::Property id; - id.Load(kv_reader.getId()); + storage::Load(&id, kv_reader.getId()); PropertyValue value; LoadCapnpPropertyValue(kv_reader.getValue(), &value); properties->set(id, value); diff --git a/src/storage/types.hpp b/src/storage/types.hpp index 503b11890..f786c1bfe 100644 --- a/src/storage/types.hpp +++ b/src/storage/types.hpp @@ -54,25 +54,23 @@ class Common : public utils::TotalOrdering { size_t operator()(const TSpecificType &t) const { return hash(t.id_); } }; - void Load(const capnp::Common::Reader &reader) { - id_ = reader.getStorage(); - } - - auto Raw() const { return id_; } - + IdT id_{0}; protected: ~Common() {} private: static constexpr IdT Mask = std::numeric_limits::max() >> 1; static constexpr IdT NotMask = ~Mask; - - IdT id_{0}; }; template void Save(const Common &common, capnp::Common::Builder *builder) { - builder->setStorage(common.Raw()); + builder->setStorage(common.id_); +} + +template +void Load(Common *common, const capnp::Common::Reader &reader) { + common->id_ = reader.getStorage(); } class Label final : public Common