Generate Load functions from LCP as top level

Summary: Depends on D1596

Reviewers: mtomic, msantl

Reviewed By: msantl

Subscribers: pullbot

Differential Revision: https://phabricator.memgraph.io/D1601
This commit is contained in:
Teon Banek 2018-09-20 10:55:49 +02:00
parent a5926b4e0f
commit 1fd9a72e10
52 changed files with 1376 additions and 1362 deletions

View File

@ -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 <id> use `capnp id` # file through `add_capnp` function. To generate the <id> use `capnp id`
# invocation, and specify it here. This preserves correct id information across # invocation, and specify it here. This preserves correct id information across
# multiple schema generations. If this wasn't the case, wrong typeId # multiple schema generations. If this wasn't the case, wrong typeId
# information will break RPC between different compilations of memgraph. # information will break serialization 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.
macro(define_add_lcp name main_src_files generated_lcp_files) macro(define_add_lcp name main_src_files generated_lcp_files)
function(${name} lcp_file) function(${name} lcp_file)
set(options CAPNP_DECLARATION)
set(one_value_kwargs CAPNP_SCHEMA) set(one_value_kwargs CAPNP_SCHEMA)
set(multi_value_kwargs DEPENDS) set(multi_value_kwargs DEPENDS)
# NOTE: ${${}ARGN} syntax escapes evaluating macro's ARGN variable; see: # 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 # 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 string(REGEX REPLACE "\.lcp$" ".hpp" h_file
"${CMAKE_CURRENT_SOURCE_DIR}/${lcp_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 string(REGEX REPLACE "\.lcp$" ".capnp" capnp_file
"${CMAKE_CURRENT_SOURCE_DIR}/${lcp_file}") "${CMAKE_CURRENT_SOURCE_DIR}/${lcp_file}")
set(capnp_id ${KW_CAPNP_SCHEMA}) 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 # Update *global* main_src_files
set(${main_src_files} ${${main_src_files}} ${cpp_file} PARENT_SCOPE) set(${main_src_files} ${${main_src_files}} ${cpp_file} PARENT_SCOPE)
endif() endif()
if (KW_CAPNP_DECLARATION)
set(capnp_id "--capnp-declaration")
endif()
add_custom_command(OUTPUT ${h_file} ${cpp_file} ${capnp_file} add_custom_command(OUTPUT ${h_file} ${cpp_file} ${capnp_file}
COMMAND ${lcp_exe} ${lcp_file} ${capnp_id} COMMAND ${lcp_exe} ${lcp_file} ${capnp_id}
VERBATIM VERBATIM

View File

@ -384,7 +384,7 @@ to perform the registration manually. For example:
rpc_server.Register<QueryResultRpc>( rpc_server.Register<QueryResultRpc>(
[](const auto &req_reader, auto *res_builder) { [](const auto &req_reader, auto *res_builder) {
QueryResultReq request; QueryResultReq request;
request.Load(req_reader); Load(&request, req_reader);
// process the request and send the response // process the request and send the response
QueryResultRes response(values_for_response); QueryResultRes response(values_for_response);
Save(response, res_builder); Save(response, res_builder);
@ -421,7 +421,7 @@ To specify a class or structure for serialization, you may pass a
For example: For example:
```lisp ```lisp
(lcp:define-class my-class () (lcp:define-struct my-struct ()
((member :int64_t)) ((member :int64_t))
(:serialize :capnp)) (:serialize :capnp))
``` ```
@ -431,11 +431,9 @@ it in the `.capnp` file. C++ code will be generated for saving and loading
members: members:
```cpp ```cpp
// Top level function // Top level functions
void Save(const MyClass &instance, capnp::MyClass::Builder *builder); void Save(const MyStruct &self, capnp::MyStruct::Builder *builder);
void Load(MyStruct *self, const capnp::MyStruct::Reader &reader);
// Member function
void MyClass::Load(const capnp::MyClass::Reader &reader);
``` ```
Since we use top level functions, the class needs to have some sort of public Since we use top level functions, the class needs to have some sort of public
@ -454,31 +452,26 @@ For example:
```lisp ```lisp
(lcp:define-class base () (lcp:define-class base ()
((base-member "std::vector<int64_t>")) ((base-member "std::vector<int64_t>" :scope :public))
(:serialize :capnp)) (:serialize :capnp))
(lcp:define-class derived (base) (lcp:define-class derived (base)
((derived-member :bool)) ((derived-member :bool :scope :public))
(:serialize :capnp)) (:serialize :capnp))
``` ```
Note that all classes need to have the `:serialize` option set. Signatures of 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 `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 base class. The `Load` function now takes a `std::unique_ptr<T> *` which is
concrete type from a base reader. 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 ```cpp
void Save(const Derived &derived, capnp::Base *builder); void Save(const Derived &self, capnp::Base::Builder *builder);
void Load(std::unique_ptr<Base> *self, const capnp::Base::Reader &reader);
class Derived {
...
static std::unique_ptr<Base> Construct(const capnp::Base &reader);
virtual void Load(const capnp::Base &reader);
``` ```
With polymorphic types, you need to call `Base::Construct` followed by `Load`.
#### Multiple Inheritance #### Multiple Inheritance
Cap'n Proto does not support any form of inheritance, instead we are 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 cases. It is usually needed when you set `:capnp-init nil`, so that you can
correctly initialize the builder. correctly initialize the builder.
Similarly, `:capnp-load` expects a function taking a reader and a member, then Similarly, `:capnp-load` expects a function taking a reader, C++ member and
returns a C++ block. Cap'n Proto member, then returns a C++ block.
Example: Example:
@ -630,7 +623,8 @@ Example:
auto my_builder = ${builder}.init${capnp-name}(); auto my_builder = ${builder}.init${capnp-name}();
my_builder.setData(data); my_builder.setData(data);
cpp<#) cpp<#)
:capnp-load (lambda (reader member) :capnp-load (lambda (reader member capnp-name)
(declare (ignore capnp-name))
#>cpp #>cpp
auto data = ${reader}.getData(); auto data = ${reader}.getData();
${member}.LoadFromData(data); ${member}.LoadFromData(data);

View File

@ -115,9 +115,9 @@ add_capnp(distributed/updates_rpc_messages.capnp)
add_lcp(distributed/dynamic_worker_rpc_messages.lcp CAPNP_SCHEMA @0x8c53f6c9a0c71b05) add_lcp(distributed/dynamic_worker_rpc_messages.lcp CAPNP_SCHEMA @0x8c53f6c9a0c71b05)
add_capnp(distributed/dynamic_worker_rpc_messages.capnp) add_capnp(distributed/dynamic_worker_rpc_messages.capnp)
# distributed_ops.lcp is leading the capnp code generation, so we only want # distributed_ops.lcp is leading the capnp code generation, so we don't need
# function declarations in generated operator.hpp # to generate any capnp for operator.lcp
add_lcp(query/plan/operator.lcp CAPNP_DECLARATION) add_lcp(query/plan/operator.lcp)
add_lcp(query/plan/distributed_ops.lcp CAPNP_SCHEMA @0xe5cae8d045d30c42 add_lcp(query/plan/distributed_ops.lcp CAPNP_SCHEMA @0xe5cae8d045d30c42
DEPENDS query/plan/operator.lcp) DEPENDS query/plan/operator.lcp)
add_capnp(query/plan/distributed_ops.capnp) add_capnp(query/plan/distributed_ops.capnp)

View File

@ -36,7 +36,7 @@ class Client {
return CallWithLoad<TRequestResponse>( return CallWithLoad<TRequestResponse>(
[](const auto &reader) { [](const auto &reader) {
typename TRequestResponse::Response response; typename TRequestResponse::Response response;
response.Load(reader); Load(&response, reader);
return response; return response;
}, },
std::forward<Args>(args)...); std::forward<Args>(args)...);

View File

@ -59,7 +59,8 @@ cpp<#
storage::SaveCapnpPropertyValue(${member}, &${builder}); storage::SaveCapnpPropertyValue(${member}, &${builder});
cpp<#) cpp<#)
:capnp-load :capnp-load
(lambda (reader member) (lambda (reader member capnp-name)
(declare (ignore capnp-name))
#>cpp #>cpp
storage::LoadCapnpPropertyValue(${reader}, &${member}); storage::LoadCapnpPropertyValue(${reader}, &${member});
cpp<#)) cpp<#))

View File

@ -21,7 +21,7 @@ class StorageGcMaster : public StorageGc {
rpc_server_.Register<distributed::RanLocalGcRpc>( rpc_server_.Register<distributed::RanLocalGcRpc>(
[this](const auto &req_reader, auto *res_builder) { [this](const auto &req_reader, auto *res_builder) {
distributed::RanLocalGcReq req; distributed::RanLocalGcReq req;
req.Load(req_reader); Load(&req, req_reader);
std::unique_lock<std::mutex> lock(worker_safe_transaction_mutex_); std::unique_lock<std::mutex> lock(worker_safe_transaction_mutex_);
worker_safe_transaction_[req.worker_id] = req.local_oldest_active; worker_safe_transaction_[req.worker_id] = req.local_oldest_active;
}); });

View File

@ -88,7 +88,7 @@ std::experimental::optional<VertexAccessor> BfsRpcClients::Pull(
auto res = coordination_->GetClientPool(worker_id)->CallWithLoad<SubcursorPullRpc>( auto res = coordination_->GetClientPool(worker_id)->CallWithLoad<SubcursorPullRpc>(
[this, dba](const auto &reader) { [this, dba](const auto &reader) {
SubcursorPullRes res; SubcursorPullRes res;
res.Load(reader, dba, this->data_manager_); Load(&res, reader, dba, this->data_manager_);
return res; return res;
}, },
subcursor_id); subcursor_id);
@ -152,7 +152,7 @@ PathSegment BfsRpcClients::ReconstructPath(
coordination_->GetClientPool(worker_id)->CallWithLoad<ReconstructPathRpc>( coordination_->GetClientPool(worker_id)->CallWithLoad<ReconstructPathRpc>(
[this, dba](const auto &reader) { [this, dba](const auto &reader) {
ReconstructPathRes res; ReconstructPathRes res;
res.Load(reader, dba, this->data_manager_); Load(&res, reader, dba, this->data_manager_);
return res; return res;
}, },
subcursor_ids.at(worker_id), vertex); subcursor_ids.at(worker_id), vertex);
@ -171,7 +171,7 @@ PathSegment BfsRpcClients::ReconstructPath(
coordination_->GetClientPool(worker_id)->CallWithLoad<ReconstructPathRpc>( coordination_->GetClientPool(worker_id)->CallWithLoad<ReconstructPathRpc>(
[this, dba](const auto &reader) { [this, dba](const auto &reader) {
ReconstructPathRes res; ReconstructPathRes res;
res.Load(reader, dba, this->data_manager_); Load(&res, reader, dba, this->data_manager_);
return res; return res;
}, },
subcursor_ids.at(worker_id), edge); subcursor_ids.at(worker_id), edge);

View File

@ -65,7 +65,8 @@ cpp<#
}); });
cpp<#) cpp<#)
:capnp-load :capnp-load
(lambda (reader member) (lambda (reader member capnp-name)
(declare (ignore capnp-name))
#>cpp #>cpp
utils::LoadMap<utils::capnp::BoxInt16, utils::capnp::BoxInt64>( utils::LoadMap<utils::capnp::BoxInt16, utils::capnp::BoxInt64>(
&${member}, ${reader}, &${member}, ${reader},

View File

@ -24,7 +24,7 @@ class BfsRpcServer {
server_->Register<CreateBfsSubcursorRpc>( server_->Register<CreateBfsSubcursorRpc>(
[this](const auto &req_reader, auto *res_builder) { [this](const auto &req_reader, auto *res_builder) {
CreateBfsSubcursorReq req; CreateBfsSubcursorReq req;
req.Load(req_reader); Load(&req, req_reader);
CreateBfsSubcursorRes res(subcursor_storage_->Create( CreateBfsSubcursorRes res(subcursor_storage_->Create(
req.tx_id, req.direction, req.edge_types, req.graph_view)); req.tx_id, req.direction, req.edge_types, req.graph_view));
Save(res, res_builder); Save(res, res_builder);
@ -33,7 +33,7 @@ class BfsRpcServer {
server_->Register<RegisterSubcursorsRpc>( server_->Register<RegisterSubcursorsRpc>(
[this](const auto &req_reader, auto *res_builder) { [this](const auto &req_reader, auto *res_builder) {
RegisterSubcursorsReq req; RegisterSubcursorsReq req;
req.Load(req_reader); Load(&req, req_reader);
subcursor_storage_->Get(req.subcursor_ids.at(db_->WorkerId())) subcursor_storage_->Get(req.subcursor_ids.at(db_->WorkerId()))
->RegisterSubcursors(req.subcursor_ids); ->RegisterSubcursors(req.subcursor_ids);
RegisterSubcursorsRes res; RegisterSubcursorsRes res;
@ -43,7 +43,7 @@ class BfsRpcServer {
server_->Register<ResetSubcursorRpc>( server_->Register<ResetSubcursorRpc>(
[this](const auto &req_reader, auto *res_builder) { [this](const auto &req_reader, auto *res_builder) {
ResetSubcursorReq req; ResetSubcursorReq req;
req.Load(req_reader); Load(&req, req_reader);
subcursor_storage_->Get(req.subcursor_id)->Reset(); subcursor_storage_->Get(req.subcursor_id)->Reset();
ResetSubcursorRes res; ResetSubcursorRes res;
Save(res, res_builder); Save(res, res_builder);
@ -52,7 +52,7 @@ class BfsRpcServer {
server_->Register<RemoveBfsSubcursorRpc>( server_->Register<RemoveBfsSubcursorRpc>(
[this](const auto &req_reader, auto *res_builder) { [this](const auto &req_reader, auto *res_builder) {
RemoveBfsSubcursorReq req; RemoveBfsSubcursorReq req;
req.Load(req_reader); Load(&req, req_reader);
subcursor_storage_->Erase(req.member); subcursor_storage_->Erase(req.member);
RemoveBfsSubcursorRes res; RemoveBfsSubcursorRes res;
Save(res, res_builder); Save(res, res_builder);
@ -61,7 +61,7 @@ class BfsRpcServer {
server_->Register<SetSourceRpc>( server_->Register<SetSourceRpc>(
[this](const auto &req_reader, auto *res_builder) { [this](const auto &req_reader, auto *res_builder) {
SetSourceReq req; SetSourceReq req;
req.Load(req_reader); Load(&req, req_reader);
subcursor_storage_->Get(req.subcursor_id)->SetSource(req.source); subcursor_storage_->Get(req.subcursor_id)->SetSource(req.source);
SetSourceRes res; SetSourceRes res;
Save(res, res_builder); Save(res, res_builder);
@ -70,7 +70,7 @@ class BfsRpcServer {
server_->Register<ExpandLevelRpc>([this](const auto &req_reader, server_->Register<ExpandLevelRpc>([this](const auto &req_reader,
auto *res_builder) { auto *res_builder) {
ExpandLevelReq req; ExpandLevelReq req;
req.Load(req_reader); Load(&req, req_reader);
ExpandLevelRes res(subcursor_storage_->Get(req.member)->ExpandLevel()); ExpandLevelRes res(subcursor_storage_->Get(req.member)->ExpandLevel());
Save(res, res_builder); Save(res, res_builder);
}); });
@ -78,7 +78,7 @@ class BfsRpcServer {
server_->Register<SubcursorPullRpc>( server_->Register<SubcursorPullRpc>(
[this](const auto &req_reader, auto *res_builder) { [this](const auto &req_reader, auto *res_builder) {
SubcursorPullReq req; SubcursorPullReq req;
req.Load(req_reader); Load(&req, req_reader);
auto vertex = subcursor_storage_->Get(req.member)->Pull(); auto vertex = subcursor_storage_->Get(req.member)->Pull();
SubcursorPullRes res(vertex); SubcursorPullRes res(vertex);
Save(res, res_builder, db_->WorkerId()); Save(res, res_builder, db_->WorkerId());
@ -87,7 +87,7 @@ class BfsRpcServer {
server_->Register<ExpandToRemoteVertexRpc>( server_->Register<ExpandToRemoteVertexRpc>(
[this](const auto &req_reader, auto *res_builder) { [this](const auto &req_reader, auto *res_builder) {
ExpandToRemoteVertexReq req; ExpandToRemoteVertexReq req;
req.Load(req_reader); Load(&req, req_reader);
ExpandToRemoteVertexRes res( ExpandToRemoteVertexRes res(
subcursor_storage_->Get(req.subcursor_id) subcursor_storage_->Get(req.subcursor_id)
->ExpandToLocalVertex(req.edge, req.vertex)); ->ExpandToLocalVertex(req.edge, req.vertex));
@ -97,7 +97,7 @@ class BfsRpcServer {
server_->Register<ReconstructPathRpc>([this](const auto &req_reader, server_->Register<ReconstructPathRpc>([this](const auto &req_reader,
auto *res_builder) { auto *res_builder) {
ReconstructPathReq req; ReconstructPathReq req;
req.Load(req_reader); Load(&req, req_reader);
auto subcursor = subcursor_storage_->Get(req.subcursor_id); auto subcursor = subcursor_storage_->Get(req.subcursor_id);
PathSegment result; PathSegment result;
if (req.vertex) { if (req.vertex) {
@ -114,7 +114,7 @@ class BfsRpcServer {
server_->Register<PrepareForExpandRpc>([this](const auto &req_reader, server_->Register<PrepareForExpandRpc>([this](const auto &req_reader,
auto *res_builder) { auto *res_builder) {
PrepareForExpandReq req; PrepareForExpandReq req;
req.Load(req_reader); Load(&req, req_reader);
subcursor_storage_->Get(req.subcursor_id)->PrepareForExpand(req.clear); subcursor_storage_->Get(req.subcursor_id)->PrepareForExpand(req.clear);
PrepareForExpandRes res; PrepareForExpandRes res;
Save(res, res_builder); Save(res, res_builder);

View File

@ -24,7 +24,7 @@ ClusterDiscoveryMaster::ClusterDiscoveryMaster(
bool durability_error = false; bool durability_error = false;
RegisterWorkerReq req; RegisterWorkerReq req;
req.Load(req_reader); Load(&req, req_reader);
// Compose the worker's endpoint from its connecting address and its // Compose the worker's endpoint from its connecting address and its
// advertised port. // advertised port.
@ -83,7 +83,7 @@ ClusterDiscoveryMaster::ClusterDiscoveryMaster(
server_->Register<NotifyWorkerRecoveredRpc>([this](const auto &req_reader, server_->Register<NotifyWorkerRecoveredRpc>([this](const auto &req_reader,
auto *res_builder) { auto *res_builder) {
NotifyWorkerRecoveredReq req; NotifyWorkerRecoveredReq req;
req.Load(req_reader); Load(&req, req_reader);
coordination_->WorkerRecoveredSnapshot(req.worker_id, req.recovery_info); coordination_->WorkerRecoveredSnapshot(req.worker_id, req.recovery_info);
}); });
} }

View File

@ -15,7 +15,7 @@ ClusterDiscoveryWorker::ClusterDiscoveryWorker(
server_.Register<ClusterDiscoveryRpc>( server_.Register<ClusterDiscoveryRpc>(
[this](const auto &req_reader, auto *res_builder) { [this](const auto &req_reader, auto *res_builder) {
ClusterDiscoveryReq req; ClusterDiscoveryReq req;
req.Load(req_reader); Load(&req, req_reader);
this->coordination_.RegisterWorker(req.worker_id, req.endpoint); this->coordination_.RegisterWorker(req.worker_id, req.endpoint);
}); });
} }

View File

@ -42,7 +42,8 @@ cpp<#
}); });
cpp<#) cpp<#)
:capnp-load :capnp-load
(lambda (reader member) (lambda (reader member capnp-name)
(declare (ignore capnp-name))
#>cpp #>cpp
${member} = utils::LoadOptional<utils::capnp::Pair<utils::capnp::BoxUInt64, utils::capnp::BoxUInt64>, std::pair<int64_t, tx::TransactionId>>( ${member} = utils::LoadOptional<utils::capnp::Pair<utils::capnp::BoxUInt64, utils::capnp::BoxUInt64>, std::pair<int64_t, tx::TransactionId>>(
${reader}, [](auto reader){ ${reader}, [](auto reader){
@ -64,12 +65,13 @@ cpp<#
}); });
cpp<#) cpp<#)
:capnp-load :capnp-load
(lambda (reader member) (lambda (reader member capnp-name)
(declare (ignore capnp-name))
#>cpp #>cpp
utils::LoadMap<utils::capnp::BoxInt16, io::network::capnp::Endpoint>(&${member}, ${reader}, utils::LoadMap<utils::capnp::BoxInt16, io::network::capnp::Endpoint>(&${member}, ${reader},
[](const auto &reader) { [](const auto &reader) {
io::network::Endpoint value; io::network::Endpoint value;
value.Load(reader.getValue()); Load(&value, reader.getValue());
return std::make_pair( return std::make_pair(
reader.getKey().getValue(), value); reader.getKey().getValue(), value);
}); });

View File

@ -38,10 +38,10 @@ cpp<#
storage::SaveVertex(*${member}, &${builder}, self.worker_id); storage::SaveVertex(*${member}, &${builder}, self.worker_id);
cpp<#) cpp<#)
:capnp-load :capnp-load
(lambda (reader member) (lambda (reader member capnp-name)
(declare (ignore member)) (declare (ignore member capnp-name))
#>cpp #>cpp
vertex_output = storage::LoadVertex(${reader}); self->vertex_output = storage::LoadVertex(${reader});
cpp<#)) cpp<#))
(worker-id :int64_t :capnp-save :dont-save) (worker-id :int64_t :capnp-save :dont-save)
(vertex-output "std::unique_ptr<Vertex>" :initarg nil (vertex-output "std::unique_ptr<Vertex>" :initarg nil
@ -60,10 +60,10 @@ cpp<#
storage::SaveEdge(*${member}, &${builder}, self.worker_id); storage::SaveEdge(*${member}, &${builder}, self.worker_id);
cpp<#) cpp<#)
:capnp-load :capnp-load
(lambda (reader member) (lambda (reader member capnp-name)
(declare (ignore member)) (declare (ignore member capnp-name))
#>cpp #>cpp
edge_output = storage::LoadEdge(${reader}); self->edge_output = storage::LoadEdge(${reader});
cpp<#)) cpp<#))
(worker-id :int64_t :capnp-save :dont-save) (worker-id :int64_t :capnp-save :dont-save)
(edge-output "std::unique_ptr<Edge>" :initarg nil (edge-output "std::unique_ptr<Edge>" :initarg nil

View File

@ -33,7 +33,7 @@ DataRpcServer::DataRpcServer(database::DistributedGraphDb *db,
rpc_server_->Register<VertexCountRpc>( rpc_server_->Register<VertexCountRpc>(
[this](const auto &req_reader, auto *res_builder) { [this](const auto &req_reader, auto *res_builder) {
VertexCountReq req; VertexCountReq req;
req.Load(req_reader); Load(&req, req_reader);
auto dba = db_->Access(req.member); auto dba = db_->Access(req.member);
int64_t size = 0; int64_t size = 0;
for (auto vertex : dba->Vertices(false)) ++size; for (auto vertex : dba->Vertices(false)) ++size;

View File

@ -19,7 +19,7 @@ DurabilityRpcWorker::DurabilityRpcWorker(database::Worker *db,
rpc_server_->Register<RecoverWalAndIndexesRpc>( rpc_server_->Register<RecoverWalAndIndexesRpc>(
[this](const auto &req_reader, auto *res_builder) { [this](const auto &req_reader, auto *res_builder) {
durability::RecoveryData recovery_data; durability::RecoveryData recovery_data;
recovery_data.Load(req_reader.getMember()); durability::Load(&recovery_data, req_reader.getMember());
this->db_->RecoverWalAndIndexes(&recovery_data); this->db_->RecoverWalAndIndexes(&recovery_data);
}); });
} }

View File

@ -13,7 +13,7 @@ DynamicWorkerAddition::DynamicWorkerAddition(database::DistributedGraphDb *db,
server_->Register<DynamicWorkerRpc>( server_->Register<DynamicWorkerRpc>(
[this](const auto &req_reader, auto *res_builder) { [this](const auto &req_reader, auto *res_builder) {
DynamicWorkerReq req; DynamicWorkerReq req;
req.Load(req_reader); Load(&req, req_reader);
DynamicWorkerRes res(this->GetIndicesToCreate()); DynamicWorkerRes res(this->GetIndicesToCreate());
Save(res, res_builder); Save(res, res_builder);
}); });

View File

@ -31,7 +31,8 @@ cpp<#
}); });
cpp<#) cpp<#)
:capnp-load :capnp-load
(lambda (reader member) (lambda (reader member capnp-name)
(declare (ignore capnp-name))
#>cpp #>cpp
utils::LoadVector<utils::capnp::Pair<::capnp::Text, ::capnp::Text>, utils::LoadVector<utils::capnp::Pair<::capnp::Text, ::capnp::Text>,
std::pair<std::string, std::string>>( std::pair<std::string, std::string>>(

View File

@ -13,7 +13,7 @@ IndexRpcServer::IndexRpcServer(database::GraphDb &db,
rpc_server_.Register<CreateIndexRpc>( rpc_server_.Register<CreateIndexRpc>(
[this](const auto &req_reader, auto *res_builder) { [this](const auto &req_reader, auto *res_builder) {
CreateIndexReq req; CreateIndexReq req;
req.Load(req_reader); Load(&req, req_reader);
database::LabelPropertyIndex::Key key{req.label, req.property}; database::LabelPropertyIndex::Key key{req.label, req.property};
db_.storage().label_property_index_.CreateIndex(key); db_.storage().label_property_index_.CreateIndex(key);
}); });
@ -21,7 +21,7 @@ IndexRpcServer::IndexRpcServer(database::GraphDb &db,
rpc_server_.Register<PopulateIndexRpc>( rpc_server_.Register<PopulateIndexRpc>(
[this](const auto &req_reader, auto *res_builder) { [this](const auto &req_reader, auto *res_builder) {
PopulateIndexReq req; PopulateIndexReq req;
req.Load(req_reader); Load(&req, req_reader);
database::LabelPropertyIndex::Key key{req.label, req.property}; database::LabelPropertyIndex::Key key{req.label, req.property};
auto dba = db_.Access(req.tx_id); auto dba = db_.Access(req.tx_id);
dba->PopulateIndex(key); dba->PopulateIndex(key);

View File

@ -7,7 +7,7 @@ PlanConsumer::PlanConsumer(communication::rpc::Server &server)
server_.Register<DispatchPlanRpc>( server_.Register<DispatchPlanRpc>(
[this](const auto &req_reader, auto *res_builder) { [this](const auto &req_reader, auto *res_builder) {
DispatchPlanReq req; DispatchPlanReq req;
req.Load(req_reader); Load(&req, req_reader);
plan_cache_.access().insert( plan_cache_.access().insert(
req.plan_id, std::make_unique<PlanPack>(req.plan, req.symbol_table, req.plan_id, std::make_unique<PlanPack>(req.plan, req.symbol_table,
std::move(req.storage))); std::move(req.storage)));

View File

@ -17,16 +17,17 @@ cpp<#
(lcp:capnp-import 'plan "/query/plan/distributed_ops.capnp") (lcp:capnp-import 'plan "/query/plan/distributed_ops.capnp")
(lcp:capnp-import 'sem "/query/frontend/semantic/symbol.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 #>cpp
query::plan::LogicalOperator::LoadHelper helper; query::plan::LogicalOperator::LoadHelper helper;
${member} = utils::LoadSharedPtr<query::plan::capnp::LogicalOperator, query::plan::LogicalOperator>( ${member} = utils::LoadSharedPtr<query::plan::capnp::LogicalOperator, query::plan::LogicalOperator>(
${reader}, [&helper](const auto &reader) { ${reader}, [&helper](const auto &reader) {
auto op = query::plan::LogicalOperator::Construct(reader); std::unique_ptr<query::plan::LogicalOperator> op;
op->Load(reader, &helper); query::plan::Load(&op, reader, &helper);
return op.release(); return op.release();
}, &helper.loaded_ops); }, &helper.loaded_ops);
storage = std::move(helper.ast_storage); self->storage = std::move(helper.ast_storage);
cpp<#) cpp<#)
(defun save-plan (builder member capnp-name) (defun save-plan (builder member capnp-name)

View File

@ -110,7 +110,7 @@ ProduceRpcServer::ProduceRpcServer(database::Worker *db,
produce_rpc_server_.Register<PullRpc>( produce_rpc_server_.Register<PullRpc>(
[this](const auto &req_reader, auto *res_builder) { [this](const auto &req_reader, auto *res_builder) {
PullReq req; PullReq req;
req.Load(req_reader); Load(&req, req_reader);
PullRes res(Pull(req)); PullRes res(Pull(req));
Save(res, res_builder); Save(res, res_builder);
}); });
@ -118,7 +118,7 @@ ProduceRpcServer::ProduceRpcServer(database::Worker *db,
produce_rpc_server_.Register<ResetCursorRpc>( produce_rpc_server_.Register<ResetCursorRpc>(
[this](const auto &req_reader, auto *res_builder) { [this](const auto &req_reader, auto *res_builder) {
ResetCursorReq req; ResetCursorReq req;
req.Load(req_reader); Load(&req, req_reader);
Reset(req); Reset(req);
ResetCursorRes res; ResetCursorRes res;
Save(res, res_builder); Save(res, res_builder);
@ -129,7 +129,7 @@ ProduceRpcServer::ProduceRpcServer(database::Worker *db,
produce_rpc_server_.Register<TransactionCommandAdvancedRpc>( produce_rpc_server_.Register<TransactionCommandAdvancedRpc>(
[this, data_manager](const auto &req_reader, auto *res_builder) { [this, data_manager](const auto &req_reader, auto *res_builder) {
TransactionCommandAdvancedReq req; TransactionCommandAdvancedReq req;
req.Load(req_reader); Load(&req, req_reader);
tx_engine_->UpdateCommand(req.member); tx_engine_->UpdateCommand(req.member);
data_manager->ClearCacheForSingleTransaction(req.member); data_manager->ClearCacheForSingleTransaction(req.member);
TransactionCommandAdvancedRes res; TransactionCommandAdvancedRes res;

View File

@ -86,7 +86,8 @@ the relevant parts of the response, ready for use."))
} }
cpp<#) cpp<#)
:capnp-load :capnp-load
(lambda (reader member) (lambda (reader member capnp-name)
(declare (ignore capnp-name))
#>cpp #>cpp
${member}.reserve(${reader}.size()); ${member}.reserve(${reader}.size());
for (const auto &frame_reader : ${reader}) { 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) (lambda (builder member capnp-name)
(declare (ignore capnp-name)) (declare (ignore capnp-name))
#>cpp #>cpp
${builder}.setTimestamp(${member}.timestamp); ${builder}.setTimestamp(${member}.timestamp);
auto params_builder = ${builder}.initParams().initEntries(${member}.parameters.size()); auto params_builder = ${builder}.initParams().initEntries(${member}.parameters.size());
size_t i = 0; size_t i = 0;
for (auto &entry : ${member}.parameters) { for (auto &entry : ${member}.parameters) {
auto builder = params_builder[i]; auto builder = params_builder[i];
auto key_builder = builder.initKey(); auto key_builder = builder.initKey();
key_builder.setValue(entry.first); key_builder.setValue(entry.first);
auto value_builder = builder.initValue(); auto value_builder = builder.initValue();
storage::SaveCapnpPropertyValue(entry.second, &value_builder); storage::SaveCapnpPropertyValue(entry.second, &value_builder);
++i; ++i;
} }
cpp<#) cpp<#)
:capnp-load :capnp-load
(lambda (reader member) (lambda (reader member capnp-name)
#>cpp (declare (ignore capnp-name))
${member}.timestamp = ${reader}.getTimestamp(); #>cpp
for (const auto &entry_reader : ${reader}.getParams().getEntries()) { ${member}.timestamp = ${reader}.getTimestamp();
PropertyValue value; for (const auto &entry_reader : ${reader}.getParams().getEntries()) {
storage::LoadCapnpPropertyValue(entry_reader.getValue(), &value); PropertyValue value;
${member}.parameters.Add(entry_reader.getKey().getValue(), value); storage::LoadCapnpPropertyValue(entry_reader.getValue(), &value);
} ${member}.parameters.Add(entry_reader.getKey().getValue(), value);
cpp<#)) }
cpp<#))
(symbols "std::vector<query::Symbol>" :capnp-type "List(Sem.Symbol)") (symbols "std::vector<query::Symbol>" :capnp-type "List(Sem.Symbol)")
(accumulate :bool) (accumulate :bool)
(batch-size :int64_t) (batch-size :int64_t)

View File

@ -18,7 +18,7 @@ utils::Future<PullData> PullRpcClients::Pull(
](int worker_id, ClientPool &client_pool) { ](int worker_id, ClientPool &client_pool) {
auto load_pull_res = [data_manager, dba](const auto &res_reader) { auto load_pull_res = [data_manager, dba](const auto &res_reader) {
PullRes res; PullRes res;
res.Load(res_reader, dba, data_manager); Load(&res, res_reader, dba, data_manager);
return res; return res;
}; };
auto result = client_pool.CallWithLoad<PullRpc>( auto result = client_pool.CallWithLoad<PullRpc>(

View File

@ -72,13 +72,14 @@ cpp<#
}); });
cpp<#) cpp<#)
:capnp-load :capnp-load
(lambda (reader member) (lambda (reader member capnp-name)
(declare (ignore capnp-name))
#>cpp #>cpp
utils::LoadMap<storage::capnp::Common, storage::capnp::PropertyValue>( utils::LoadMap<storage::capnp::Common, storage::capnp::PropertyValue>(
&${member}, ${reader}, &${member}, ${reader},
[](const auto &reader) { [](const auto &reader) {
storage::Property prop; storage::Property prop;
prop.Load(reader.getKey()); storage::Load(&prop, reader.getKey());
PropertyValue value; PropertyValue value;
storage::LoadCapnpPropertyValue(reader.getValue(), &value); storage::LoadCapnpPropertyValue(reader.getValue(), &value);
return std::make_pair(prop, value); return std::make_pair(prop, value);
@ -96,9 +97,10 @@ cpp<#
}); });
cpp<#) cpp<#)
:capnp-load :capnp-load
(lambda (reader member) (lambda (reader member capnp-name)
(declare (ignore capnp-name))
#>cpp #>cpp
cypher_id = utils::LoadOptional<utils::capnp::BoxInt64, int64_t>( ${member} = utils::LoadOptional<utils::capnp::BoxInt64, int64_t>(
${reader}, [](const auto &reader) { ${reader}, [](const auto &reader) {
return reader.getValue(); return reader.getValue();
}); });
@ -126,9 +128,10 @@ cpp<#
}); });
cpp<#) cpp<#)
:capnp-load :capnp-load
(lambda (reader member) (lambda (reader member capnp-name)
(declare (ignore capnp-name))
#>cpp #>cpp
cypher_id = utils::LoadOptional<utils::capnp::BoxInt64, int64_t>( ${member} = utils::LoadOptional<utils::capnp::BoxInt64, int64_t>(
${reader}, [](const auto &reader) { ${reader}, [](const auto &reader) {
return reader.getValue(); return reader.getValue();
}); });

View File

@ -182,7 +182,7 @@ UpdatesRpcServer::UpdatesRpcServer(database::DistributedGraphDb *db,
server->Register<UpdateRpc>([this](const auto &req_reader, server->Register<UpdateRpc>([this](const auto &req_reader,
auto *res_builder) { auto *res_builder) {
UpdateReq req; UpdateReq req;
req.Load(req_reader); Load(&req, req_reader);
using DeltaType = database::StateDelta::Type; using DeltaType = database::StateDelta::Type;
auto &delta = req.member; auto &delta = req.member;
switch (delta.type) { switch (delta.type) {
@ -211,7 +211,7 @@ UpdatesRpcServer::UpdatesRpcServer(database::DistributedGraphDb *db,
server->Register<UpdateApplyRpc>( server->Register<UpdateApplyRpc>(
[this](const auto &req_reader, auto *res_builder) { [this](const auto &req_reader, auto *res_builder) {
UpdateApplyReq req; UpdateApplyReq req;
req.Load(req_reader); Load(&req, req_reader);
UpdateApplyRes res(Apply(req.member)); UpdateApplyRes res(Apply(req.member));
Save(res, res_builder); Save(res, res_builder);
}); });
@ -219,7 +219,7 @@ UpdatesRpcServer::UpdatesRpcServer(database::DistributedGraphDb *db,
server->Register<CreateVertexRpc>([this](const auto &req_reader, server->Register<CreateVertexRpc>([this](const auto &req_reader,
auto *res_builder) { auto *res_builder) {
CreateVertexReq req; CreateVertexReq req;
req.Load(req_reader); Load(&req, req_reader);
auto result = GetUpdates(vertex_updates_, req.member.tx_id) auto result = GetUpdates(vertex_updates_, req.member.tx_id)
.CreateVertex(req.member.labels, req.member.properties, .CreateVertex(req.member.labels, req.member.properties,
req.member.cypher_id); req.member.cypher_id);
@ -231,7 +231,7 @@ UpdatesRpcServer::UpdatesRpcServer(database::DistributedGraphDb *db,
server->Register<CreateEdgeRpc>( server->Register<CreateEdgeRpc>(
[this](const auto &req_reader, auto *res_builder) { [this](const auto &req_reader, auto *res_builder) {
CreateEdgeReq req; CreateEdgeReq req;
req.Load(req_reader); Load(&req, req_reader);
auto data = req.member; auto data = req.member;
auto creation_result = CreateEdge(data); auto creation_result = CreateEdge(data);
@ -253,7 +253,7 @@ UpdatesRpcServer::UpdatesRpcServer(database::DistributedGraphDb *db,
server->Register<AddInEdgeRpc>( server->Register<AddInEdgeRpc>(
[this](const auto &req_reader, auto *res_builder) { [this](const auto &req_reader, auto *res_builder) {
AddInEdgeReq req; AddInEdgeReq req;
req.Load(req_reader); Load(&req, req_reader);
auto to_delta = database::StateDelta::AddInEdge( auto to_delta = database::StateDelta::AddInEdge(
req.member.tx_id, req.member.to, req.member.from, req.member.tx_id, req.member.to, req.member.from,
req.member.edge_address, req.member.edge_type); req.member.edge_address, req.member.edge_type);
@ -266,7 +266,7 @@ UpdatesRpcServer::UpdatesRpcServer(database::DistributedGraphDb *db,
server->Register<RemoveVertexRpc>( server->Register<RemoveVertexRpc>(
[this](const auto &req_reader, auto *res_builder) { [this](const auto &req_reader, auto *res_builder) {
RemoveVertexReq req; RemoveVertexReq req;
req.Load(req_reader); Load(&req, req_reader);
auto to_delta = database::StateDelta::RemoveVertex( auto to_delta = database::StateDelta::RemoveVertex(
req.member.tx_id, req.member.gid, req.member.check_empty); req.member.tx_id, req.member.gid, req.member.check_empty);
auto result = auto result =
@ -278,7 +278,7 @@ UpdatesRpcServer::UpdatesRpcServer(database::DistributedGraphDb *db,
server->Register<RemoveEdgeRpc>( server->Register<RemoveEdgeRpc>(
[this](const auto &req_reader, auto *res_builder) { [this](const auto &req_reader, auto *res_builder) {
RemoveEdgeReq req; RemoveEdgeReq req;
req.Load(req_reader); Load(&req, req_reader);
RemoveEdgeRes res(RemoveEdge(req.member)); RemoveEdgeRes res(RemoveEdge(req.member));
Save(res, res_builder); Save(res, res_builder);
}); });
@ -286,7 +286,7 @@ UpdatesRpcServer::UpdatesRpcServer(database::DistributedGraphDb *db,
server->Register<RemoveInEdgeRpc>([this](const auto &req_reader, server->Register<RemoveInEdgeRpc>([this](const auto &req_reader,
auto *res_builder) { auto *res_builder) {
RemoveInEdgeReq req; RemoveInEdgeReq req;
req.Load(req_reader); Load(&req, req_reader);
auto data = req.member; auto data = req.member;
RemoveInEdgeRes res(GetUpdates(vertex_updates_, data.tx_id) RemoveInEdgeRes res(GetUpdates(vertex_updates_, data.tx_id)
.Emplace(database::StateDelta::RemoveInEdge( .Emplace(database::StateDelta::RemoveInEdge(

View File

@ -34,13 +34,6 @@ struct RecoveryInfo {
wal_recovered == other.wal_recovered; wal_recovered == other.wal_recovered;
} }
bool operator!=(const RecoveryInfo &other) const { return !(*this == other); } 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, inline void Save(const RecoveryInfo &info,
@ -51,6 +44,14 @@ inline void Save(const RecoveryInfo &info,
utils::SaveVector(info.wal_recovered, &list_builder); 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 // A data structure for exchanging info between main recovery function and
// snapshot and WAL recovery functions. // snapshot and WAL recovery functions.
struct RecoveryData { struct RecoveryData {
@ -66,26 +67,6 @@ struct RecoveryData {
snapshooter_tx_snapshot.clear(); snapshooter_tx_snapshot.clear();
indexes.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<utils::capnp::Pair<::capnp::Text, ::capnp::Text>,
std::pair<std::string, std::string>>(
&indexes, list_reader, [](const auto &reader) {
return std::make_pair(reader.getFirst(), reader.getSecond());
});
}
}
}; };
inline void Save(const RecoveryData &data, 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<utils::capnp::Pair<::capnp::Text, ::capnp::Text>,
std::pair<std::string, std::string>>(
&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 /** Reads snapshot metadata from the end of the file without messing up the
* hash. */ * hash. */
bool ReadSnapshotSummary(HashedFileReader &buffer, int64_t &vertex_count, bool ReadSnapshotSummary(HashedFileReader &buffer, int64_t &vertex_count,

View File

@ -30,10 +30,10 @@ void Save(const Endpoint &endpoint, capnp::Endpoint::Builder *builder) {
builder->setFamily(endpoint.family()); builder->setFamily(endpoint.family());
} }
void Endpoint::Load(const capnp::Endpoint::Reader &reader) { void Load(Endpoint *endpoint, const capnp::Endpoint::Reader &reader) {
address_ = reader.getAddress(); endpoint->address_ = reader.getAddress();
port_ = reader.getPort(); endpoint->port_ = reader.getPort();
family_ = reader.getFamily(); endpoint->family_ = reader.getFamily();
} }
bool Endpoint::operator==(const Endpoint &other) const { bool Endpoint::operator==(const Endpoint &other) const {

View File

@ -20,6 +20,7 @@ class Endpoint {
Endpoint(); Endpoint();
Endpoint(const std::string &address, uint16_t port); Endpoint(const std::string &address, uint16_t port);
// TODO: Remove these since members are public
std::string address() const { return address_; } std::string address() const { return address_; }
uint16_t port() const { return port_; } uint16_t port() const { return port_; }
unsigned char family() const { return family_; } unsigned char family() const { return family_; }
@ -27,9 +28,6 @@ class Endpoint {
bool operator==(const Endpoint &other) const; bool operator==(const Endpoint &other) const;
friend std::ostream &operator<<(std::ostream &os, const Endpoint &endpoint); friend std::ostream &operator<<(std::ostream &os, const Endpoint &endpoint);
void Load(const capnp::Endpoint::Reader &reader);
private:
std::string address_; std::string address_;
uint16_t port_{0}; uint16_t port_{0};
unsigned char family_{0}; unsigned char family_{0};
@ -37,4 +35,6 @@ class Endpoint {
void Save(const Endpoint &endpoint, capnp::Endpoint::Builder *builder); void Save(const Endpoint &endpoint, capnp::Endpoint::Builder *builder);
void Load(Endpoint *endpoint, const capnp::Endpoint::Reader &reader);
} // namespace io::network } // namespace io::network

View File

@ -346,15 +346,31 @@ produces:
(let ((cpp-name (cpp-variable-name (cpp-member-symbol cpp-member)))) (let ((cpp-name (cpp-variable-name (cpp-member-symbol cpp-member))))
(if struct cpp-name (format nil "~A_" cpp-name)))) (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) (defun cpp-enum-definition (cpp-enum)
"Get C++ style `CPP-ENUM' definition as a string." "Get C++ style `CPP-ENUM' definition as a string."
(declare (type cpp-enum cpp-enum)) (declare (type cpp-enum cpp-enum))
(with-output-to-string (s) (with-output-to-string (s)
(when (cpp-type-documentation cpp-enum) (when (cpp-type-documentation cpp-enum)
(write-line (cpp-documentation (cpp-type-documentation cpp-enum)) s)) (write-line (cpp-documentation (cpp-type-documentation cpp-enum)) s))
(format s "enum class ~A {~%" (cpp-type-name cpp-enum)) (with-cpp-block-output (s :name (format nil "enum class ~A" (cpp-type-name cpp-enum))
(format s "~{ ~A~^,~%~}~%" (mapcar #'cpp-constant-name (cpp-enum-values cpp-enum))) :semicolonp t)
(write-line "};" s))) (format s "~{ ~A~^,~%~}~%" (mapcar #'cpp-constant-name (cpp-enum-values cpp-enum))))))
(defun cpp-member-declaration (cpp-member &key struct) (defun cpp-member-declaration (cpp-member &key struct)
"Get C++ style `CPP-MEMBER' declaration as a string." "Get C++ style `CPP-MEMBER' declaration as a string."
@ -403,32 +419,26 @@ NIL, returns a string."
(when (cpp-class-super-classes cpp-class) (when (cpp-class-super-classes cpp-class)
(format s " : ~{public ~A~^, ~}" (format s " : ~{public ~A~^, ~}"
(mapcar #'cpp-type-name (cpp-class-super-classes cpp-class)))) (mapcar #'cpp-type-name (cpp-class-super-classes cpp-class))))
(write-line " {" s) (with-cpp-block-output (s :semicolonp t)
(let ((reader-members (remove-if (complement #'cpp-member-reader) (let ((reader-members (remove-if (complement #'cpp-member-reader)
(cpp-class-members cpp-class)))) (cpp-class-members cpp-class))))
(when (or (cpp-class-public cpp-class) (cpp-class-members-scoped :public) reader-members) (when (or (cpp-class-public cpp-class) (cpp-class-members-scoped :public) reader-members)
(unless (cpp-class-structp cpp-class) (unless (cpp-class-structp cpp-class)
(write-line " public:" s)) (write-line " public:" s))
(format s "~{~A~%~}" (mapcar #'cpp-code (cpp-class-public cpp-class))) (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 #'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~}~%" (format s "~{ ~%~A~}~%"
(mapcar #'member-declaration (cpp-class-members-scoped :public))))) (mapcar #'member-declaration (cpp-class-members-scoped :protected))))
(when (cpp-class-capnp-opts cpp-class) (when (or (cpp-class-private cpp-class) (cpp-class-members-scoped :private))
(let ((construct (capnp-construct-declaration cpp-class)) (write-line " private:" s)
(load (capnp-load-declaration cpp-class))) (format s "~{~A~%~}" (mapcar #'cpp-code (cpp-class-private cpp-class)))
(when construct (format s " ~A;~2%" construct)) (format s "~{ ~%~A~}~%"
(when load (format s " ~A;~2%" load)))) (mapcar #'member-declaration (cpp-class-members-scoped :private))))))))
(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))))
(defun cpp-function-declaration (name &key args (returns "void") type-params) (defun cpp-function-declaration (name &key args (returns "void") type-params)
"Generate a C++ top level function declaration named NAME as a string. ARGS "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" "Generate Cap'n Proto serialization schema for CPP-ENUM"
(declare (type cpp-enum cpp-enum)) (declare (type cpp-enum cpp-enum))
(with-output-to-string (s) (with-output-to-string (s)
(format s "enum ~A {~%" (cpp-type-name cpp-enum)) (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 (loop for val in (cpp-enum-values cpp-enum) and field-number from 0
do (format s " ~A @~A;~%" do (format s " ~A @~A;~%"
(string-downcase (cpp-type-name val) :end 1) (string-downcase (cpp-type-name val) :end 1)
field-number)) field-number)))))
(write-line "}" s)))
(defun capnp-schema (cpp-class) (defun capnp-schema (cpp-class)
"Generate Cap'n Proto serialiation schema for 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 (error "Class ~A has multiple inheritance. Use :inherit-compose for
remaining parents." class-name)) remaining parents." class-name))
(with-output-to-string (s) (with-output-to-string (s)
(format s "struct ~A {~%" (cpp-type-name class-name)) (with-cpp-block-output (s :name (format nil "struct ~A" (cpp-type-name class-name)))
(dolist (compose compose-parents) (dolist (compose compose-parents)
(format s " ~A @~A :~A;~%" (format s " ~A @~A :~A;~%"
(field-name<-symbol compose) (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))
field-number field-number
(capnp-type<-cpp-type (cpp-type-base-name subclass))) (capnp-type<-cpp-type compose))
(incf field-number)) (incf field-number))
(write-line " }" s)) (when capnp-type-args
(write-line "}" s)))))) (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 ;;; Capnp C++ serialization code generation
;;; ;;;
@ -951,25 +956,25 @@ Proto schema."
(capnp-primitive-type-p (capnp-type-of-member member))) (capnp-primitive-type-p (capnp-type-of-member member)))
(format s " builder->set~A(~A);~%" capnp-name member-access)) (format s " builder->set~A(~A);~%" capnp-name member-access))
(t (t
(write-line "{" s) ;; Enclose larger save code in new scope ;; Enclose larger save code in new scope
(let ((size (if (string= "vector" (cpp-type-base-name (with-cpp-block-output (s)
(parse-cpp-type-declaration (let ((size (if (string= "vector" (cpp-type-base-name
(cpp-member-type member)))) (parse-cpp-type-declaration
(format nil "~A.size()" member-access) (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)))) (if (and (cpp-member-capnp-init member)
(format s " auto ~A = builder->init~A(~A);~%" (not (find-cpp-enum (cpp-member-type member))))
member-builder capnp-name size) (format s " auto ~A = builder->init~A(~A);~%"
(setf member-builder "builder"))) member-builder capnp-name size)
(if (cpp-member-capnp-save member) (setf member-builder "builder")))
(format s " ~A~%" (if (cpp-member-capnp-save member)
(cpp-code (funcall (cpp-member-capnp-save member) (format s " ~A~%"
member-builder member-access capnp-name))) (cpp-code (funcall (cpp-member-capnp-save member)
(write-line (capnp-save-default member-access (cpp-member-type member) member-builder member-access capnp-name)))
member-builder capnp-name) (write-line (capnp-save-default member-access (cpp-member-type member)
s)) member-builder capnp-name)
(write-line "}" s)))))))) s))))))))))
(defun capnp-save-parents (cpp-class save-parent) (defun capnp-save-parents (cpp-class save-parent)
"Generate Cap'n Proto code for serializing parent classes of CPP-CLASS. "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))) (let ((parents (capnp-union-parents-rec cpp-class)))
(when parents (when parents
(let ((first-parent (first parents))) (let ((first-parent (first parents)))
(write-line (write-line (funcall save-parent first-parent) s))
(funcall save-parent first-parent) s))
(if (or compose-parents (cpp-class-members cpp-class)) (if (or compose-parents (cpp-class-members cpp-class))
(progn (progn
(format s " auto ~A_builder = base_builder->~{get~A().~}init~A();~%" (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))))) (format s " builder->set~A();" (cpp-type-name cpp-class)))))
;; Now handle composite inheritance calls. ;; Now handle composite inheritance calls.
(dolist (parent compose-parents) (dolist (parent compose-parents)
(write-line "{" s) (with-cpp-block-output (s)
(let* ((builder (format nil "~A_builder" (cpp-variable-name parent)))) (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 ~A = builder->init~A();~%" builder (cpp-type-name parent))
(format s " auto *builder = &~A;~%" builder) (format s " auto *builder = &~A;~%" builder)
(write-line (funcall save-parent parent) s)) (write-line (funcall save-parent parent) s)))))))
(write-line "}" s)))))
(defun capnp-save-function-code (cpp-class) (defun capnp-save-function-code (cpp-class)
"Generate Cap'n Proto save code for 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." "Generate serialization code for parent class."
(let ((cpp-class (find-cpp-class parent))) (let ((cpp-class (find-cpp-class parent)))
(with-output-to-string (s) (with-output-to-string (s)
(write-line "{" s) (with-cpp-block-output (s)
(format s "// Save base class ~A~%" (cpp-type-name parent)) (format s "// Save base class ~A~%" (cpp-type-name parent))
(save-class cpp-class s) (save-class cpp-class s))))))
(write-line "}" s)))))
(with-output-to-string (cpp-out) (with-output-to-string (cpp-out)
(let ((subclasses (direct-subclasses-of cpp-class))) (let ((subclasses (direct-subclasses-of cpp-class)))
(when subclasses (when subclasses
@ -1082,84 +1084,59 @@ It takes a parent class symbol."
"Generate Cap'n Proto save function." "Generate Cap'n Proto save function."
(declare (type cpp-class cpp-class)) (declare (type cpp-class cpp-class))
(with-output-to-string (cpp-out) (with-output-to-string (cpp-out)
(format cpp-out "~A {~%" (capnp-save-function-declaration cpp-class)) (with-cpp-block-output (cpp-out :name (capnp-save-function-declaration cpp-class))
(write-line (capnp-save-function-code cpp-class) cpp-out) (write-line (capnp-save-function-code cpp-class) cpp-out))))
(write-line "}" cpp-out)))
;;; Capnp C++ deserialization code generation ;;; Capnp C++ deserialization code generation
;;; ;;;
;;; This is almost the same as serialization, but with a special case for ;;; This is almost the same as serialization, but with a special case for
;;; handling serialized pointers to base classes. ;;; handling serialized pointers to base classes.
;;; ;;;
;;; We need to generate a static Construct function, which dispatches on the ;;; The usual function signature for data types with no inheritance is:
;;; union of the Capnp struct schema. This needs to recursively traverse
;;; unions to instantiate a concrete C++ class.
;;; ;;;
;;; When loading such a pointer, first we call Construct and then follow it ;;; void Load(Data *self, const capnp::Data::Reader &, <extra args>)
;;; with calling Load on the constructed instance. ;;;
;;; 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<Data> *self, const capnp::Data::Reader &,
;;; <extra args>)
;;;
;;; 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)) (defun capnp-load-function-declaration (cpp-class)
"Generate Cap'n Proto construct function declaration for CPP-CLASS. If "Generate Cap'n Proto load function declaration for CPP-CLASS."
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)) (declare (type cpp-class cpp-class))
;; Don't generate Construct if this class is only inherited as composite. (let* ((parents (capnp-union-parents-rec cpp-class))
(when (and (not (capnp-union-subclasses cpp-class)) (top-parent-class (if parents
(direct-subclasses-of cpp-class)) (cpp-type-decl (find-cpp-class (car (last parents))) :type-args nil :namespace nil)
(return-from capnp-construct-declaration)) (cpp-type-decl cpp-class :type-args nil :namespace nil)))
(let ((reader-type (format nil "const capnp::~A::Reader &" (reader-arg (list (if (or parents (capnp-union-subclasses cpp-class))
(cpp-type-decl cpp-class :type-args nil :namespace nil)))) 'base-reader
(cpp-method-declaration 'reader)
cpp-class "Construct" :args (list (list 'reader reader-type)) (format nil "const capnp::~A::Reader &" top-parent-class)))
:returns (format nil "std::unique_ptr<~A>" (cpp-type-decl cpp-class :namespace nil)) (out-arg (list 'self
:inline inline :static t))) (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) (defun capnp-load-default (member-name member-type member-reader capnp-name)
"Generate Cap'n Proto construct code for CPP-CLASS" "Generate default load call for member. MEMBER-NAME and MEMBER-TYPE are
(declare (type cpp-class cpp-class)) strings describing the member being loaded. MEMBER-READER is the name of the
(let ((construct-declaration (capnp-construct-declaration cpp-class :inline nil))) reader variable. CAPNP-NAME is the name of the member in Cap'n Proto schema."
(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."
(declare (type string member-name member-type member-reader)) (declare (type string member-name member-type member-reader))
(let* ((type (parse-cpp-type-declaration member-type)) (let* ((type (parse-cpp-type-declaration member-type))
(type-name (cpp-type-base-name type)) (type-name (cpp-type-base-name type))
@ -1168,8 +1145,8 @@ used for outside definition."
(cpp-enum (cpp-enum
(funcall (funcall
(capnp-load-enum (cpp-type-decl (capnp-cpp-type<-cpp-type cpp-enum)) (capnp-load-enum (cpp-type-decl (capnp-cpp-type<-cpp-type cpp-enum))
member-type (cpp-enum-values cpp-enum)) (cpp-type-decl cpp-enum) (cpp-enum-values cpp-enum))
member-reader member-name)) member-reader member-name capnp-name))
((string= "vector" type-name) ((string= "vector" type-name)
(let* ((elem-type (car (cpp-type-type-args type))) (let* ((elem-type (car (cpp-type-type-args type)))
(capnp-cpp-type (capnp-cpp-type<-cpp-type elem-type))) (capnp-cpp-type (capnp-cpp-type<-cpp-type elem-type)))
@ -1180,7 +1157,7 @@ used for outside definition."
cpp<#) cpp<#)
(raw-cpp-string (raw-cpp-string
(funcall (capnp-load-vector (cpp-type-decl capnp-cpp-type) (cpp-type-decl elem-type)) (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) ((string= "optional" type-name)
(let* ((elem-type (car (cpp-type-type-args type))) (let* ((elem-type (car (cpp-type-type-args type)))
(capnp-cpp-type (capnp-cpp-type<-cpp-type elem-type :boxp t)) (capnp-cpp-type (capnp-cpp-type<-cpp-type elem-type :boxp t))
@ -1189,7 +1166,7 @@ used for outside definition."
(raw-cpp-string (raw-cpp-string
(funcall (capnp-load-optional (funcall (capnp-load-optional
(cpp-type-decl capnp-cpp-type) (cpp-type-decl elem-type) lambda-code) (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=) ((member type-name '("unique_ptr" "shared_ptr" "vector") :test #'string=)
(error "Use a custom :capnp-load function for ~A ~A" type-name member-name)) (error "Use a custom :capnp-load function for ~A ~A" type-name member-name))
(t (t
@ -1198,81 +1175,148 @@ used for outside definition."
(mapcar (lambda (name-and-type) (mapcar (lambda (name-and-type)
(cpp-variable-name (first name-and-type))) (cpp-variable-name (first name-and-type)))
(capnp-extra-args cpp-class :load))))) (capnp-extra-args cpp-class :load)))))
(format nil "~A.Load(~A~{, ~A~});" (format nil "Load(&~A, ~A~{, ~A~});"
member-name member-reader extra-args)))))) member-name member-reader extra-args))))))
(defun capnp-load-declaration (cpp-class &key (inline t)) (defun capnp-load-members (cpp-class &key instance-access)
"Generate Cap'n Proto load function declaration for CPP-CLASS. If "Generate Cap'n Proto loading code for members of CPP-CLASS.
INLINE is NIL, the declaration is namespaced for the class so that it can be INSTANCE-ACCESS is a C++ string which will be prefixed to member access. For
used for outside definition." example, INSTANCE-ACCESS could be `my_struct->`"
(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"
(declare (type cpp-class cpp-class)) (declare (type cpp-class cpp-class))
(declare (type string instance-access))
(with-output-to-string (s) (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)) (dolist (member (cpp-class-members cpp-class))
(unless (and (eq :dont-save (cpp-member-capnp-save member)) (unless (and (eq :dont-save (cpp-member-capnp-save member))
(not (cpp-member-capnp-load 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))) (member-reader (format nil "~A_reader" (cpp-member-name member :struct t)))
(capnp-name (cpp-type-name (cpp-member-symbol member)))) (capnp-name (cpp-type-name (cpp-member-symbol member))))
(cond (cond
((and (not (cpp-member-capnp-load member)) ((and (not (cpp-member-capnp-load member))
(capnp-primitive-type-p (capnp-type-of-member 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 (t
(write-line "{" s) ;; Enclose larger load code in new scope ;; Enclose larger load code in new scope
(if (and (cpp-member-capnp-init member) (with-cpp-block-output (s)
(not (find-cpp-enum (cpp-member-type member)))) (if (and (cpp-member-capnp-init member)
(format s " auto ~A = reader.get~A();~%" member-reader capnp-name) (not (find-cpp-enum (cpp-member-type member))))
(setf member-reader "reader")) (format s " auto ~A = reader.get~A();~%" member-reader capnp-name)
(if (cpp-member-capnp-load member) (setf member-reader "reader"))
(format s " ~A~%" (if (cpp-member-capnp-load member)
(cpp-code (funcall (cpp-member-capnp-load member) (format s " ~A~%"
member-reader member-name))) (cpp-code (funcall (cpp-member-capnp-load member)
(write-line (capnp-load-default member-name member-reader member-access capnp-name)))
(cpp-member-type member) (write-line (capnp-load-default member-access
member-reader) s)) (cpp-member-type member)
(write-line "}" s)))))) member-reader capnp-name) s))))))))))
(write-line "}" 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 (defvar *capnp-imports* nil
"List of pairs (namespace, import-file), which will be imported in Cap'n "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." load the value of std::optional."
(declare (type string capnp-type cpp-type) (declare (type string capnp-type cpp-type)
(type (or null string) lambda-code)) (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 lambda-code
(format nil (format nil
"[](const auto &reader) { ~A val; val.Load(reader); return val; }" "[](const auto &reader) { ~A val; ~ALoad(&val, reader); return val; }"
cpp-type)))) cpp-type namespace))))
(lambda (reader member) (lambda (reader member capnp-name)
(declare (ignore capnp-name))
#>cpp #>cpp
${member} = utils::LoadOptional<${capnp-type}, ${cpp-type}>(${reader}, ${lambda-code}); ${member} = utils::LoadOptional<${capnp-type}, ${cpp-type}>(${reader}, ${lambda-code});
cpp<#))) cpp<#)))
@ -1354,12 +1401,15 @@ are passed as template parameters, while LAMBDA-CODE is used to load each
element." element."
(declare (type string capnp-type cpp-type) (declare (type string capnp-type cpp-type)
(type (or null string) lambda-code)) (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 lambda-code
(format nil (format nil
"[](const auto &reader) { ~A val; val.Load(reader); return val; }" "[](const auto &reader) { ~A val; ~ALoad(&val, reader); return val; }"
cpp-type)))) cpp-type namespace))))
(lambda (reader member-name) (lambda (reader member-name capnp-name)
(declare (ignore capnp-name))
#>cpp #>cpp
utils::LoadVector<${capnp-type}, ${cpp-type}>(&${member-name}, ${reader}, ${lambda-code}); utils::LoadVector<${capnp-type}, ${cpp-type}>(&${member-name}, ${reader}, ${lambda-code});
cpp<#))) 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." CPP-TYPE among defined enums."
(declare (type string capnp-type) (declare (type string capnp-type)
(type (or symbol string) cpp-type)) (type (or symbol string) cpp-type))
(lambda (reader member) (lambda (reader member capnp-name)
(let* ((enum-values (if enum-values (let* ((enum-values (if enum-values
enum-values enum-values
(cpp-enum-values (find-cpp-enum cpp-type)))) (cpp-enum-values (find-cpp-enum cpp-type))))
(member-getter (remove #\_ (string-capitalize member)))
(cases (mapcar (lambda (value-symbol) (cases (mapcar (lambda (value-symbol)
(let ((value (cl-ppcre:regex-replace-all "-" (string value-symbol) "_"))) (let ((value (cl-ppcre:regex-replace-all "-" (string value-symbol) "_")))
#>cpp #>cpp
@ -1404,7 +1453,7 @@ CPP-TYPE among defined enums."
cpp<#)) cpp<#))
enum-values))) enum-values)))
(format nil "switch (~A.get~A()) {~%~{~A~%~}}" (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 (defvar *cpp-namespaces* nil
"Stack of C++ namespaces we are generating the code in.") "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)) (format cpp-out "// Serialize code for ~A~2%" (cpp-type-name cpp-class))
;; Top level functions ;; Top level functions
(write-line (capnp-save-function-definition cpp-class) cpp-out) (write-line (capnp-save-function-definition cpp-class) cpp-out)
;; Member functions (write-line (capnp-load-function-definition cpp-class) cpp-out))))
(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))))))
(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. "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 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 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")) (cpp-file (concatenate 'string lcp-file ".cpp"))
(capnp-file (concatenate 'string filename ".capnp")) (capnp-file (concatenate 'string filename ".capnp"))
;; Reset globals ;; Reset globals
(*capnp-serialize-p* (or capnp-id capnp-declaration)) (*capnp-serialize-p* capnp-id)
(*capnp-namespace* nil) (*capnp-namespace* nil)
(*capnp-imports* nil) (*capnp-imports* nil)
(*capnp-type-converters* nil) (*capnp-type-converters* nil)
@ -1784,7 +1829,8 @@ file."
(dolist (type-for-capnp types-for-capnp) (dolist (type-for-capnp types-for-capnp)
(when (typep type-for-capnp 'cpp-class) (when (typep type-for-capnp 'cpp-class)
(open-namespace (cpp-type-namespace type-for-capnp)) (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 we have either capnp or C++ code for the .cpp file, generate the .cpp file
(when (or *cpp-impl* types-for-capnp) (when (or *cpp-impl* types-for-capnp)
(with-open-file (out cpp-file :direction :output :if-exists :supersede) (with-open-file (out cpp-file :direction :output :if-exists :supersede)

View File

@ -284,16 +284,6 @@ bool TypedValueVectorCompare::operator()(
return (c1_it == c1.end()) && (c2_it != c2.end()); 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, void Save(const TypedValueVectorCompare &comparator,
capnp::TypedValueVectorCompare::Builder *builder) { capnp::TypedValueVectorCompare::Builder *builder) {
auto ordering_builder = builder->initOrdering(comparator.ordering().size()); auto ordering_builder = builder->initOrdering(comparator.ordering().size());
@ -304,8 +294,8 @@ void Save(const TypedValueVectorCompare &comparator,
} }
} }
void TypedValueVectorCompare::Load( void Load(TypedValueVectorCompare *comparator,
const capnp::TypedValueVectorCompare::Reader &reader) { const capnp::TypedValueVectorCompare::Reader &reader) {
std::vector<Ordering> ordering; std::vector<Ordering> ordering;
ordering.reserve(reader.getOrdering().size()); ordering.reserve(reader.getOrdering().size());
for (auto ordering_reader : reader.getOrdering()) { for (auto ordering_reader : reader.getOrdering()) {
@ -313,7 +303,7 @@ void TypedValueVectorCompare::Load(
? Ordering::ASC ? Ordering::ASC
: Ordering::DESC); : Ordering::DESC);
} }
ordering_ = ordering; comparator->ordering_ = ordering;
} }
template <typename TAccessor> template <typename TAccessor>

View File

@ -44,18 +44,18 @@ class TypedValueVectorCompare final {
bool operator()(const std::vector<TypedValue> &c1, bool operator()(const std::vector<TypedValue> &c1,
const std::vector<TypedValue> &c2) const; const std::vector<TypedValue> &c2) const;
// TODO: Remove this, member is public
const auto &ordering() const { return ordering_; } const auto &ordering() const { return ordering_; }
void Save(capnp::TypedValueVectorCompare::Builder *builder) const;
void Load(const capnp::TypedValueVectorCompare::Reader &reader);
private:
std::vector<Ordering> ordering_; std::vector<Ordering> ordering_;
}; };
void Save(const TypedValueVectorCompare &comparator, void Save(const TypedValueVectorCompare &comparator,
capnp::TypedValueVectorCompare::Builder *builder); capnp::TypedValueVectorCompare::Builder *builder);
void Load(TypedValueVectorCompare *comparator,
const capnp::TypedValueVectorCompare::Reader &reader);
/// Switch the given [Vertex/Edge]Accessor to the desired state. /// Switch the given [Vertex/Edge]Accessor to the desired state.
template <class TAccessor> template <class TAccessor>
void SwitchAccessor(TAccessor &accessor, GraphView graph_view); void SwitchAccessor(TAccessor &accessor, GraphView graph_view);

View File

@ -315,7 +315,7 @@ void MapLiteral::Load(const capnp::Tree::Reader &base_reader,
auto key_first = key_pair_reader.getFirst().cStr(); auto key_first = key_pair_reader.getFirst().cStr();
auto storage_property_reader = key_pair_reader.getSecond(); auto storage_property_reader = key_pair_reader.getSecond();
storage::Property key_second; storage::Property key_second;
key_second.Load(storage_property_reader); storage::Load(&key_second, storage_property_reader);
const auto value_reader = entry_reader.getValue(); const auto value_reader = entry_reader.getValue();
auto value = storage->Load(value_reader, loaded_uids); auto value = storage->Load(value_reader, loaded_uids);
auto key = std::make_pair(key_first, key_second); 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()) { for (auto label_reader : reader.getLabels()) {
storage::Label label; storage::Label label;
label.Load(label_reader); storage::Load(&label, label_reader);
labels_.push_back(label); labels_.push_back(label);
} }
} }
@ -1041,7 +1041,7 @@ void PropertyLookup::Load(const capnp::Tree::Reader &base_reader,
} }
property_name_ = reader.getPropertyName().cStr(); property_name_ = reader.getPropertyName().cStr();
auto storage_property_reader = reader.getProperty(); auto storage_property_reader = reader.getProperty();
property_.Load(storage_property_reader); storage::Load(&property_, storage_property_reader);
} }
PropertyLookup *PropertyLookup::Construct( PropertyLookup *PropertyLookup::Construct(
@ -1356,10 +1356,10 @@ CreateIndex *CreateIndex::Construct(const capnp::CreateIndex::Reader &reader,
AstStorage *storage) { AstStorage *storage) {
auto label_reader = reader.getLabel(); auto label_reader = reader.getLabel();
storage::Label label; storage::Label label;
label.Load(label_reader); storage::Load(&label, label_reader);
auto property_reader = reader.getProperty(); auto property_reader = reader.getProperty();
storage::Property property; storage::Property property;
property.Load(property_reader); storage::Load(&property, property_reader);
return storage->Create<CreateIndex>(label, property); return storage->Create<CreateIndex>(label, property);
} }
@ -1740,7 +1740,7 @@ void RemoveLabels::Load(const capnp::Tree::Reader &base_reader,
} }
for (auto label_reader : reader.getLabels()) { for (auto label_reader : reader.getLabels()) {
storage::Label label; storage::Label label;
label.Load(label_reader); storage::Load(&label, label_reader);
labels_.push_back(label); labels_.push_back(label);
} }
} }
@ -1908,7 +1908,7 @@ void SetLabels::Load(const capnp::Tree::Reader &base_reader,
} }
for (auto label_reader : reader.getLabels()) { for (auto label_reader : reader.getLabels()) {
storage::Label label; storage::Label label;
label.Load(label_reader); storage::Load(&label, label_reader);
labels_.push_back(label); labels_.push_back(label);
} }
} }
@ -2301,7 +2301,7 @@ void CypherUnion::Load(const capnp::Tree::Reader &base_reader,
distinct_ = reader.getDistinct(); distinct_ = reader.getDistinct();
for (auto symbol_reader : reader.getUnionSymbols()) { for (auto symbol_reader : reader.getUnionSymbols()) {
Symbol symbol; Symbol symbol;
symbol.Load(symbol_reader); query::Load(&symbol, symbol_reader);
union_symbols_.push_back(symbol); 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 key_first = key_pair_reader.getFirst().cStr();
auto storage_property_reader = key_pair_reader.getSecond(); auto storage_property_reader = key_pair_reader.getSecond();
storage::Property property; storage::Property property;
property.Load(storage_property_reader); storage::Load(&property, storage_property_reader);
const auto value_reader = entry_reader.getValue(); const auto value_reader = entry_reader.getValue();
auto value = storage->Load(value_reader, loaded_uids); auto value = storage->Load(value_reader, loaded_uids);
auto key = std::make_pair(key_first, property); 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()) { for (auto label_reader : reader.getLabels()) {
storage::Label label; storage::Label label;
label.Load(label_reader); storage::Load(&label, label_reader);
labels_.push_back(label); 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 key_first = key_pair_reader.getFirst().cStr();
auto storage_property_reader = key_pair_reader.getSecond(); auto storage_property_reader = key_pair_reader.getSecond();
storage::Property property; storage::Property property;
property.Load(storage_property_reader); storage::Load(&property, storage_property_reader);
const auto value_reader = entry_reader.getValue(); const auto value_reader = entry_reader.getValue();
auto value = storage->Load(value_reader, loaded_uids); auto value = storage->Load(value_reader, loaded_uids);
auto key = std::make_pair(key_first, property); 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()) { for (auto edge_type_reader : reader.getEdgeTypes()) {
storage::EdgeType edge_type; storage::EdgeType edge_type;
edge_type.Load(edge_type_reader); storage::Load(&edge_type, edge_type_reader);
edge_types_.push_back(edge_type); edge_types_.push_back(edge_type);
} }
} }

View File

@ -33,40 +33,13 @@ class Symbol {
} }
bool operator!=(const Symbol &other) const { return !operator==(other); } bool operator!=(const Symbol &other) const { return !operator==(other); }
// TODO: Remove these since members are public
const auto &name() const { return name_; } const auto &name() const { return name_; }
int position() const { return position_; } int position() const { return position_; }
Type type() const { return type_; } Type type() const { return type_; }
bool user_declared() const { return user_declared_; } bool user_declared() const { return user_declared_; }
int token_position() const { return token_position_; } 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_; std::string name_;
int position_; int position_;
bool user_declared_ = true; 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 query
namespace std { namespace std {

View File

@ -24,22 +24,11 @@ class SymbolTable final {
Symbol &at(const Tree &tree) { return table_.at(tree.uid()); } Symbol &at(const Tree &tree) { return table_.at(tree.uid()); }
const Symbol &at(const Tree &tree) const { 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_; } int max_position() const { return position_; }
const auto &table() const { return table_; } 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}; int position_{0};
std::map<int, Symbol> table_; std::map<int, Symbol> 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 } // namespace query

View File

@ -76,7 +76,7 @@ class CostEstimator : public HierarchicalLogicalOperatorVisitor {
} }
bool PostVisit(ScanAllByLabel &scan_all_by_label) override { 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 // ScanAll performs some work for every element that is produced
IncrementCost(CostParam::kScanAllByLabel); IncrementCost(CostParam::kScanAllByLabel);
return true; return true;
@ -86,16 +86,16 @@ class CostEstimator : public HierarchicalLogicalOperatorVisitor {
// This cardinality estimation depends on the property value (expression). // This cardinality estimation depends on the property value (expression).
// If it's a constant, we can evaluate cardinality exactly, otherwise // If it's a constant, we can evaluate cardinality exactly, otherwise
// we estimate // we estimate
auto property_value = ConstPropertyValue(logical_op.expression()); auto property_value = ConstPropertyValue(logical_op.expression_);
double factor = 1.0; double factor = 1.0;
if (property_value) if (property_value)
// get the exact influence based on ScanAll(label, property, value) // get the exact influence based on ScanAll(label, property, value)
factor = db_accessor_.VerticesCount( factor = db_accessor_.VerticesCount(
logical_op.label(), logical_op.property(), property_value.value()); logical_op.label_, logical_op.property_, property_value.value());
else else
// estimate the influence as ScanAll(label, property) * filtering // estimate the influence as ScanAll(label, property) * filtering
factor = db_accessor_.VerticesCount(logical_op.label(), factor = db_accessor_.VerticesCount(logical_op.label_,
logical_op.property()) * logical_op.property_) *
CardParam::kFilter; CardParam::kFilter;
cardinality_ *= factor; cardinality_ *= factor;
@ -108,23 +108,23 @@ class CostEstimator : public HierarchicalLogicalOperatorVisitor {
bool PostVisit(ScanAllByLabelPropertyRange &logical_op) override { bool PostVisit(ScanAllByLabelPropertyRange &logical_op) override {
// this cardinality estimation depends on Bound expressions. // this cardinality estimation depends on Bound expressions.
// if they are literals we can evaluate cardinality properly // if they are literals we can evaluate cardinality properly
auto lower = BoundToPropertyValue(logical_op.lower_bound()); auto lower = BoundToPropertyValue(logical_op.lower_bound_);
auto upper = BoundToPropertyValue(logical_op.upper_bound()); auto upper = BoundToPropertyValue(logical_op.upper_bound_);
int64_t factor = 1; int64_t factor = 1;
if (upper || lower) if (upper || lower)
// if we have either Bound<PropertyValue>, use the value index // if we have either Bound<PropertyValue>, use the value index
factor = db_accessor_.VerticesCount(logical_op.label(), factor = db_accessor_.VerticesCount(logical_op.label_,
logical_op.property(), lower, upper); logical_op.property_, lower, upper);
else else
// no values, but we still have the label // no values, but we still have the label
factor = 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 // if we failed to take either bound from the op into account, then apply
// the filtering constant to the factor // the filtering constant to the factor
if ((logical_op.upper_bound() && !upper) || if ((logical_op.upper_bound_ && !upper) ||
(logical_op.lower_bound() && !lower)) (logical_op.lower_bound_ && !lower))
factor *= CardParam::kFilter; factor *= CardParam::kFilter;
cardinality_ *= factor; cardinality_ *= factor;
@ -174,7 +174,7 @@ class CostEstimator : public HierarchicalLogicalOperatorVisitor {
// exactly, otherwise we approximate // exactly, otherwise we approximate
int unwind_value; int unwind_value;
if (auto literal = if (auto literal =
dynamic_cast<query::ListLiteral *>(unwind.input_expression())) dynamic_cast<query::ListLiteral *>(unwind.input_expression_))
unwind_value = literal->elements_.size(); unwind_value = literal->elements_.size();
else else
unwind_value = MiscParam::kUnwindNoLiteral; unwind_value = MiscParam::kUnwindNoLiteral;

View File

@ -26,9 +26,9 @@ std::pair<std::unique_ptr<LogicalOperator>, AstStorage> Clone(
Save(original_plan, &builder, &helper); Save(original_plan, &builder, &helper);
} }
auto reader = message.getRoot<query::plan::capnp::LogicalOperator>(); auto reader = message.getRoot<query::plan::capnp::LogicalOperator>();
auto plan_copy = LogicalOperator::Construct(reader); std::unique_ptr<LogicalOperator> plan_copy;
LogicalOperator::LoadHelper helper; 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)); 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); maybe_bound->value()->Accept(collector);
return this->ContainsForbidden(collector.symbols_); return this->ContainsForbidden(collector.symbols_);
}; };
CHECK(scan.lower_bound() || scan.upper_bound()); CHECK(scan.lower_bound_ || scan.upper_bound_);
auto lower_depends = find_forbidden(scan.lower_bound()); auto lower_depends = find_forbidden(scan.lower_bound_);
auto upper_depends = find_forbidden(scan.upper_bound()); auto upper_depends = find_forbidden(scan.upper_bound_);
if (!lower_depends && !upper_depends) return true; if (!lower_depends && !upper_depends) return true;
// Since we have dependencies, we need to extract them as a Filter. There // 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 make_prop_lookup = [&]() {
auto ident = storage_->Create<Identifier>( auto ident = storage_->Create<Identifier>(
scan.output_symbol().name(), scan.output_symbol().user_declared()); scan.output_symbol_.name(), scan.output_symbol_.user_declared());
(*symbol_table_)[*ident] = scan.output_symbol(); (*symbol_table_)[*ident] = scan.output_symbol_;
return storage_->Create<PropertyLookup>(ident, "", scan.property()); return storage_->Create<PropertyLookup>(ident, "", scan.property_);
}; };
Expression *extracted_filter = nullptr; Expression *extracted_filter = nullptr;
std::shared_ptr<ScanAll> new_scan; std::shared_ptr<ScanAll> new_scan;
if (lower_depends) { if (lower_depends) {
// Extract the filtering expression // Extract the filtering expression
auto prop_lookup = make_prop_lookup(); auto prop_lookup = make_prop_lookup();
if (scan.lower_bound()->IsInclusive()) { if (scan.lower_bound_->IsInclusive()) {
extracted_filter = storage_->Create<GreaterEqualOperator>( extracted_filter = storage_->Create<GreaterEqualOperator>(
prop_lookup, scan.lower_bound()->value()); prop_lookup, scan.lower_bound_->value());
} else { } else {
extracted_filter = storage_->Create<GreaterOperator>( extracted_filter = storage_->Create<GreaterOperator>(
prop_lookup, scan.lower_bound()->value()); prop_lookup, scan.lower_bound_->value());
} }
// Choose new scan operation // Choose new scan operation
branch_.depends_on = lower_depends; branch_.depends_on = lower_depends;
if (upper_depends || !scan.upper_bound()) { if (upper_depends || !scan.upper_bound_) {
// Cases 2) and 1.b) // Cases 2) and 1.b)
new_scan = new_scan =
std::make_shared<ScanAllByLabel>(scan.input(), scan.output_symbol(), std::make_shared<ScanAllByLabel>(scan.input(), scan.output_symbol_,
scan.label(), scan.graph_view()); scan.label_, scan.graph_view_);
} else { } else {
// Case 1.a) // Case 1.a)
new_scan = std::make_shared<ScanAllByLabelPropertyRange>( new_scan = std::make_shared<ScanAllByLabelPropertyRange>(
scan.input(), scan.output_symbol(), scan.label(), scan.property(), scan.input(), scan.output_symbol_, scan.label_, scan.property_,
std::experimental::nullopt, scan.upper_bound(), scan.graph_view()); std::experimental::nullopt, scan.upper_bound_, scan.graph_view_);
} }
} }
if (upper_depends) { if (upper_depends) {
Expression *filter; Expression *filter;
auto prop_lookup = make_prop_lookup(); auto prop_lookup = make_prop_lookup();
if (scan.upper_bound()->IsInclusive()) { if (scan.upper_bound_->IsInclusive()) {
filter = storage_->Create<LessEqualOperator>( filter = storage_->Create<LessEqualOperator>(
prop_lookup, scan.upper_bound()->value()); prop_lookup, scan.upper_bound_->value());
} else { } else {
filter = storage_->Create<LessOperator>(prop_lookup, filter = storage_->Create<LessOperator>(prop_lookup,
scan.upper_bound()->value()); scan.upper_bound_->value());
} }
if (lower_depends) { if (lower_depends) {
CHECK(extracted_filter); CHECK(extracted_filter);
@ -207,17 +207,17 @@ class IndependentSubtreeFinder : public DistributedOperatorVisitor {
CHECK(!branch_.depends_on); CHECK(!branch_.depends_on);
branch_.depends_on = upper_depends; branch_.depends_on = upper_depends;
extracted_filter = filter; extracted_filter = filter;
if (scan.lower_bound()) { if (scan.lower_bound_) {
// Case 1.a) // Case 1.a)
new_scan = std::make_shared<ScanAllByLabelPropertyRange>( new_scan = std::make_shared<ScanAllByLabelPropertyRange>(
scan.input(), scan.output_symbol(), scan.label(), scan.property(), scan.input(), scan.output_symbol_, scan.label_, scan.property_,
scan.lower_bound(), std::experimental::nullopt, scan.lower_bound_, std::experimental::nullopt,
scan.graph_view()); scan.graph_view_);
} else { } else {
// Case 1.b) // Case 1.b)
new_scan = std::make_shared<ScanAllByLabel>( new_scan = std::make_shared<ScanAllByLabel>(
scan.input(), scan.output_symbol(), scan.label(), scan.input(), scan.output_symbol_, scan.label_,
scan.graph_view()); scan.graph_view_);
} }
} }
} }
@ -244,18 +244,18 @@ class IndependentSubtreeFinder : public DistributedOperatorVisitor {
prev_ops_.pop_back(); prev_ops_.pop_back();
if (branch_.subtree) return true; if (branch_.subtree) return true;
UsedSymbolsCollector collector(*symbol_table_); UsedSymbolsCollector collector(*symbol_table_);
scan.expression()->Accept(collector); scan.expression_->Accept(collector);
if (auto found = ContainsForbidden(collector.symbols_)) { if (auto found = ContainsForbidden(collector.symbols_)) {
// Split to ScanAllByLabel + Filter on property // Split to ScanAllByLabel + Filter on property
auto subtree = std::make_shared<ScanAllByLabel>( auto subtree = std::make_shared<ScanAllByLabel>(
scan.input(), scan.output_symbol(), scan.label(), scan.graph_view()); scan.input(), scan.output_symbol_, scan.label_, scan.graph_view_);
auto ident = storage_->Create<Identifier>( auto ident = storage_->Create<Identifier>(
scan.output_symbol().name(), scan.output_symbol().user_declared()); scan.output_symbol_.name(), scan.output_symbol_.user_declared());
(*symbol_table_)[*ident] = scan.output_symbol(); (*symbol_table_)[*ident] = scan.output_symbol_;
auto prop_lookup = auto prop_lookup =
storage_->Create<PropertyLookup>(ident, "", scan.property()); storage_->Create<PropertyLookup>(ident, "", scan.property_);
auto prop_equal = auto prop_equal =
storage_->Create<EqualOperator>(prop_lookup, scan.expression()); storage_->Create<EqualOperator>(prop_lookup, scan.expression_);
auto parent = std::make_shared<Filter>(subtree, prop_equal); auto parent = std::make_shared<Filter>(subtree, prop_equal);
SetBranch(subtree, parent.get(), *found); SetBranch(subtree, parent.get(), *found);
if (prev_ops_.empty()) { if (prev_ops_.empty()) {
@ -274,15 +274,15 @@ class IndependentSubtreeFinder : public DistributedOperatorVisitor {
bool PostVisit(DistributedExpand &exp) override { bool PostVisit(DistributedExpand &exp) override {
prev_ops_.pop_back(); prev_ops_.pop_back();
if (branch_.subtree) return true; if (branch_.subtree) return true;
if (auto found = FindForbidden(exp.input_symbol())) { if (auto found = FindForbidden(exp.input_symbol_)) {
SetBranch(exp.input(), &exp, *found); SetBranch(exp.input(), &exp, *found);
} }
if (exp.existing_node()) { if (exp.existing_node_) {
if (auto found = FindForbidden(exp.node_symbol())) { if (auto found = FindForbidden(exp.node_symbol_)) {
SetBranch(exp.input(), &exp, *found); SetBranch(exp.input(), &exp, *found);
} }
} }
CHECK(!FindForbidden(exp.edge_symbol())) CHECK(!FindForbidden(exp.edge_symbol_))
<< "Expand uses an already used edge symbol."; << "Expand uses an already used edge symbol.";
return true; return true;
} }
@ -294,44 +294,44 @@ class IndependentSubtreeFinder : public DistributedOperatorVisitor {
bool PostVisit(ExpandVariable &exp) override { bool PostVisit(ExpandVariable &exp) override {
prev_ops_.pop_back(); prev_ops_.pop_back();
if (branch_.subtree) return true; if (branch_.subtree) return true;
if (auto found = FindForbidden(exp.input_symbol())) { if (auto found = FindForbidden(exp.input_symbol_)) {
SetBranch(exp.input(), &exp, *found); SetBranch(exp.input(), &exp, *found);
} }
if (exp.existing_node()) { if (exp.existing_node_) {
if (auto found = FindForbidden(exp.node_symbol())) { if (auto found = FindForbidden(exp.node_symbol_)) {
SetBranch(exp.input(), &exp, *found); SetBranch(exp.input(), &exp, *found);
} }
} }
CHECK(!FindForbidden(exp.edge_symbol())) CHECK(!FindForbidden(exp.edge_symbol_))
<< "Expand uses an already used edge symbol."; << "Expand uses an already used edge symbol.";
// Check for bounding expressions. // Check for bounding expressions.
if (exp.lower_bound()) { if (exp.lower_bound_) {
UsedSymbolsCollector collector(*symbol_table_); UsedSymbolsCollector collector(*symbol_table_);
exp.lower_bound()->Accept(collector); exp.lower_bound_->Accept(collector);
if (auto found = ContainsForbidden(collector.symbols_)) { if (auto found = ContainsForbidden(collector.symbols_)) {
SetBranch(exp.input(), &exp, *found); SetBranch(exp.input(), &exp, *found);
} }
} }
if (exp.upper_bound()) { if (exp.upper_bound_) {
UsedSymbolsCollector collector(*symbol_table_); UsedSymbolsCollector collector(*symbol_table_);
exp.upper_bound()->Accept(collector); exp.upper_bound_->Accept(collector);
if (auto found = ContainsForbidden(collector.symbols_)) { if (auto found = ContainsForbidden(collector.symbols_)) {
SetBranch(exp.input(), &exp, *found); SetBranch(exp.input(), &exp, *found);
} }
} }
// Check for lambda expressions // Check for lambda expressions
if (exp.filter_lambda().expression) { if (exp.filter_lambda_.expression) {
UsedSymbolsCollector collector(*symbol_table_); UsedSymbolsCollector collector(*symbol_table_);
exp.filter_lambda().expression->Accept(collector); exp.filter_lambda_.expression->Accept(collector);
if (auto found = ContainsForbidden(collector.symbols_)) { if (auto found = ContainsForbidden(collector.symbols_)) {
SetBranch(exp.input(), &exp, *found); SetBranch(exp.input(), &exp, *found);
} }
} }
if (exp.weight_lambda()) { if (exp.weight_lambda_) {
CHECK(exp.weight_lambda()->expression) CHECK(exp.weight_lambda_->expression)
<< "Unexpected nullptr expression in lambda"; << "Unexpected nullptr expression in lambda";
UsedSymbolsCollector collector(*symbol_table_); UsedSymbolsCollector collector(*symbol_table_);
exp.weight_lambda()->expression->Accept(collector); exp.weight_lambda_->expression->Accept(collector);
if (auto found = ContainsForbidden(collector.symbols_)) { if (auto found = ContainsForbidden(collector.symbols_)) {
SetBranch(exp.input(), &exp, *found); SetBranch(exp.input(), &exp, *found);
} }
@ -346,35 +346,35 @@ class IndependentSubtreeFinder : public DistributedOperatorVisitor {
bool PostVisit(DistributedExpandBfs &exp) override { bool PostVisit(DistributedExpandBfs &exp) override {
prev_ops_.pop_back(); prev_ops_.pop_back();
if (branch_.subtree) return true; if (branch_.subtree) return true;
if (auto found = FindForbidden(exp.input_symbol())) { if (auto found = FindForbidden(exp.input_symbol_)) {
SetBranch(exp.input(), &exp, *found); SetBranch(exp.input(), &exp, *found);
} }
if (exp.existing_node()) { if (exp.existing_node_) {
if (auto found = FindForbidden(exp.node_symbol())) { if (auto found = FindForbidden(exp.node_symbol_)) {
SetBranch(exp.input(), &exp, *found); SetBranch(exp.input(), &exp, *found);
} }
} }
CHECK(!FindForbidden(exp.edge_symbol())) CHECK(!FindForbidden(exp.edge_symbol_))
<< "Expand uses an already used edge symbol."; << "Expand uses an already used edge symbol.";
// Check for bounding expressions. // Check for bounding expressions.
if (exp.lower_bound()) { if (exp.lower_bound_) {
UsedSymbolsCollector collector(*symbol_table_); UsedSymbolsCollector collector(*symbol_table_);
exp.lower_bound()->Accept(collector); exp.lower_bound_->Accept(collector);
if (auto found = ContainsForbidden(collector.symbols_)) { if (auto found = ContainsForbidden(collector.symbols_)) {
SetBranch(exp.input(), &exp, *found); SetBranch(exp.input(), &exp, *found);
} }
} }
if (exp.upper_bound()) { if (exp.upper_bound_) {
UsedSymbolsCollector collector(*symbol_table_); UsedSymbolsCollector collector(*symbol_table_);
exp.upper_bound()->Accept(collector); exp.upper_bound_->Accept(collector);
if (auto found = ContainsForbidden(collector.symbols_)) { if (auto found = ContainsForbidden(collector.symbols_)) {
SetBranch(exp.input(), &exp, *found); SetBranch(exp.input(), &exp, *found);
} }
} }
// Check for lambda expressions // Check for lambda expressions
if (exp.filter_lambda().expression) { if (exp.filter_lambda_.expression) {
UsedSymbolsCollector collector(*symbol_table_); UsedSymbolsCollector collector(*symbol_table_);
exp.filter_lambda().expression->Accept(collector); exp.filter_lambda_.expression->Accept(collector);
if (auto found = ContainsForbidden(collector.symbols_)) { if (auto found = ContainsForbidden(collector.symbols_)) {
SetBranch(exp.input(), &exp, *found); SetBranch(exp.input(), &exp, *found);
} }
@ -389,10 +389,10 @@ class IndependentSubtreeFinder : public DistributedOperatorVisitor {
bool PostVisit(ExpandUniquenessFilter<EdgeAccessor> &op) override { bool PostVisit(ExpandUniquenessFilter<EdgeAccessor> &op) override {
prev_ops_.pop_back(); prev_ops_.pop_back();
if (branch_.subtree) return true; if (branch_.subtree) return true;
if (auto found = FindForbidden(op.expand_symbol())) { if (auto found = FindForbidden(op.expand_symbol_)) {
SetBranch(op.input(), &op, *found); SetBranch(op.input(), &op, *found);
} }
if (auto found = ContainsForbidden(op.previous_symbols())) { if (auto found = ContainsForbidden(op.previous_symbols_)) {
SetBranch(op.input(), &op, *found); SetBranch(op.input(), &op, *found);
} }
return true; return true;
@ -405,7 +405,7 @@ class IndependentSubtreeFinder : public DistributedOperatorVisitor {
bool PostVisit(ConstructNamedPath &op) override { bool PostVisit(ConstructNamedPath &op) override {
prev_ops_.pop_back(); prev_ops_.pop_back();
if (branch_.subtree) return true; if (branch_.subtree) return true;
if (auto found = ContainsForbidden(op.path_elements())) { if (auto found = ContainsForbidden(op.path_elements_)) {
SetBranch(op.input(), &op, *found); SetBranch(op.input(), &op, *found);
} }
return true; return true;
@ -419,7 +419,7 @@ class IndependentSubtreeFinder : public DistributedOperatorVisitor {
prev_ops_.pop_back(); prev_ops_.pop_back();
if (branch_.subtree) return true; if (branch_.subtree) return true;
UsedSymbolsCollector collector(*symbol_table_); UsedSymbolsCollector collector(*symbol_table_);
op.expression()->Accept(collector); op.expression_->Accept(collector);
if (auto found = ContainsForbidden(collector.symbols_)) { if (auto found = ContainsForbidden(collector.symbols_)) {
SetBranch(op.input(), &op, *found); SetBranch(op.input(), &op, *found);
} }
@ -433,7 +433,7 @@ class IndependentSubtreeFinder : public DistributedOperatorVisitor {
bool PostVisit(Produce &produce) override { bool PostVisit(Produce &produce) override {
prev_ops_.pop_back(); prev_ops_.pop_back();
if (branch_.subtree) return true; if (branch_.subtree) return true;
for (auto *named_expr : produce.named_expressions()) { for (auto *named_expr : produce.named_expressions_) {
UsedSymbolsCollector collector(*symbol_table_); UsedSymbolsCollector collector(*symbol_table_);
named_expr->expression_->Accept(collector); named_expr->expression_->Accept(collector);
if (auto found = ContainsForbidden(collector.symbols_)) { if (auto found = ContainsForbidden(collector.symbols_)) {
@ -453,7 +453,7 @@ class IndependentSubtreeFinder : public DistributedOperatorVisitor {
prev_ops_.pop_back(); prev_ops_.pop_back();
if (branch_.subtree) return true; if (branch_.subtree) return true;
auto optional_branch = FindIndependentSubtree( auto optional_branch = FindIndependentSubtree(
optional.optional(), forbidden_symbols_, symbol_table_, storage_); optional.optional_, forbidden_symbols_, symbol_table_, storage_);
if (optional_branch.depends_on) { if (optional_branch.depends_on) {
SetBranch(optional.input(), &optional, *optional_branch.depends_on); SetBranch(optional.input(), &optional, *optional_branch.depends_on);
} }
@ -468,7 +468,7 @@ class IndependentSubtreeFinder : public DistributedOperatorVisitor {
prev_ops_.pop_back(); prev_ops_.pop_back();
if (branch_.subtree) return true; if (branch_.subtree) return true;
UsedSymbolsCollector collector(*symbol_table_); UsedSymbolsCollector collector(*symbol_table_);
unwind.input_expression()->Accept(collector); unwind.input_expression_->Accept(collector);
if (auto found = ContainsForbidden(collector.symbols_)) { if (auto found = ContainsForbidden(collector.symbols_)) {
SetBranch(unwind.input(), &unwind, *found); SetBranch(unwind.input(), &unwind, *found);
} }
@ -485,8 +485,8 @@ class IndependentSubtreeFinder : public DistributedOperatorVisitor {
} }
bool PostVisit(DistributedCreateNode &op) override { bool PostVisit(DistributedCreateNode &op) override {
prev_ops_.pop_back(); prev_ops_.pop_back();
CHECK(!FindForbidden(symbol_table_->at(*(op.node_atom()->identifier_)))); CHECK(!FindForbidden(symbol_table_->at(*(op.node_atom_->identifier_))));
for (auto &kv : op.node_atom()->properties_) { for (auto &kv : op.node_atom_->properties_) {
UsedSymbolsCollector collector(*symbol_table_); UsedSymbolsCollector collector(*symbol_table_);
kv.second->Accept(collector); kv.second->Accept(collector);
CHECK(!ContainsForbidden(collector.symbols_)); CHECK(!ContainsForbidden(collector.symbols_));
@ -500,15 +500,15 @@ class IndependentSubtreeFinder : public DistributedOperatorVisitor {
} }
bool PostVisit(DistributedCreateExpand &op) override { bool PostVisit(DistributedCreateExpand &op) override {
prev_ops_.pop_back(); prev_ops_.pop_back();
CHECK(!FindForbidden(op.input_symbol())); CHECK(!FindForbidden(op.input_symbol_));
CHECK(!FindForbidden(symbol_table_->at(*(op.node_atom()->identifier_)))); CHECK(!FindForbidden(symbol_table_->at(*(op.node_atom_->identifier_))));
CHECK(!FindForbidden(symbol_table_->at(*(op.edge_atom()->identifier_)))); CHECK(!FindForbidden(symbol_table_->at(*(op.edge_atom_->identifier_))));
for (auto &kv : op.node_atom()->properties_) { for (auto &kv : op.node_atom_->properties_) {
UsedSymbolsCollector collector(*symbol_table_); UsedSymbolsCollector collector(*symbol_table_);
kv.second->Accept(collector); kv.second->Accept(collector);
CHECK(!ContainsForbidden(collector.symbols_)); CHECK(!ContainsForbidden(collector.symbols_));
} }
for (auto &kv : op.edge_atom()->properties_) { for (auto &kv : op.edge_atom_->properties_) {
UsedSymbolsCollector collector(*symbol_table_); UsedSymbolsCollector collector(*symbol_table_);
kv.second->Accept(collector); kv.second->Accept(collector);
CHECK(!ContainsForbidden(collector.symbols_)); CHECK(!ContainsForbidden(collector.symbols_));
@ -522,7 +522,7 @@ class IndependentSubtreeFinder : public DistributedOperatorVisitor {
} }
bool PostVisit(Delete &op) override { bool PostVisit(Delete &op) override {
prev_ops_.pop_back(); prev_ops_.pop_back();
for (auto *expr : op.expressions()) { for (auto *expr : op.expressions_) {
UsedSymbolsCollector collector(*symbol_table_); UsedSymbolsCollector collector(*symbol_table_);
expr->Accept(collector); expr->Accept(collector);
CHECK(!ContainsForbidden(collector.symbols_)); CHECK(!ContainsForbidden(collector.symbols_));
@ -537,8 +537,8 @@ class IndependentSubtreeFinder : public DistributedOperatorVisitor {
bool PostVisit(SetProperty &op) override { bool PostVisit(SetProperty &op) override {
prev_ops_.pop_back(); prev_ops_.pop_back();
UsedSymbolsCollector collector(*symbol_table_); UsedSymbolsCollector collector(*symbol_table_);
op.lhs()->Accept(collector); op.lhs_->Accept(collector);
op.rhs()->Accept(collector); op.rhs_->Accept(collector);
CHECK(!ContainsForbidden(collector.symbols_)); CHECK(!ContainsForbidden(collector.symbols_));
return true; return true;
} }
@ -549,9 +549,9 @@ class IndependentSubtreeFinder : public DistributedOperatorVisitor {
} }
bool PostVisit(SetProperties &op) override { bool PostVisit(SetProperties &op) override {
prev_ops_.pop_back(); prev_ops_.pop_back();
CHECK(!FindForbidden(op.input_symbol())); CHECK(!FindForbidden(op.input_symbol_));
UsedSymbolsCollector collector(*symbol_table_); UsedSymbolsCollector collector(*symbol_table_);
op.rhs()->Accept(collector); op.rhs_->Accept(collector);
CHECK(!ContainsForbidden(collector.symbols_)); CHECK(!ContainsForbidden(collector.symbols_));
return true; return true;
} }
@ -562,7 +562,7 @@ class IndependentSubtreeFinder : public DistributedOperatorVisitor {
} }
bool PostVisit(SetLabels &op) override { bool PostVisit(SetLabels &op) override {
prev_ops_.pop_back(); prev_ops_.pop_back();
CHECK(!FindForbidden(op.input_symbol())); CHECK(!FindForbidden(op.input_symbol_));
return true; return true;
} }
@ -573,7 +573,7 @@ class IndependentSubtreeFinder : public DistributedOperatorVisitor {
bool PostVisit(RemoveProperty &op) override { bool PostVisit(RemoveProperty &op) override {
prev_ops_.pop_back(); prev_ops_.pop_back();
UsedSymbolsCollector collector(*symbol_table_); UsedSymbolsCollector collector(*symbol_table_);
op.lhs()->Accept(collector); op.lhs_->Accept(collector);
CHECK(!ContainsForbidden(collector.symbols_)); CHECK(!ContainsForbidden(collector.symbols_));
return true; return true;
} }
@ -584,7 +584,7 @@ class IndependentSubtreeFinder : public DistributedOperatorVisitor {
} }
bool PostVisit(RemoveLabels &op) override { bool PostVisit(RemoveLabels &op) override {
prev_ops_.pop_back(); prev_ops_.pop_back();
CHECK(!FindForbidden(op.input_symbol())); CHECK(!FindForbidden(op.input_symbol_));
return true; return true;
} }
@ -594,14 +594,14 @@ class IndependentSubtreeFinder : public DistributedOperatorVisitor {
} }
bool PostVisit(Aggregate &aggr) override { bool PostVisit(Aggregate &aggr) override {
prev_ops_.pop_back(); prev_ops_.pop_back();
CHECK(!ContainsForbidden(aggr.remember())); CHECK(!ContainsForbidden(aggr.remember_));
for (auto &elem : aggr.aggregations()) { for (auto &elem : aggr.aggregations_) {
UsedSymbolsCollector collector(*symbol_table_); UsedSymbolsCollector collector(*symbol_table_);
if (elem.value) elem.value->Accept(collector); if (elem.value) elem.value->Accept(collector);
if (elem.key) elem.key->Accept(collector); if (elem.key) elem.key->Accept(collector);
CHECK(!ContainsForbidden(collector.symbols_)); CHECK(!ContainsForbidden(collector.symbols_));
} }
for (auto *expr : aggr.group_by()) { for (auto *expr : aggr.group_by_) {
UsedSymbolsCollector collector(*symbol_table_); UsedSymbolsCollector collector(*symbol_table_);
expr->Accept(collector); expr->Accept(collector);
CHECK(!ContainsForbidden(collector.symbols_)); CHECK(!ContainsForbidden(collector.symbols_));
@ -616,7 +616,7 @@ class IndependentSubtreeFinder : public DistributedOperatorVisitor {
bool PostVisit(Skip &skip) override { bool PostVisit(Skip &skip) override {
prev_ops_.pop_back(); prev_ops_.pop_back();
UsedSymbolsCollector collector(*symbol_table_); UsedSymbolsCollector collector(*symbol_table_);
skip.expression()->Accept(collector); skip.expression_->Accept(collector);
CHECK(!ContainsForbidden(collector.symbols_)); CHECK(!ContainsForbidden(collector.symbols_));
return true; return true;
} }
@ -628,7 +628,7 @@ class IndependentSubtreeFinder : public DistributedOperatorVisitor {
bool PostVisit(Limit &limit) override { bool PostVisit(Limit &limit) override {
prev_ops_.pop_back(); prev_ops_.pop_back();
UsedSymbolsCollector collector(*symbol_table_); UsedSymbolsCollector collector(*symbol_table_);
limit.expression()->Accept(collector); limit.expression_->Accept(collector);
CHECK(!ContainsForbidden(collector.symbols_)); CHECK(!ContainsForbidden(collector.symbols_));
return true; return true;
} }
@ -639,8 +639,8 @@ class IndependentSubtreeFinder : public DistributedOperatorVisitor {
} }
bool PostVisit(OrderBy &order_by) override { bool PostVisit(OrderBy &order_by) override {
prev_ops_.pop_back(); prev_ops_.pop_back();
CHECK(!ContainsForbidden(order_by.output_symbols())); CHECK(!ContainsForbidden(order_by.output_symbols_));
for (auto *expr : order_by.order_by()) { for (auto *expr : order_by.order_by_) {
UsedSymbolsCollector collector(*symbol_table_); UsedSymbolsCollector collector(*symbol_table_);
expr->Accept(collector); expr->Accept(collector);
CHECK(!ContainsForbidden(collector.symbols_)); CHECK(!ContainsForbidden(collector.symbols_));
@ -654,7 +654,7 @@ class IndependentSubtreeFinder : public DistributedOperatorVisitor {
} }
bool PostVisit(Distinct &distinct) override { bool PostVisit(Distinct &distinct) override {
prev_ops_.pop_back(); prev_ops_.pop_back();
CHECK(!ContainsForbidden(distinct.value_symbols())); CHECK(!ContainsForbidden(distinct.value_symbols_));
return true; return true;
} }
@ -664,8 +664,8 @@ class IndependentSubtreeFinder : public DistributedOperatorVisitor {
} }
bool PostVisit(Cartesian &cart) override { bool PostVisit(Cartesian &cart) override {
prev_ops_.pop_back(); prev_ops_.pop_back();
CHECK(!ContainsForbidden(cart.left_symbols()) && CHECK(!ContainsForbidden(cart.left_symbols_) &&
!ContainsForbidden(cart.right_symbols())); !ContainsForbidden(cart.right_symbols_));
return true; return true;
} }
@ -684,7 +684,7 @@ class IndependentSubtreeFinder : public DistributedOperatorVisitor {
} }
bool PostVisit(PullRemote &pull) override { bool PostVisit(PullRemote &pull) override {
prev_ops_.pop_back(); prev_ops_.pop_back();
CHECK(!ContainsForbidden(pull.symbols())); CHECK(!ContainsForbidden(pull.symbols_));
return true; return true;
} }
@ -694,8 +694,8 @@ class IndependentSubtreeFinder : public DistributedOperatorVisitor {
} }
bool PostVisit(PullRemoteOrderBy &pull) override { bool PostVisit(PullRemoteOrderBy &pull) override {
prev_ops_.pop_back(); prev_ops_.pop_back();
CHECK(!ContainsForbidden(pull.symbols())); CHECK(!ContainsForbidden(pull.symbols_));
for (auto *expr : pull.order_by()) { for (auto *expr : pull.order_by_) {
UsedSymbolsCollector collector(*symbol_table_); UsedSymbolsCollector collector(*symbol_table_);
expr->Accept(collector); expr->Accept(collector);
CHECK(!ContainsForbidden(collector.symbols_)); CHECK(!ContainsForbidden(collector.symbols_));
@ -978,8 +978,8 @@ class DistributedPlanner : public HierarchicalLogicalOperatorVisitor {
bool PostVisit(Expand &exp) override { bool PostVisit(Expand &exp) override {
prev_ops_.pop_back(); prev_ops_.pop_back();
auto distributed_expand = std::make_unique<DistributedExpand>( auto distributed_expand = std::make_unique<DistributedExpand>(
exp.node_symbol(), exp.edge_symbol(), exp.direction(), exp.edge_types(), exp.node_symbol_, exp.edge_symbol_, exp.direction_, exp.edge_types_,
exp.input(), exp.input_symbol(), exp.existing_node(), exp.graph_view()); exp.input(), exp.input_symbol_, exp.existing_node_, exp.graph_view_);
SetOnPrevious(std::move(distributed_expand)); SetOnPrevious(std::move(distributed_expand));
return true; return true;
} }
@ -990,12 +990,12 @@ class DistributedPlanner : public HierarchicalLogicalOperatorVisitor {
} }
bool PostVisit(ExpandVariable &exp) override { bool PostVisit(ExpandVariable &exp) override {
prev_ops_.pop_back(); prev_ops_.pop_back();
if (exp.type() == EdgeAtom::Type::BREADTH_FIRST) { if (exp.type_ == EdgeAtom::Type::BREADTH_FIRST) {
auto distributed_bfs = std::make_unique<DistributedExpandBfs>( auto distributed_bfs = std::make_unique<DistributedExpandBfs>(
exp.node_symbol(), exp.edge_symbol(), exp.direction(), exp.node_symbol_, exp.edge_symbol_, exp.direction_,
exp.edge_types(), exp.input(), exp.input_symbol(), exp.edge_types_, exp.input(), exp.input_symbol_,
exp.existing_node(), exp.graph_view(), exp.lower_bound(), exp.existing_node_, exp.graph_view_, exp.lower_bound_,
exp.upper_bound(), exp.filter_lambda()); exp.upper_bound_, exp.filter_lambda_);
SetOnPrevious(std::move(distributed_bfs)); SetOnPrevious(std::move(distributed_bfs));
} }
return true; return true;
@ -1046,7 +1046,7 @@ class DistributedPlanner : public HierarchicalLogicalOperatorVisitor {
// Use dummy produce to simulate an end of the query, thus forcing merge // Use dummy produce to simulate an end of the query, thus forcing merge
// points to be planned (like Cartesian). // points to be planned (like Cartesian).
optional_plan.master_plan = std::make_unique<Produce>( optional_plan.master_plan = std::make_unique<Produce>(
op.optional(), std::vector<NamedExpression *>{}); op.optional_, std::vector<NamedExpression *>{});
// Temporary transfer symbol table and storage // Temporary transfer symbol table and storage
optional_plan.symbol_table = std::move(distributed_plan_.symbol_table); optional_plan.symbol_table = std::move(distributed_plan_.symbol_table);
optional_plan.ast_storage = std::move(distributed_plan_.ast_storage); optional_plan.ast_storage = std::move(distributed_plan_.ast_storage);
@ -1070,7 +1070,7 @@ class DistributedPlanner : public HierarchicalLogicalOperatorVisitor {
// we continue as normal. // we continue as normal.
SetOnPrevious(std::make_unique<Optional>( SetOnPrevious(std::make_unique<Optional>(
op.input(), optional_plan.master_plan->input(), op.input(), optional_plan.master_plan->input(),
op.optional_symbols())); op.optional_symbols_));
return true; return true;
} }
// Case 2) // Case 2)
@ -1095,7 +1095,7 @@ class DistributedPlanner : public HierarchicalLogicalOperatorVisitor {
// on LHS symbols should have been taken care of. // on LHS symbols should have been taken care of.
SetOnPrevious(std::make_unique<Optional>( SetOnPrevious(std::make_unique<Optional>(
op.input(), optional_plan.master_plan->input(), op.input(), optional_plan.master_plan->input(),
op.optional_symbols())); op.optional_symbols_));
return true; return true;
} }
CHECK(optional_planner.ShouldSplit()); CHECK(optional_planner.ShouldSplit());
@ -1116,7 +1116,7 @@ class DistributedPlanner : public HierarchicalLogicalOperatorVisitor {
new_opt = branch.parent_start; new_opt = branch.parent_start;
} }
SetOnPrevious( SetOnPrevious(
std::make_unique<Optional>(op.input(), new_opt, op.optional_symbols())); std::make_unique<Optional>(op.input(), new_opt, op.optional_symbols_));
return true; return true;
} }
@ -1197,8 +1197,8 @@ class DistributedPlanner : public HierarchicalLogicalOperatorVisitor {
prev_ops_.pop_back(); prev_ops_.pop_back();
// TODO: Associative combination of OrderBy // TODO: Associative combination of OrderBy
if (ShouldSplit()) { if (ShouldSplit()) {
std::unordered_set<Symbol> pull_symbols(order_by.output_symbols().begin(), std::unordered_set<Symbol> pull_symbols(order_by.output_symbols_.begin(),
order_by.output_symbols().end()); order_by.output_symbols_.end());
// Pull symbols need to also include those used in order by expressions. // 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 // For example, `RETURN n AS m ORDER BY n.prop`, output symbols will
// contain `m`, while we also need to pull `n`. // 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 // and sending them instead. It's possible that the evaluated expression
// requires less network traffic than sending the value of the used symbol // requires less network traffic than sending the value of the used symbol
// `n` itself. // `n` itself.
for (const auto &expr : order_by.order_by()) { for (const auto &expr : order_by.order_by_) {
UsedSymbolsCollector collector(distributed_plan_.symbol_table); UsedSymbolsCollector collector(distributed_plan_.symbol_table);
expr->Accept(collector); expr->Accept(collector);
pull_symbols.insert(collector.symbols_.begin(), 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 // Create a copy of OrderBy but with added symbols used in expressions, so
// that they can be pulled. // that they can be pulled.
std::vector<std::pair<Ordering, Expression *>> ordering; std::vector<std::pair<Ordering, Expression *>> ordering;
ordering.reserve(order_by.order_by().size()); ordering.reserve(order_by.order_by_.size());
for (int i = 0; i < order_by.order_by().size(); ++i) { for (int i = 0; i < order_by.order_by_.size(); ++i) {
ordering.emplace_back(order_by.compare().ordering()[i], ordering.emplace_back(order_by.compare_.ordering()[i],
order_by.order_by()[i]); order_by.order_by_[i]);
} }
auto worker_plan = std::make_shared<OrderBy>( auto worker_plan = std::make_shared<OrderBy>(
order_by.input(), ordering, order_by.input(), ordering,
@ -1281,7 +1281,7 @@ class DistributedPlanner : public HierarchicalLogicalOperatorVisitor {
return true; return true;
} }
auto is_associative = [&aggr_op]() { auto is_associative = [&aggr_op]() {
for (const auto &aggr : aggr_op.aggregations()) { for (const auto &aggr : aggr_op.aggregations_) {
switch (aggr.op) { switch (aggr.op) {
case Aggregation::Op::COUNT: case Aggregation::Op::COUNT:
case Aggregation::Op::MIN: case Aggregation::Op::MIN:
@ -1298,9 +1298,9 @@ class DistributedPlanner : public HierarchicalLogicalOperatorVisitor {
if (!is_associative()) { if (!is_associative()) {
auto input = aggr_op.input(); auto input = aggr_op.input();
auto pull_id = AddWorkerPlan(input); auto pull_id = AddWorkerPlan(input);
std::unordered_set<Symbol> pull_symbols(aggr_op.remember().begin(), std::unordered_set<Symbol> pull_symbols(aggr_op.remember_.begin(),
aggr_op.remember().end()); aggr_op.remember_.end());
for (const auto &elem : aggr_op.aggregations()) { for (const auto &elem : aggr_op.aggregations_) {
UsedSymbolsCollector collector(distributed_plan_.symbol_table); UsedSymbolsCollector collector(distributed_plan_.symbol_table);
elem.value->Accept(collector); elem.value->Accept(collector);
if (elem.key) elem.key->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 // Aggregate uses associative operation(s), so split the work across master
// and workers. // and workers.
std::vector<Aggregate::Element> master_aggrs; std::vector<Aggregate::Element> master_aggrs;
master_aggrs.reserve(aggr_op.aggregations().size()); master_aggrs.reserve(aggr_op.aggregations_.size());
std::vector<Aggregate::Element> worker_aggrs; std::vector<Aggregate::Element> 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 // We will need to create a Produce operator which moves the final results
// from new (merge) symbols into old aggregation symbols, because // from new (merge) symbols into old aggregation symbols, because
// expressions following the aggregation expect the result in old symbols. // expressions following the aggregation expect the result in old symbols.
std::vector<NamedExpression *> produce_exprs; std::vector<NamedExpression *> produce_exprs;
produce_exprs.reserve(aggr_op.aggregations().size()); produce_exprs.reserve(aggr_op.aggregations_.size());
for (const auto &aggr : aggr_op.aggregations()) { for (const auto &aggr : aggr_op.aggregations_) {
switch (aggr.op) { switch (aggr.op) {
// Count, like sum, only needs to sum all of the results on master. // Count, like sum, only needs to sum all of the results on master.
case Aggregation::Op::COUNT: case Aggregation::Op::COUNT:
@ -1406,17 +1406,17 @@ class DistributedPlanner : public HierarchicalLogicalOperatorVisitor {
} }
// Rewire master/worker aggregation. // Rewire master/worker aggregation.
auto worker_plan = std::make_shared<Aggregate>( auto worker_plan = std::make_shared<Aggregate>(
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); auto pull_id = AddWorkerPlan(worker_plan);
std::vector<Symbol> pull_symbols; std::vector<Symbol> 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) for (const auto &aggr : worker_aggrs)
pull_symbols.push_back(aggr.output_sym); 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 = auto pull_op =
std::make_shared<PullRemote>(worker_plan, pull_id, pull_symbols); std::make_shared<PullRemote>(worker_plan, pull_id, pull_symbols);
auto master_aggr_op = std::make_shared<Aggregate>( auto master_aggr_op = std::make_shared<Aggregate>(
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 // Make our master Aggregate into Produce + Aggregate
auto master_plan = std::make_unique<Produce>(master_aggr_op, produce_exprs); auto master_plan = std::make_unique<Produce>(master_aggr_op, produce_exprs);
SplitOnPrevious(std::move(master_plan)); SplitOnPrevious(std::move(master_plan));
@ -1484,10 +1484,10 @@ class DistributedPlanner : public HierarchicalLogicalOperatorVisitor {
if (ShouldSplit()) { if (ShouldSplit()) {
auto pull_id = AddWorkerPlan(acc.input()); auto pull_id = AddWorkerPlan(acc.input());
pull_remote = pull_remote =
std::make_shared<PullRemote>(nullptr, pull_id, acc.symbols()); std::make_shared<PullRemote>(nullptr, pull_id, acc.symbols_);
} }
auto sync = std::make_unique<Synchronize>(acc.input(), pull_remote, auto sync = std::make_unique<Synchronize>(acc.input(), pull_remote,
acc.advance_command()); acc.advance_command_);
SetOnPrevious(std::move(sync)); SetOnPrevious(std::move(sync));
on_master_ = true; on_master_ = true;
needs_synchronize_ = false; needs_synchronize_ = false;
@ -1509,7 +1509,7 @@ class DistributedPlanner : public HierarchicalLogicalOperatorVisitor {
// node creation to workers. // node creation to workers.
bool create_on_random_worker = !ShouldSplit(); bool create_on_random_worker = !ShouldSplit();
auto distributed_create = std::make_unique<DistributedCreateNode>( auto distributed_create = std::make_unique<DistributedCreateNode>(
op.input(), op.node_atom(), create_on_random_worker); op.input(), op.node_atom_, create_on_random_worker);
if (prev_ops_.empty()) if (prev_ops_.empty())
distributed_plan_.master_plan = std::move(distributed_create); distributed_plan_.master_plan = std::move(distributed_create);
else else
@ -1528,8 +1528,8 @@ class DistributedPlanner : public HierarchicalLogicalOperatorVisitor {
Split(op, PlanCartesian(op.input())); Split(op, PlanCartesian(op.input()));
} }
auto distributed_create = std::make_unique<DistributedCreateExpand>( auto distributed_create = std::make_unique<DistributedCreateExpand>(
op.node_atom(), op.edge_atom(), op.input(), op.input_symbol(), op.node_atom_, op.edge_atom_, op.input(), op.input_symbol_,
op.existing_node()); op.existing_node_);
if (prev_ops_.empty()) if (prev_ops_.empty())
distributed_plan_.master_plan = std::move(distributed_create); distributed_plan_.master_plan = std::move(distributed_create);
else else

View File

@ -113,8 +113,8 @@ ACCEPT_WITH_INPUT(DistributedExpand);
std::vector<Symbol> DistributedExpand::ModifiedSymbols( std::vector<Symbol> DistributedExpand::ModifiedSymbols(
const SymbolTable &table) const { const SymbolTable &table) const {
auto symbols = input_->ModifiedSymbols(table); auto symbols = input_->ModifiedSymbols(table);
symbols.emplace_back(node_symbol()); symbols.emplace_back(node_symbol_);
symbols.emplace_back(edge_symbol()); symbols.emplace_back(edge_symbol_);
return symbols; return symbols;
} }
@ -135,8 +135,8 @@ ACCEPT_WITH_INPUT(DistributedExpandBfs);
std::vector<Symbol> DistributedExpandBfs::ModifiedSymbols( std::vector<Symbol> DistributedExpandBfs::ModifiedSymbols(
const SymbolTable &table) const { const SymbolTable &table) const {
auto symbols = input_->ModifiedSymbols(table); auto symbols = input_->ModifiedSymbols(table);
symbols.emplace_back(node_symbol()); symbols.emplace_back(node_symbol_);
symbols.emplace_back(edge_symbol()); symbols.emplace_back(edge_symbol_);
return symbols; return symbols;
} }
@ -367,7 +367,7 @@ class PullRemoteCursor : public Cursor {
remote_puller_( remote_puller_(
// TODO: Pass in a Master GraphDb. // TODO: Pass in a Master GraphDb.
&dynamic_cast<database::Master *>(&db.db())->pull_clients(), db, &dynamic_cast<database::Master *>(&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 { bool Pull(Frame &frame, Context &context) override {
if (context.db_accessor_.should_abort()) throw HintedAbortError(); if (context.db_accessor_.should_abort()) throw HintedAbortError();
@ -403,14 +403,14 @@ class PullRemoteCursor : public Cursor {
if (input_cursor_ && input_cursor_->Pull(frame, context)) { if (input_cursor_ && input_cursor_->Pull(frame, context)) {
VLOG(10) << "[PullRemoteCursor] [" VLOG(10) << "[PullRemoteCursor] ["
<< context.db_accessor_.transaction_id() << "] [" << context.db_accessor_.transaction_id() << "] ["
<< self_.plan_id() << "] [" << command_id_ << self_.plan_id_ << "] [" << command_id_
<< "] producing local results "; << "] producing local results ";
return true; return true;
} }
VLOG(10) << "[PullRemoteCursor] [" VLOG(10) << "[PullRemoteCursor] ["
<< context.db_accessor_.transaction_id() << "] [" << context.db_accessor_.transaction_id() << "] ["
<< self_.plan_id() << "] [" << command_id_ << self_.plan_id_ << "] [" << command_id_
<< "] no results available, sleeping "; << "] no results available, sleeping ";
// If there aren't any local/remote results available, sleep. // If there aren't any local/remote results available, sleep.
std::this_thread::sleep_for( std::this_thread::sleep_for(
@ -423,7 +423,7 @@ class PullRemoteCursor : public Cursor {
if (input_cursor_ && input_cursor_->Pull(frame, context)) { if (input_cursor_ && input_cursor_->Pull(frame, context)) {
VLOG(10) << "[PullRemoteCursor] [" VLOG(10) << "[PullRemoteCursor] ["
<< context.db_accessor_.transaction_id() << "] [" << context.db_accessor_.transaction_id() << "] ["
<< self_.plan_id() << "] [" << command_id_ << self_.plan_id_ << "] [" << command_id_
<< "] producing local results "; << "] producing local results ";
return true; return true;
} }
@ -434,11 +434,11 @@ class PullRemoteCursor : public Cursor {
int worker_id = remote_puller_.GetWorkerId(last_pulled_worker_id_index_); int worker_id = remote_puller_.GetWorkerId(last_pulled_worker_id_index_);
VLOG(10) << "[PullRemoteCursor] [" VLOG(10) << "[PullRemoteCursor] ["
<< context.db_accessor_.transaction_id() << "] [" << context.db_accessor_.transaction_id() << "] ["
<< self_.plan_id() << "] [" << command_id_ << self_.plan_id_ << "] [" << command_id_
<< "] producing results from worker " << worker_id; << "] producing results from worker " << worker_id;
auto result = remote_puller_.PopResultFromWorker(worker_id); auto result = remote_puller_.PopResultFromWorker(worker_id);
for (size_t i = 0; i < self_.symbols().size(); ++i) { for (size_t i = 0; i < self_.symbols_.size(); ++i) {
frame[self_.symbols()[i]] = std::move(result[i]); frame[self_.symbols_[i]] = std::move(result[i]);
} }
} }
return true; return true;
@ -478,7 +478,7 @@ class SynchronizeCursor : public Cursor {
&dynamic_cast<database::Master *>(&db.db())->updates_server()), &dynamic_cast<database::Master *>(&db.db())->updates_server()),
input_cursor_(self.input()->MakeCursor(db)), input_cursor_(self.input()->MakeCursor(db)),
pull_remote_cursor_( 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()), command_id_(db.transaction().cid()),
master_id_( master_id_(
// TODO: Pass in a Master GraphDb. // TODO: Pass in a Master GraphDb.
@ -496,7 +496,7 @@ class SynchronizeCursor : public Cursor {
<< "] producing local results"; << "] producing local results";
auto &result = local_frames_.back(); auto &result = local_frames_.back();
for (size_t i = 0; i < frame.elems().size(); ++i) { for (size_t i = 0; i < frame.elems().size(); ++i) {
if (self_.advance_command()) { if (self_.advance_command_) {
query::ReconstructTypedValue(result[i]); query::ReconstructTypedValue(result[i]);
} }
frame.elems()[i] = std::move(result[i]); frame.elems()[i] = std::move(result[i]);
@ -550,9 +550,9 @@ class SynchronizeCursor : public Cursor {
for (auto worker_id : pull_clients_->GetWorkerIds()) { for (auto worker_id : pull_clients_->GetWorkerIds()) {
if (worker_id == master_id_) continue; if (worker_id == master_id_) continue;
worker_accumulations.emplace_back(pull_clients_->Pull( 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_, 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(); context.db_accessor_.AdvanceCommand();
} }
@ -628,7 +628,7 @@ class SynchronizeCursor : public Cursor {
} }
// If the command advanced, let the workers know. // If the command advanced, let the workers know.
if (self_.advance_command()) { if (self_.advance_command_) {
auto futures = pull_clients_->NotifyAllTransactionCommandAdvanced(tx_id); auto futures = pull_clients_->NotifyAllTransactionCommandAdvanced(tx_id);
for (auto &future : futures) future.get(); for (auto &future : futures) future.get();
} }
@ -645,7 +645,7 @@ class PullRemoteOrderByCursor : public Cursor {
remote_puller_( remote_puller_(
// TODO: Pass in a Master GraphDb. // TODO: Pass in a Master GraphDb.
&dynamic_cast<database::Master *>(&db.db())->pull_clients(), db, &dynamic_cast<database::Master *>(&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 { bool Pull(Frame &frame, Context &context) override {
if (context.db_accessor_.should_abort()) throw HintedAbortError(); if (context.db_accessor_.should_abort()) throw HintedAbortError();
@ -655,8 +655,8 @@ class PullRemoteOrderByCursor : public Cursor {
auto evaluate_result = [this, &evaluator]() { auto evaluate_result = [this, &evaluator]() {
std::vector<TypedValue> order_by; std::vector<TypedValue> order_by;
order_by.reserve(self_.order_by().size()); order_by.reserve(self_.order_by_.size());
for (auto expression_ptr : self_.order_by()) { for (auto expression_ptr : self_.order_by_) {
order_by.emplace_back(expression_ptr->Accept(evaluator)); order_by.emplace_back(expression_ptr->Accept(evaluator));
} }
return order_by; return order_by;
@ -665,14 +665,14 @@ class PullRemoteOrderByCursor : public Cursor {
auto restore_frame = [&frame, auto restore_frame = [&frame,
this](const std::vector<TypedValue> &restore_from) { this](const std::vector<TypedValue> &restore_from) {
for (size_t i = 0; i < restore_from.size(); ++i) { 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_) { if (!merge_initialized_) {
VLOG(10) << "[PullRemoteOrderBy] [" VLOG(10) << "[PullRemoteOrderBy] ["
<< context.db_accessor_.transaction_id() << "] [" << context.db_accessor_.transaction_id() << "] ["
<< self_.plan_id() << "] [" << command_id_ << "] initialize"; << self_.plan_id_ << "] [" << command_id_ << "] initialize";
remote_puller_.Initialize(context); remote_puller_.Initialize(context);
missing_results_from_ = remote_puller_.Workers(); missing_results_from_ = remote_puller_.Workers();
missing_master_result_ = true; missing_master_result_ = true;
@ -682,8 +682,8 @@ class PullRemoteOrderByCursor : public Cursor {
if (missing_master_result_) { if (missing_master_result_) {
if (input_->Pull(frame, context)) { if (input_->Pull(frame, context)) {
std::vector<TypedValue> output; std::vector<TypedValue> output;
output.reserve(self_.symbols().size()); output.reserve(self_.symbols_.size());
for (const Symbol &symbol : self_.symbols()) { for (const Symbol &symbol : self_.symbols_) {
output.emplace_back(frame[symbol]); output.emplace_back(frame[symbol]);
} }
@ -709,7 +709,7 @@ class PullRemoteOrderByCursor : public Cursor {
if (!has_all_result) { if (!has_all_result) {
VLOG(10) << "[PullRemoteOrderByCursor] [" VLOG(10) << "[PullRemoteOrderByCursor] ["
<< context.db_accessor_.transaction_id() << "] [" << context.db_accessor_.transaction_id() << "] ["
<< self_.plan_id() << "] [" << command_id_ << self_.plan_id_ << "] [" << command_id_
<< "] missing results, sleep"; << "] missing results, sleep";
// If we don't have results from all workers, sleep before continuing. // If we don't have results from all workers, sleep before continuing.
std::this_thread::sleep_for( std::this_thread::sleep_for(
@ -734,7 +734,7 @@ class PullRemoteOrderByCursor : public Cursor {
auto result_it = std::min_element( auto result_it = std::min_element(
merge_.begin(), merge_.end(), [this](const auto &lhs, const auto &rhs) { 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); restore_frame(result_it->remote_result);
@ -742,14 +742,14 @@ class PullRemoteOrderByCursor : public Cursor {
if (result_it->worker_id) { if (result_it->worker_id) {
VLOG(10) << "[PullRemoteOrderByCursor] [" VLOG(10) << "[PullRemoteOrderByCursor] ["
<< context.db_accessor_.transaction_id() << "] [" << context.db_accessor_.transaction_id() << "] ["
<< self_.plan_id() << "] [" << command_id_ << self_.plan_id_ << "] [" << command_id_
<< "] producing results from worker " << "] producing results from worker "
<< result_it->worker_id.value(); << result_it->worker_id.value();
missing_results_from_.push_back(result_it->worker_id.value()); missing_results_from_.push_back(result_it->worker_id.value());
} else { } else {
VLOG(10) << "[PullRemoteOrderByCursor] [" VLOG(10) << "[PullRemoteOrderByCursor] ["
<< context.db_accessor_.transaction_id() << "] [" << context.db_accessor_.transaction_id() << "] ["
<< self_.plan_id() << "] [" << command_id_ << self_.plan_id_ << "] [" << command_id_
<< "] producing local results"; << "] producing local results";
missing_master_result_ = true; missing_master_result_ = true;
} }
@ -799,13 +799,13 @@ class DistributedExpandCursor : public query::plan::Cursor {
// A helper function for expanding a node from an edge. // A helper function for expanding a node from an edge.
auto pull_node = [this, &frame](const EdgeAccessor &new_edge, auto pull_node = [this, &frame](const EdgeAccessor &new_edge,
EdgeAtom::Direction direction) { EdgeAtom::Direction direction) {
if (self_->existing_node()) return; if (self_->existing_node_) return;
switch (direction) { switch (direction) {
case EdgeAtom::Direction::IN: case EdgeAtom::Direction::IN:
frame[self_->node_symbol()] = new_edge.from(); frame[self_->node_symbol_] = new_edge.from();
break; break;
case EdgeAtom::Direction::OUT: case EdgeAtom::Direction::OUT:
frame[self_->node_symbol()] = new_edge.to(); frame[self_->node_symbol_] = new_edge.to();
break; break;
case EdgeAtom::Direction::BOTH: case EdgeAtom::Direction::BOTH:
LOG(FATAL) << "Must indicate exact expansion direction here"; 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 put_future_edge_on_frame = [this, &frame](auto &future) {
auto edge_to = future.edge_to.get(); auto edge_to = future.edge_to.get();
frame.elems() = future.frame_elems; frame.elems() = future.frame_elems;
frame[self_->edge_symbol()] = edge_to.first; frame[self_->edge_symbol_] = edge_to.first;
frame[self_->node_symbol()] = edge_to.second; frame[self_->node_symbol_] = edge_to.second;
}; };
while (true) { while (true) {
@ -863,8 +863,8 @@ class DistributedExpandCursor : public query::plan::Cursor {
// attempt to get a value from the incoming edges // attempt to get a value from the incoming edges
if (in_edges_ && *in_edges_it_ != in_edges_->end()) { if (in_edges_ && *in_edges_it_ != in_edges_->end()) {
auto edge = *(*in_edges_it_)++; auto edge = *(*in_edges_it_)++;
if (edge.address().is_local() || self_->existing_node()) { if (edge.address().is_local() || self_->existing_node_) {
frame[self_->edge_symbol()] = edge; frame[self_->edge_symbol_] = edge;
pull_node(edge, EdgeAtom::Direction::IN); pull_node(edge, EdgeAtom::Direction::IN);
return true; return true;
} else { } else {
@ -879,10 +879,10 @@ class DistributedExpandCursor : public query::plan::Cursor {
// when expanding in EdgeAtom::Direction::BOTH directions // when expanding in EdgeAtom::Direction::BOTH directions
// we should do only one expansion for cycles, and it was // we should do only one expansion for cycles, and it was
// already done in the block above // 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; continue;
if (edge.address().is_local() || self_->existing_node()) { if (edge.address().is_local() || self_->existing_node_) {
frame[self_->edge_symbol()] = edge; frame[self_->edge_symbol_] = edge;
pull_node(edge, EdgeAtom::Direction::OUT); pull_node(edge, EdgeAtom::Direction::OUT);
return true; return true;
} else { } else {
@ -945,46 +945,46 @@ class DistributedExpandCursor : public query::plan::Cursor {
// In those cases we skip that input pull and continue with the next. // In those cases we skip that input pull and continue with the next.
while (true) { while (true) {
if (!input_cursor_->Pull(frame, context)) return false; 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. // Null check due to possible failed optional match.
if (vertex_value.IsNull()) continue; 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<VertexAccessor>(); auto &vertex = vertex_value.Value<VertexAccessor>();
SwitchAccessor(vertex, self_->graph_view()); SwitchAccessor(vertex, self_->graph_view_);
auto direction = self_->direction(); auto direction = self_->direction_;
if (direction == EdgeAtom::Direction::IN || if (direction == EdgeAtom::Direction::IN ||
direction == EdgeAtom::Direction::BOTH) { direction == EdgeAtom::Direction::BOTH) {
if (self_->existing_node()) { if (self_->existing_node_) {
TypedValue &existing_node = frame[self_->node_symbol()]; TypedValue &existing_node = frame[self_->node_symbol_];
// old_node_value may be Null when using optional matching // old_node_value may be Null when using optional matching
if (!existing_node.IsNull()) { if (!existing_node.IsNull()) {
ExpectType(self_->node_symbol(), existing_node, ExpectType(self_->node_symbol_, existing_node,
TypedValue::Type::Vertex); TypedValue::Type::Vertex);
in_edges_.emplace( in_edges_.emplace(
vertex.in(existing_node.ValueVertex(), &self_->edge_types())); vertex.in(existing_node.ValueVertex(), &self_->edge_types_));
} }
} else { } else {
in_edges_.emplace(vertex.in(&self_->edge_types())); in_edges_.emplace(vertex.in(&self_->edge_types_));
} }
in_edges_it_.emplace(in_edges_->begin()); in_edges_it_.emplace(in_edges_->begin());
} }
if (direction == EdgeAtom::Direction::OUT || if (direction == EdgeAtom::Direction::OUT ||
direction == EdgeAtom::Direction::BOTH) { direction == EdgeAtom::Direction::BOTH) {
if (self_->existing_node()) { if (self_->existing_node_) {
TypedValue &existing_node = frame[self_->node_symbol()]; TypedValue &existing_node = frame[self_->node_symbol_];
// old_node_value may be Null when using optional matching // old_node_value may be Null when using optional matching
if (!existing_node.IsNull()) { if (!existing_node.IsNull()) {
ExpectType(self_->node_symbol(), existing_node, ExpectType(self_->node_symbol_, existing_node,
TypedValue::Type::Vertex); TypedValue::Type::Vertex);
out_edges_.emplace( out_edges_.emplace(
vertex.out(existing_node.ValueVertex(), &self_->edge_types())); vertex.out(existing_node.ValueVertex(), &self_->edge_types_));
} }
} else { } else {
out_edges_.emplace(vertex.out(&self_->edge_types())); out_edges_.emplace(vertex.out(&self_->edge_types_));
} }
out_edges_it_.emplace(out_edges_->begin()); out_edges_it_.emplace(out_edges_->begin());
} }
@ -1030,8 +1030,8 @@ class DistributedExpandBfsCursor : public query::plan::Cursor {
} }
CHECK(bfs_subcursor_clients_); CHECK(bfs_subcursor_clients_);
subcursor_ids_ = bfs_subcursor_clients_->CreateBfsSubcursors( subcursor_ids_ = bfs_subcursor_clients_->CreateBfsSubcursors(
db_.transaction_id(), self_.direction(), self_.edge_types(), db_.transaction_id(), self_.direction_, self_.edge_types_,
self_.graph_view()); self_.graph_view_);
bfs_subcursor_clients_->RegisterSubcursors(subcursor_ids_); bfs_subcursor_clients_->RegisterSubcursors(subcursor_ids_);
VLOG(10) << "BFS subcursors initialized"; VLOG(10) << "BFS subcursors initialized";
pull_pos_ = subcursor_ids_.end(); pull_pos_ = subcursor_ids_.end();
@ -1044,14 +1044,14 @@ class DistributedExpandBfsCursor : public query::plan::Cursor {
bool Pull(Frame &frame, Context &context) override { bool Pull(Frame &frame, Context &context) override {
// TODO(mtomic): lambda filtering in distributed // TODO(mtomic): lambda filtering in distributed
if (self_.filter_lambda().expression) { if (self_.filter_lambda_.expression) {
throw utils::NotYetImplemented("lambda filtering in distributed BFS"); throw utils::NotYetImplemented("lambda filtering in distributed BFS");
} }
// Evaluator for the filtering condition and expansion depth. // Evaluator for the filtering condition and expansion depth.
ExpressionEvaluator evaluator(&frame, context.symbol_table_, ExpressionEvaluator evaluator(&frame, context.symbol_table_,
context.evaluation_context_, context.evaluation_context_,
&context.db_accessor_, self_.graph_view()); &context.db_accessor_, self_.graph_view_);
while (true) { while (true) {
if (context.db_accessor_.should_abort()) throw HintedAbortError(); if (context.db_accessor_.should_abort()) throw HintedAbortError();
@ -1064,7 +1064,7 @@ class DistributedExpandBfsCursor : public query::plan::Cursor {
pull_pos_->second, &db_); pull_pos_->second, &db_);
if (vertex) { if (vertex) {
last_vertex = *vertex; last_vertex = *vertex;
SwitchAccessor(last_vertex.ValueVertex(), self_.graph_view()); SwitchAccessor(last_vertex.ValueVertex(), self_.graph_view_);
break; break;
} }
VLOG(10) << "Nothing to pull from " << pull_pos_->first; VLOG(10) << "Nothing to pull from " << pull_pos_->first;
@ -1073,15 +1073,15 @@ class DistributedExpandBfsCursor : public query::plan::Cursor {
if (last_vertex.IsVertex()) { if (last_vertex.IsVertex()) {
// Handle existence flag // Handle existence flag
if (self_.existing_node()) { if (self_.existing_node_) {
TypedValue &node = frame[self_.node_symbol()]; TypedValue &node = frame[self_.node_symbol_];
// Due to optional matching the existing node could be null // Due to optional matching the existing node could be null
if (node.IsNull() || (node != last_vertex).ValueBool()) continue; if (node.IsNull() || (node != last_vertex).ValueBool()) continue;
// There is no point in traversing the rest of the graph because BFS // There is no point in traversing the rest of the graph because BFS
// can find only one path to a certain node. // can find only one path to a certain node.
skip_rest_ = true; skip_rest_ = true;
} else { } else {
frame[self_.node_symbol()] = last_vertex; frame[self_.node_symbol_] = last_vertex;
} }
VLOG(10) << "Expanded to vertex: " << 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()); std::reverse(edges.begin(), edges.end());
for (auto &edge : edges) for (auto &edge : edges)
SwitchAccessor(edge.ValueEdge(), self_.graph_view()); SwitchAccessor(edge.ValueEdge(), self_.graph_view_);
frame[self_.edge_symbol()] = std::move(edges); frame[self_.edge_symbol_] = std::move(edges);
return true; return true;
} }
@ -1139,18 +1139,18 @@ class DistributedExpandBfsCursor : public query::plan::Cursor {
// We're done with this source, try getting a new one // We're done with this source, try getting a new one
if (!input_cursor_->Pull(frame, context)) return false; 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. // It is possible that the vertex is Null due to optional matching.
if (vertex_value.IsNull()) continue; if (vertex_value.IsNull()) continue;
auto vertex = vertex_value.ValueVertex(); auto vertex = vertex_value.ValueVertex();
lower_bound_ = self_.lower_bound() lower_bound_ = self_.lower_bound_
? EvaluateInt(&evaluator, self_.lower_bound(), ? EvaluateInt(&evaluator, self_.lower_bound_,
"Min depth in breadth-first expansion") "Min depth in breadth-first expansion")
: 1; : 1;
upper_bound_ = self_.upper_bound() upper_bound_ = self_.upper_bound_
? EvaluateInt(&evaluator, self_.upper_bound(), ? EvaluateInt(&evaluator, self_.upper_bound_,
"Max depth in breadth-first expansion") "Max depth in breadth-first expansion")
: std::numeric_limits<int64_t>::max(); : std::numeric_limits<int64_t>::max();
skip_rest_ = false; skip_rest_ = false;
@ -1257,8 +1257,8 @@ class DistributedCreateNodeCursor : public query::plan::Cursor {
: input_cursor_(self->input()->MakeCursor(*dba)), : input_cursor_(self->input()->MakeCursor(*dba)),
// TODO: Replace this with some other mechanism // TODO: Replace this with some other mechanism
db_(dynamic_cast<database::DistributedGraphDb *>(&dba->db())), db_(dynamic_cast<database::DistributedGraphDb *>(&dba->db())),
node_atom_(self->node_atom()), node_atom_(self->node_atom_),
on_random_worker_(self->on_random_worker()) { on_random_worker_(self->on_random_worker_) {
CHECK(db_); CHECK(db_);
CHECK(node_atom_); CHECK(node_atom_);
} }
@ -1301,8 +1301,8 @@ class DistributedCreateExpandCursor : public query::plan::Cursor {
if (!input_cursor_->Pull(frame, context)) return false; if (!input_cursor_->Pull(frame, context)) return false;
// get the origin vertex // get the origin vertex
TypedValue &vertex_value = frame[self_->input_symbol()]; TypedValue &vertex_value = frame[self_->input_symbol_];
ExpectType(self_->input_symbol(), vertex_value, TypedValue::Type::Vertex); ExpectType(self_->input_symbol_, vertex_value, TypedValue::Type::Vertex);
auto &v1 = vertex_value.Value<VertexAccessor>(); auto &v1 = vertex_value.Value<VertexAccessor>();
// Similarly to CreateNode, newly created edges and nodes should use the // 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_; auto *dba = &context.db_accessor_;
// create an edge between the two nodes // create an edge between the two nodes
switch (self_->edge_atom()->direction_) { switch (self_->edge_atom_->direction_) {
case EdgeAtom::Direction::IN: case EdgeAtom::Direction::IN:
CreateEdge(&v2, &v1, &frame, context.symbol_table_, &evaluator, dba); CreateEdge(&v2, &v1, &frame, context.symbol_table_, &evaluator, dba);
break; break;
@ -1342,14 +1342,14 @@ class DistributedCreateExpandCursor : public query::plan::Cursor {
void Reset() override { input_cursor_->Reset(); } void Reset() override { input_cursor_->Reset(); }
VertexAccessor &OtherVertex(int worker_id, Frame &frame, Context &context) { VertexAccessor &OtherVertex(int worker_id, Frame &frame, Context &context) {
if (self_->existing_node()) { if (self_->existing_node_) {
const auto &dest_node_symbol = 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]; TypedValue &dest_node_value = frame[dest_node_symbol];
ExpectType(dest_node_symbol, dest_node_value, TypedValue::Type::Vertex); ExpectType(dest_node_symbol, dest_node_value, TypedValue::Type::Vertex);
return dest_node_value.Value<VertexAccessor>(); return dest_node_value.Value<VertexAccessor>();
} else { } else {
return CreateVertexOnWorker(worker_id, self_->node_atom(), frame, return CreateVertexOnWorker(worker_id, self_->node_atom_, frame,
context); context);
} }
} }
@ -1359,10 +1359,10 @@ class DistributedCreateExpandCursor : public query::plan::Cursor {
ExpressionEvaluator *evaluator, ExpressionEvaluator *evaluator,
database::GraphDbAccessor *dba) { database::GraphDbAccessor *dba) {
EdgeAccessor edge = EdgeAccessor edge =
dba->InsertEdge(*from, *to, self_->edge_atom()->edge_types_[0]); dba->InsertEdge(*from, *to, self_->edge_atom_->edge_types_[0]);
for (auto kv : self_->edge_atom()->properties_) for (auto kv : self_->edge_atom_->properties_)
PropsSetChecked(&edge, kv.first.second, kv.second->Accept(*evaluator)); 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: private:

View File

@ -3,7 +3,9 @@
#pragma once #pragma once
#include "query/plan/distributed_ops.capnp.h"
#include "query/plan/operator.hpp" #include "query/plan/operator.hpp"
cpp<# cpp<#
(load "query/plan/operator.lcp") (load "query/plan/operator.lcp")
@ -46,11 +48,11 @@ class DistributedOperatorVisitor : public virtual HierarchicalLogicalOperatorVis
cpp<# cpp<#
(lcp:define-class pull-remote (logical-operator) (lcp:define-class pull-remote (logical-operator)
((input "std::shared_ptr<LogicalOperator>" ((input "std::shared_ptr<LogicalOperator>" :scope :public
:capnp-save #'save-operator-pointer :capnp-save #'save-operator-pointer
:capnp-load #'load-operator-pointer) :capnp-load #'load-operator-pointer)
(plan-id :int64_t :initval 0 :reader t) (plan-id :int64_t :initval 0 :scope :public)
(symbols "std::vector<Symbol>" :reader t (symbols "std::vector<Symbol>" :scope :public
:capnp-save (lcp:capnp-save-vector "::query::capnp::Symbol" "Symbol") :capnp-save (lcp:capnp-save-vector "::query::capnp::Symbol" "Symbol")
:capnp-load (lcp:capnp-load-vector "::query::capnp::Symbol" "Symbol"))) :capnp-load (lcp:capnp-load-vector "::query::capnp::Symbol" "Symbol")))
(:documentation (: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.") time on data transfer. It gives no guarantees on result order.")
(:public (:public
#>cpp #>cpp
PullRemote() {}
PullRemote(const std::shared_ptr<LogicalOperator> &input, int64_t plan_id, PullRemote(const std::shared_ptr<LogicalOperator> &input, int64_t plan_id,
const std::vector<Symbol> &symbols) const std::vector<Symbol> &symbols)
: input_(input), plan_id_(plan_id), symbols_(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; input_ = input;
} }
cpp<#) cpp<#)
(:private #>cpp PullRemote() {} cpp<#)
(:serialize :capnp)) (:serialize :capnp))
(defun load-pull-remote (reader member-name) (defun load-pull-remote (reader member-name capnp-name)
(declare (ignore capnp-name))
#>cpp #>cpp
${member-name} = std::static_pointer_cast<PullRemote>( ${member-name} = std::static_pointer_cast<PullRemote>(
utils::LoadSharedPtr<capnp::LogicalOperator, LogicalOperator>(${reader}, utils::LoadSharedPtr<capnp::LogicalOperator, LogicalOperator>(${reader},
[helper](const auto &reader) { [helper](const auto &reader) {
auto op = LogicalOperator::Construct(reader); std::unique_ptr<LogicalOperator> op;
op->Load(reader, helper); Load(&op, reader, helper);
return op.release(); return op.release();
}, &helper->loaded_ops)); }, &helper->loaded_ops));
cpp<#) cpp<#)
(lcp:define-class synchronize (logical-operator) (lcp:define-class synchronize (logical-operator)
((input "std::shared_ptr<LogicalOperator>" ((input "std::shared_ptr<LogicalOperator>" :scope :public
:capnp-save #'save-operator-pointer :capnp-save #'save-operator-pointer
:capnp-load #'load-operator-pointer) :capnp-load #'load-operator-pointer)
(pull-remote "std::shared_ptr<PullRemote>" :reader t (pull-remote "std::shared_ptr<PullRemote>" :scope :public
:capnp-save #'save-operator-pointer :capnp-save #'save-operator-pointer
:capnp-load #'load-pull-remote) :capnp-load #'load-pull-remote)
(advance-command :bool :initval "false" :reader t)) (advance-command :bool :initval "false" :scope :public))
(:documentation (:documentation
"Operator used to synchronize stages of plan execution between the master and "Operator used to synchronize stages of plan execution between the master and
all the workers. Synchronization is necessary in queries that update that 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.") 8. Yield all the results, first local, then from Pull if available.")
(:public (:public
#>cpp #>cpp
Synchronize() {}
Synchronize(const std::shared_ptr<LogicalOperator> &input, Synchronize(const std::shared_ptr<LogicalOperator> &input,
const std::shared_ptr<PullRemote> &pull_remote, const std::shared_ptr<PullRemote> &pull_remote,
bool advance_command) bool advance_command)
@ -141,22 +145,21 @@ Logic of the synchronize operator is:
input_ = input; input_ = input;
} }
cpp<#) cpp<#)
(:private #>cpp Synchronize() {} cpp<#)
(:serialize :capnp)) (:serialize :capnp))
(lcp:define-class pull-remote-order-by (logical-operator) (lcp:define-class pull-remote-order-by (logical-operator)
((input "std::shared_ptr<LogicalOperator>" ((input "std::shared_ptr<LogicalOperator>" :scope :public
:capnp-save #'save-operator-pointer :capnp-save #'save-operator-pointer
:capnp-load #'load-operator-pointer) :capnp-load #'load-operator-pointer)
(plan-id :int64_t :initval 0 :reader t) (plan-id :int64_t :initval 0 :scope :public)
(symbols "std::vector<Symbol>" :reader t (symbols "std::vector<Symbol>" :scope :public
:capnp-save (lcp:capnp-save-vector "::query::capnp::Symbol" "Symbol") :capnp-save (lcp:capnp-save-vector "::query::capnp::Symbol" "Symbol")
:capnp-load (lcp:capnp-load-vector "::query::capnp::Symbol" "Symbol")) :capnp-load (lcp:capnp-load-vector "::query::capnp::Symbol" "Symbol"))
(order-by "std::vector<Expression *>" :reader t (order-by "std::vector<Expression *>" :scope :public
:capnp-type "List(Ast.Tree)" :capnp-type "List(Ast.Tree)"
:capnp-save (save-ast-vector "Expression *") :capnp-save (save-ast-vector "Expression *")
:capnp-load (load-ast-vector "Expression *")) :capnp-load (load-ast-vector "Expression *"))
(compare "TypedValueVectorCompare" :reader t (compare "TypedValueVectorCompare" :scope :public
:capnp-type "Common.TypedValueVectorCompare")) :capnp-type "Common.TypedValueVectorCompare"))
(:documentation (:documentation
"Operator that merges distributed OrderBy operators. "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.") by having only one result from each worker.")
(:public (:public
#>cpp #>cpp
PullRemoteOrderBy( PullRemoteOrderBy() {}
const std::shared_ptr<LogicalOperator> &input, int64_t plan_id, PullRemoteOrderBy(
const std::vector<std::pair<Ordering, Expression *>> &order_by, const std::shared_ptr<LogicalOperator> &input, int64_t plan_id,
const std::vector<Symbol> &symbols); const std::vector<std::pair<Ordering, Expression *>> &order_by,
bool Accept(HierarchicalLogicalOperatorVisitor &visitor) override; const std::vector<Symbol> &symbols);
std::unique_ptr<Cursor> MakeCursor( bool Accept(HierarchicalLogicalOperatorVisitor &visitor) override;
database::GraphDbAccessor &db) const override; std::unique_ptr<Cursor> MakeCursor(
database::GraphDbAccessor &db) const override;
std::vector<Symbol> ModifiedSymbols(const SymbolTable &) const override; std::vector<Symbol> ModifiedSymbols(const SymbolTable &) const override;
std::vector<Symbol> OutputSymbols(const SymbolTable &) const override; std::vector<Symbol> OutputSymbols(const SymbolTable &) const override;
bool HasSingleInput() const override { return true; } bool HasSingleInput() const override { return true; }
std::shared_ptr<LogicalOperator> input() const override { return input_; } std::shared_ptr<LogicalOperator> input() const override { return input_; }
void set_input(std::shared_ptr<LogicalOperator> input) override { void set_input(std::shared_ptr<LogicalOperator> input) override {
input_ = input; input_ = input;
} }
cpp<#) cpp<#)
(:private #>cpp PullRemoteOrderBy() {} cpp<#)
(:serialize :capnp)) (:serialize :capnp))
(lcp:define-class distributed-expand (logical-operator expand-common) (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))) (:serialize :capnp :inherit-compose '(expand-common)))
(lcp:define-class distributed-expand-bfs (logical-operator 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" :documentation "Optional lower bound, default is 1"
:capnp-type "Ast.Tree" :capnp-init nil :capnp-type "Ast.Tree" :capnp-init nil
:capnp-save #'save-ast-pointer :capnp-save #'save-ast-pointer
:capnp-load (load-ast-pointer "Expression *")) :capnp-load (load-ast-pointer "Expression *"))
(upper-bound "Expression *" :reader t (upper-bound "Expression *" :scope :public
:documentation "Optional upper bound, default is infinity" :documentation "Optional upper bound, default is infinity"
:capnp-type "Ast.Tree" :capnp-init nil :capnp-type "Ast.Tree" :capnp-init nil
:capnp-save #'save-ast-pointer :capnp-save #'save-ast-pointer
:capnp-load (load-ast-pointer "Expression *")) :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." :documentation "Filter that must be satisfied for expansion to succeed."
:capnp-type "ExpandVariable.Lambda")) :capnp-type "ExpandVariable.Lambda"))
(:documentation "BFS expansion operator suited for distributed execution.") (:documentation "BFS expansion operator suited for distributed execution.")
(:public (:public
#>cpp #>cpp
DistributedExpandBfs() {}
DistributedExpandBfs(Symbol node_symbol, Symbol edge_symbol, DistributedExpandBfs(Symbol node_symbol, Symbol edge_symbol,
EdgeAtom::Direction direction, EdgeAtom::Direction direction,
const std::vector<storage::EdgeType> &edge_types, const std::vector<storage::EdgeType> &edge_types,
@ -243,20 +247,20 @@ by having only one result from each worker.")
input_ = input; input_ = input;
} }
cpp<#) cpp<#)
(:private #>cpp DistributedExpandBfs() {} cpp<#)
(:serialize :capnp :inherit-compose '(expand-common))) (:serialize :capnp :inherit-compose '(expand-common)))
(lcp:define-class distributed-create-node (logical-operator) (lcp:define-class distributed-create-node (logical-operator)
((input "std::shared_ptr<LogicalOperator>" ((input "std::shared_ptr<LogicalOperator>" :scope :public
:capnp-save #'save-operator-pointer :capnp-save #'save-operator-pointer
:capnp-load #'load-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-type "Ast.Tree" :capnp-init nil
:capnp-save #'save-ast-pointer :capnp-load (load-ast-pointer "NodeAtom *")) :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.") (:documentation "Create nodes in distributed environment.")
(:public (:public
#>cpp #>cpp
DistributedCreateNode() {}
DistributedCreateNode(const std::shared_ptr<LogicalOperator> &input, DistributedCreateNode(const std::shared_ptr<LogicalOperator> &input,
NodeAtom *node_atom, bool on_random_worker); NodeAtom *node_atom, bool on_random_worker);
@ -271,24 +275,24 @@ by having only one result from each worker.")
input_ = input; input_ = input;
} }
cpp<#) cpp<#)
(:private #>cpp DistributedCreateNode() {} cpp<#)
(:serialize :capnp)) (:serialize :capnp))
(lcp:define-class distributed-create-expand (logical-operator) (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-type "Ast.Tree" :capnp-init nil
:capnp-save #'save-ast-pointer :capnp-load (load-ast-pointer "NodeAtom *")) :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-type "Ast.Tree" :capnp-init nil
:capnp-save #'save-ast-pointer :capnp-load (load-ast-pointer "EdgeAtom *")) :capnp-save #'save-ast-pointer :capnp-load (load-ast-pointer "EdgeAtom *"))
(input "std::shared_ptr<LogicalOperator>" (input "std::shared_ptr<LogicalOperator>" :scope :public
:capnp-save #'save-operator-pointer :capnp-save #'save-operator-pointer
:capnp-load #'load-operator-pointer) :capnp-load #'load-operator-pointer)
(input-symbol "Symbol" :reader t) (input-symbol "Symbol" :scope :public)
(existing-node :bool :reader t)) (existing-node :bool :scope :public))
(:documentation "Distributed version of CreateExpand") (:documentation "Distributed version of CreateExpand")
(:public (:public
#>cpp #>cpp
DistributedCreateExpand() {}
DistributedCreateExpand(NodeAtom *node_atom, EdgeAtom *edge_atom, DistributedCreateExpand(NodeAtom *node_atom, EdgeAtom *edge_atom,
const std::shared_ptr<LogicalOperator> &input, const std::shared_ptr<LogicalOperator> &input,
Symbol input_symbol, bool existing_node); Symbol input_symbol, bool existing_node);
@ -303,7 +307,6 @@ by having only one result from each worker.")
input_ = input; input_ = input;
} }
cpp<#) cpp<#)
(:private #>cpp DistributedCreateExpand() {} cpp<#)
(:serialize :capnp)) (:serialize :capnp))
(lcp:pop-namespace) (lcp:pop-namespace)

View File

@ -20,8 +20,8 @@ bool DistributedPlanPrinter::PreVisit(query::plan::DistributedExpandBfs &op) {
bool DistributedPlanPrinter::PreVisit(query::plan::PullRemote &op) { bool DistributedPlanPrinter::PreVisit(query::plan::PullRemote &op) {
WithPrintLn([&op](auto &out) { WithPrintLn([&op](auto &out) {
out << "* PullRemote [" << op.plan_id() << "] {"; out << "* PullRemote [" << op.plan_id_ << "] {";
utils::PrintIterable(out, op.symbols(), ", ", utils::PrintIterable(out, op.symbols_, ", ",
[](auto &out, const auto &sym) { out << sym.name(); }); [](auto &out, const auto &sym) { out << sym.name(); });
out << "}"; out << "}";
}); });
@ -35,7 +35,7 @@ bool DistributedPlanPrinter::PreVisit(query::plan::PullRemote &op) {
bool DistributedPlanPrinter::PreVisit(query::plan::PullRemoteOrderBy &op) { bool DistributedPlanPrinter::PreVisit(query::plan::PullRemoteOrderBy &op) {
WithPrintLn([&op](auto &out) { WithPrintLn([&op](auto &out) {
out << "* PullRemoteOrderBy {"; out << "* PullRemoteOrderBy {";
utils::PrintIterable(out, op.symbols(), ", ", utils::PrintIterable(out, op.symbols_, ", ",
[](auto &out, const auto &sym) { out << sym.name(); }); [](auto &out, const auto &sym) { out << sym.name(); });
out << "}"; out << "}";
}); });
@ -61,10 +61,10 @@ PRE_VISIT(DistributedCreateExpand);
bool DistributedPlanPrinter::PreVisit(query::plan::Synchronize &op) { bool DistributedPlanPrinter::PreVisit(query::plan::Synchronize &op) {
WithPrintLn([&op](auto &out) { WithPrintLn([&op](auto &out) {
out << "* Synchronize"; out << "* Synchronize";
if (op.advance_command()) out << " (ADV CMD)"; if (op.advance_command_) out << " (ADV CMD)";
}); });
if (op.pull_remote()) Branch(*op.pull_remote()); if (op.pull_remote_) Branch(*op.pull_remote_);
op.input()->Accept(*this); op.input_->Accept(*this);
return false; return false;
} }

View File

@ -223,7 +223,7 @@ VertexAccessor &CreateExpand::CreateExpandCursor::OtherVertex(
ExpectType(dest_node_symbol, dest_node_value, TypedValue::Type::Vertex); ExpectType(dest_node_symbol, dest_node_value, TypedValue::Type::Vertex);
return dest_node_value.Value<VertexAccessor>(); return dest_node_value.Value<VertexAccessor>();
} else { } else {
return CreateLocalVertex(self_.node_atom(), frame, context); return CreateLocalVertex(self_.node_atom_, frame, context);
} }
} }
@ -365,8 +365,8 @@ std::unique_ptr<Cursor> ScanAllByLabelPropertyRange::MakeCursor(
value.type()); value.type());
} }
}; };
auto maybe_lower = convert(lower_bound()); auto maybe_lower = convert(lower_bound_);
auto maybe_upper = convert(upper_bound()); auto maybe_upper = convert(upper_bound_);
// If any bound is null, then the comparison would result in nulls. This // If any bound is null, then the comparison would result in nulls. This
// is treated as not satisfying the filter, so return no vertices. // is treated as not satisfying the filter, so return no vertices.
if (maybe_lower && maybe_lower->value().IsNull()) if (maybe_lower && maybe_lower->value().IsNull())
@ -454,8 +454,8 @@ std::unique_ptr<Cursor> Expand::MakeCursor(
std::vector<Symbol> Expand::ModifiedSymbols(const SymbolTable &table) const { std::vector<Symbol> Expand::ModifiedSymbols(const SymbolTable &table) const {
auto symbols = input_->ModifiedSymbols(table); auto symbols = input_->ModifiedSymbols(table);
symbols.emplace_back(node_symbol()); symbols.emplace_back(node_symbol_);
symbols.emplace_back(edge_symbol()); symbols.emplace_back(edge_symbol_);
return symbols; return symbols;
} }
@ -549,10 +549,10 @@ bool Expand::ExpandCursor::InitEdges(Frame &frame, Context &context) {
ExpectType(self_.node_symbol_, existing_node, ExpectType(self_.node_symbol_, existing_node,
TypedValue::Type::Vertex); TypedValue::Type::Vertex);
in_edges_.emplace( in_edges_.emplace(
vertex.in(existing_node.ValueVertex(), &self_.edge_types())); vertex.in(existing_node.ValueVertex(), &self_.edge_types_));
} }
} else { } else {
in_edges_.emplace(vertex.in(&self_.edge_types())); in_edges_.emplace(vertex.in(&self_.edge_types_));
} }
in_edges_it_.emplace(in_edges_->begin()); 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, ExpectType(self_.node_symbol_, existing_node,
TypedValue::Type::Vertex); TypedValue::Type::Vertex);
out_edges_.emplace( out_edges_.emplace(
vertex.out(existing_node.ValueVertex(), &self_.edge_types())); vertex.out(existing_node.ValueVertex(), &self_.edge_types_));
} }
} else { } else {
out_edges_.emplace(vertex.out(&self_.edge_types())); out_edges_.emplace(vertex.out(&self_.edge_types_));
} }
out_edges_it_.emplace(out_edges_->begin()); out_edges_it_.emplace(out_edges_->begin());
} }
@ -610,8 +610,8 @@ ACCEPT_WITH_INPUT(ExpandVariable)
std::vector<Symbol> ExpandVariable::ModifiedSymbols( std::vector<Symbol> ExpandVariable::ModifiedSymbols(
const SymbolTable &table) const { const SymbolTable &table) const {
auto symbols = input_->ModifiedSymbols(table); auto symbols = input_->ModifiedSymbols(table);
symbols.emplace_back(node_symbol()); symbols.emplace_back(node_symbol_);
symbols.emplace_back(edge_symbol()); symbols.emplace_back(edge_symbol_);
return symbols; return symbols;
} }
@ -895,11 +895,11 @@ class STShortestPathCursor : public query::plan::Cursor {
STShortestPathCursor(const ExpandVariable &self, STShortestPathCursor(const ExpandVariable &self,
database::GraphDbAccessor &dba) database::GraphDbAccessor &dba)
: self_(self), input_cursor_(self_.input()->MakeCursor(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"; << "ExpandVariable should only be planned with GraphView::OLD";
CHECK(self_.existing_node()) << "s-t shortest path algorithm should only " CHECK(self_.existing_node_) << "s-t shortest path algorithm should only "
"be used when `existing_node` flag is " "be used when `existing_node` flag is "
"set!"; "set!";
} }
bool Pull(Frame &frame, Context &context) override { bool Pull(Frame &frame, Context &context) override {
@ -907,8 +907,8 @@ class STShortestPathCursor : public query::plan::Cursor {
context.evaluation_context_, context.evaluation_context_,
&context.db_accessor_, GraphView::OLD); &context.db_accessor_, GraphView::OLD);
while (input_cursor_->Pull(frame, context)) { while (input_cursor_->Pull(frame, context)) {
auto source_tv = frame[self_.input_symbol()]; auto source_tv = frame[self_.input_symbol_];
auto sink_tv = frame[self_.node_symbol()]; auto sink_tv = frame[self_.node_symbol_];
// It is possible that source or sink vertex is Null due to optional // It is possible that source or sink vertex is Null due to optional
// matching. // matching.
@ -918,13 +918,13 @@ class STShortestPathCursor : public query::plan::Cursor {
auto sink = sink_tv.ValueVertex(); auto sink = sink_tv.ValueVertex();
int64_t lower_bound = int64_t lower_bound =
self_.lower_bound() self_.lower_bound_
? EvaluateInt(&evaluator, self_.lower_bound(), ? EvaluateInt(&evaluator, self_.lower_bound_,
"Min depth in breadth-first expansion") "Min depth in breadth-first expansion")
: 1; : 1;
int64_t upper_bound = int64_t upper_bound =
self_.upper_bound() self_.upper_bound_
? EvaluateInt(&evaluator, self_.upper_bound(), ? EvaluateInt(&evaluator, self_.upper_bound_,
"Max depth in breadth-first expansion") "Max depth in breadth-first expansion")
: std::numeric_limits<int64_t>::max(); : std::numeric_limits<int64_t>::max();
@ -971,17 +971,17 @@ class STShortestPathCursor : public query::plan::Cursor {
last_edge->from_is(last_vertex) ? last_edge->to() : last_edge->from(); last_edge->from_is(last_vertex) ? last_edge->to() : last_edge->from();
result.emplace_back(*last_edge); 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, bool ShouldExpand(const VertexAccessor &vertex, const EdgeAccessor &edge,
Frame *frame, ExpressionEvaluator *evaluator) { 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_node_symbol) = vertex;
frame->at(self_.filter_lambda().inner_edge_symbol) = edge; 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.IsNull()) return false;
if (result.IsBool()) return result.ValueBool(); if (result.IsBool()) return result.ValueBool();
@ -1031,8 +1031,8 @@ class STShortestPathCursor : public query::plan::Cursor {
if (current_length > upper_bound) return false; if (current_length > upper_bound) return false;
for (const auto &vertex : source_frontier) { for (const auto &vertex : source_frontier) {
if (self_.direction() != EdgeAtom::Direction::IN) { if (self_.direction_ != EdgeAtom::Direction::IN) {
for (const auto &edge : vertex.out(&self_.edge_types())) { for (const auto &edge : vertex.out(&self_.edge_types_)) {
if (ShouldExpand(edge.to(), edge, frame, evaluator) && if (ShouldExpand(edge.to(), edge, frame, evaluator) &&
!Contains(in_edge, edge.to())) { !Contains(in_edge, edge.to())) {
in_edge.emplace(edge.to(), edge); in_edge.emplace(edge.to(), edge);
@ -1048,8 +1048,8 @@ class STShortestPathCursor : public query::plan::Cursor {
} }
} }
} }
if (self_.direction() != EdgeAtom::Direction::OUT) { if (self_.direction_ != EdgeAtom::Direction::OUT) {
for (const auto &edge : vertex.in(&self_.edge_types())) { for (const auto &edge : vertex.in(&self_.edge_types_)) {
if (ShouldExpand(edge.from(), edge, frame, evaluator) && if (ShouldExpand(edge.from(), edge, frame, evaluator) &&
!Contains(in_edge, edge.from())) { !Contains(in_edge, edge.from())) {
in_edge.emplace(edge.from(), edge); 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 // endpoint we pass to `should_expand`, because everything is
// reversed. // reversed.
for (const auto &vertex : sink_frontier) { for (const auto &vertex : sink_frontier) {
if (self_.direction() != EdgeAtom::Direction::OUT) { if (self_.direction_ != EdgeAtom::Direction::OUT) {
for (const auto &edge : vertex.out(&self_.edge_types())) { for (const auto &edge : vertex.out(&self_.edge_types_)) {
if (ShouldExpand(vertex, edge, frame, evaluator) && if (ShouldExpand(vertex, edge, frame, evaluator) &&
!Contains(out_edge, edge.to())) { !Contains(out_edge, edge.to())) {
out_edge.emplace(edge.to(), edge); out_edge.emplace(edge.to(), edge);
@ -1096,8 +1096,8 @@ class STShortestPathCursor : public query::plan::Cursor {
} }
} }
} }
if (self_.direction() != EdgeAtom::Direction::IN) { if (self_.direction_ != EdgeAtom::Direction::IN) {
for (const auto &edge : vertex.in(&self_.edge_types())) { for (const auto &edge : vertex.in(&self_.edge_types_)) {
if (ShouldExpand(vertex, edge, frame, evaluator) && if (ShouldExpand(vertex, edge, frame, evaluator) &&
!Contains(out_edge, edge.from())) { !Contains(out_edge, edge.from())) {
out_edge.emplace(edge.from(), edge); out_edge.emplace(edge.from(), edge);
@ -1127,9 +1127,9 @@ class SingleSourceShortestPathCursor : public query::plan::Cursor {
SingleSourceShortestPathCursor(const ExpandVariable &self, SingleSourceShortestPathCursor(const ExpandVariable &self,
database::GraphDbAccessor &db) database::GraphDbAccessor &db)
: self_(self), input_cursor_(self_.input()->MakeCursor(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"; << "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` " "should not be used when `existing_node` "
"flag is set, s-t shortest path algorithm " "flag is set, s-t shortest path algorithm "
"should be used instead!"; "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 we already processed the given vertex it doesn't get expanded
if (processed_.find(vertex) != processed_.end()) return; if (processed_.find(vertex) != processed_.end()) return;
frame[self_.filter_lambda().inner_edge_symbol] = edge; frame[self_.filter_lambda_.inner_edge_symbol] = edge;
frame[self_.filter_lambda().inner_node_symbol] = vertex; frame[self_.filter_lambda_.inner_node_symbol] = vertex;
if (self_.filter_lambda().expression) { if (self_.filter_lambda_.expression) {
TypedValue result = self_.filter_lambda().expression->Accept(evaluator); TypedValue result = self_.filter_lambda_.expression->Accept(evaluator);
switch (result.type()) { switch (result.type()) {
case TypedValue::Type::Null: case TypedValue::Type::Null:
return; return;
@ -1171,12 +1171,12 @@ class SingleSourceShortestPathCursor : public query::plan::Cursor {
// from the given vertex. skips expansions that don't satisfy // from the given vertex. skips expansions that don't satisfy
// the "where" condition. // the "where" condition.
auto expand_from_vertex = [this, &expand_pair](VertexAccessor &vertex) { auto expand_from_vertex = [this, &expand_pair](VertexAccessor &vertex) {
if (self_.direction() != EdgeAtom::Direction::IN) { if (self_.direction_ != EdgeAtom::Direction::IN) {
for (const EdgeAccessor &edge : vertex.out(&self_.edge_types())) for (const EdgeAccessor &edge : vertex.out(&self_.edge_types_))
expand_pair(edge, edge.to()); expand_pair(edge, edge.to());
} }
if (self_.direction() != EdgeAtom::Direction::OUT) { if (self_.direction_ != EdgeAtom::Direction::OUT) {
for (const EdgeAccessor &edge : vertex.in(&self_.edge_types())) for (const EdgeAccessor &edge : vertex.in(&self_.edge_types_))
expand_pair(edge, edge.from()); expand_pair(edge, edge.from());
} }
}; };
@ -1195,18 +1195,18 @@ class SingleSourceShortestPathCursor : public query::plan::Cursor {
to_visit_next_.clear(); to_visit_next_.clear();
processed_.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 // it is possible that the vertex is Null due to optional matching
if (vertex_value.IsNull()) continue; if (vertex_value.IsNull()) continue;
auto vertex = vertex_value.Value<VertexAccessor>(); auto vertex = vertex_value.Value<VertexAccessor>();
processed_.emplace(vertex, std::experimental::nullopt); processed_.emplace(vertex, std::experimental::nullopt);
expand_from_vertex(vertex); expand_from_vertex(vertex);
lower_bound_ = self_.lower_bound() lower_bound_ = self_.lower_bound_
? EvaluateInt(&evaluator, self_.lower_bound(), ? EvaluateInt(&evaluator, self_.lower_bound_,
"Min depth in breadth-first expansion") "Min depth in breadth-first expansion")
: 1; : 1;
upper_bound_ = self_.upper_bound() upper_bound_ = self_.upper_bound_
? EvaluateInt(&evaluator, self_.upper_bound(), ? EvaluateInt(&evaluator, self_.upper_bound_,
"Max depth in breadth-first expansion") "Max depth in breadth-first expansion")
: std::numeric_limits<int64_t>::max(); : std::numeric_limits<int64_t>::max();
if (upper_bound_ < 1) if (upper_bound_ < 1)
@ -1242,11 +1242,11 @@ class SingleSourceShortestPathCursor : public query::plan::Cursor {
if (static_cast<int64_t>(edge_list.size()) < lower_bound_) continue; if (static_cast<int64_t>(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 // place edges on the frame in the correct order
std::reverse(edge_list.begin(), edge_list.end()); 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; return true;
} }
@ -1549,15 +1549,15 @@ class ConstructNamedPathCursor : public Cursor {
bool Pull(Frame &frame, Context &context) override { bool Pull(Frame &frame, Context &context) override {
if (!input_cursor_->Pull(frame, context)) return false; if (!input_cursor_->Pull(frame, context)) return false;
auto symbol_it = self_.path_elements().begin(); auto symbol_it = self_.path_elements_.begin();
DCHECK(symbol_it != self_.path_elements().end()) DCHECK(symbol_it != self_.path_elements_.end())
<< "Named path must contain at least one node"; << "Named path must contain at least one node";
TypedValue start_vertex = frame[*symbol_it++]; TypedValue start_vertex = frame[*symbol_it++];
// In an OPTIONAL MATCH everything could be Null. // In an OPTIONAL MATCH everything could be Null.
if (start_vertex.IsNull()) { if (start_vertex.IsNull()) {
frame[self_.path_symbol()] = TypedValue::Null; frame[self_.path_symbol_] = TypedValue::Null;
return true; return true;
} }
@ -1571,13 +1571,13 @@ class ConstructNamedPathCursor : public Cursor {
// expansion already did it. // expansion already did it.
bool last_was_edge_list = false; 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]; TypedValue expansion = frame[*symbol_it];
// We can have Null (OPTIONAL MATCH), a vertex, an edge, or an edge // We can have Null (OPTIONAL MATCH), a vertex, an edge, or an edge
// list (variable expand or BFS). // list (variable expand or BFS).
switch (expansion.type()) { switch (expansion.type()) {
case TypedValue::Type::Null: case TypedValue::Type::Null:
frame[self_.path_symbol()] = TypedValue::Null; frame[self_.path_symbol_] = TypedValue::Null;
return true; return true;
case TypedValue::Type::Vertex: case TypedValue::Type::Vertex:
if (!last_was_edge_list) path.Expand(expansion.ValueVertex()); 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; return true;
} }
@ -3037,7 +3037,7 @@ class CreateIndexCursor : public Cursor {
throw IndexInMulticommandTxException(); throw IndexInMulticommandTxException();
} }
try { try {
db_.BuildIndex(self_.label(), self_.property()); db_.BuildIndex(self_.label_, self_.property_);
} catch (const database::IndexExistsException &) { } catch (const database::IndexExistsException &) {
// Ignore creating an existing index. // Ignore creating an existing index.
} }
@ -3155,8 +3155,8 @@ class CartesianCursor : public Cursor {
public: public:
CartesianCursor(const Cartesian &self, database::GraphDbAccessor &db) CartesianCursor(const Cartesian &self, database::GraphDbAccessor &db)
: self_(self), : self_(self),
left_op_cursor_(self.left_op()->MakeCursor(db)), left_op_cursor_(self.left_op_->MakeCursor(db)),
right_op_cursor_(self_.right_op()->MakeCursor(db)) { right_op_cursor_(self_.right_op_->MakeCursor(db)) {
CHECK(left_op_cursor_ != nullptr) CHECK(left_op_cursor_ != nullptr)
<< "CartesianCursor: Missing left operator cursor."; << "CartesianCursor: Missing left operator cursor.";
CHECK(right_op_cursor_ != nullptr) CHECK(right_op_cursor_ != nullptr)
@ -3204,12 +3204,12 @@ class CartesianCursor : public Cursor {
left_op_frames_it_ = left_op_frames_.begin(); left_op_frames_it_ = left_op_frames_.begin();
} else { } else {
// Make sure right_op_cursor last pulled results are on frame. // 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(); 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_++; left_op_frames_it_++;
return true; return true;
} }
@ -3301,7 +3301,7 @@ class AuthHandlerCursor : public Cursor {
std::vector<auth::Permission> GetAuthPermissions() { std::vector<auth::Permission> GetAuthPermissions() {
std::vector<auth::Permission> ret; std::vector<auth::Permission> ret;
for (const auto &privilege : self_.privileges()) { for (const auto &privilege : self_.privileges_) {
ret.push_back(glue::PrivilegeToPermission(privilege)); ret.push_back(glue::PrivilegeToPermission(privilege));
} }
return ret; return ret;
@ -3368,8 +3368,8 @@ class AuthHandlerCursor : public Cursor {
ctx.evaluation_context_, &ctx.db_accessor_, ctx.evaluation_context_, &ctx.db_accessor_,
GraphView::OLD); GraphView::OLD);
std::experimental::optional<std::string> password; std::experimental::optional<std::string> password;
if (self_.password()) { if (self_.password_) {
auto password_tv = self_.password()->Accept(evaluator); auto password_tv = self_.password_->Accept(evaluator);
if (!password_tv.IsString() && !password_tv.IsNull()) { if (!password_tv.IsString() && !password_tv.IsNull()) {
throw QueryRuntimeException( throw QueryRuntimeException(
"Expected string or null for password, got {}.", "Expected string or null for password, got {}.",
@ -3382,35 +3382,35 @@ class AuthHandlerCursor : public Cursor {
auto &auth = *ctx.auth_; auto &auth = *ctx.auth_;
switch (self_.action()) { switch (self_.action_) {
case AuthQuery::Action::CREATE_USER: { case AuthQuery::Action::CREATE_USER: {
std::lock_guard<std::mutex> lock(auth.WithLock()); std::lock_guard<std::mutex> lock(auth.WithLock());
auto user = auth.AddUser(self_.user(), password); auto user = auth.AddUser(self_.user_, password);
if (!user) { if (!user) {
throw QueryRuntimeException("User or role '{}' already exists.", throw QueryRuntimeException("User or role '{}' already exists.",
self_.user()); self_.user_);
} }
return false; return false;
} }
case AuthQuery::Action::DROP_USER: { case AuthQuery::Action::DROP_USER: {
std::lock_guard<std::mutex> lock(auth.WithLock()); std::lock_guard<std::mutex> lock(auth.WithLock());
auto user = auth.GetUser(self_.user()); auto user = auth.GetUser(self_.user_);
if (!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 '{}'.", throw QueryRuntimeException("Couldn't remove user '{}'.",
self_.user()); self_.user_);
} }
return false; return false;
} }
case AuthQuery::Action::SET_PASSWORD: { case AuthQuery::Action::SET_PASSWORD: {
std::lock_guard<std::mutex> lock(auth.WithLock()); std::lock_guard<std::mutex> lock(auth.WithLock());
auto user = auth.GetUser(self_.user()); auto user = auth.GetUser(self_.user_);
if (!user) { if (!user) {
throw QueryRuntimeException("User '{}' doesn't exist.", self_.user()); throw QueryRuntimeException("User '{}' doesn't exist.", self_.user_);
} }
user->UpdatePassword(password); user->UpdatePassword(password);
auth.SaveUser(*user); auth.SaveUser(*user);
@ -3419,23 +3419,23 @@ class AuthHandlerCursor : public Cursor {
case AuthQuery::Action::CREATE_ROLE: { case AuthQuery::Action::CREATE_ROLE: {
std::lock_guard<std::mutex> lock(auth.WithLock()); std::lock_guard<std::mutex> lock(auth.WithLock());
auto role = auth.AddRole(self_.role()); auto role = auth.AddRole(self_.role_);
if (!role) { if (!role) {
throw QueryRuntimeException("User or role '{}' already exists.", throw QueryRuntimeException("User or role '{}' already exists.",
self_.role()); self_.role_);
} }
return false; return false;
} }
case AuthQuery::Action::DROP_ROLE: { case AuthQuery::Action::DROP_ROLE: {
std::lock_guard<std::mutex> lock(auth.WithLock()); std::lock_guard<std::mutex> lock(auth.WithLock());
auto role = auth.GetRole(self_.role()); auto role = auth.GetRole(self_.role_);
if (!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 '{}'.", throw QueryRuntimeException("Couldn't remove role '{}'.",
self_.role()); self_.role_);
} }
return false; return false;
} }
@ -3449,7 +3449,7 @@ class AuthHandlerCursor : public Cursor {
if (users_it_ == users_->end()) return false; if (users_it_ == users_->end()) return false;
frame[self_.user_symbol()] = users_it_->username(); frame[self_.user_symbol_] = users_it_->username();
users_it_++; users_it_++;
return true; return true;
@ -3464,7 +3464,7 @@ class AuthHandlerCursor : public Cursor {
if (roles_it_ == roles_->end()) return false; if (roles_it_ == roles_->end()) return false;
frame[self_.role_symbol()] = roles_it_->rolename(); frame[self_.role_symbol_] = roles_it_->rolename();
roles_it_++; roles_it_++;
return true; return true;
@ -3472,17 +3472,17 @@ class AuthHandlerCursor : public Cursor {
case AuthQuery::Action::SET_ROLE: { case AuthQuery::Action::SET_ROLE: {
std::lock_guard<std::mutex> lock(auth.WithLock()); std::lock_guard<std::mutex> lock(auth.WithLock());
auto user = auth.GetUser(self_.user()); auto user = auth.GetUser(self_.user_);
if (!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) { if (!role) {
throw QueryRuntimeException("Role '{}' doesn't exist.", self_.role()); throw QueryRuntimeException("Role '{}' doesn't exist.", self_.role_);
} }
if (user->role()) { if (user->role()) {
throw QueryRuntimeException( throw QueryRuntimeException(
"User '{}' is already a member of role '{}'.", self_.user(), "User '{}' is already a member of role '{}'.", self_.user_,
user->role()->rolename()); user->role()->rolename());
} }
user->SetRole(*role); user->SetRole(*role);
@ -3492,9 +3492,9 @@ class AuthHandlerCursor : public Cursor {
case AuthQuery::Action::CLEAR_ROLE: { case AuthQuery::Action::CLEAR_ROLE: {
std::lock_guard<std::mutex> lock(auth.WithLock()); std::lock_guard<std::mutex> lock(auth.WithLock());
auto user = auth.GetUser(self_.user()); auto user = auth.GetUser(self_.user_);
if (!user) { if (!user) {
throw QueryRuntimeException("User '{}' doesn't exist.", self_.user()); throw QueryRuntimeException("User '{}' doesn't exist.", self_.user_);
} }
user->ClearRole(); user->ClearRole();
auth.SaveUser(*user); auth.SaveUser(*user);
@ -3505,11 +3505,11 @@ class AuthHandlerCursor : public Cursor {
case AuthQuery::Action::DENY_PRIVILEGE: case AuthQuery::Action::DENY_PRIVILEGE:
case AuthQuery::Action::REVOKE_PRIVILEGE: { case AuthQuery::Action::REVOKE_PRIVILEGE: {
std::lock_guard<std::mutex> lock(auth.WithLock()); std::lock_guard<std::mutex> lock(auth.WithLock());
auto user = auth.GetUser(self_.user_or_role()); auto user = auth.GetUser(self_.user_or_role_);
auto role = auth.GetRole(self_.user_or_role()); auto role = auth.GetRole(self_.user_or_role_);
if (!user && !role) { if (!user && !role) {
throw QueryRuntimeException("User or role '{}' doesn't exist.", throw QueryRuntimeException("User or role '{}' doesn't exist.",
self_.user_or_role()); self_.user_or_role_);
} }
auto permissions = GetAuthPermissions(); auto permissions = GetAuthPermissions();
if (user) { if (user) {
@ -3517,9 +3517,9 @@ class AuthHandlerCursor : public Cursor {
// TODO (mferencevic): should we first check that the privilege // TODO (mferencevic): should we first check that the privilege
// is granted/denied/revoked before unconditionally // is granted/denied/revoked before unconditionally
// granting/denying/revoking it? // granting/denying/revoking it?
if (self_.action() == AuthQuery::Action::GRANT_PRIVILEGE) { if (self_.action_ == AuthQuery::Action::GRANT_PRIVILEGE) {
user->permissions().Grant(permission); user->permissions().Grant(permission);
} else if (self_.action() == AuthQuery::Action::DENY_PRIVILEGE) { } else if (self_.action_ == AuthQuery::Action::DENY_PRIVILEGE) {
user->permissions().Deny(permission); user->permissions().Deny(permission);
} else { } else {
user->permissions().Revoke(permission); user->permissions().Revoke(permission);
@ -3531,9 +3531,9 @@ class AuthHandlerCursor : public Cursor {
// TODO (mferencevic): should we first check that the privilege // TODO (mferencevic): should we first check that the privilege
// is granted/denied/revoked before unconditionally // is granted/denied/revoked before unconditionally
// granting/denying/revoking it? // granting/denying/revoking it?
if (self_.action() == AuthQuery::Action::GRANT_PRIVILEGE) { if (self_.action_ == AuthQuery::Action::GRANT_PRIVILEGE) {
role->permissions().Grant(permission); role->permissions().Grant(permission);
} else if (self_.action() == AuthQuery::Action::DENY_PRIVILEGE) { } else if (self_.action_ == AuthQuery::Action::DENY_PRIVILEGE) {
role->permissions().Deny(permission); role->permissions().Deny(permission);
} else { } else {
role->permissions().Revoke(permission); role->permissions().Revoke(permission);
@ -3547,11 +3547,11 @@ class AuthHandlerCursor : public Cursor {
case AuthQuery::Action::SHOW_PRIVILEGES: { case AuthQuery::Action::SHOW_PRIVILEGES: {
if (!grants_) { if (!grants_) {
std::lock_guard<std::mutex> lock(auth.WithLock()); std::lock_guard<std::mutex> lock(auth.WithLock());
auto user = auth.GetUser(self_.user_or_role()); auto user = auth.GetUser(self_.user_or_role_);
auto role = auth.GetRole(self_.user_or_role()); auto role = auth.GetRole(self_.user_or_role_);
if (!user && !role) { if (!user && !role) {
throw QueryRuntimeException("User or role '{}' doesn't exist.", throw QueryRuntimeException("User or role '{}' doesn't exist.",
self_.user_or_role()); self_.user_or_role_);
} }
if (user) { if (user) {
grants_.emplace(GetGrantsForAuthUser(*user)); grants_.emplace(GetGrantsForAuthUser(*user));
@ -3563,9 +3563,9 @@ class AuthHandlerCursor : public Cursor {
if (grants_it_ == grants_->end()) return false; if (grants_it_ == grants_->end()) return false;
frame[self_.privilege_symbol()] = std::get<0>(*grants_it_); frame[self_.privilege_symbol_] = std::get<0>(*grants_it_);
frame[self_.effective_symbol()] = std::get<1>(*grants_it_); frame[self_.effective_symbol_] = std::get<1>(*grants_it_);
frame[self_.details_symbol()] = std::get<2>(*grants_it_); frame[self_.details_symbol_] = std::get<2>(*grants_it_);
grants_it_++; grants_it_++;
return true; return true;
@ -3574,14 +3574,14 @@ class AuthHandlerCursor : public Cursor {
case AuthQuery::Action::SHOW_ROLE_FOR_USER: { case AuthQuery::Action::SHOW_ROLE_FOR_USER: {
if (returned_role_for_user_) return false; if (returned_role_for_user_) return false;
std::lock_guard<std::mutex> lock(auth.WithLock()); std::lock_guard<std::mutex> lock(auth.WithLock());
auto user = auth.GetUser(self_.user()); auto user = auth.GetUser(self_.user_);
if (!user) { if (!user) {
throw QueryRuntimeException("User '{}' doesn't exist.", self_.user()); throw QueryRuntimeException("User '{}' doesn't exist.", self_.user_);
} }
if (user->role()) { if (user->role()) {
frame[self_.role_symbol()] = user->role()->rolename(); frame[self_.role_symbol_] = user->role()->rolename();
} else { } else {
frame[self_.role_symbol()] = TypedValue::Null; frame[self_.role_symbol_] = TypedValue::Null;
} }
returned_role_for_user_ = true; returned_role_for_user_ = true;
return true; return true;
@ -3590,18 +3590,18 @@ class AuthHandlerCursor : public Cursor {
case AuthQuery::Action::SHOW_USERS_FOR_ROLE: { case AuthQuery::Action::SHOW_USERS_FOR_ROLE: {
if (!users_) { if (!users_) {
std::lock_guard<std::mutex> lock(auth.WithLock()); std::lock_guard<std::mutex> lock(auth.WithLock());
auto role = auth.GetRole(self_.role()); auto role = auth.GetRole(self_.role_);
if (!role) { if (!role) {
throw QueryRuntimeException("Role '{}' doesn't exist.", 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(); users_it_ = users_->begin();
} }
if (users_it_ == users_->end()) return false; if (users_it_ == users_->end()) return false;
frame[self_.user_symbol()] = users_it_->username(); frame[self_.user_symbol_] = users_it_->username();
users_it_++; users_it_++;
return true; return true;
@ -3664,23 +3664,23 @@ class CreateStreamCursor : public Cursor {
ctx.evaluation_context_, &ctx.db_accessor_, ctx.evaluation_context_, &ctx.db_accessor_,
GraphView::OLD); GraphView::OLD);
TypedValue stream_uri = self_.stream_uri()->Accept(evaluator); TypedValue stream_uri = self_.stream_uri_->Accept(evaluator);
TypedValue stream_topic = self_.stream_topic()->Accept(evaluator); TypedValue stream_topic = self_.stream_topic_->Accept(evaluator);
TypedValue transform_uri = self_.transform_uri()->Accept(evaluator); TypedValue transform_uri = self_.transform_uri_->Accept(evaluator);
std::experimental::optional<int64_t> batch_interval_in_ms, batch_size; std::experimental::optional<int64_t> batch_interval_in_ms, batch_size;
if (self_.batch_interval_in_ms()) { if (self_.batch_interval_in_ms_) {
batch_interval_in_ms = batch_interval_in_ms =
self_.batch_interval_in_ms()->Accept(evaluator).Value<int64_t>(); self_.batch_interval_in_ms_->Accept(evaluator).Value<int64_t>();
} }
if (self_.batch_size()) { if (self_.batch_size_) {
batch_size = self_.batch_size()->Accept(evaluator).Value<int64_t>(); batch_size = self_.batch_size_->Accept(evaluator).Value<int64_t>();
} }
try { try {
StreamInfo info; StreamInfo info;
info.stream_name = self_.stream_name(); info.stream_name = self_.stream_name_;
info.stream_uri = stream_uri.Value<std::string>(); info.stream_uri = stream_uri.Value<std::string>();
info.stream_topic = stream_topic.Value<std::string>(); info.stream_topic = stream_topic.Value<std::string>();
info.transform_uri = transform_uri.Value<std::string>(); info.transform_uri = transform_uri.Value<std::string>();
@ -3724,7 +3724,7 @@ class DropStreamCursor : public Cursor {
} }
try { try {
ctx.kafka_streams_->Drop(self_.stream_name()); ctx.kafka_streams_->Drop(self_.stream_name_);
} catch (const integrations::kafka::KafkaStreamException &e) { } catch (const integrations::kafka::KafkaStreamException &e) {
throw QueryRuntimeException(e.what()); throw QueryRuntimeException(e.what());
} }
@ -3778,11 +3778,11 @@ class ShowStreamsCursor : public Cursor {
if (streams_it_ == streams_.end()) return false; if (streams_it_ == streams_.end()) return false;
frame[self_.name_symbol()] = streams_it_->stream_name; frame[self_.name_symbol_] = streams_it_->stream_name;
frame[self_.uri_symbol()] = streams_it_->stream_uri; frame[self_.uri_symbol_] = streams_it_->stream_uri;
frame[self_.topic_symbol()] = streams_it_->stream_topic; frame[self_.topic_symbol_] = streams_it_->stream_topic;
frame[self_.transform_symbol()] = streams_it_->transform_uri; frame[self_.transform_symbol_] = streams_it_->transform_uri;
frame[self_.status_symbol()] = streams_it_->stream_status; frame[self_.status_symbol_] = streams_it_->stream_status;
streams_it_++; streams_it_++;
@ -3831,15 +3831,15 @@ class StartStopStreamCursor : public Cursor {
GraphView::OLD); GraphView::OLD);
std::experimental::optional<int64_t> limit_batches; std::experimental::optional<int64_t> limit_batches;
if (self_.limit_batches()) { if (self_.limit_batches_) {
limit_batches = self_.limit_batches()->Accept(evaluator).Value<int64_t>(); limit_batches = self_.limit_batches_->Accept(evaluator).Value<int64_t>();
} }
try { try {
if (self_.is_start()) { if (self_.is_start_) {
ctx.kafka_streams_->Start(self_.stream_name(), limit_batches); ctx.kafka_streams_->Start(self_.stream_name_, limit_batches);
} else { } else {
ctx.kafka_streams_->Stop(self_.stream_name()); ctx.kafka_streams_->Stop(self_.stream_name_);
} }
} catch (const integrations::kafka::KafkaStreamException &e) { } catch (const integrations::kafka::KafkaStreamException &e) {
throw QueryRuntimeException(e.what()); throw QueryRuntimeException(e.what());
@ -3877,7 +3877,7 @@ class StartStopAllStreamsCursor : public Cursor {
} }
try { try {
if (self_.is_start()) { if (self_.is_start_) {
ctx.kafka_streams_->StartAll(); ctx.kafka_streams_->StartAll();
} else { } else {
ctx.kafka_streams_->StopAll(); ctx.kafka_streams_->StopAll();
@ -3933,14 +3933,14 @@ class TestStreamCursor : public Cursor {
GraphView::OLD); GraphView::OLD);
std::experimental::optional<int64_t> limit_batches; std::experimental::optional<int64_t> limit_batches;
if (self_.limit_batches()) { if (self_.limit_batches_) {
limit_batches = limit_batches =
self_.limit_batches()->Accept(evaluator).Value<int64_t>(); self_.limit_batches_->Accept(evaluator).Value<int64_t>();
} }
try { try {
auto results = 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) { for (const auto &result : results) {
std::map<std::string, query::TypedValue> params_tv; std::map<std::string, query::TypedValue> params_tv;
for (const auto &kv : result.second) { for (const auto &kv : result.second) {
@ -3957,8 +3957,8 @@ class TestStreamCursor : public Cursor {
if (results_it_ == results_.end()) return false; if (results_it_ == results_.end()) return false;
frame[self_.query_symbol()] = results_it_->first; frame[self_.query_symbol_] = results_it_->first;
frame[self_.params_symbol()] = results_it_->second; frame[self_.params_symbol_] = results_it_->second;
results_it_++; results_it_++;
return true; return true;
@ -3986,9 +3986,9 @@ Explain::Explain(
const std::shared_ptr<LogicalOperator> &input, const Symbol &output_symbol, const std::shared_ptr<LogicalOperator> &input, const Symbol &output_symbol,
const std::function<void(const database::GraphDbAccessor &, const std::function<void(const database::GraphDbAccessor &,
LogicalOperator *, std::ostream *)> &pretty_print) LogicalOperator *, std::ostream *)> &pretty_print)
: pretty_print_(pretty_print), : input_(input),
input_(input), output_symbol_(output_symbol),
output_symbol_(output_symbol) {} pretty_print_(pretty_print) {}
ACCEPT_WITH_INPUT(Explain); ACCEPT_WITH_INPUT(Explain);

File diff suppressed because it is too large Load Diff

View File

@ -21,7 +21,7 @@ PRE_VISIT(Delete);
bool PlanPrinter::PreVisit(query::plan::ScanAll &op) { bool PlanPrinter::PreVisit(query::plan::ScanAll &op) {
WithPrintLn([&](auto &out) { WithPrintLn([&](auto &out) {
out << "* ScanAll" out << "* ScanAll"
<< " (" << op.output_symbol().name() << ")"; << " (" << op.output_symbol_.name() << ")";
}); });
return true; return true;
} }
@ -29,8 +29,8 @@ bool PlanPrinter::PreVisit(query::plan::ScanAll &op) {
bool PlanPrinter::PreVisit(query::plan::ScanAllByLabel &op) { bool PlanPrinter::PreVisit(query::plan::ScanAllByLabel &op) {
WithPrintLn([&](auto &out) { WithPrintLn([&](auto &out) {
out << "* ScanAllByLabel" out << "* ScanAllByLabel"
<< " (" << op.output_symbol().name() << " :" << " (" << op.output_symbol_.name() << " :"
<< dba_->LabelName(op.label()) << ")"; << dba_->LabelName(op.label_) << ")";
}); });
return true; return true;
} }
@ -38,9 +38,9 @@ bool PlanPrinter::PreVisit(query::plan::ScanAllByLabel &op) {
bool PlanPrinter::PreVisit(query::plan::ScanAllByLabelPropertyValue &op) { bool PlanPrinter::PreVisit(query::plan::ScanAllByLabelPropertyValue &op) {
WithPrintLn([&](auto &out) { WithPrintLn([&](auto &out) {
out << "* ScanAllByLabelPropertyValue" out << "* ScanAllByLabelPropertyValue"
<< " (" << op.output_symbol().name() << " :" << " (" << op.output_symbol_.name() << " :"
<< dba_->LabelName(op.label()) << " {" << dba_->LabelName(op.label_) << " {"
<< dba_->PropertyName(op.property()) << "})"; << dba_->PropertyName(op.property_) << "})";
}); });
return true; return true;
} }
@ -48,9 +48,9 @@ bool PlanPrinter::PreVisit(query::plan::ScanAllByLabelPropertyValue &op) {
bool PlanPrinter::PreVisit(query::plan::ScanAllByLabelPropertyRange &op) { bool PlanPrinter::PreVisit(query::plan::ScanAllByLabelPropertyRange &op) {
WithPrintLn([&](auto &out) { WithPrintLn([&](auto &out) {
out << "* ScanAllByLabelPropertyRange" out << "* ScanAllByLabelPropertyRange"
<< " (" << op.output_symbol().name() << " :" << " (" << op.output_symbol_.name() << " :"
<< dba_->LabelName(op.label()) << " {" << dba_->LabelName(op.label_) << " {"
<< dba_->PropertyName(op.property()) << "})"; << dba_->PropertyName(op.property_) << "})";
}); });
return true; return true;
} }
@ -75,7 +75,7 @@ bool PlanPrinter::PreVisit(query::plan::Produce &op) {
WithPrintLn([&](auto &out) { WithPrintLn([&](auto &out) {
out << "* Produce {"; out << "* Produce {";
utils::PrintIterable( utils::PrintIterable(
out, op.named_expressions(), ", ", out, op.named_expressions_, ", ",
[](auto &out, const auto &nexpr) { out << nexpr->name_; }); [](auto &out, const auto &nexpr) { out << nexpr->name_; });
out << "}"; out << "}";
}); });
@ -97,10 +97,10 @@ bool PlanPrinter::PreVisit(query::plan::Aggregate &op) {
WithPrintLn([&](auto &out) { WithPrintLn([&](auto &out) {
out << "* Aggregate {"; out << "* Aggregate {";
utils::PrintIterable( utils::PrintIterable(
out, op.aggregations(), ", ", out, op.aggregations_, ", ",
[](auto &out, const auto &aggr) { out << aggr.output_sym.name(); }); [](auto &out, const auto &aggr) { out << aggr.output_sym.name(); });
out << "} {"; out << "} {";
utils::PrintIterable(out, op.remember(), ", ", utils::PrintIterable(out, op.remember_, ", ",
[](auto &out, const auto &sym) { out << sym.name(); }); [](auto &out, const auto &sym) { out << sym.name(); });
out << "}"; out << "}";
}); });
@ -113,7 +113,7 @@ PRE_VISIT(Limit);
bool PlanPrinter::PreVisit(query::plan::OrderBy &op) { bool PlanPrinter::PreVisit(query::plan::OrderBy &op) {
WithPrintLn([&op](auto &out) { WithPrintLn([&op](auto &out) {
out << "* OrderBy {"; out << "* OrderBy {";
utils::PrintIterable(out, op.output_symbols(), ", ", utils::PrintIterable(out, op.output_symbols_, ", ",
[](auto &out, const auto &sym) { out << sym.name(); }); [](auto &out, const auto &sym) { out << sym.name(); });
out << "}"; out << "}";
}); });
@ -122,16 +122,16 @@ bool PlanPrinter::PreVisit(query::plan::OrderBy &op) {
bool PlanPrinter::PreVisit(query::plan::Merge &op) { bool PlanPrinter::PreVisit(query::plan::Merge &op) {
WithPrintLn([](auto &out) { out << "* Merge"; }); WithPrintLn([](auto &out) { out << "* Merge"; });
Branch(*op.merge_match(), "On Match"); Branch(*op.merge_match_, "On Match");
Branch(*op.merge_create(), "On Create"); Branch(*op.merge_create_, "On Create");
op.input()->Accept(*this); op.input_->Accept(*this);
return false; return false;
} }
bool PlanPrinter::PreVisit(query::plan::Optional &op) { bool PlanPrinter::PreVisit(query::plan::Optional &op) {
WithPrintLn([](auto &out) { out << "* Optional"; }); WithPrintLn([](auto &out) { out << "* Optional"; });
Branch(*op.optional()); Branch(*op.optional_);
op.input()->Accept(*this); op.input_->Accept(*this);
return false; return false;
} }
@ -185,7 +185,7 @@ bool PlanPrinter::Visit(query::plan::TestStream &op) {
bool PlanPrinter::PreVisit(query::plan::Explain &explain) { bool PlanPrinter::PreVisit(query::plan::Explain &explain) {
WithPrintLn([&explain](auto &out) { WithPrintLn([&explain](auto &out) {
out << "* Explain {" << explain.output_symbol().name() << "}"; out << "* Explain {" << explain.output_symbol_.name() << "}";
}); });
return true; return true;
} }
@ -193,15 +193,15 @@ bool PlanPrinter::PreVisit(query::plan::Explain &explain) {
bool PlanPrinter::PreVisit(query::plan::Cartesian &op) { bool PlanPrinter::PreVisit(query::plan::Cartesian &op) {
WithPrintLn([&op](auto &out) { WithPrintLn([&op](auto &out) {
out << "* Cartesian {"; out << "* Cartesian {";
utils::PrintIterable(out, op.left_symbols(), ", ", utils::PrintIterable(out, op.left_symbols_, ", ",
[](auto &out, const auto &sym) { out << sym.name(); }); [](auto &out, const auto &sym) { out << sym.name(); });
out << " : "; out << " : ";
utils::PrintIterable(out, op.right_symbols(), ", ", utils::PrintIterable(out, op.right_symbols_, ", ",
[](auto &out, const auto &sym) { out << sym.name(); }); [](auto &out, const auto &sym) { out << sym.name(); });
out << "}"; out << "}";
}); });
Branch(*op.right_op()); Branch(*op.right_op_);
op.left_op()->Accept(*this); op.left_op_->Accept(*this);
return false; return false;
} }
@ -221,11 +221,11 @@ void PlanPrinter::Branch(query::plan::LogicalOperator &op,
} }
void PlanPrinter::PrintExpand(const query::plan::ExpandCommon &op) { void PlanPrinter::PrintExpand(const query::plan::ExpandCommon &op) {
*out_ << " (" << op.input_symbol().name() << ")" *out_ << " (" << op.input_symbol_.name() << ")"
<< (op.direction() == query::EdgeAtom::Direction::IN ? "<-" : "-") << (op.direction_ == query::EdgeAtom::Direction::IN ? "<-" : "-") << "["
<< "[" << op.edge_symbol().name() << "]" << op.edge_symbol_.name() << "]"
<< (op.direction() == query::EdgeAtom::Direction::OUT ? "->" : "-") << (op.direction_ == query::EdgeAtom::Direction::OUT ? "->" : "-")
<< "(" << op.node_symbol().name() << ")"; << "(" << op.node_symbol_.name() << ")";
} }
void PrettyPrint(const database::GraphDbAccessor &dba, void PrettyPrint(const database::GraphDbAccessor &dba,

View File

@ -89,11 +89,6 @@ class Address {
return storage_ == other.storage_; return storage_ == other.storage_;
} }
void Load(const capnp::Address::Reader &reader) {
storage_ = reader.getStorage();
}
private:
StorageT storage_{0}; StorageT storage_{0};
}; };
@ -103,8 +98,8 @@ void Save(const Address<TLocalObj> &address, capnp::Address::Builder *builder) {
} }
template <typename TLocalObj> template <typename TLocalObj>
Address<TLocalObj> Load(const capnp::Address::Reader &reader) { void Load(Address<TLocalObj> *address, const capnp::Address::Reader &reader) {
return Address<TLocalObj>(reader.getStorage()); address->storage_ = reader.getStorage();
} }
} // namespace storage } // namespace storage

View File

@ -17,14 +17,14 @@ void RegisterRpc(MasterConcurrentIdMapper<TId> &mapper,
rpc_server.Register<type##IdRpc>( \ rpc_server.Register<type##IdRpc>( \
[&mapper](const auto &req_reader, auto *res_builder) { \ [&mapper](const auto &req_reader, auto *res_builder) { \
type##IdReq req; \ type##IdReq req; \
req.Load(req_reader); \ Load(&req, req_reader); \
type##IdRes res(mapper.value_to_id(req.member)); \ type##IdRes res(mapper.value_to_id(req.member)); \
Save(res, res_builder); \ Save(res, res_builder); \
}); \ }); \
rpc_server.Register<Id##type##Rpc>( \ rpc_server.Register<Id##type##Rpc>( \
[&mapper](const auto &req_reader, auto *res_builder) { \ [&mapper](const auto &req_reader, auto *res_builder) { \
Id##type##Req req; \ Id##type##Req req; \
req.Load(req_reader); \ Load(&req, req_reader); \
Id##type##Res res(mapper.id_to_value(req.member)); \ Id##type##Res res(mapper.id_to_value(req.member)); \
Save(res, res_builder); \ Save(res, res_builder); \
}); \ }); \

View File

@ -107,7 +107,7 @@ void LoadProperties(const capnp::PropertyValueStore::Reader &reader,
auto props_reader = reader.getProperties(); auto props_reader = reader.getProperties();
for (const auto &kv_reader : props_reader) { for (const auto &kv_reader : props_reader) {
storage::Property id; storage::Property id;
id.Load(kv_reader.getId()); storage::Load(&id, kv_reader.getId());
PropertyValue value; PropertyValue value;
LoadCapnpPropertyValue(kv_reader.getValue(), &value); LoadCapnpPropertyValue(kv_reader.getValue(), &value);
properties->set(id, value); properties->set(id, value);

View File

@ -54,25 +54,23 @@ class Common : public utils::TotalOrdering<TSpecificType> {
size_t operator()(const TSpecificType &t) const { return hash(t.id_); } size_t operator()(const TSpecificType &t) const { return hash(t.id_); }
}; };
void Load(const capnp::Common::Reader &reader) { IdT id_{0};
id_ = reader.getStorage();
}
auto Raw() const { return id_; }
protected: protected:
~Common() {} ~Common() {}
private: private:
static constexpr IdT Mask = std::numeric_limits<IdT>::max() >> 1; static constexpr IdT Mask = std::numeric_limits<IdT>::max() >> 1;
static constexpr IdT NotMask = ~Mask; static constexpr IdT NotMask = ~Mask;
IdT id_{0};
}; };
template <class Type> template <class Type>
void Save(const Common<Type> &common, capnp::Common::Builder *builder) { void Save(const Common<Type> &common, capnp::Common::Builder *builder) {
builder->setStorage(common.Raw()); builder->setStorage(common.id_);
}
template <class Type>
void Load(Common<Type> *common, const capnp::Common::Reader &reader) {
common->id_ = reader.getStorage();
} }
class Label final : public Common<Label> { class Label final : public Common<Label> {

View File

@ -5,9 +5,9 @@
${builder}->set${capnp-name}(${member}); ${builder}->set${capnp-name}(${member});
cpp<#) cpp<#)
(defun load-commitlog-info (reader member) (defun load-commitlog-info (reader member capnp-name)
#>cpp #>cpp
${member} = CommitLog::Info(${reader}.getMember()); ${member} = CommitLog::Info(${reader}.get${capnp-name}());
cpp<#) cpp<#)
(defun save-snapshot (builder member capnp-name) (defun save-snapshot (builder member capnp-name)
@ -16,10 +16,9 @@
utils::SaveVector(${member}.transaction_ids(), &list_builder); utils::SaveVector(${member}.transaction_ids(), &list_builder);
cpp<#) cpp<#)
(defun load-snapshot (reader member) (defun load-snapshot (reader member capnp-name)
(let ((capnp-member (remove #\_ (string-capitalize member)))) #>cpp
#>cpp std::vector<uint64_t> transaction_ids;
std::vector<uint64_t> transaction_ids; utils::LoadVector(&transaction_ids, ${reader}.get${capnp-name}());
utils::LoadVector(&transaction_ids, ${reader}.get${capnp-member}()); ${member} = tx::Snapshot(std::move(transaction_ids));
${member} = tx::Snapshot(std::move(transaction_ids)); cpp<#)
cpp<#))

View File

@ -28,7 +28,7 @@ std::vector<std::vector<TypedValue>> CollectProduce(
// collect the symbols from the return clause // collect the symbols from the return clause
std::vector<Symbol> symbols; std::vector<Symbol> symbols;
for (auto named_expression : produce->named_expressions()) for (auto named_expression : produce->named_expressions_)
symbols.emplace_back(symbol_table[*named_expression]); symbols.emplace_back(symbol_table[*named_expression]);
Context context(db_accessor); Context context(db_accessor);

View File

@ -204,14 +204,14 @@ using ExpectDistributedCreateExpand = OpChecker<DistributedCreateExpand>;
class ExpectExpandVariable : public OpChecker<ExpandVariable> { class ExpectExpandVariable : public OpChecker<ExpandVariable> {
public: public:
void ExpectOp(ExpandVariable &op, const SymbolTable &) override { void ExpectOp(ExpandVariable &op, const SymbolTable &) override {
EXPECT_EQ(op.type(), query::EdgeAtom::Type::DEPTH_FIRST); EXPECT_EQ(op.type_, query::EdgeAtom::Type::DEPTH_FIRST);
} }
}; };
class ExpectExpandBfs : public OpChecker<ExpandVariable> { class ExpectExpandBfs : public OpChecker<ExpandVariable> {
public: public:
void ExpectOp(ExpandVariable &op, const SymbolTable &) override { void ExpectOp(ExpandVariable &op, const SymbolTable &) override {
EXPECT_EQ(op.type(), query::EdgeAtom::Type::BREADTH_FIRST); EXPECT_EQ(op.type_, query::EdgeAtom::Type::BREADTH_FIRST);
} }
}; };
@ -221,8 +221,8 @@ class ExpectAccumulate : public OpChecker<Accumulate> {
: symbols_(symbols) {} : symbols_(symbols) {}
void ExpectOp(Accumulate &op, const SymbolTable &) override { void ExpectOp(Accumulate &op, const SymbolTable &) override {
std::unordered_set<Symbol> got_symbols(op.symbols().begin(), std::unordered_set<Symbol> got_symbols(op.symbols_.begin(),
op.symbols().end()); op.symbols_.end());
EXPECT_EQ(symbols_, got_symbols); EXPECT_EQ(symbols_, got_symbols);
} }
@ -244,7 +244,7 @@ class ExpectAggregate : public OpChecker<Aggregate> {
void ExpectOp(Aggregate &op, const SymbolTable &symbol_table) override { void ExpectOp(Aggregate &op, const SymbolTable &symbol_table) override {
auto aggr_it = aggregations_.begin(); auto aggr_it = aggregations_.begin();
for (const auto &aggr_elem : op.aggregations()) { for (const auto &aggr_elem : op.aggregations_) {
ASSERT_NE(aggr_it, aggregations_.end()); ASSERT_NE(aggr_it, aggregations_.end());
auto aggr = *aggr_it++; auto aggr = *aggr_it++;
// TODO: Proper expression equality // TODO: Proper expression equality
@ -262,7 +262,7 @@ class ExpectAggregate : public OpChecker<Aggregate> {
EXPECT_EQ(aggr_it, aggregations_.end()); EXPECT_EQ(aggr_it, aggregations_.end());
// TODO: Proper group by expression equality // TODO: Proper group by expression equality
std::unordered_set<size_t> got_group_by; std::unordered_set<size_t> got_group_by;
for (auto *expr : op.group_by()) for (auto *expr : op.group_by_)
got_group_by.insert(typeid(*expr).hash_code()); got_group_by.insert(typeid(*expr).hash_code());
std::unordered_set<size_t> expected_group_by; std::unordered_set<size_t> expected_group_by;
for (auto *expr : group_by_) for (auto *expr : group_by_)
@ -290,9 +290,9 @@ class ExpectMerge : public OpChecker<Merge> {
void ExpectOp(Merge &merge, const SymbolTable &symbol_table) override { void ExpectOp(Merge &merge, const SymbolTable &symbol_table) override {
PlanChecker check_match(on_match_, symbol_table); PlanChecker check_match(on_match_, symbol_table);
merge.merge_match()->Accept(check_match); merge.merge_match_->Accept(check_match);
PlanChecker check_create(on_create_, symbol_table); PlanChecker check_create(on_create_, symbol_table);
merge.merge_create()->Accept(check_create); merge.merge_create_->Accept(check_create);
} }
private: private:
@ -311,11 +311,11 @@ class ExpectOptional : public OpChecker<Optional> {
void ExpectOp(Optional &optional, const SymbolTable &symbol_table) override { void ExpectOp(Optional &optional, const SymbolTable &symbol_table) override {
if (!optional_symbols_.empty()) { if (!optional_symbols_.empty()) {
EXPECT_THAT(optional.optional_symbols(), EXPECT_THAT(optional.optional_symbols_,
testing::UnorderedElementsAreArray(optional_symbols_)); testing::UnorderedElementsAreArray(optional_symbols_));
} }
PlanChecker check_optional(optional_, symbol_table); PlanChecker check_optional(optional_, symbol_table);
optional.optional()->Accept(check_optional); optional.optional_->Accept(check_optional);
} }
private: private:
@ -334,10 +334,10 @@ class ExpectScanAllByLabelPropertyValue
void ExpectOp(ScanAllByLabelPropertyValue &scan_all, void ExpectOp(ScanAllByLabelPropertyValue &scan_all,
const SymbolTable &) override { const SymbolTable &) override {
EXPECT_EQ(scan_all.label(), label_); EXPECT_EQ(scan_all.label_, label_);
EXPECT_EQ(scan_all.property(), property_); EXPECT_EQ(scan_all.property_, property_);
// TODO: Proper expression equality // TODO: Proper expression equality
EXPECT_EQ(typeid(scan_all.expression()).hash_code(), EXPECT_EQ(typeid(scan_all.expression_).hash_code(),
typeid(expression_).hash_code()); typeid(expression_).hash_code());
} }
@ -361,21 +361,21 @@ class ExpectScanAllByLabelPropertyRange
void ExpectOp(ScanAllByLabelPropertyRange &scan_all, void ExpectOp(ScanAllByLabelPropertyRange &scan_all,
const SymbolTable &) override { const SymbolTable &) override {
EXPECT_EQ(scan_all.label(), label_); EXPECT_EQ(scan_all.label_, label_);
EXPECT_EQ(scan_all.property(), property_); EXPECT_EQ(scan_all.property_, property_);
if (lower_bound_) { if (lower_bound_) {
ASSERT_TRUE(scan_all.lower_bound()); ASSERT_TRUE(scan_all.lower_bound_);
// TODO: Proper expression equality // TODO: Proper expression equality
EXPECT_EQ(typeid(scan_all.lower_bound()->value()).hash_code(), EXPECT_EQ(typeid(scan_all.lower_bound_->value()).hash_code(),
typeid(lower_bound_->value()).hash_code()); typeid(lower_bound_->value()).hash_code());
EXPECT_EQ(scan_all.lower_bound()->type(), lower_bound_->type()); EXPECT_EQ(scan_all.lower_bound_->type(), lower_bound_->type());
} }
if (upper_bound_) { if (upper_bound_) {
ASSERT_TRUE(scan_all.upper_bound()); ASSERT_TRUE(scan_all.upper_bound_);
// TODO: Proper expression equality // TODO: Proper expression equality
EXPECT_EQ(typeid(scan_all.upper_bound()->value()).hash_code(), EXPECT_EQ(typeid(scan_all.upper_bound_->value()).hash_code(),
typeid(upper_bound_->value()).hash_code()); typeid(upper_bound_->value()).hash_code());
EXPECT_EQ(scan_all.upper_bound()->type(), upper_bound_->type()); EXPECT_EQ(scan_all.upper_bound_->type(), upper_bound_->type());
} }
} }
@ -400,14 +400,14 @@ class ExpectAuthHandler : public OpChecker<AuthHandler> {
privileges_(privileges) {} privileges_(privileges) {}
void ExpectOp(AuthHandler &auth_handler, const SymbolTable &) override { void ExpectOp(AuthHandler &auth_handler, const SymbolTable &) override {
EXPECT_EQ(auth_handler.action(), action_); EXPECT_EQ(auth_handler.action_, action_);
EXPECT_EQ(auth_handler.user(), user_); EXPECT_EQ(auth_handler.user_, user_);
EXPECT_EQ(auth_handler.role(), role_); EXPECT_EQ(auth_handler.role_, role_);
EXPECT_EQ(auth_handler.user_or_role(), user_or_role_); EXPECT_EQ(auth_handler.user_or_role_, user_or_role_);
// TODO(mtomic): We need to somehow test the password expression. // TODO(mtomic): We need to somehow test the password expression.
EXPECT_TRUE(password_); EXPECT_TRUE(password_);
EXPECT_TRUE(auth_handler.password()); EXPECT_TRUE(auth_handler.password_);
EXPECT_EQ(auth_handler.privileges(), privileges_); EXPECT_EQ(auth_handler.privileges_, privileges_);
} }
private: private:
@ -425,8 +425,8 @@ class ExpectCreateIndex : public OpChecker<CreateIndex> {
: label_(label), property_(property) {} : label_(label), property_(property) {}
void ExpectOp(CreateIndex &create_index, const SymbolTable &) override { void ExpectOp(CreateIndex &create_index, const SymbolTable &) override {
EXPECT_EQ(create_index.label(), label_); EXPECT_EQ(create_index.label_, label_);
EXPECT_EQ(create_index.property(), property_); EXPECT_EQ(create_index.property_, property_);
} }
private: private:
@ -440,7 +440,7 @@ class ExpectPullRemote : public OpChecker<PullRemote> {
ExpectPullRemote(const std::vector<Symbol> &symbols) : symbols_(symbols) {} ExpectPullRemote(const std::vector<Symbol> &symbols) : symbols_(symbols) {}
void ExpectOp(PullRemote &op, const SymbolTable &) override { void ExpectOp(PullRemote &op, const SymbolTable &) override {
EXPECT_THAT(op.symbols(), testing::UnorderedElementsAreArray(symbols_)); EXPECT_THAT(op.symbols_, testing::UnorderedElementsAreArray(symbols_));
} }
private: private:
@ -459,12 +459,12 @@ class ExpectSynchronize : public OpChecker<Synchronize> {
void ExpectOp(Synchronize &op, const SymbolTable &symbol_table) override { void ExpectOp(Synchronize &op, const SymbolTable &symbol_table) override {
if (has_pull_) { if (has_pull_) {
ASSERT_TRUE(op.pull_remote()); ASSERT_TRUE(op.pull_remote_);
expect_pull_.ExpectOp(*op.pull_remote(), symbol_table); expect_pull_.ExpectOp(*op.pull_remote_, symbol_table);
} else { } else {
EXPECT_FALSE(op.pull_remote()); EXPECT_FALSE(op.pull_remote_);
} }
EXPECT_EQ(op.advance_command(), advance_command_); EXPECT_EQ(op.advance_command_, advance_command_);
} }
private: private:
@ -480,12 +480,12 @@ class ExpectCartesian : public OpChecker<Cartesian> {
: left_(left), right_(right) {} : left_(left), right_(right) {}
void ExpectOp(Cartesian &op, const SymbolTable &symbol_table) override { void ExpectOp(Cartesian &op, const SymbolTable &symbol_table) override {
ASSERT_TRUE(op.left_op()); ASSERT_TRUE(op.left_op_);
PlanChecker left_checker(left_, symbol_table); PlanChecker left_checker(left_, symbol_table);
op.left_op()->Accept(left_checker); op.left_op_->Accept(left_checker);
ASSERT_TRUE(op.right_op()); ASSERT_TRUE(op.right_op_);
PlanChecker right_checker(right_, symbol_table); PlanChecker right_checker(right_, symbol_table);
op.right_op()->Accept(right_checker); op.right_op_->Accept(right_checker);
} }
private: private:
@ -499,7 +499,7 @@ class ExpectDistributedCreateNode : public OpChecker<DistributedCreateNode> {
: on_random_worker_(on_random_worker) {} : on_random_worker_(on_random_worker) {}
void ExpectOp(DistributedCreateNode &op, const SymbolTable &) override { void ExpectOp(DistributedCreateNode &op, const SymbolTable &) override {
EXPECT_EQ(op.on_random_worker(), on_random_worker_); EXPECT_EQ(op.on_random_worker_, on_random_worker_);
} }
private: private:
@ -512,7 +512,7 @@ class ExpectPullRemoteOrderBy : public OpChecker<PullRemoteOrderBy> {
: symbols_(symbols) {} : symbols_(symbols) {}
void ExpectOp(PullRemoteOrderBy &op, const SymbolTable &) override { void ExpectOp(PullRemoteOrderBy &op, const SymbolTable &) override {
EXPECT_THAT(op.symbols(), testing::UnorderedElementsAreArray(symbols_)); EXPECT_THAT(op.symbols_, testing::UnorderedElementsAreArray(symbols_));
} }
private: private:
@ -534,27 +534,27 @@ class ExpectCreateStream : public OpChecker<CreateStream> {
batch_size_(batch_size) {} batch_size_(batch_size) {}
void ExpectOp(CreateStream &create_stream, const SymbolTable &) override { void ExpectOp(CreateStream &create_stream, const SymbolTable &) override {
EXPECT_EQ(create_stream.stream_name(), stream_name_); EXPECT_EQ(create_stream.stream_name_, stream_name_);
// TODO: Proper expression equality // TODO: Proper expression equality
EXPECT_EQ(typeid(create_stream.stream_uri()).hash_code(), EXPECT_EQ(typeid(create_stream.stream_uri_).hash_code(),
typeid(stream_uri_).hash_code()); typeid(stream_uri_).hash_code());
EXPECT_EQ(typeid(create_stream.stream_topic()).hash_code(), EXPECT_EQ(typeid(create_stream.stream_topic_).hash_code(),
typeid(stream_topic_).hash_code()); typeid(stream_topic_).hash_code());
EXPECT_EQ(typeid(create_stream.transform_uri()).hash_code(), EXPECT_EQ(typeid(create_stream.transform_uri_).hash_code(),
typeid(transform_uri_).hash_code()); typeid(transform_uri_).hash_code());
if (batch_interval_in_ms_ && create_stream.batch_interval_in_ms()) { if (batch_interval_in_ms_ && create_stream.batch_interval_in_ms_) {
EXPECT_EQ(typeid(create_stream.batch_interval_in_ms()).hash_code(), EXPECT_EQ(typeid(create_stream.batch_interval_in_ms_).hash_code(),
typeid(batch_interval_in_ms_).hash_code()); typeid(batch_interval_in_ms_).hash_code());
} else { } else {
EXPECT_TRUE(batch_interval_in_ms_ == nullptr && EXPECT_TRUE(batch_interval_in_ms_ == nullptr &&
create_stream.batch_interval_in_ms() == nullptr); create_stream.batch_interval_in_ms_ == nullptr);
} }
if (batch_size_ && create_stream.batch_size()) { if (batch_size_ && create_stream.batch_size_) {
EXPECT_EQ(typeid(create_stream.batch_size()).hash_code(), EXPECT_EQ(typeid(create_stream.batch_size_).hash_code(),
typeid(batch_size_).hash_code()); typeid(batch_size_).hash_code());
} else { } else {
EXPECT_TRUE(batch_size_ == nullptr && EXPECT_TRUE(batch_size_ == nullptr &&
create_stream.batch_size() == nullptr); create_stream.batch_size_ == nullptr);
} }
} }
@ -573,7 +573,7 @@ class ExpectDropStream : public OpChecker<DropStream> {
: stream_name_(stream_name) {} : stream_name_(stream_name) {}
void ExpectOp(DropStream &drop_stream, const SymbolTable &) override { void ExpectOp(DropStream &drop_stream, const SymbolTable &) override {
EXPECT_EQ(drop_stream.stream_name(), stream_name_); EXPECT_EQ(drop_stream.stream_name_, stream_name_);
} }
private: private:
@ -590,15 +590,15 @@ class ExpectStartStopStream : public OpChecker<StartStopStream> {
void ExpectOp(StartStopStream &start_stop_stream, void ExpectOp(StartStopStream &start_stop_stream,
const SymbolTable &) override { const SymbolTable &) override {
EXPECT_EQ(start_stop_stream.stream_name(), stream_name_); EXPECT_EQ(start_stop_stream.stream_name_, stream_name_);
EXPECT_EQ(start_stop_stream.is_start(), is_start_); EXPECT_EQ(start_stop_stream.is_start_, is_start_);
// TODO: Proper expression equality // TODO: Proper expression equality
if (limit_batches_ && start_stop_stream.limit_batches()) { if (limit_batches_ && start_stop_stream.limit_batches_) {
EXPECT_EQ(typeid(start_stop_stream.limit_batches()).hash_code(), EXPECT_EQ(typeid(start_stop_stream.limit_batches_).hash_code(),
typeid(limit_batches_).hash_code()); typeid(limit_batches_).hash_code());
} else { } else {
EXPECT_TRUE(limit_batches_ == nullptr && EXPECT_TRUE(limit_batches_ == nullptr &&
start_stop_stream.limit_batches() == nullptr); start_stop_stream.limit_batches_ == nullptr);
} }
} }
@ -614,7 +614,7 @@ class ExpectStartStopAllStreams : public OpChecker<StartStopAllStreams> {
void ExpectOp(StartStopAllStreams &start_stop_all_streams, void ExpectOp(StartStopAllStreams &start_stop_all_streams,
const SymbolTable &) override { const SymbolTable &) override {
EXPECT_EQ(start_stop_all_streams.is_start(), is_start_); EXPECT_EQ(start_stop_all_streams.is_start_, is_start_);
} }
private: private:
@ -627,14 +627,14 @@ class ExpectTestStream : public OpChecker<TestStream> {
: stream_name_(stream_name), limit_batches_(limit_batches) {} : stream_name_(stream_name), limit_batches_(limit_batches) {}
void ExpectOp(TestStream &test_stream, const SymbolTable &) override { void ExpectOp(TestStream &test_stream, const SymbolTable &) override {
EXPECT_EQ(test_stream.stream_name(), stream_name_); EXPECT_EQ(test_stream.stream_name_, stream_name_);
// TODO: Proper expression equality // TODO: Proper expression equality
if (limit_batches_ && test_stream.limit_batches()) { if (limit_batches_ && test_stream.limit_batches_) {
EXPECT_EQ(typeid(test_stream.limit_batches()).hash_code(), EXPECT_EQ(typeid(test_stream.limit_batches_).hash_code(),
typeid(limit_batches_).hash_code()); typeid(limit_batches_).hash_code());
} else { } else {
EXPECT_TRUE(limit_batches_ == nullptr && EXPECT_TRUE(limit_batches_ == nullptr &&
test_stream.limit_batches() == nullptr); test_stream.limit_batches_ == nullptr);
} }
} }
@ -672,9 +672,9 @@ void SavePlan(const LogicalOperator &plan, ::capnp::MessageBuilder *message) {
} }
auto LoadPlan(const ::query::plan::capnp::LogicalOperator::Reader &reader) { auto LoadPlan(const ::query::plan::capnp::LogicalOperator::Reader &reader) {
auto plan = LogicalOperator::Construct(reader); std::unique_ptr<LogicalOperator> plan;
LogicalOperator::LoadHelper helper; LogicalOperator::LoadHelper helper;
plan->Load(reader, &helper); Load(&plan, reader, &helper);
return std::make_pair(std::move(plan), std::move(helper.ast_storage)); return std::make_pair(std::move(plan), std::move(helper.ast_storage));
} }
@ -1823,7 +1823,7 @@ TYPED_TEST(TestPlanner, MatchReturnAsteriskSum) {
auto planner = MakePlanner<TypeParam>(dba, storage, symbol_table); auto planner = MakePlanner<TypeParam>(dba, storage, symbol_table);
auto *produce = dynamic_cast<Produce *>(&planner.plan()); auto *produce = dynamic_cast<Produce *>(&planner.plan());
ASSERT_TRUE(produce); ASSERT_TRUE(produce);
const auto &named_expressions = produce->named_expressions(); const auto &named_expressions = produce->named_expressions_;
ASSERT_EQ(named_expressions.size(), 2); ASSERT_EQ(named_expressions.size(), 2);
auto *expanded_ident = auto *expanded_ident =
dynamic_cast<query::Identifier *>(named_expressions[0]->expression_); dynamic_cast<query::Identifier *>(named_expressions[0]->expression_);
@ -2585,9 +2585,9 @@ TYPED_TEST(TestPlanner, DistributedAvg) {
auto worker_plan = distributed_plan.worker_plans.back().second; auto worker_plan = distributed_plan.worker_plans.back().second;
auto worker_aggr_op = std::dynamic_pointer_cast<Aggregate>(worker_plan); auto worker_aggr_op = std::dynamic_pointer_cast<Aggregate>(worker_plan);
ASSERT_TRUE(worker_aggr_op); ASSERT_TRUE(worker_aggr_op);
ASSERT_EQ(worker_aggr_op->aggregations().size(), 2U); ASSERT_EQ(worker_aggr_op->aggregations_.size(), 2U);
symbol_table[*worker_sum] = worker_aggr_op->aggregations()[0].output_sym; symbol_table[*worker_sum] = worker_aggr_op->aggregations_[0].output_sym;
symbol_table[*worker_count] = worker_aggr_op->aggregations()[1].output_sym; symbol_table[*worker_count] = worker_aggr_op->aggregations_[1].output_sym;
} }
auto worker_aggr = ExpectAggregate({worker_sum, worker_count}, {}); auto worker_aggr = ExpectAggregate({worker_sum, worker_count}, {});
auto merge_sum = SUM(IDENT("worker_sum")); auto merge_sum = SUM(IDENT("worker_sum"));
@ -3134,11 +3134,11 @@ TEST(CapnpSerial, Union) {
ASSERT_TRUE(loaded_plan); ASSERT_TRUE(loaded_plan);
auto *loaded_op = dynamic_cast<Union *>(loaded_plan.get()); auto *loaded_op = dynamic_cast<Union *>(loaded_plan.get());
ASSERT_TRUE(loaded_op); ASSERT_TRUE(loaded_op);
EXPECT_FALSE(loaded_op->left_op()); EXPECT_FALSE(loaded_op->left_op_);
EXPECT_FALSE(loaded_op->right_op()); EXPECT_FALSE(loaded_op->right_op_);
EXPECT_EQ(loaded_op->left_symbols(), left_symbols); EXPECT_EQ(loaded_op->left_symbols_, left_symbols);
EXPECT_EQ(loaded_op->right_symbols(), right_symbols); EXPECT_EQ(loaded_op->right_symbols_, right_symbols);
EXPECT_EQ(loaded_op->union_symbols(), union_symbols); EXPECT_EQ(loaded_op->union_symbols_, union_symbols);
} }
TEST(CapnpSerial, Cartesian) { TEST(CapnpSerial, Cartesian) {
@ -3157,10 +3157,10 @@ TEST(CapnpSerial, Cartesian) {
ASSERT_TRUE(loaded_plan); ASSERT_TRUE(loaded_plan);
auto *loaded_op = dynamic_cast<Cartesian *>(loaded_plan.get()); auto *loaded_op = dynamic_cast<Cartesian *>(loaded_plan.get());
ASSERT_TRUE(loaded_op); ASSERT_TRUE(loaded_op);
EXPECT_FALSE(loaded_op->left_op()); EXPECT_FALSE(loaded_op->left_op_);
EXPECT_FALSE(loaded_op->right_op()); EXPECT_FALSE(loaded_op->right_op_);
EXPECT_EQ(loaded_op->left_symbols(), left_symbols); EXPECT_EQ(loaded_op->left_symbols_, left_symbols);
EXPECT_EQ(loaded_op->right_symbols(), right_symbols); EXPECT_EQ(loaded_op->right_symbols_, right_symbols);
} }
TEST(CapnpSerial, Synchronize) { TEST(CapnpSerial, Synchronize) {
@ -3175,8 +3175,8 @@ TEST(CapnpSerial, Synchronize) {
auto *loaded_op = dynamic_cast<Synchronize *>(loaded_plan.get()); auto *loaded_op = dynamic_cast<Synchronize *>(loaded_plan.get());
ASSERT_TRUE(loaded_op); ASSERT_TRUE(loaded_op);
EXPECT_FALSE(loaded_op->input()); EXPECT_FALSE(loaded_op->input());
EXPECT_FALSE(loaded_op->pull_remote()); EXPECT_FALSE(loaded_op->pull_remote_);
EXPECT_TRUE(loaded_op->advance_command()); EXPECT_TRUE(loaded_op->advance_command_);
} }
TEST(CapnpSerial, PullRemote) { TEST(CapnpSerial, PullRemote) {
@ -3192,8 +3192,8 @@ TEST(CapnpSerial, PullRemote) {
auto *loaded_op = dynamic_cast<PullRemote *>(loaded_plan.get()); auto *loaded_op = dynamic_cast<PullRemote *>(loaded_plan.get());
ASSERT_TRUE(loaded_op); ASSERT_TRUE(loaded_op);
EXPECT_FALSE(loaded_op->input()); EXPECT_FALSE(loaded_op->input());
EXPECT_EQ(loaded_op->plan_id(), 42); EXPECT_EQ(loaded_op->plan_id_, 42);
EXPECT_EQ(loaded_op->symbols(), symbols); EXPECT_EQ(loaded_op->symbols_, symbols);
} }
TEST(CapnpSerial, PullRemoteOrderBy) { TEST(CapnpSerial, PullRemoteOrderBy) {
@ -3215,12 +3215,12 @@ TEST(CapnpSerial, PullRemoteOrderBy) {
auto *loaded_op = dynamic_cast<PullRemoteOrderBy *>(loaded_plan.get()); auto *loaded_op = dynamic_cast<PullRemoteOrderBy *>(loaded_plan.get());
ASSERT_TRUE(loaded_op); ASSERT_TRUE(loaded_op);
ASSERT_TRUE(std::dynamic_pointer_cast<Once>(loaded_op->input())); ASSERT_TRUE(std::dynamic_pointer_cast<Once>(loaded_op->input()));
EXPECT_EQ(loaded_op->plan_id(), 42); EXPECT_EQ(loaded_op->plan_id_, 42);
EXPECT_EQ(loaded_op->symbols(), symbols); EXPECT_EQ(loaded_op->symbols_, symbols);
ASSERT_EQ(loaded_op->order_by().size(), 1); ASSERT_EQ(loaded_op->order_by_.size(), 1);
EXPECT_TRUE(dynamic_cast<query::Identifier *>(loaded_op->order_by()[0])); EXPECT_TRUE(dynamic_cast<query::Identifier *>(loaded_op->order_by_[0]));
ASSERT_EQ(loaded_op->compare().ordering().size(), 1); ASSERT_EQ(loaded_op->compare_.ordering().size(), 1);
EXPECT_EQ(loaded_op->compare().ordering()[0], query::Ordering::ASC); EXPECT_EQ(loaded_op->compare_.ordering()[0], query::Ordering::ASC);
} }
} // namespace } // namespace

View File

@ -21,12 +21,6 @@ struct SumReq {
SumReq(int x, int y) : x(x), y(y) {} SumReq(int x, int y) : x(x), y(y) {}
int x; int x;
int y; int y;
void Load(const ::capnp::AnyPointer::Reader &reader) {
auto list_reader = reader.getAs<::capnp::List<int>>();
x = list_reader[0];
y = list_reader[1];
}
}; };
void Save(const SumReq &sum, ::capnp::AnyPointer::Builder *builder) { void Save(const SumReq &sum, ::capnp::AnyPointer::Builder *builder) {
@ -35,6 +29,12 @@ void Save(const SumReq &sum, ::capnp::AnyPointer::Builder *builder) {
list_builder.set(1, sum.y); list_builder.set(1, sum.y);
} }
void Load(SumReq *sum, const ::capnp::AnyPointer::Reader &reader) {
auto list_reader = reader.getAs<::capnp::List<int>>();
sum->x = list_reader[0];
sum->y = list_reader[1];
}
const MessageType SumReq::TypeInfo{0, "SumReq"}; const MessageType SumReq::TypeInfo{0, "SumReq"};
struct SumRes { struct SumRes {
@ -45,11 +45,6 @@ struct SumRes {
SumRes(int sum) : sum(sum) {} SumRes(int sum) : sum(sum) {}
int sum; int sum;
void Load(const ::capnp::AnyPointer::Reader &reader) {
auto list_reader = reader.getAs<::capnp::List<int>>();
sum = list_reader[0];
}
}; };
void Save(const SumRes &res, ::capnp::AnyPointer::Builder *builder) { void Save(const SumRes &res, ::capnp::AnyPointer::Builder *builder) {
@ -57,6 +52,11 @@ void Save(const SumRes &res, ::capnp::AnyPointer::Builder *builder) {
list_builder.set(0, res.sum); list_builder.set(0, res.sum);
} }
void Load(SumRes *res, const ::capnp::AnyPointer::Reader &reader) {
auto list_reader = reader.getAs<::capnp::List<int>>();
res->sum = list_reader[0];
}
const MessageType SumRes::TypeInfo{1, "SumRes"}; const MessageType SumRes::TypeInfo{1, "SumRes"};
using Sum = RequestResponse<SumReq, SumRes>; using Sum = RequestResponse<SumReq, SumRes>;
@ -69,11 +69,6 @@ struct EchoMessage {
EchoMessage(const std::string &data) : data(data) {} EchoMessage(const std::string &data) : data(data) {}
std::string data; std::string data;
void Load(const ::capnp::AnyPointer::Reader &reader) {
auto list_reader = reader.getAs<::capnp::List<::capnp::Text>>();
data = list_reader[0];
}
}; };
void Save(const EchoMessage &echo, ::capnp::AnyPointer::Builder *builder) { void Save(const EchoMessage &echo, ::capnp::AnyPointer::Builder *builder) {
@ -81,6 +76,11 @@ void Save(const EchoMessage &echo, ::capnp::AnyPointer::Builder *builder) {
list_builder.set(0, echo.data); list_builder.set(0, echo.data);
} }
void Load(EchoMessage *echo, const ::capnp::AnyPointer::Reader &reader) {
auto list_reader = reader.getAs<::capnp::List<::capnp::Text>>();
echo->data = list_reader[0];
}
const MessageType EchoMessage::TypeInfo{2, "EchoMessage"}; const MessageType EchoMessage::TypeInfo{2, "EchoMessage"};
using Echo = RequestResponse<EchoMessage, EchoMessage>; using Echo = RequestResponse<EchoMessage, EchoMessage>;
@ -89,7 +89,7 @@ TEST(Rpc, Call) {
Server server({"127.0.0.1", 0}); Server server({"127.0.0.1", 0});
server.Register<Sum>([](const auto &req_reader, auto *res_builder) { server.Register<Sum>([](const auto &req_reader, auto *res_builder) {
SumReq req; SumReq req;
req.Load(req_reader); Load(&req, req_reader);
SumRes res(req.x + req.y); SumRes res(req.x + req.y);
Save(res, res_builder); Save(res, res_builder);
}); });
@ -107,7 +107,7 @@ TEST(Rpc, Abort) {
Server server({"127.0.0.1", 0}); Server server({"127.0.0.1", 0});
server.Register<Sum>([](const auto &req_reader, auto *res_builder) { server.Register<Sum>([](const auto &req_reader, auto *res_builder) {
SumReq req; SumReq req;
req.Load(req_reader); Load(&req, req_reader);
std::this_thread::sleep_for(500ms); std::this_thread::sleep_for(500ms);
SumRes res(req.x + req.y); SumRes res(req.x + req.y);
Save(res, res_builder); Save(res, res_builder);
@ -137,7 +137,7 @@ TEST(Rpc, ClientPool) {
Server server({"127.0.0.1", 0}); Server server({"127.0.0.1", 0});
server.Register<Sum>([](const auto &req_reader, auto *res_builder) { server.Register<Sum>([](const auto &req_reader, auto *res_builder) {
SumReq req; SumReq req;
req.Load(req_reader); Load(&req, req_reader);
std::this_thread::sleep_for(100ms); std::this_thread::sleep_for(100ms);
SumRes res(req.x + req.y); SumRes res(req.x + req.y);
Save(res, res_builder); Save(res, res_builder);
@ -191,7 +191,7 @@ TEST(Rpc, LargeMessage) {
Server server({"127.0.0.1", 0}); Server server({"127.0.0.1", 0});
server.Register<Echo>([](const auto &req_reader, auto *res_builder) { server.Register<Echo>([](const auto &req_reader, auto *res_builder) {
EchoMessage res; EchoMessage res;
res.Load(req_reader); Load(&res, req_reader);
Save(res, res_builder); Save(res, res_builder);
}); });
std::this_thread::sleep_for(100ms); std::this_thread::sleep_for(100ms);

View File

@ -1,11 +1,9 @@
#!/bin/bash -e #!/bin/bash -e
if [[ $# -ne 1 && $# -ne 2 ]]; then if [[ $# -ne 1 && $# -ne 2 ]]; then
echo "Usage: $0 LCP_FILE [--capnp-declaration | CAPNP_ID]" echo "Usage: $0 LCP_FILE [CAPNP_ID]"
echo "Convert a LCP_FILE to C++ header file and output to stdout." echo "Convert a LCP_FILE to C++ header file and output to stdout."
echo "If CAPNP_ID is provided, then the Cap'n Proto schema is generated." echo "If CAPNP_ID is provided, then the Cap'n Proto schema is generated."
echo "Passing --capnp-declaration flag will declare serialization functions in "
echo "C++ header without actually generating the Cap'n Proto schema or code."
exit 1 exit 1
fi fi
@ -24,11 +22,7 @@ fi
capnp="" capnp=""
if [[ $# -eq 2 ]]; then if [[ $# -eq 2 ]]; then
if [[ "$2" == "--capnp-declaration" ]]; then capnp=":capnp-id \"$2\""
capnp=":capnp-declaration t"
else
capnp=":capnp-id \"$2\""
fi
fi fi
echo \ echo \

View File

@ -44,7 +44,7 @@ int main(int argc, char *argv[]) {
server.Register<stats::StatsRpc>( server.Register<stats::StatsRpc>(
[&](const auto &req_reader, auto *res_builder) { [&](const auto &req_reader, auto *res_builder) {
stats::StatsReq req; stats::StatsReq req;
req.Load(req_reader); Load(&req, req_reader);
LOG(INFO) << "StatsRpc::Received"; LOG(INFO) << "StatsRpc::Received";
std::string data = GraphiteFormat(req); std::string data = GraphiteFormat(req);
graphite_socket.Write(data); graphite_socket.Write(data);
@ -56,7 +56,7 @@ int main(int argc, char *argv[]) {
[&](const auto &req_reader, auto *res_builder) { [&](const auto &req_reader, auto *res_builder) {
// TODO(mtomic): batching? // TODO(mtomic): batching?
stats::BatchStatsReq req; stats::BatchStatsReq req;
req.Load(req_reader); Load(&req, req_reader);
LOG(INFO) << fmt::format("BatchStatsRpc::Received: {}", LOG(INFO) << fmt::format("BatchStatsRpc::Received: {}",
req.requests.size()); req.requests.size());
for (size_t i = 0; i < req.requests.size(); ++i) { for (size_t i = 0; i < req.requests.size(); ++i) {