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:
parent
a5926b4e0f
commit
1fd9a72e10
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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)...);
|
||||
|
@ -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<#))
|
||||
|
@ -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;
|
||||
});
|
||||
|
@ -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);
|
||||
|
@ -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},
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
});
|
||||
}
|
||||
|
@ -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);
|
||||
});
|
||||
}
|
||||
|
@ -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);
|
||||
});
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
});
|
||||
}
|
||||
|
@ -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);
|
||||
});
|
||||
|
@ -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>>(
|
||||
|
@ -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);
|
||||
|
@ -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)));
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -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>(
|
||||
|
@ -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();
|
||||
});
|
||||
|
@ -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(
|
||||
|
@ -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,
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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>
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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:
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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); \
|
||||
}); \
|
||||
|
@ -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);
|
||||
|
@ -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> {
|
||||
|
@ -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<#)
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
10
tools/lcp
10
tools/lcp
@ -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 \
|
||||
|
@ -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) {
|
||||
|
Loading…
Reference in New Issue
Block a user