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`
# invocation, and specify it here. This preserves correct id information across
# multiple schema generations. If this wasn't the case, wrong typeId
# information will break RPC between different compilations of memgraph.
# Instead of CAPNP_SCHEMA, you may pass the CAPNP_DECLARATION option. This will
# generate serialization declarations but not the implementation.
# information will break serialization between different compilations of memgraph.
macro(define_add_lcp name main_src_files generated_lcp_files)
function(${name} lcp_file)
set(options CAPNP_DECLARATION)
set(one_value_kwargs CAPNP_SCHEMA)
set(multi_value_kwargs DEPENDS)
# NOTE: ${${}ARGN} syntax escapes evaluating macro's ARGN variable; see:
# https://stackoverflow.com/questions/50365544/how-to-access-enclosing-functions-arguments-from-within-a-macro
cmake_parse_arguments(KW "${options}" "${one_value_kwargs}" "${multi_value_kwargs}" ${${}ARGN})
cmake_parse_arguments(KW "" "${one_value_kwargs}" "${multi_value_kwargs}" ${${}ARGN})
string(REGEX REPLACE "\.lcp$" ".hpp" h_file
"${CMAKE_CURRENT_SOURCE_DIR}/${lcp_file}")
if (KW_CAPNP_SCHEMA AND NOT KW_CAPNP_DECLARATION)
if (KW_CAPNP_SCHEMA)
string(REGEX REPLACE "\.lcp$" ".capnp" capnp_file
"${CMAKE_CURRENT_SOURCE_DIR}/${lcp_file}")
set(capnp_id ${KW_CAPNP_SCHEMA})
@ -150,9 +147,6 @@ macro(define_add_lcp name main_src_files generated_lcp_files)
# Update *global* main_src_files
set(${main_src_files} ${${main_src_files}} ${cpp_file} PARENT_SCOPE)
endif()
if (KW_CAPNP_DECLARATION)
set(capnp_id "--capnp-declaration")
endif()
add_custom_command(OUTPUT ${h_file} ${cpp_file} ${capnp_file}
COMMAND ${lcp_exe} ${lcp_file} ${capnp_id}
VERBATIM

View File

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

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_capnp(distributed/dynamic_worker_rpc_messages.capnp)
# distributed_ops.lcp is leading the capnp code generation, so we only want
# function declarations in generated operator.hpp
add_lcp(query/plan/operator.lcp CAPNP_DECLARATION)
# distributed_ops.lcp is leading the capnp code generation, so we don't need
# to generate any capnp for operator.lcp
add_lcp(query/plan/operator.lcp)
add_lcp(query/plan/distributed_ops.lcp CAPNP_SCHEMA @0xe5cae8d045d30c42
DEPENDS query/plan/operator.lcp)
add_capnp(query/plan/distributed_ops.capnp)

View File

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

View File

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

View File

@ -21,7 +21,7 @@ class StorageGcMaster : public StorageGc {
rpc_server_.Register<distributed::RanLocalGcRpc>(
[this](const auto &req_reader, auto *res_builder) {
distributed::RanLocalGcReq req;
req.Load(req_reader);
Load(&req, req_reader);
std::unique_lock<std::mutex> lock(worker_safe_transaction_mutex_);
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>(
[this, dba](const auto &reader) {
SubcursorPullRes res;
res.Load(reader, dba, this->data_manager_);
Load(&res, reader, dba, this->data_manager_);
return res;
},
subcursor_id);
@ -152,7 +152,7 @@ PathSegment BfsRpcClients::ReconstructPath(
coordination_->GetClientPool(worker_id)->CallWithLoad<ReconstructPathRpc>(
[this, dba](const auto &reader) {
ReconstructPathRes res;
res.Load(reader, dba, this->data_manager_);
Load(&res, reader, dba, this->data_manager_);
return res;
},
subcursor_ids.at(worker_id), vertex);
@ -171,7 +171,7 @@ PathSegment BfsRpcClients::ReconstructPath(
coordination_->GetClientPool(worker_id)->CallWithLoad<ReconstructPathRpc>(
[this, dba](const auto &reader) {
ReconstructPathRes res;
res.Load(reader, dba, this->data_manager_);
Load(&res, reader, dba, this->data_manager_);
return res;
},
subcursor_ids.at(worker_id), edge);

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -34,13 +34,6 @@ struct RecoveryInfo {
wal_recovered == other.wal_recovered;
}
bool operator!=(const RecoveryInfo &other) const { return !(*this == other); }
void Load(const capnp::RecoveryInfo::Reader &reader) {
durability_version = reader.getDurabilityVersion();
snapshot_tx_id = reader.getSnapshotTxId();
auto list_reader = reader.getWalRecovered();
utils::LoadVector(&wal_recovered, list_reader);
}
};
inline void Save(const RecoveryInfo &info,
@ -51,6 +44,14 @@ inline void Save(const RecoveryInfo &info,
utils::SaveVector(info.wal_recovered, &list_builder);
}
inline void Load(RecoveryInfo *info,
const capnp::RecoveryInfo::Reader &reader) {
info->durability_version = reader.getDurabilityVersion();
info->snapshot_tx_id = reader.getSnapshotTxId();
auto list_reader = reader.getWalRecovered();
utils::LoadVector(&info->wal_recovered, list_reader);
}
// A data structure for exchanging info between main recovery function and
// snapshot and WAL recovery functions.
struct RecoveryData {
@ -66,26 +67,6 @@ struct RecoveryData {
snapshooter_tx_snapshot.clear();
indexes.clear();
}
void Load(const capnp::RecoveryData::Reader &reader) {
snapshooter_tx_id = reader.getSnapshooterTxId();
{
auto list_reader = reader.getWalTxToRecover();
utils::LoadVector(&wal_tx_to_recover, list_reader);
}
{
auto list_reader = reader.getSnapshooterTxSnapshot();
utils::LoadVector(&snapshooter_tx_snapshot, list_reader);
}
{
auto list_reader = reader.getIndexes();
utils::LoadVector<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,
@ -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
* hash. */
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());
}
void Endpoint::Load(const capnp::Endpoint::Reader &reader) {
address_ = reader.getAddress();
port_ = reader.getPort();
family_ = reader.getFamily();
void Load(Endpoint *endpoint, const capnp::Endpoint::Reader &reader) {
endpoint->address_ = reader.getAddress();
endpoint->port_ = reader.getPort();
endpoint->family_ = reader.getFamily();
}
bool Endpoint::operator==(const Endpoint &other) const {

View File

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

View File

@ -346,15 +346,31 @@ produces:
(let ((cpp-name (cpp-variable-name (cpp-member-symbol cpp-member))))
(if struct cpp-name (format nil "~A_" cpp-name))))
(defun call-with-cpp-block-output (out fun &key semicolonp name)
"Surround the invocation of FUN by emitting '{' and '}' to OUT. If
SEMICOLONP is set, the closing '}' is suffixed with ';'. NAME is used to
prepend the starting block with a name, for example \"class MyClass\"."
(if name
(format out "~A {~%" name)
(write-line "{" out))
(funcall fun)
(if semicolonp (write-line "};" out) (write-line "}" out)))
(defmacro with-cpp-block-output ((out &rest rest &key semicolonp name) &body body)
"Surround BODY with emitting '{' and '}' to OUT. For additional arguments,
see `CALL-WITH-CPP-BLOCK-OUTPUT' documentation."
(declare (ignorable semicolonp name))
`(call-with-cpp-block-output ,out (lambda () ,@body) ,@rest))
(defun cpp-enum-definition (cpp-enum)
"Get C++ style `CPP-ENUM' definition as a string."
(declare (type cpp-enum cpp-enum))
(with-output-to-string (s)
(when (cpp-type-documentation cpp-enum)
(write-line (cpp-documentation (cpp-type-documentation cpp-enum)) s))
(format s "enum class ~A {~%" (cpp-type-name cpp-enum))
(format s "~{ ~A~^,~%~}~%" (mapcar #'cpp-constant-name (cpp-enum-values cpp-enum)))
(write-line "};" s)))
(with-cpp-block-output (s :name (format nil "enum class ~A" (cpp-type-name cpp-enum))
:semicolonp t)
(format s "~{ ~A~^,~%~}~%" (mapcar #'cpp-constant-name (cpp-enum-values cpp-enum))))))
(defun cpp-member-declaration (cpp-member &key struct)
"Get C++ style `CPP-MEMBER' declaration as a string."
@ -403,32 +419,26 @@ NIL, returns a string."
(when (cpp-class-super-classes cpp-class)
(format s " : ~{public ~A~^, ~}"
(mapcar #'cpp-type-name (cpp-class-super-classes cpp-class))))
(write-line " {" s)
(let ((reader-members (remove-if (complement #'cpp-member-reader)
(cpp-class-members cpp-class))))
(when (or (cpp-class-public cpp-class) (cpp-class-members-scoped :public) reader-members)
(unless (cpp-class-structp cpp-class)
(write-line " public:" s))
(format s "~{~A~%~}" (mapcar #'cpp-code (cpp-class-public cpp-class)))
(format s "~{~%~A~}~%" (mapcar #'cpp-member-reader-definition reader-members))
(with-cpp-block-output (s :semicolonp t)
(let ((reader-members (remove-if (complement #'cpp-member-reader)
(cpp-class-members cpp-class))))
(when (or (cpp-class-public cpp-class) (cpp-class-members-scoped :public) reader-members)
(unless (cpp-class-structp cpp-class)
(write-line " public:" s))
(format s "~{~A~%~}" (mapcar #'cpp-code (cpp-class-public cpp-class)))
(format s "~{~%~A~}~%" (mapcar #'cpp-member-reader-definition reader-members))
(format s "~{ ~%~A~}~%"
(mapcar #'member-declaration (cpp-class-members-scoped :public)))))
(when (or (cpp-class-protected cpp-class) (cpp-class-members-scoped :protected))
(write-line " protected:" s)
(format s "~{~A~%~}" (mapcar #'cpp-code (cpp-class-protected cpp-class)))
(format s "~{ ~%~A~}~%"
(mapcar #'member-declaration (cpp-class-members-scoped :public)))))
(when (cpp-class-capnp-opts cpp-class)
(let ((construct (capnp-construct-declaration cpp-class))
(load (capnp-load-declaration cpp-class)))
(when construct (format s " ~A;~2%" construct))
(when load (format s " ~A;~2%" load))))
(when (or (cpp-class-protected cpp-class) (cpp-class-members-scoped :protected))
(write-line " protected:" s)
(format s "~{~A~%~}" (mapcar #'cpp-code (cpp-class-protected cpp-class)))
(format s "~{ ~%~A~}~%"
(mapcar #'member-declaration (cpp-class-members-scoped :protected))))
(when (or (cpp-class-private cpp-class) (cpp-class-members-scoped :private))
(write-line " private:" s)
(format s "~{~A~%~}" (mapcar #'cpp-code (cpp-class-private cpp-class)))
(format s "~{ ~%~A~}~%"
(mapcar #'member-declaration (cpp-class-members-scoped :private))))
(write-line "};" s))))
(mapcar #'member-declaration (cpp-class-members-scoped :protected))))
(when (or (cpp-class-private cpp-class) (cpp-class-members-scoped :private))
(write-line " private:" s)
(format s "~{~A~%~}" (mapcar #'cpp-code (cpp-class-private cpp-class)))
(format s "~{ ~%~A~}~%"
(mapcar #'member-declaration (cpp-class-members-scoped :private))))))))
(defun cpp-function-declaration (name &key args (returns "void") type-params)
"Generate a C++ top level function declaration named NAME as a string. ARGS
@ -680,12 +690,11 @@ encoded as union inheritance in Cap'n Proto."
"Generate Cap'n Proto serialization schema for CPP-ENUM"
(declare (type cpp-enum cpp-enum))
(with-output-to-string (s)
(format s "enum ~A {~%" (cpp-type-name cpp-enum))
(loop for val in (cpp-enum-values cpp-enum) and field-number from 0
do (format s " ~A @~A;~%"
(string-downcase (cpp-type-name val) :end 1)
field-number))
(write-line "}" s)))
(with-cpp-block-output (s :name (format nil "enum ~A" (cpp-type-name cpp-enum)))
(loop for val in (cpp-enum-values cpp-enum) and field-number from 0
do (format s " ~A @~A;~%"
(string-downcase (cpp-type-name val) :end 1)
field-number)))))
(defun capnp-schema (cpp-class)
"Generate Cap'n Proto serialiation schema for CPP-CLASS"
@ -715,57 +724,53 @@ encoded as union inheritance in Cap'n Proto."
(error "Class ~A has multiple inheritance. Use :inherit-compose for
remaining parents." class-name))
(with-output-to-string (s)
(format s "struct ~A {~%" (cpp-type-name class-name))
(dolist (compose compose-parents)
(format s " ~A @~A :~A;~%"
(field-name<-symbol compose)
field-number
(capnp-type<-cpp-type compose))
(incf field-number))
(when capnp-type-args
(write-line " union {" s)
(dolist (type-arg capnp-type-args)
(format s " ~A @~A :Void;~%" (field-name<-symbol type-arg) field-number)
(incf field-number))
(write-line " }" s))
(dolist (member members)
(unless (eq :dont-save (cpp-member-capnp-save member))
(let ((capnp-type (capnp-type-of-member member))
(field-name (field-name<-symbol (cpp-member-symbol member))))
(if (stringp capnp-type)
(progn
(format s " ~A @~A :~A;~%"
field-name field-number capnp-type)
(incf field-number))
;; capnp-type is a list specifying a union type
(progn
(format s " ~A :union {~%" field-name)
(dolist (union-member capnp-type)
(format s " ~A @~A :~A;~%"
(field-name<-symbol (first union-member))
field-number (second union-member))
(incf field-number))
(write-line " }" s))))))
(dolist (inner inner-types)
(when (or (and (typep inner 'cpp-class) (cpp-class-capnp-opts inner))
(and (typep inner 'cpp-enum) (cpp-enum-capnp-schema inner)))
(write-line (capnp-schema inner) s)))
(when union-subclasses
(write-line " union {" s)
(when union-parents
;; Allow instantiating classes in the middle of inheritance
;; hierarchy.
(format s " ~A @~A :Void;~%"
(field-name<-symbol class-name) field-number)
(incf field-number))
(dolist (subclass union-subclasses)
(format s " ~A @~A :~A;~%"
(field-name<-symbol (cpp-type-base-name subclass))
(with-cpp-block-output (s :name (format nil "struct ~A" (cpp-type-name class-name)))
(dolist (compose compose-parents)
(format s " ~A @~A :~A;~%"
(field-name<-symbol compose)
field-number
(capnp-type<-cpp-type (cpp-type-base-name subclass)))
(capnp-type<-cpp-type compose))
(incf field-number))
(write-line " }" s))
(write-line "}" s))))))
(when capnp-type-args
(with-cpp-block-output (s :name "union")
(dolist (type-arg capnp-type-args)
(format s " ~A @~A :Void;~%" (field-name<-symbol type-arg) field-number)
(incf field-number))))
(dolist (member members)
(unless (eq :dont-save (cpp-member-capnp-save member))
(let ((capnp-type (capnp-type-of-member member))
(field-name (field-name<-symbol (cpp-member-symbol member))))
(if (stringp capnp-type)
(progn
(format s " ~A @~A :~A;~%"
field-name field-number capnp-type)
(incf field-number))
;; capnp-type is a list specifying a union type
(progn
(with-cpp-block-output (s :name (format nil " ~A :union" field-name))
(dolist (union-member capnp-type)
(format s " ~A @~A :~A;~%"
(field-name<-symbol (first union-member))
field-number (second union-member))
(incf field-number))))))))
(dolist (inner inner-types)
(when (or (and (typep inner 'cpp-class) (cpp-class-capnp-opts inner))
(and (typep inner 'cpp-enum) (cpp-enum-capnp-schema inner)))
(write-line (capnp-schema inner) s)))
(when union-subclasses
(with-cpp-block-output (s :name "union")
(when union-parents
;; Allow instantiating classes in the middle of inheritance
;; hierarchy.
(format s " ~A @~A :Void;~%"
(field-name<-symbol class-name) field-number)
(incf field-number))
(dolist (subclass union-subclasses)
(format s " ~A @~A :~A;~%"
(field-name<-symbol (cpp-type-base-name subclass))
field-number
(capnp-type<-cpp-type (cpp-type-base-name subclass)))
(incf field-number))))))))))
;;; Capnp C++ serialization code generation
;;;
@ -951,25 +956,25 @@ Proto schema."
(capnp-primitive-type-p (capnp-type-of-member member)))
(format s " builder->set~A(~A);~%" capnp-name member-access))
(t
(write-line "{" s) ;; Enclose larger save code in new scope
(let ((size (if (string= "vector" (cpp-type-base-name
(parse-cpp-type-declaration
(cpp-member-type member))))
(format nil "~A.size()" member-access)
"")))
(if (and (cpp-member-capnp-init member)
(not (find-cpp-enum (cpp-member-type member))))
(format s " auto ~A = builder->init~A(~A);~%"
member-builder capnp-name size)
(setf member-builder "builder")))
(if (cpp-member-capnp-save member)
(format s " ~A~%"
(cpp-code (funcall (cpp-member-capnp-save member)
member-builder member-access capnp-name)))
(write-line (capnp-save-default member-access (cpp-member-type member)
member-builder capnp-name)
s))
(write-line "}" s))))))))
;; Enclose larger save code in new scope
(with-cpp-block-output (s)
(let ((size (if (string= "vector" (cpp-type-base-name
(parse-cpp-type-declaration
(cpp-member-type member))))
(format nil "~A.size()" member-access)
"")))
(if (and (cpp-member-capnp-init member)
(not (find-cpp-enum (cpp-member-type member))))
(format s " auto ~A = builder->init~A(~A);~%"
member-builder capnp-name size)
(setf member-builder "builder")))
(if (cpp-member-capnp-save member)
(format s " ~A~%"
(cpp-code (funcall (cpp-member-capnp-save member)
member-builder member-access capnp-name)))
(write-line (capnp-save-default member-access (cpp-member-type member)
member-builder capnp-name)
s))))))))))
(defun capnp-save-parents (cpp-class save-parent)
"Generate Cap'n Proto code for serializing parent classes of CPP-CLASS.
@ -985,8 +990,7 @@ It takes a parent class symbol."
(let ((parents (capnp-union-parents-rec cpp-class)))
(when parents
(let ((first-parent (first parents)))
(write-line
(funcall save-parent first-parent) s))
(write-line (funcall save-parent first-parent) s))
(if (or compose-parents (cpp-class-members cpp-class))
(progn
(format s " auto ~A_builder = base_builder->~{get~A().~}init~A();~%"
@ -1004,12 +1008,11 @@ It takes a parent class symbol."
(format s " builder->set~A();" (cpp-type-name cpp-class)))))
;; Now handle composite inheritance calls.
(dolist (parent compose-parents)
(write-line "{" s)
(let* ((builder (format nil "~A_builder" (cpp-variable-name parent))))
(format s " auto ~A = builder->init~A();~%" builder (cpp-type-name parent))
(format s " auto *builder = &~A;~%" builder)
(write-line (funcall save-parent parent) s))
(write-line "}" s)))))
(with-cpp-block-output (s)
(let* ((builder (format nil "~A_builder" (cpp-variable-name parent))))
(format s " auto ~A = builder->init~A();~%" builder (cpp-type-name parent))
(format s " auto *builder = &~A;~%" builder)
(write-line (funcall save-parent parent) s)))))))
(defun capnp-save-function-code (cpp-class)
"Generate Cap'n Proto save code for CPP-CLASS."
@ -1037,10 +1040,9 @@ It takes a parent class symbol."
"Generate serialization code for parent class."
(let ((cpp-class (find-cpp-class parent)))
(with-output-to-string (s)
(write-line "{" s)
(format s "// Save base class ~A~%" (cpp-type-name parent))
(save-class cpp-class s)
(write-line "}" s)))))
(with-cpp-block-output (s)
(format s "// Save base class ~A~%" (cpp-type-name parent))
(save-class cpp-class s))))))
(with-output-to-string (cpp-out)
(let ((subclasses (direct-subclasses-of cpp-class)))
(when subclasses
@ -1082,84 +1084,59 @@ It takes a parent class symbol."
"Generate Cap'n Proto save function."
(declare (type cpp-class cpp-class))
(with-output-to-string (cpp-out)
(format cpp-out "~A {~%" (capnp-save-function-declaration cpp-class))
(write-line (capnp-save-function-code cpp-class) cpp-out)
(write-line "}" cpp-out)))
(with-cpp-block-output (cpp-out :name (capnp-save-function-declaration cpp-class))
(write-line (capnp-save-function-code cpp-class) cpp-out))))
;;; Capnp C++ deserialization code generation
;;;
;;; This is almost the same as serialization, but with a special case for
;;; handling serialized pointers to base classes.
;;;
;;; We need to generate a static Construct function, which dispatches on the
;;; union of the Capnp struct schema. This needs to recursively traverse
;;; unions to instantiate a concrete C++ class.
;;; The usual function signature for data types with no inheritance is:
;;;
;;; When loading such a pointer, first we call Construct and then follow it
;;; with calling Load on the constructed instance.
;;; void Load(Data *self, const capnp::Data::Reader &, <extra args>)
;;;
;;; 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))
"Generate Cap'n Proto construct function declaration for CPP-CLASS. If
INLINE is NIL, the declaration is namespaced for the class so that it can be
used for outside definition."
(defun capnp-load-function-declaration (cpp-class)
"Generate Cap'n Proto load function declaration for CPP-CLASS."
(declare (type cpp-class cpp-class))
;; Don't generate Construct if this class is only inherited as composite.
(when (and (not (capnp-union-subclasses cpp-class))
(direct-subclasses-of cpp-class))
(return-from capnp-construct-declaration))
(let ((reader-type (format nil "const capnp::~A::Reader &"
(cpp-type-decl cpp-class :type-args nil :namespace nil))))
(cpp-method-declaration
cpp-class "Construct" :args (list (list 'reader reader-type))
:returns (format nil "std::unique_ptr<~A>" (cpp-type-decl cpp-class :namespace nil))
:inline inline :static t)))
(let* ((parents (capnp-union-parents-rec cpp-class))
(top-parent-class (if parents
(cpp-type-decl (find-cpp-class (car (last parents))) :type-args nil :namespace nil)
(cpp-type-decl cpp-class :type-args nil :namespace nil)))
(reader-arg (list (if (or parents (capnp-union-subclasses cpp-class))
'base-reader
'reader)
(format nil "const capnp::~A::Reader &" top-parent-class)))
(out-arg (list 'self
(if (or parents (direct-subclasses-of cpp-class))
(format nil "std::unique_ptr<~A> *" (cpp-type-decl cpp-class :namespace nil))
(format nil "~A *" (cpp-type-decl cpp-class :namespace nil))))))
(cpp-function-declaration
"Load"
:args (cons out-arg (cons reader-arg (capnp-extra-args cpp-class :load)))
:returns "void"
:type-params (cpp-type-type-params cpp-class))))
(defun capnp-construct-code (cpp-class)
"Generate Cap'n Proto construct code for CPP-CLASS"
(declare (type cpp-class cpp-class))
(let ((construct-declaration (capnp-construct-declaration cpp-class :inline nil)))
(unless construct-declaration
(return-from capnp-construct-code))
(let ((class-name (cpp-type-base-name cpp-class))
(union-subclasses (capnp-union-subclasses cpp-class)))
(with-output-to-string (s)
(format s "~A {~%" construct-declaration)
(if (not union-subclasses)
;; No inheritance, just instantiate the concrete class.
(format s " return std::unique_ptr<~A>(new ~A());~%"
(cpp-type-name class-name) (cpp-type-name class-name))
;; Inheritance, so forward the Construct.
(progn
(write-line " switch (reader.which()) {" s)
(when (capnp-union-and-compose-parents cpp-class)
;; We are in the middle of the hierarchy, so allow
;; constructing us.
(format s " case capnp::~A::~A: return std::unique_ptr<~A>(new ~A());~%"
(cpp-type-name class-name) (cpp-constant-name class-name)
(cpp-type-name class-name) (cpp-type-name class-name)))
(dolist (subclass union-subclasses)
(format s " case capnp::~A::~A:~%"
(cpp-type-name class-name)
(cpp-constant-name (cpp-type-base-name subclass)))
(let ((subclass-name (cpp-type-name (cpp-type-base-name subclass))))
(if (capnp-opts-type-args (cpp-class-capnp-opts subclass))
;; Handle template instantiation
(progn
(format s " switch (reader.get~A().which()) {~%" subclass-name)
(dolist (type-arg (capnp-opts-type-args (cpp-class-capnp-opts subclass)))
(format s " case capnp::~A::~A: return ~A<~A>::Construct(reader.get~A());~%"
subclass-name (cpp-constant-name type-arg)
subclass-name (cpp-type-name type-arg)
subclass-name))
(write-line " }" s))
;; Just forward the construct normally.
(format s " return ~A::Construct(reader.get~A());~%"
subclass-name subclass-name))))
(write-line " }" s))) ;; close switch
(write-line "}" s))))) ;; close function
(defun capnp-load-default (member-name member-type member-reader)
"Generate default load call for member."
(defun capnp-load-default (member-name member-type member-reader capnp-name)
"Generate default load call for member. MEMBER-NAME and MEMBER-TYPE are
strings describing the member being loaded. MEMBER-READER is the name of the
reader variable. CAPNP-NAME is the name of the member in Cap'n Proto schema."
(declare (type string member-name member-type member-reader))
(let* ((type (parse-cpp-type-declaration member-type))
(type-name (cpp-type-base-name type))
@ -1168,8 +1145,8 @@ used for outside definition."
(cpp-enum
(funcall
(capnp-load-enum (cpp-type-decl (capnp-cpp-type<-cpp-type cpp-enum))
member-type (cpp-enum-values cpp-enum))
member-reader member-name))
(cpp-type-decl cpp-enum) (cpp-enum-values cpp-enum))
member-reader member-name capnp-name))
((string= "vector" type-name)
(let* ((elem-type (car (cpp-type-type-args type)))
(capnp-cpp-type (capnp-cpp-type<-cpp-type elem-type)))
@ -1180,7 +1157,7 @@ used for outside definition."
cpp<#)
(raw-cpp-string
(funcall (capnp-load-vector (cpp-type-decl capnp-cpp-type) (cpp-type-decl elem-type))
member-reader member-name)))))
member-reader member-name capnp-name)))))
((string= "optional" type-name)
(let* ((elem-type (car (cpp-type-type-args type)))
(capnp-cpp-type (capnp-cpp-type<-cpp-type elem-type :boxp t))
@ -1189,7 +1166,7 @@ used for outside definition."
(raw-cpp-string
(funcall (capnp-load-optional
(cpp-type-decl capnp-cpp-type) (cpp-type-decl elem-type) lambda-code)
member-reader member-name))))
member-reader member-name capnp-name))))
((member type-name '("unique_ptr" "shared_ptr" "vector") :test #'string=)
(error "Use a custom :capnp-load function for ~A ~A" type-name member-name))
(t
@ -1198,81 +1175,148 @@ used for outside definition."
(mapcar (lambda (name-and-type)
(cpp-variable-name (first name-and-type)))
(capnp-extra-args cpp-class :load)))))
(format nil "~A.Load(~A~{, ~A~});"
(format nil "Load(&~A, ~A~{, ~A~});"
member-name member-reader extra-args))))))
(defun capnp-load-declaration (cpp-class &key (inline t))
"Generate Cap'n Proto load function declaration for CPP-CLASS. If
INLINE is NIL, the declaration is namespaced for the class so that it can be
used for outside definition."
(declare (type cpp-class cpp-class))
(let* ((parents (capnp-union-parents-rec cpp-class))
(top-parent-class (if parents
(cpp-type-decl (find-cpp-class (car (last parents))) :type-args nil :namespace nil)
(cpp-type-decl cpp-class :type-args nil :namespace nil)))
(reader-arg
(list (if parents 'base-reader 'reader)
(format nil "const capnp::~A::Reader &" top-parent-class))))
(cpp-method-declaration
cpp-class "Load" :args (cons reader-arg (capnp-extra-args cpp-class :load))
:virtual (and (not parents) (capnp-union-subclasses cpp-class))
:override parents :inline inline)))
(defun capnp-load-code (cpp-class)
"Generate Cap'n Proto loading code for CPP-CLASS"
(defun capnp-load-members (cpp-class &key instance-access)
"Generate Cap'n Proto loading code for members of CPP-CLASS.
INSTANCE-ACCESS is a C++ string which will be prefixed to member access. For
example, INSTANCE-ACCESS could be `my_struct->`"
(declare (type cpp-class cpp-class))
(declare (type string instance-access))
(with-output-to-string (s)
(format s "~A {~%" (capnp-load-declaration cpp-class :inline nil))
(flet ((parent-args (parent)
(mapcar (lambda (name-and-type)
(cpp-variable-name (first name-and-type)))
(capnp-extra-args (find-cpp-class parent) :load))))
(multiple-value-bind (direct-union-parents compose-parents)
(capnp-union-and-compose-parents cpp-class)
(declare (ignore direct-union-parents))
;; Handle the union inheritance calls first.
(let ((parents (capnp-union-parents-rec cpp-class)))
(when parents
(let ((first-parent (first parents)))
(format s " ~A::Load(base_reader~{, ~A~});~%"
(cpp-type-name first-parent) (parent-args first-parent)))
(when (or compose-parents (cpp-class-members cpp-class))
(format s " auto reader = base_reader.~{get~A().~}get~A();~%"
(mapcar #'cpp-type-name (cdr (reverse parents)))
(cpp-type-name cpp-class)))
;; Now handle composite inheritance calls.
(dolist (parent compose-parents)
(write-line "{" s)
(format s " auto ~A_reader = reader.get~A();~%"
(cpp-variable-name parent) (cpp-type-name parent))
(format s " ~A::Load(~A_reader~{, ~A~});~%"
(cpp-type-name parent) (cpp-variable-name parent) (parent-args parent))
(write-line "}" s))))))
(dolist (member (cpp-class-members cpp-class))
(unless (and (eq :dont-save (cpp-member-capnp-save member))
(not (cpp-member-capnp-load member)))
(let ((member-name (cpp-member-name member :struct (cpp-class-structp cpp-class)))
(let ((member-access
(concatenate 'string instance-access
(cpp-member-name member :struct (cpp-class-structp cpp-class))))
(member-reader (format nil "~A_reader" (cpp-member-name member :struct t)))
(capnp-name (cpp-type-name (cpp-member-symbol member))))
(cond
((and (not (cpp-member-capnp-load member))
(capnp-primitive-type-p (capnp-type-of-member member)))
(format s " ~A = reader.get~A();~%" member-name capnp-name))
(format s " ~A = reader.get~A();~%" member-access capnp-name))
(t
(write-line "{" s) ;; Enclose larger load code in new scope
(if (and (cpp-member-capnp-init member)
(not (find-cpp-enum (cpp-member-type member))))
(format s " auto ~A = reader.get~A();~%" member-reader capnp-name)
(setf member-reader "reader"))
(if (cpp-member-capnp-load member)
(format s " ~A~%"
(cpp-code (funcall (cpp-member-capnp-load member)
member-reader member-name)))
(write-line (capnp-load-default member-name
(cpp-member-type member)
member-reader) s))
(write-line "}" s))))))
(write-line "}" s)))
;; Enclose larger load code in new scope
(with-cpp-block-output (s)
(if (and (cpp-member-capnp-init member)
(not (find-cpp-enum (cpp-member-type member))))
(format s " auto ~A = reader.get~A();~%" member-reader capnp-name)
(setf member-reader "reader"))
(if (cpp-member-capnp-load member)
(format s " ~A~%"
(cpp-code (funcall (cpp-member-capnp-load member)
member-reader member-access capnp-name)))
(write-line (capnp-load-default member-access
(cpp-member-type member)
member-reader capnp-name) s))))))))))
(defun capnp-load-parents (cpp-class load-parent)
"Generate Cap'n Proto code for loading parent classes of CPP-CLASS.
LOAD-PARENT is a function which generates the code for loading parent members.
It takes a parent class symbol."
(declare (type cpp-class cpp-class))
(declare (type (function (symbol) string) load-parent))
(with-output-to-string (s)
(multiple-value-bind (direct-union-parents compose-parents)
(capnp-union-and-compose-parents cpp-class)
(declare (ignore direct-union-parents))
;; Handle the union inheritance calls first.
(let ((parents (capnp-union-parents-rec cpp-class)))
(when parents
(let ((first-parent (first parents)))
(write-line (funcall load-parent first-parent) s))
(when (or compose-parents (cpp-class-members cpp-class))
(format s " auto reader = base_reader.~{get~A().~}get~A();~%"
(mapcar #'cpp-type-name (cdr (reverse parents)))
(cpp-type-name cpp-class)))
;; Now handle composite inheritance calls.
(dolist (parent compose-parents)
(with-cpp-block-output (s)
(let ((reader (format nil "~A_reader" (cpp-variable-name parent))))
(format s " auto ~A = reader.get~A();~%" reader (cpp-type-name parent))
(format s " const auto &reader = ~A;" reader)
(write-line (funcall load-parent parent) s)))))))))
(defun capnp-load-function-code (cpp-class)
"Generate Cap'n Proto loadd code for CPP-CLASS."
(declare (type cpp-class cpp-class))
(let ((instance-access (if (or (direct-subclasses-of cpp-class)
(capnp-union-parents-rec cpp-class))
"self->get()->"
"self->")))
(labels ((load-class (cpp-class)
(with-output-to-string (s)
(write-line (capnp-load-parents cpp-class #'load-parent) s)
(write-line (capnp-load-members cpp-class :instance-access instance-access) s)))
(load-parent (parent)
(with-output-to-string (s)
(with-cpp-block-output (s)
(format s "// Load base class ~A~%" (cpp-type-name parent))
(write-line (load-class (find-cpp-class parent)) s)))))
(with-output-to-string (s)
(cond
((and (capnp-union-and-compose-parents cpp-class)
(not (direct-subclasses-of cpp-class)))
;; CPP-CLASS is the most derived class, so construct and load.
(format s "*self = std::make_unique<~A>();~%" (cpp-type-decl cpp-class :namespace nil))
(write-line (load-class cpp-class) s))
((capnp-union-subclasses cpp-class)
;; Forward the load to most derived class by switching on reader.which()
(let ((parents (capnp-union-parents-rec cpp-class)))
(if parents
(format s "switch (base_reader.~{get~A().~}get~A().which()) "
(mapcar #'cpp-type-name (cdr (reverse parents)))
(cpp-type-name cpp-class))
(write-string "switch (base_reader.which()) " s)))
(with-cpp-block-output (s)
(dolist (subclass (capnp-union-subclasses cpp-class))
(format s " case capnp::~A::~A: "
(cpp-type-name cpp-class)
(cpp-constant-name (cpp-type-base-name subclass)))
(flet ((load-derived (derived-type-name)
(with-cpp-block-output (s)
(format s "std::unique_ptr<~A> derived;~%" derived-type-name)
(format s "Load(&derived, base_reader~{, ~A~});~%"
(mapcar (lambda (name-and-type)
(cpp-variable-name (first name-and-type)))
(capnp-extra-args cpp-class :load)))
(write-line "*self = std::move(derived);" s))))
(if (capnp-opts-type-args (cpp-class-capnp-opts subclass))
;; Handle template instantiation
(progn
(format s "switch (base_reader.get~A().which()) " (cpp-type-name subclass))
(with-cpp-block-output (s)
(dolist (type-arg (capnp-opts-type-args (cpp-class-capnp-opts subclass)))
(format s " case capnp::~A::~A: "
(cpp-type-name subclass) (cpp-constant-name type-arg))
(load-derived (format nil "~A<~A>"
(cpp-type-name subclass)
(cpp-type-name type-arg))))))
;; Regular forward to derived
(load-derived (cpp-type-name subclass))))
(write-line "break;" s))
(when (capnp-union-and-compose-parents cpp-class)
;; We are in the middle of the hierarchy, so allow constructing and loading us.
(with-cpp-block-output (s :name (format nil "case capnp::~A::~A:"
(cpp-type-name cpp-class)
(cpp-constant-name (cpp-type-base-name cpp-class))))
(format s "*self = std::make_unique<~A>();~%"
(cpp-type-decl cpp-class :namespace nil))
(write-line (load-class cpp-class) s)))))
(t
;; Regular load for absolutely no inheritance class
(assert (not (capnp-union-subclasses cpp-class)))
(assert (not (capnp-union-and-compose-parents cpp-class)))
(write-line (load-class cpp-class) s)))))))
(defun capnp-load-function-definition (cpp-class)
"Generate Cap'n Proto load function."
(declare (type cpp-class cpp-class))
(with-output-to-string (cpp-out)
(with-cpp-block-output (cpp-out :name (capnp-load-function-declaration cpp-class))
(write-line (capnp-load-function-code cpp-class) cpp-out))))
(defvar *capnp-imports* nil
"List of pairs (namespace, import-file), which will be imported in Cap'n
@ -1318,12 +1362,15 @@ are passed as template parameters, while the optional LAMBDA-CODE is used to
load the value of std::optional."
(declare (type string capnp-type cpp-type)
(type (or null string) lambda-code))
(let ((lambda-code (if lambda-code
(let* ((namespace (format nil "~{~A::~}"
(cpp-type-namespace (parse-cpp-type-declaration cpp-type))))
(lambda-code (if lambda-code
lambda-code
(format nil
"[](const auto &reader) { ~A val; val.Load(reader); return val; }"
cpp-type))))
(lambda (reader member)
"[](const auto &reader) { ~A val; ~ALoad(&val, reader); return val; }"
cpp-type namespace))))
(lambda (reader member capnp-name)
(declare (ignore capnp-name))
#>cpp
${member} = utils::LoadOptional<${capnp-type}, ${cpp-type}>(${reader}, ${lambda-code});
cpp<#)))
@ -1354,12 +1401,15 @@ are passed as template parameters, while LAMBDA-CODE is used to load each
element."
(declare (type string capnp-type cpp-type)
(type (or null string) lambda-code))
(let ((lambda-code (if lambda-code
(let* ((namespace (format nil "~{~A::~}"
(cpp-type-namespace (parse-cpp-type-declaration cpp-type))))
(lambda-code (if lambda-code
lambda-code
(format nil
"[](const auto &reader) { ~A val; val.Load(reader); return val; }"
cpp-type))))
(lambda (reader member-name)
"[](const auto &reader) { ~A val; ~ALoad(&val, reader); return val; }"
cpp-type namespace))))
(lambda (reader member-name capnp-name)
(declare (ignore capnp-name))
#>cpp
utils::LoadVector<${capnp-type}, ${cpp-type}>(&${member-name}, ${reader}, ${lambda-code});
cpp<#)))
@ -1390,11 +1440,10 @@ the values from CAPNP-TYPE. If ENUM-VALUES are not specified, tries to find the
CPP-TYPE among defined enums."
(declare (type string capnp-type)
(type (or symbol string) cpp-type))
(lambda (reader member)
(lambda (reader member capnp-name)
(let* ((enum-values (if enum-values
enum-values
(cpp-enum-values (find-cpp-enum cpp-type))))
(member-getter (remove #\_ (string-capitalize member)))
(cases (mapcar (lambda (value-symbol)
(let ((value (cl-ppcre:regex-replace-all "-" (string value-symbol) "_")))
#>cpp
@ -1404,7 +1453,7 @@ CPP-TYPE among defined enums."
cpp<#))
enum-values)))
(format nil "switch (~A.get~A()) {~%~{~A~%~}}"
reader member-getter (mapcar #'raw-cpp-string cases)))))
reader capnp-name (mapcar #'raw-cpp-string cases)))))
(defvar *cpp-namespaces* nil
"Stack of C++ namespaces we are generating the code in.")
@ -1730,13 +1779,9 @@ code generation."
(format cpp-out "// Serialize code for ~A~2%" (cpp-type-name cpp-class))
;; Top level functions
(write-line (capnp-save-function-definition cpp-class) cpp-out)
;; Member functions
(let ((construct-code (capnp-construct-code cpp-class))
(load-code (capnp-load-code cpp-class)))
(when construct-code (write-line construct-code cpp-out))
(when load-code (write-line load-code cpp-out))))))
(write-line (capnp-load-function-definition cpp-class) cpp-out))))
(defun process-file (lcp-file &key capnp-id capnp-declaration)
(defun process-file (lcp-file &key capnp-id)
"Process a LCP-FILE and write the output to .hpp file in the same directory.
If CAPNP-ID is passed, generates the Cap'n Proto schema to .capnp file in the
same directory, while the loading code is generated in LCP-FILE.cpp source
@ -1750,7 +1795,7 @@ file."
(cpp-file (concatenate 'string lcp-file ".cpp"))
(capnp-file (concatenate 'string filename ".capnp"))
;; Reset globals
(*capnp-serialize-p* (or capnp-id capnp-declaration))
(*capnp-serialize-p* capnp-id)
(*capnp-namespace* nil)
(*capnp-imports* nil)
(*capnp-type-converters* nil)
@ -1784,7 +1829,8 @@ file."
(dolist (type-for-capnp types-for-capnp)
(when (typep type-for-capnp 'cpp-class)
(open-namespace (cpp-type-namespace type-for-capnp))
(format out "~A;~%" (capnp-save-function-declaration type-for-capnp))))))
(format out "~A;~%" (capnp-save-function-declaration type-for-capnp))
(format out "~A;~%" (capnp-load-function-declaration type-for-capnp))))))
;; When we have either capnp or C++ code for the .cpp file, generate the .cpp file
(when (or *cpp-impl* types-for-capnp)
(with-open-file (out cpp-file :direction :output :if-exists :supersede)

View File

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

View File

@ -44,18 +44,18 @@ class TypedValueVectorCompare final {
bool operator()(const std::vector<TypedValue> &c1,
const std::vector<TypedValue> &c2) const;
// TODO: Remove this, member is public
const auto &ordering() const { return ordering_; }
void Save(capnp::TypedValueVectorCompare::Builder *builder) const;
void Load(const capnp::TypedValueVectorCompare::Reader &reader);
private:
std::vector<Ordering> ordering_;
};
void Save(const TypedValueVectorCompare &comparator,
capnp::TypedValueVectorCompare::Builder *builder);
void Load(TypedValueVectorCompare *comparator,
const capnp::TypedValueVectorCompare::Reader &reader);
/// Switch the given [Vertex/Edge]Accessor to the desired state.
template <class TAccessor>
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 storage_property_reader = key_pair_reader.getSecond();
storage::Property key_second;
key_second.Load(storage_property_reader);
storage::Load(&key_second, storage_property_reader);
const auto value_reader = entry_reader.getValue();
auto value = storage->Load(value_reader, loaded_uids);
auto key = std::make_pair(key_first, key_second);
@ -982,7 +982,7 @@ void LabelsTest::Load(const capnp::Tree::Reader &base_reader,
}
for (auto label_reader : reader.getLabels()) {
storage::Label label;
label.Load(label_reader);
storage::Load(&label, label_reader);
labels_.push_back(label);
}
}
@ -1041,7 +1041,7 @@ void PropertyLookup::Load(const capnp::Tree::Reader &base_reader,
}
property_name_ = reader.getPropertyName().cStr();
auto storage_property_reader = reader.getProperty();
property_.Load(storage_property_reader);
storage::Load(&property_, storage_property_reader);
}
PropertyLookup *PropertyLookup::Construct(
@ -1356,10 +1356,10 @@ CreateIndex *CreateIndex::Construct(const capnp::CreateIndex::Reader &reader,
AstStorage *storage) {
auto label_reader = reader.getLabel();
storage::Label label;
label.Load(label_reader);
storage::Load(&label, label_reader);
auto property_reader = reader.getProperty();
storage::Property property;
property.Load(property_reader);
storage::Load(&property, property_reader);
return storage->Create<CreateIndex>(label, property);
}
@ -1740,7 +1740,7 @@ void RemoveLabels::Load(const capnp::Tree::Reader &base_reader,
}
for (auto label_reader : reader.getLabels()) {
storage::Label label;
label.Load(label_reader);
storage::Load(&label, label_reader);
labels_.push_back(label);
}
}
@ -1908,7 +1908,7 @@ void SetLabels::Load(const capnp::Tree::Reader &base_reader,
}
for (auto label_reader : reader.getLabels()) {
storage::Label label;
label.Load(label_reader);
storage::Load(&label, label_reader);
labels_.push_back(label);
}
}
@ -2301,7 +2301,7 @@ void CypherUnion::Load(const capnp::Tree::Reader &base_reader,
distinct_ = reader.getDistinct();
for (auto symbol_reader : reader.getUnionSymbols()) {
Symbol symbol;
symbol.Load(symbol_reader);
query::Load(&symbol, symbol_reader);
union_symbols_.push_back(symbol);
}
}
@ -2481,7 +2481,7 @@ void NodeAtom::Load(const capnp::Tree::Reader &base_reader, AstStorage *storage,
auto key_first = key_pair_reader.getFirst().cStr();
auto storage_property_reader = key_pair_reader.getSecond();
storage::Property property;
property.Load(storage_property_reader);
storage::Load(&property, storage_property_reader);
const auto value_reader = entry_reader.getValue();
auto value = storage->Load(value_reader, loaded_uids);
auto key = std::make_pair(key_first, property);
@ -2490,7 +2490,7 @@ void NodeAtom::Load(const capnp::Tree::Reader &base_reader, AstStorage *storage,
}
for (auto label_reader : reader.getLabels()) {
storage::Label label;
label.Load(label_reader);
storage::Load(&label, label_reader);
labels_.push_back(label);
}
}
@ -2670,7 +2670,7 @@ void EdgeAtom::Load(const capnp::Tree::Reader &base_reader, AstStorage *storage,
auto key_first = key_pair_reader.getFirst().cStr();
auto storage_property_reader = key_pair_reader.getSecond();
storage::Property property;
property.Load(storage_property_reader);
storage::Load(&property, storage_property_reader);
const auto value_reader = entry_reader.getValue();
auto value = storage->Load(value_reader, loaded_uids);
auto key = std::make_pair(key_first, property);
@ -2680,7 +2680,7 @@ void EdgeAtom::Load(const capnp::Tree::Reader &base_reader, AstStorage *storage,
for (auto edge_type_reader : reader.getEdgeTypes()) {
storage::EdgeType edge_type;
edge_type.Load(edge_type_reader);
storage::Load(&edge_type, edge_type_reader);
edge_types_.push_back(edge_type);
}
}

View File

@ -33,40 +33,13 @@ class Symbol {
}
bool operator!=(const Symbol &other) const { return !operator==(other); }
// TODO: Remove these since members are public
const auto &name() const { return name_; }
int position() const { return position_; }
Type type() const { return type_; }
bool user_declared() const { return user_declared_; }
int token_position() const { return token_position_; }
void Load(const capnp::Symbol::Reader &reader) {
name_ = reader.getName();
position_ = reader.getPosition();
user_declared_ = reader.getUserDeclared();
token_position_ = reader.getTokenPosition();
switch (reader.getType()) {
case capnp::Symbol::Type::ANY:
type_ = Type::Any;
break;
case capnp::Symbol::Type::EDGE:
type_ = Type::Edge;
break;
case capnp::Symbol::Type::EDGE_LIST:
type_ = Type::EdgeList;
break;
case capnp::Symbol::Type::NUMBER:
type_ = Type::Number;
break;
case capnp::Symbol::Type::PATH:
type_ = Type::Path;
break;
case capnp::Symbol::Type::VERTEX:
type_ = Type::Vertex;
break;
}
}
private:
std::string name_;
int position_;
bool user_declared_ = true;
@ -101,6 +74,33 @@ inline void Save(const Symbol &symbol, capnp::Symbol::Builder *builder) {
}
}
inline void Load(Symbol *symbol, const capnp::Symbol::Reader &reader) {
symbol->name_ = reader.getName();
symbol->position_ = reader.getPosition();
symbol->user_declared_ = reader.getUserDeclared();
symbol->token_position_ = reader.getTokenPosition();
switch (reader.getType()) {
case capnp::Symbol::Type::ANY:
symbol->type_ = Symbol::Type::Any;
break;
case capnp::Symbol::Type::EDGE:
symbol->type_ = Symbol::Type::Edge;
break;
case capnp::Symbol::Type::EDGE_LIST:
symbol->type_ = Symbol::Type::EdgeList;
break;
case capnp::Symbol::Type::NUMBER:
symbol->type_ = Symbol::Type::Number;
break;
case capnp::Symbol::Type::PATH:
symbol->type_ = Symbol::Type::Path;
break;
case capnp::Symbol::Type::VERTEX:
symbol->type_ = Symbol::Type::Vertex;
break;
}
}
} // namespace query
namespace std {

View File

@ -24,22 +24,11 @@ class SymbolTable final {
Symbol &at(const Tree &tree) { return table_.at(tree.uid()); }
const Symbol &at(const Tree &tree) const { return table_.at(tree.uid()); }
// TODO: Remove these since members are public
int max_position() const { return position_; }
const auto &table() const { return table_; }
void Load(const capnp::SymbolTable::Reader &reader) {
position_ = reader.getPosition();
table_.clear();
for (const auto &entry_reader : reader.getTable()) {
int key = entry_reader.getKey();
Symbol val;
val.Load(entry_reader.getVal());
table_[key] = val;
}
}
private:
int position_{0};
std::map<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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -28,7 +28,7 @@ std::vector<std::vector<TypedValue>> CollectProduce(
// collect the symbols from the return clause
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]);
Context context(db_accessor);

View File

@ -204,14 +204,14 @@ using ExpectDistributedCreateExpand = OpChecker<DistributedCreateExpand>;
class ExpectExpandVariable : public OpChecker<ExpandVariable> {
public:
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> {
public:
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) {}
void ExpectOp(Accumulate &op, const SymbolTable &) override {
std::unordered_set<Symbol> got_symbols(op.symbols().begin(),
op.symbols().end());
std::unordered_set<Symbol> got_symbols(op.symbols_.begin(),
op.symbols_.end());
EXPECT_EQ(symbols_, got_symbols);
}
@ -244,7 +244,7 @@ class ExpectAggregate : public OpChecker<Aggregate> {
void ExpectOp(Aggregate &op, const SymbolTable &symbol_table) override {
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());
auto aggr = *aggr_it++;
// TODO: Proper expression equality
@ -262,7 +262,7 @@ class ExpectAggregate : public OpChecker<Aggregate> {
EXPECT_EQ(aggr_it, aggregations_.end());
// TODO: Proper group by expression equality
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());
std::unordered_set<size_t> expected_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 {
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);
merge.merge_create()->Accept(check_create);
merge.merge_create_->Accept(check_create);
}
private:
@ -311,11 +311,11 @@ class ExpectOptional : public OpChecker<Optional> {
void ExpectOp(Optional &optional, const SymbolTable &symbol_table) override {
if (!optional_symbols_.empty()) {
EXPECT_THAT(optional.optional_symbols(),
EXPECT_THAT(optional.optional_symbols_,
testing::UnorderedElementsAreArray(optional_symbols_));
}
PlanChecker check_optional(optional_, symbol_table);
optional.optional()->Accept(check_optional);
optional.optional_->Accept(check_optional);
}
private:
@ -334,10 +334,10 @@ class ExpectScanAllByLabelPropertyValue
void ExpectOp(ScanAllByLabelPropertyValue &scan_all,
const SymbolTable &) override {
EXPECT_EQ(scan_all.label(), label_);
EXPECT_EQ(scan_all.property(), property_);
EXPECT_EQ(scan_all.label_, label_);
EXPECT_EQ(scan_all.property_, property_);
// TODO: Proper expression equality
EXPECT_EQ(typeid(scan_all.expression()).hash_code(),
EXPECT_EQ(typeid(scan_all.expression_).hash_code(),
typeid(expression_).hash_code());
}
@ -361,21 +361,21 @@ class ExpectScanAllByLabelPropertyRange
void ExpectOp(ScanAllByLabelPropertyRange &scan_all,
const SymbolTable &) override {
EXPECT_EQ(scan_all.label(), label_);
EXPECT_EQ(scan_all.property(), property_);
EXPECT_EQ(scan_all.label_, label_);
EXPECT_EQ(scan_all.property_, property_);
if (lower_bound_) {
ASSERT_TRUE(scan_all.lower_bound());
ASSERT_TRUE(scan_all.lower_bound_);
// 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());
EXPECT_EQ(scan_all.lower_bound()->type(), lower_bound_->type());
EXPECT_EQ(scan_all.lower_bound_->type(), lower_bound_->type());
}
if (upper_bound_) {
ASSERT_TRUE(scan_all.upper_bound());
ASSERT_TRUE(scan_all.upper_bound_);
// 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());
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) {}
void ExpectOp(AuthHandler &auth_handler, const SymbolTable &) override {
EXPECT_EQ(auth_handler.action(), action_);
EXPECT_EQ(auth_handler.user(), user_);
EXPECT_EQ(auth_handler.role(), role_);
EXPECT_EQ(auth_handler.user_or_role(), user_or_role_);
EXPECT_EQ(auth_handler.action_, action_);
EXPECT_EQ(auth_handler.user_, user_);
EXPECT_EQ(auth_handler.role_, role_);
EXPECT_EQ(auth_handler.user_or_role_, user_or_role_);
// TODO(mtomic): We need to somehow test the password expression.
EXPECT_TRUE(password_);
EXPECT_TRUE(auth_handler.password());
EXPECT_EQ(auth_handler.privileges(), privileges_);
EXPECT_TRUE(auth_handler.password_);
EXPECT_EQ(auth_handler.privileges_, privileges_);
}
private:
@ -425,8 +425,8 @@ class ExpectCreateIndex : public OpChecker<CreateIndex> {
: label_(label), property_(property) {}
void ExpectOp(CreateIndex &create_index, const SymbolTable &) override {
EXPECT_EQ(create_index.label(), label_);
EXPECT_EQ(create_index.property(), property_);
EXPECT_EQ(create_index.label_, label_);
EXPECT_EQ(create_index.property_, property_);
}
private:
@ -440,7 +440,7 @@ class ExpectPullRemote : public OpChecker<PullRemote> {
ExpectPullRemote(const std::vector<Symbol> &symbols) : symbols_(symbols) {}
void ExpectOp(PullRemote &op, const SymbolTable &) override {
EXPECT_THAT(op.symbols(), testing::UnorderedElementsAreArray(symbols_));
EXPECT_THAT(op.symbols_, testing::UnorderedElementsAreArray(symbols_));
}
private:
@ -459,12 +459,12 @@ class ExpectSynchronize : public OpChecker<Synchronize> {
void ExpectOp(Synchronize &op, const SymbolTable &symbol_table) override {
if (has_pull_) {
ASSERT_TRUE(op.pull_remote());
expect_pull_.ExpectOp(*op.pull_remote(), symbol_table);
ASSERT_TRUE(op.pull_remote_);
expect_pull_.ExpectOp(*op.pull_remote_, symbol_table);
} 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:
@ -480,12 +480,12 @@ class ExpectCartesian : public OpChecker<Cartesian> {
: left_(left), right_(right) {}
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);
op.left_op()->Accept(left_checker);
ASSERT_TRUE(op.right_op());
op.left_op_->Accept(left_checker);
ASSERT_TRUE(op.right_op_);
PlanChecker right_checker(right_, symbol_table);
op.right_op()->Accept(right_checker);
op.right_op_->Accept(right_checker);
}
private:
@ -499,7 +499,7 @@ class ExpectDistributedCreateNode : public OpChecker<DistributedCreateNode> {
: on_random_worker_(on_random_worker) {}
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:
@ -512,7 +512,7 @@ class ExpectPullRemoteOrderBy : public OpChecker<PullRemoteOrderBy> {
: symbols_(symbols) {}
void ExpectOp(PullRemoteOrderBy &op, const SymbolTable &) override {
EXPECT_THAT(op.symbols(), testing::UnorderedElementsAreArray(symbols_));
EXPECT_THAT(op.symbols_, testing::UnorderedElementsAreArray(symbols_));
}
private:
@ -534,27 +534,27 @@ class ExpectCreateStream : public OpChecker<CreateStream> {
batch_size_(batch_size) {}
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
EXPECT_EQ(typeid(create_stream.stream_uri()).hash_code(),
EXPECT_EQ(typeid(create_stream.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());
EXPECT_EQ(typeid(create_stream.transform_uri()).hash_code(),
EXPECT_EQ(typeid(create_stream.transform_uri_).hash_code(),
typeid(transform_uri_).hash_code());
if (batch_interval_in_ms_ && create_stream.batch_interval_in_ms()) {
EXPECT_EQ(typeid(create_stream.batch_interval_in_ms()).hash_code(),
if (batch_interval_in_ms_ && create_stream.batch_interval_in_ms_) {
EXPECT_EQ(typeid(create_stream.batch_interval_in_ms_).hash_code(),
typeid(batch_interval_in_ms_).hash_code());
} else {
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()) {
EXPECT_EQ(typeid(create_stream.batch_size()).hash_code(),
if (batch_size_ && create_stream.batch_size_) {
EXPECT_EQ(typeid(create_stream.batch_size_).hash_code(),
typeid(batch_size_).hash_code());
} else {
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) {}
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:
@ -590,15 +590,15 @@ class ExpectStartStopStream : public OpChecker<StartStopStream> {
void ExpectOp(StartStopStream &start_stop_stream,
const SymbolTable &) override {
EXPECT_EQ(start_stop_stream.stream_name(), stream_name_);
EXPECT_EQ(start_stop_stream.is_start(), is_start_);
EXPECT_EQ(start_stop_stream.stream_name_, stream_name_);
EXPECT_EQ(start_stop_stream.is_start_, is_start_);
// TODO: Proper expression equality
if (limit_batches_ && start_stop_stream.limit_batches()) {
EXPECT_EQ(typeid(start_stop_stream.limit_batches()).hash_code(),
if (limit_batches_ && start_stop_stream.limit_batches_) {
EXPECT_EQ(typeid(start_stop_stream.limit_batches_).hash_code(),
typeid(limit_batches_).hash_code());
} else {
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,
const SymbolTable &) override {
EXPECT_EQ(start_stop_all_streams.is_start(), is_start_);
EXPECT_EQ(start_stop_all_streams.is_start_, is_start_);
}
private:
@ -627,14 +627,14 @@ class ExpectTestStream : public OpChecker<TestStream> {
: stream_name_(stream_name), limit_batches_(limit_batches) {}
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
if (limit_batches_ && test_stream.limit_batches()) {
EXPECT_EQ(typeid(test_stream.limit_batches()).hash_code(),
if (limit_batches_ && test_stream.limit_batches_) {
EXPECT_EQ(typeid(test_stream.limit_batches_).hash_code(),
typeid(limit_batches_).hash_code());
} else {
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 plan = LogicalOperator::Construct(reader);
std::unique_ptr<LogicalOperator> plan;
LogicalOperator::LoadHelper helper;
plan->Load(reader, &helper);
Load(&plan, reader, &helper);
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 *produce = dynamic_cast<Produce *>(&planner.plan());
ASSERT_TRUE(produce);
const auto &named_expressions = produce->named_expressions();
const auto &named_expressions = produce->named_expressions_;
ASSERT_EQ(named_expressions.size(), 2);
auto *expanded_ident =
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_aggr_op = std::dynamic_pointer_cast<Aggregate>(worker_plan);
ASSERT_TRUE(worker_aggr_op);
ASSERT_EQ(worker_aggr_op->aggregations().size(), 2U);
symbol_table[*worker_sum] = worker_aggr_op->aggregations()[0].output_sym;
symbol_table[*worker_count] = worker_aggr_op->aggregations()[1].output_sym;
ASSERT_EQ(worker_aggr_op->aggregations_.size(), 2U);
symbol_table[*worker_sum] = worker_aggr_op->aggregations_[0].output_sym;
symbol_table[*worker_count] = worker_aggr_op->aggregations_[1].output_sym;
}
auto worker_aggr = ExpectAggregate({worker_sum, worker_count}, {});
auto merge_sum = SUM(IDENT("worker_sum"));
@ -3134,11 +3134,11 @@ TEST(CapnpSerial, Union) {
ASSERT_TRUE(loaded_plan);
auto *loaded_op = dynamic_cast<Union *>(loaded_plan.get());
ASSERT_TRUE(loaded_op);
EXPECT_FALSE(loaded_op->left_op());
EXPECT_FALSE(loaded_op->right_op());
EXPECT_EQ(loaded_op->left_symbols(), left_symbols);
EXPECT_EQ(loaded_op->right_symbols(), right_symbols);
EXPECT_EQ(loaded_op->union_symbols(), union_symbols);
EXPECT_FALSE(loaded_op->left_op_);
EXPECT_FALSE(loaded_op->right_op_);
EXPECT_EQ(loaded_op->left_symbols_, left_symbols);
EXPECT_EQ(loaded_op->right_symbols_, right_symbols);
EXPECT_EQ(loaded_op->union_symbols_, union_symbols);
}
TEST(CapnpSerial, Cartesian) {
@ -3157,10 +3157,10 @@ TEST(CapnpSerial, Cartesian) {
ASSERT_TRUE(loaded_plan);
auto *loaded_op = dynamic_cast<Cartesian *>(loaded_plan.get());
ASSERT_TRUE(loaded_op);
EXPECT_FALSE(loaded_op->left_op());
EXPECT_FALSE(loaded_op->right_op());
EXPECT_EQ(loaded_op->left_symbols(), left_symbols);
EXPECT_EQ(loaded_op->right_symbols(), right_symbols);
EXPECT_FALSE(loaded_op->left_op_);
EXPECT_FALSE(loaded_op->right_op_);
EXPECT_EQ(loaded_op->left_symbols_, left_symbols);
EXPECT_EQ(loaded_op->right_symbols_, right_symbols);
}
TEST(CapnpSerial, Synchronize) {
@ -3175,8 +3175,8 @@ TEST(CapnpSerial, Synchronize) {
auto *loaded_op = dynamic_cast<Synchronize *>(loaded_plan.get());
ASSERT_TRUE(loaded_op);
EXPECT_FALSE(loaded_op->input());
EXPECT_FALSE(loaded_op->pull_remote());
EXPECT_TRUE(loaded_op->advance_command());
EXPECT_FALSE(loaded_op->pull_remote_);
EXPECT_TRUE(loaded_op->advance_command_);
}
TEST(CapnpSerial, PullRemote) {
@ -3192,8 +3192,8 @@ TEST(CapnpSerial, PullRemote) {
auto *loaded_op = dynamic_cast<PullRemote *>(loaded_plan.get());
ASSERT_TRUE(loaded_op);
EXPECT_FALSE(loaded_op->input());
EXPECT_EQ(loaded_op->plan_id(), 42);
EXPECT_EQ(loaded_op->symbols(), symbols);
EXPECT_EQ(loaded_op->plan_id_, 42);
EXPECT_EQ(loaded_op->symbols_, symbols);
}
TEST(CapnpSerial, PullRemoteOrderBy) {
@ -3215,12 +3215,12 @@ TEST(CapnpSerial, PullRemoteOrderBy) {
auto *loaded_op = dynamic_cast<PullRemoteOrderBy *>(loaded_plan.get());
ASSERT_TRUE(loaded_op);
ASSERT_TRUE(std::dynamic_pointer_cast<Once>(loaded_op->input()));
EXPECT_EQ(loaded_op->plan_id(), 42);
EXPECT_EQ(loaded_op->symbols(), symbols);
ASSERT_EQ(loaded_op->order_by().size(), 1);
EXPECT_TRUE(dynamic_cast<query::Identifier *>(loaded_op->order_by()[0]));
ASSERT_EQ(loaded_op->compare().ordering().size(), 1);
EXPECT_EQ(loaded_op->compare().ordering()[0], query::Ordering::ASC);
EXPECT_EQ(loaded_op->plan_id_, 42);
EXPECT_EQ(loaded_op->symbols_, symbols);
ASSERT_EQ(loaded_op->order_by_.size(), 1);
EXPECT_TRUE(dynamic_cast<query::Identifier *>(loaded_op->order_by_[0]));
ASSERT_EQ(loaded_op->compare_.ordering().size(), 1);
EXPECT_EQ(loaded_op->compare_.ordering()[0], query::Ordering::ASC);
}
} // namespace

View File

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

View File

@ -1,11 +1,9 @@
#!/bin/bash -e
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 "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
fi
@ -24,11 +22,7 @@ fi
capnp=""
if [[ $# -eq 2 ]]; then
if [[ "$2" == "--capnp-declaration" ]]; then
capnp=":capnp-declaration t"
else
capnp=":capnp-id \"$2\""
fi
capnp=":capnp-id \"$2\""
fi
echo \

View File

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