#include "glue/communication.hpp" #include <map> #include <string> #include <vector> #include "storage/v2/edge_accessor.hpp" #include "storage/v2/storage.hpp" #include "storage/v2/vertex_accessor.hpp" using communication::bolt::Value; namespace glue { query::TypedValue ToTypedValue(const Value &value) { switch (value.type()) { case Value::Type::Null: return query::TypedValue(); case Value::Type::Bool: return query::TypedValue(value.ValueBool()); case Value::Type::Int: return query::TypedValue(value.ValueInt()); case Value::Type::Double: return query::TypedValue(value.ValueDouble()); case Value::Type::String: return query::TypedValue(value.ValueString()); case Value::Type::List: { std::vector<query::TypedValue> list; list.reserve(value.ValueList().size()); for (const auto &v : value.ValueList()) list.push_back(ToTypedValue(v)); return query::TypedValue(std::move(list)); } case Value::Type::Map: { std::map<std::string, query::TypedValue> map; for (const auto &kv : value.ValueMap()) map.emplace(kv.first, ToTypedValue(kv.second)); return query::TypedValue(std::move(map)); } case Value::Type::Vertex: case Value::Type::Edge: case Value::Type::UnboundedEdge: case Value::Type::Path: throw communication::bolt::ValueException( "Unsupported conversion from Value to TypedValue"); } } storage::Result<communication::bolt::Vertex> ToBoltVertex( const query::VertexAccessor &vertex, const storage::Storage &db, storage::View view) { return ToBoltVertex(vertex.impl_, db, view); } storage::Result<communication::bolt::Edge> ToBoltEdge( const query::EdgeAccessor &edge, const storage::Storage &db, storage::View view) { return ToBoltEdge(edge.impl_, db, view); } storage::Result<Value> ToBoltValue(const query::TypedValue &value, const storage::Storage &db, storage::View view) { switch (value.type()) { case query::TypedValue::Type::Null: return Value(); case query::TypedValue::Type::Bool: return Value(value.ValueBool()); case query::TypedValue::Type::Int: return Value(value.ValueInt()); case query::TypedValue::Type::Double: return Value(value.ValueDouble()); case query::TypedValue::Type::String: return Value(std::string(value.ValueString())); case query::TypedValue::Type::List: { std::vector<Value> values; values.reserve(value.ValueList().size()); for (const auto &v : value.ValueList()) { auto maybe_value = ToBoltValue(v, db, view); if (maybe_value.HasError()) return maybe_value.GetError(); values.emplace_back(std::move(*maybe_value)); } return Value(std::move(values)); } case query::TypedValue::Type::Map: { std::map<std::string, Value> map; for (const auto &kv : value.ValueMap()) { auto maybe_value = ToBoltValue(kv.second, db, view); if (maybe_value.HasError()) return maybe_value.GetError(); map.emplace(kv.first, std::move(*maybe_value)); } return Value(std::move(map)); } case query::TypedValue::Type::Vertex: { auto maybe_vertex = ToBoltVertex(value.ValueVertex(), db, view); if (maybe_vertex.HasError()) return maybe_vertex.GetError(); return Value(std::move(*maybe_vertex)); } case query::TypedValue::Type::Edge: { auto maybe_edge = ToBoltEdge(value.ValueEdge(), db, view); if (maybe_edge.HasError()) return maybe_edge.GetError(); return Value(std::move(*maybe_edge)); } case query::TypedValue::Type::Path: { auto maybe_path = ToBoltPath(value.ValuePath(), db, view); if (maybe_path.HasError()) return maybe_path.GetError(); return Value(std::move(*maybe_path)); } } } storage::Result<communication::bolt::Vertex> ToBoltVertex( const storage::VertexAccessor &vertex, const storage::Storage &db, storage::View view) { auto id = communication::bolt::Id::FromUint(vertex.Gid().AsUint()); auto maybe_labels = vertex.Labels(view); if (maybe_labels.HasError()) return maybe_labels.GetError(); std::vector<std::string> labels; labels.reserve(maybe_labels->size()); for (const auto &label : *maybe_labels) { labels.push_back(db.LabelToName(label)); } auto maybe_properties = vertex.Properties(view); if (maybe_properties.HasError()) return maybe_properties.GetError(); std::map<std::string, Value> properties; for (const auto &prop : *maybe_properties) { properties[db.PropertyToName(prop.first)] = ToBoltValue(prop.second); } return communication::bolt::Vertex{id, labels, properties}; } storage::Result<communication::bolt::Edge> ToBoltEdge( const storage::EdgeAccessor &edge, const storage::Storage &db, storage::View view) { auto id = communication::bolt::Id::FromUint(edge.Gid().AsUint()); auto from = communication::bolt::Id::FromUint(edge.FromVertex().Gid().AsUint()); auto to = communication::bolt::Id::FromUint(edge.ToVertex().Gid().AsUint()); auto type = db.EdgeTypeToName(edge.EdgeType()); auto maybe_properties = edge.Properties(view); if (maybe_properties.HasError()) return maybe_properties.GetError(); std::map<std::string, Value> properties; for (const auto &prop : *maybe_properties) { properties[db.PropertyToName(prop.first)] = ToBoltValue(prop.second); } return communication::bolt::Edge{id, from, to, type, properties}; } storage::Result<communication::bolt::Path> ToBoltPath( const query::Path &path, const storage::Storage &db, storage::View view) { std::vector<communication::bolt::Vertex> vertices; vertices.reserve(path.vertices().size()); for (const auto &v : path.vertices()) { auto maybe_vertex = ToBoltVertex(v, db, view); if (maybe_vertex.HasError()) return maybe_vertex.GetError(); vertices.emplace_back(std::move(*maybe_vertex)); } std::vector<communication::bolt::Edge> edges; edges.reserve(path.edges().size()); for (const auto &e : path.edges()) { auto maybe_edge = ToBoltEdge(e, db, view); if (maybe_edge.HasError()) return maybe_edge.GetError(); edges.emplace_back(std::move(*maybe_edge)); } return communication::bolt::Path(vertices, edges); } storage::PropertyValue ToPropertyValue(const Value &value) { switch (value.type()) { case Value::Type::Null: return storage::PropertyValue(); case Value::Type::Bool: return storage::PropertyValue(value.ValueBool()); case Value::Type::Int: return storage::PropertyValue(value.ValueInt()); case Value::Type::Double: return storage::PropertyValue(value.ValueDouble()); case Value::Type::String: return storage::PropertyValue(value.ValueString()); case Value::Type::List: { std::vector<storage::PropertyValue> vec; vec.reserve(value.ValueList().size()); for (const auto &value : value.ValueList()) vec.emplace_back(ToPropertyValue(value)); return storage::PropertyValue(std::move(vec)); } case Value::Type::Map: { std::map<std::string, storage::PropertyValue> map; for (const auto &kv : value.ValueMap()) map.emplace(kv.first, ToPropertyValue(kv.second)); return storage::PropertyValue(std::move(map)); } case Value::Type::Vertex: case Value::Type::Edge: case Value::Type::UnboundedEdge: case Value::Type::Path: throw communication::bolt::ValueException( "Unsupported conversion from Value to PropertyValue"); } } Value ToBoltValue(const storage::PropertyValue &value) { switch (value.type()) { case storage::PropertyValue::Type::Null: return Value(); case storage::PropertyValue::Type::Bool: return Value(value.ValueBool()); case storage::PropertyValue::Type::Int: return Value(value.ValueInt()); break; case storage::PropertyValue::Type::Double: return Value(value.ValueDouble()); case storage::PropertyValue::Type::String: return Value(value.ValueString()); case storage::PropertyValue::Type::List: { const auto &values = value.ValueList(); std::vector<Value> vec; vec.reserve(values.size()); for (const auto &v : values) { vec.push_back(ToBoltValue(v)); } return Value(std::move(vec)); } case storage::PropertyValue::Type::Map: { const auto &map = value.ValueMap(); std::map<std::string, Value> dv_map; for (const auto &kv : map) { dv_map.emplace(kv.first, ToBoltValue(kv.second)); } return Value(std::move(dv_map)); } } } } // namespace glue