memgraph/src/query/serialization.cpp
Teon Banek 26d23959d3 Serialize C++ part of query folder via SLK
Reviewers: mtomic, mferencevic, llugovic

Reviewed By: mferencevic

Subscribers: pullbot

Differential Revision: https://phabricator.memgraph.io/D1761
2018-12-10 14:29:28 +01:00

412 lines
13 KiB
C++

#include "query/serialization.hpp"
#include "distributed/data_manager.hpp"
#include "query/frontend/ast/ast_serialization.hpp"
namespace query {
void SaveCapnpTypedValue(const TypedValue &value,
capnp::TypedValue::Builder *builder,
storage::SendVersions versions, int worker_id) {
switch (value.type()) {
case TypedValue::Type::Null:
builder->setNullType();
return;
case TypedValue::Type::Bool:
builder->setBool(value.Value<bool>());
return;
case TypedValue::Type::Int:
builder->setInteger(value.Value<int64_t>());
return;
case TypedValue::Type::Double:
builder->setDouble(value.Value<double>());
return;
case TypedValue::Type::String:
builder->setString(value.Value<std::string>());
return;
case TypedValue::Type::List: {
const auto &values = value.Value<std::vector<TypedValue>>();
auto list_builder = builder->initList(values.size());
for (size_t i = 0; i < values.size(); ++i) {
auto value_builder = list_builder[i];
SaveCapnpTypedValue(values[i], &value_builder, versions, worker_id);
}
return;
}
case TypedValue::Type::Map: {
const auto &map = value.Value<std::map<std::string, TypedValue>>();
auto map_builder = builder->initMap(map.size());
size_t i = 0;
for (const auto &kv : map) {
auto kv_builder = map_builder[i];
kv_builder.setKey(kv.first);
auto value_builder = kv_builder.initValue();
SaveCapnpTypedValue(kv.second, &value_builder, versions, worker_id);
++i;
}
return;
}
case TypedValue::Type::Vertex: {
auto vertex_builder = builder->initVertex();
storage::SaveVertexAccessor(value.ValueVertex(), &vertex_builder,
versions, worker_id);
return;
}
case TypedValue::Type::Edge: {
auto edge_builder = builder->initEdge();
storage::SaveEdgeAccessor(value.ValueEdge(), &edge_builder, versions,
worker_id);
return;
}
case TypedValue::Type::Path: {
auto path_builder = builder->initPath();
const auto &path = value.ValuePath();
auto vertices_builder = path_builder.initVertices(path.vertices().size());
for (size_t i = 0; i < path.vertices().size(); ++i) {
auto vertex_builder = vertices_builder[i];
storage::SaveVertexAccessor(path.vertices()[i], &vertex_builder,
versions, worker_id);
}
auto edges_builder = path_builder.initEdges(path.edges().size());
for (size_t i = 0; i < path.edges().size(); ++i) {
auto edge_builder = edges_builder[i];
storage::SaveEdgeAccessor(path.edges()[i], &edge_builder, versions,
worker_id);
}
return;
}
}
}
void LoadCapnpTypedValue(const capnp::TypedValue::Reader &reader,
TypedValue *value, database::GraphDbAccessor *dba,
distributed::DataManager *data_manager) {
switch (reader.which()) {
case capnp::TypedValue::NULL_TYPE:
*value = TypedValue::Null;
return;
case capnp::TypedValue::BOOL:
*value = reader.getBool();
return;
case capnp::TypedValue::INTEGER:
*value = reader.getInteger();
return;
case capnp::TypedValue::DOUBLE:
*value = reader.getDouble();
return;
case capnp::TypedValue::STRING:
*value = reader.getString().cStr();
return;
case capnp::TypedValue::LIST: {
std::vector<TypedValue> list;
list.reserve(reader.getList().size());
for (const auto &value_reader : reader.getList()) {
list.emplace_back();
LoadCapnpTypedValue(value_reader, &list.back(), dba, data_manager);
}
*value = list;
return;
}
case capnp::TypedValue::MAP: {
std::map<std::string, TypedValue> map;
for (const auto &kv_reader : reader.getMap()) {
auto key = kv_reader.getKey().cStr();
LoadCapnpTypedValue(kv_reader.getValue(), &map[key], dba, data_manager);
}
*value = map;
return;
}
case capnp::TypedValue::VERTEX:
*value =
storage::LoadVertexAccessor(reader.getVertex(), dba, data_manager);
return;
case capnp::TypedValue::EDGE:
*value = storage::LoadEdgeAccessor(reader.getEdge(), dba, data_manager);
return;
case capnp::TypedValue::PATH: {
auto vertices_reader = reader.getPath().getVertices();
auto edges_reader = reader.getPath().getEdges();
query::Path path(
storage::LoadVertexAccessor(vertices_reader[0], dba, data_manager));
for (size_t i = 0; i < edges_reader.size(); ++i) {
path.Expand(
storage::LoadEdgeAccessor(edges_reader[i], dba, data_manager));
path.Expand(storage::LoadVertexAccessor(vertices_reader[i + 1], dba,
data_manager));
}
*value = path;
return;
}
}
}
void SaveEvaluationContext(const EvaluationContext &ctx,
capnp::EvaluationContext::Builder *builder) {
builder->setTimestamp(ctx.timestamp);
auto params_builder =
builder->initParams().initEntries(ctx.parameters.size());
size_t i = 0;
for (auto &entry : ctx.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;
}
}
void LoadEvaluationContext(const capnp::EvaluationContext::Reader &reader,
EvaluationContext *ctx) {
ctx->timestamp = reader.getTimestamp();
for (const auto &entry_reader : reader.getParams().getEntries()) {
PropertyValue value;
storage::LoadCapnpPropertyValue(entry_reader.getValue(), &value);
ctx->parameters.Add(entry_reader.getKey().getValue(), value);
}
}
void Save(const TypedValueVectorCompare &comparator,
capnp::TypedValueVectorCompare::Builder *builder) {
auto ordering_builder = builder->initOrdering(comparator.ordering().size());
for (size_t i = 0; i < comparator.ordering().size(); ++i) {
ordering_builder.set(i, comparator.ordering()[i] == Ordering::ASC
? capnp::Ordering::ASC
: capnp::Ordering::DESC);
}
}
void Load(TypedValueVectorCompare *comparator,
const capnp::TypedValueVectorCompare::Reader &reader) {
std::vector<Ordering> ordering;
ordering.reserve(reader.getOrdering().size());
for (auto ordering_reader : reader.getOrdering()) {
ordering.push_back(ordering_reader == capnp::Ordering::ASC
? Ordering::ASC
: Ordering::DESC);
}
comparator->ordering_ = ordering;
}
} // namespace query
namespace slk {
void Save(const query::TypedValue &value, slk::Builder *builder,
storage::SendVersions versions, int16_t worker_id) {
switch (value.type()) {
case query::TypedValue::Type::Null:
slk::Save(static_cast<uint8_t>(0), builder);
return;
case query::TypedValue::Type::Bool:
slk::Save(static_cast<uint8_t>(1), builder);
slk::Save(value.Value<bool>(), builder);
return;
case query::TypedValue::Type::Int:
slk::Save(static_cast<uint8_t>(2), builder);
slk::Save(value.Value<int64_t>(), builder);
return;
case query::TypedValue::Type::Double:
slk::Save(static_cast<uint8_t>(3), builder);
slk::Save(value.Value<double>(), builder);
return;
case query::TypedValue::Type::String:
slk::Save(static_cast<uint8_t>(4), builder);
slk::Save(value.Value<std::string>(), builder);
return;
case query::TypedValue::Type::List: {
slk::Save(static_cast<uint8_t>(5), builder);
const auto &values = value.Value<std::vector<query::TypedValue>>();
size_t size = values.size();
slk::Save(size, builder);
for (const auto &v : values) {
slk::Save(v, builder, versions, worker_id);
}
return;
}
case query::TypedValue::Type::Map: {
slk::Save(static_cast<uint8_t>(6), builder);
const auto &map = value.Value<std::map<std::string, query::TypedValue>>();
size_t size = map.size();
slk::Save(size, builder);
for (const auto &kv : map) {
slk::Save(kv.first, builder);
slk::Save(kv.second, builder, versions, worker_id);
}
return;
}
case query::TypedValue::Type::Vertex: {
slk::Save(static_cast<uint8_t>(7), builder);
slk::Save(value.ValueVertex(), builder, versions, worker_id);
return;
}
case query::TypedValue::Type::Edge: {
slk::Save(static_cast<uint8_t>(8), builder);
slk::Save(value.ValueEdge(), builder, versions, worker_id);
return;
}
case query::TypedValue::Type::Path: {
slk::Save(static_cast<uint8_t>(9), builder);
const auto &path = value.ValuePath();
size_t v_size = path.vertices().size();
slk::Save(v_size, builder);
for (const auto &v : path.vertices()) {
slk::Save(v, builder, versions, worker_id);
}
size_t e_size = path.edges().size();
slk::Save(e_size, builder);
for (const auto &e : path.edges()) {
slk::Save(e, builder, versions, worker_id);
}
return;
}
}
}
void Load(query::TypedValue *value, slk::Reader *reader,
database::GraphDbAccessor *dba,
distributed::DataManager *data_manager) {
uint8_t type;
slk::Load(&type, reader);
switch (type) {
case static_cast<uint8_t>(0):
*value = query::TypedValue::Null;
return;
case static_cast<uint8_t>(1): {
bool v;
slk::Load(&v, reader);
*value = v;
return;
}
case static_cast<uint8_t>(2): {
int64_t v;
slk::Load(&v, reader);
*value = v;
return;
}
case static_cast<uint8_t>(3): {
double v;
slk::Load(&v, reader);
*value = v;
return;
}
case static_cast<uint8_t>(4): {
std::string v;
slk::Load(&v, reader);
*value = std::move(v);
return;
}
case static_cast<uint8_t>(5): {
size_t size;
slk::Load(&size, reader);
std::vector<query::TypedValue> list;
list.resize(size);
for (size_t i = 0; i < size; ++i) {
slk::Load(&list[i], reader, dba, data_manager);
}
*value = std::move(list);
return;
}
case static_cast<uint8_t>(6): {
size_t size;
slk::Load(&size, reader);
std::map<std::string, query::TypedValue> map;
for (size_t i = 0; i < size; ++i) {
std::string key;
slk::Load(&key, reader);
slk::Load(&map[key], reader, dba, data_manager);
}
*value = std::move(map);
return;
}
case static_cast<uint8_t>(7):
*value = slk::LoadVertexAccessor(reader, dba, data_manager);
return;
case static_cast<uint8_t>(8):
*value = slk::LoadEdgeAccessor(reader, dba, data_manager);
return;
case static_cast<uint8_t>(9): {
size_t v_size;
slk::Load(&v_size, reader);
std::vector<VertexAccessor> vertices;
vertices.reserve(v_size);
for (size_t i = 0; i < v_size; ++i) {
vertices.push_back(slk::LoadVertexAccessor(reader, dba, data_manager));
}
size_t e_size;
slk::Load(&e_size, reader);
std::vector<EdgeAccessor> edges;
edges.reserve(e_size);
for (size_t i = 0; i < e_size; ++i) {
edges.push_back(slk::LoadEdgeAccessor(reader, dba, data_manager));
}
query::Path path(vertices[0]);
path.vertices() = std::move(vertices);
path.edges() = std::move(edges);
*value = std::move(path);
return;
}
default:
throw slk::SlkDecodeException("Trying to load unknown TypedValue!");
}
}
void Save(const query::EvaluationContext &ctx, slk::Builder *builder) {
slk::Save(ctx.timestamp, builder);
slk::Save(ctx.parameters.size(), builder);
for (auto &entry : ctx.parameters) {
slk::Save(entry, builder);
}
}
void Load(query::EvaluationContext *ctx, slk::Reader *reader) {
slk::Load(&ctx->timestamp, reader);
size_t size = 0;
slk::Load(&size, reader);
for (size_t i = 0; i < size; ++i) {
std::pair<int, PropertyValue> entry;
slk::Load(&entry, reader);
ctx->parameters.Add(entry.first, entry.second);
}
}
void Save(const query::TypedValueVectorCompare &comparator,
slk::Builder *builder) {
slk::Save(comparator.ordering_, builder);
}
void Load(query::TypedValueVectorCompare *comparator, slk::Reader *reader) {
slk::Load(&comparator->ordering_, reader);
}
void Save(const query::GraphView &graph_view, slk::Builder *builder) {
uint8_t enum_value;
switch (graph_view) {
case query::GraphView::OLD:
enum_value = 0;
break;
case query::GraphView::NEW:
enum_value = 1;
break;
}
slk::Save(enum_value, builder);
}
void Load(query::GraphView *graph_view, slk::Reader *reader) {
uint8_t enum_value;
slk::Load(&enum_value, reader);
switch (enum_value) {
case static_cast<uint8_t>(0):
*graph_view = query::GraphView::OLD;
break;
case static_cast<uint8_t>(1):
*graph_view = query::GraphView::NEW;
break;
default:
throw slk::SlkDecodeException("Trying to load unknown enum value!");
}
}
} // namespace slk