Delete import and serialisation

Reviewers: buda

Reviewed By: buda

Subscribers: pullbot

Differential Revision: https://phabricator.memgraph.io/D294
This commit is contained in:
Mislav Bradac 2017-04-18 18:31:32 +02:00
parent 5434e79ea6
commit d42d519956
20 changed files with 0 additions and 1324 deletions

View File

@ -1,172 +0,0 @@
#pragma once
#include <algorithm>
#include <chrono>
#include <cstring>
#include <ctime>
#include <fstream>
#include <iostream>
#include <queue>
#include <regex>
#include <sstream>
#include <string>
#include <vector>
#include "import/element_skeleton.hpp"
#include "import/fillings/filler.hpp"
#include "logging/default.hpp"
#include "storage/model/properties/flags.hpp"
#include "storage/vertex_accessor.hpp"
#include "utils/option.hpp"
using namespace std;
static Option<VertexAccessor> empty_op_vacc;
// Base importer with common facilities.
class BaseImporter {
public:
BaseImporter(DbAccessor &db, Logger &&logger)
: db(db), logger(std::move(logger)) {}
char *cstr(string &str) { return &str[0]; }
bool split(string &str, char mark, vector<char *> &sub_str) {
return split(cstr(str), mark, sub_str);
}
// Occurances of mark are changed with '\0'. sub_str is filled with
// pointers to parts of str splited by mark in ascending order. Empty
// sub_str are included. Doesn't split inside quotations and
// open_bracket,closed_bracket.
// Returns true if it was succesfully parsed.
bool split(char *str, char mark, vector<char *> &sub_str) {
int head = 0;
bool in_text = false;
bool in_array = false;
for (int i = 0; str[i] != '\0'; i++) {
char &c = str[i];
// IN TEXT check
if (c == quotations_mark) {
in_text = !in_text;
if (in_text && head == i) {
c = '\0';
head = i + 1;
} else if (!in_text && !in_array) {
c = '\0';
}
continue;
} else if (in_text) {
continue;
}
// IN ARRAY check
if (c == open_bracket) {
if (in_array) {
logger.error("Nested arrays aren't supported.");
return false;
}
in_array = true;
continue;
}
if (in_array) {
if (c == closed_bracket) {
in_array = false;
}
continue;
}
// SPLIT CHECK
if (c == mark) {
c = '\0';
sub_str.push_back(&str[head]);
head = i + 1;
}
}
sub_str.push_back(&str[head]);
return true;
}
// Extracts parts of str while stripping parts of array chars and qutation
// marks. Parts are separated with delimiter.
void extract(char *str, const char delimiter, vector<char *> &sub_str) {
int head = 0;
bool in_text = false;
for (int i = 0; str[i] != '\0'; i++) {
char &c = str[i];
// IN TEXT check
if (c == quotations_mark) {
in_text = !in_text;
if (in_text) {
} else {
c = '\0';
sub_str.push_back(&str[head]);
head = i + 1;
}
head = i + 1;
continue;
} else if (in_text) {
continue;
}
// IN ARRAY check
if (c == open_bracket) {
head = i + 1;
continue;
} else if (c == closed_bracket) {
c = '\0';
if (i > head) {
sub_str.push_back(&str[head]);
}
head = i + 1;
continue;
}
// SPLIT CHECK
if (c == delimiter) {
c = '\0';
if (i > head) {
sub_str.push_back(&str[head]);
}
head = i + 1;
} else if (c == ' ' && i == head) {
head++;
}
}
sub_str.push_back(&str[head]);
}
// Optionaly return vertex with given import local id if it exists.
Option<VertexAccessor> const &get_vertex(size_t id) {
if (vertices.size() > id) {
return vertices[id];
} else {
cout << vertices.size() << " -> " << id << endl;
return empty_op_vacc;
}
}
public:
DbAccessor &db;
Logger logger;
// Varius marks and delimiters. They can be freely changed here and
// everything will work.
char parts_mark = ',';
char parts_array_mark = ',';
char type_mark = ':';
char quotations_mark = '"';
char open_bracket = '[';
char closed_bracket = ']';
protected:
// All created vertices which have import local id.
vector<Option<VertexAccessor>> vertices;
};

View File

@ -1,400 +0,0 @@
#pragma once
#include <algorithm>
#include <chrono>
#include <cstring>
#include <ctime>
#include <fstream>
#include <iostream>
#include <queue>
#include <regex>
#include <sstream>
#include <string>
#include <vector>
#include "import/base_import.hpp"
#include "import/element_skeleton.hpp"
#include "import/fillings/array.hpp"
#include "import/fillings/bool.hpp"
#include "import/fillings/double.hpp"
#include "import/fillings/filler.hpp"
#include "import/fillings/float.hpp"
#include "import/fillings/from.hpp"
#include "import/fillings/id.hpp"
#include "import/fillings/int32.hpp"
#include "import/fillings/int64.hpp"
#include "import/fillings/label.hpp"
#include "import/fillings/skip.hpp"
#include "import/fillings/string.hpp"
#include "import/fillings/to.hpp"
#include "import/fillings/type.hpp"
#include "storage/model/properties/all.hpp"
#include "storage/model/properties/flags.hpp"
#include "storage/vertex_accessor.hpp"
#include "utils/assert.hpp"
#include "utils/command_line/arguments.hpp"
#include "utils/option.hpp"
using namespace std;
constexpr char const *_string = "string";
// Will change all int32 into int64, and all float into double from csv into
// database. Uplifting will occure even in arrays.
constexpr const bool UPLIFT_PRIMITIVES = true;
bool equal_str(const char *a, const char *b) { return strcasecmp(a, b) == 0; }
// CSV importer for importing multiple files regarding same graph.
// CSV format of file should be following:
// header
// line of data
// line of data
// ...
//
// Where header should be composed of parts splited by parts_mark. Number of
// parts should be same as number of parts in every line of data. Parts should
// be of format name:type where name is alfanumeric identifyer of data in thath
// column and type should be one of: id, from, to, label, type, bool, int, long,
// float, double, string, bool[], int[], long[], float[], double[], string[].
// If name is missing the column data wont be saved into the elements.
// if the type is missing the column will be interperted as type string. If
// neither name nor type are present column will be skipped.
class CSVImporter : public BaseImporter {
public:
CSVImporter(DbAccessor &db)
: BaseImporter(db, logging::log->logger("CSV_import")) {}
// Loads data from stream and returns number of loaded vertexes.
size_t import_vertices(std::fstream &file) {
return import<TypeGroupVertex>(file, create_vertex, true);
}
// Loads data from stream and returns number of loaded edges.
size_t import_edges(std::fstream &file) {
return import<TypeGroupEdge>(file, create_edge, false);
}
private:
// Loads data from file and returns number of loaded name.
// TG - TypeGroup
// F - function which will create element from filled element skelleton.
template <class TG, class F>
size_t import(std::fstream &file, F f, bool vertex) {
string line;
vector<char *> sub_str;
vector<unique_ptr<Filler>> fillers;
vector<char *> tmp;
// HEADERS
if (!getline(file, line)) {
logger.error("No lines");
return 0;
}
if (!split(line, parts_mark, sub_str)) {
logger.error("Illegal headers");
return 0;
}
for (auto p : sub_str) {
auto o = get_filler<TG>(p, tmp, vertex);
if (o.is_present()) {
fillers.push_back(o.take());
} else {
return 0;
}
}
sub_str.clear();
// LOAD DATA LINES
size_t count = 0;
size_t line_no = 1;
ElementSkeleton es(db);
while (std::getline(file, line)) {
sub_str.clear();
es.clear();
if (split(line, parts_mark, sub_str)) {
check_for_part_count(sub_str.size() - fillers.size(), line_no);
int n = min(sub_str.size(), fillers.size());
for (int i = 0; i < n; i++) {
auto er = fillers[i]->fill(es, sub_str[i]);
if (er.is_present()) {
logger.error("{} on line: {}", er.get(), line_no);
}
}
if (f(this, es, line_no)) {
count++;
}
}
line_no++;
}
return count;
}
static bool create_vertex(CSVImporter *im, ElementSkeleton &es,
size_t line_no) {
auto va = es.add_vertex();
auto id = es.element_id();
if (id.is_present()) {
if (im->vertices.size() <= id.get()) {
Option<VertexAccessor> empty = make_option<VertexAccessor>();
im->vertices.insert(im->vertices.end(),
id.get() - im->vertices.size() + 1, empty);
}
if (im->vertices[id.get()].is_present()) {
im->logger.error(
"Vertex on line: {} has same id with another "
"previously loaded vertex",
line_no);
return false;
} else {
im->vertices[id.get()] = make_option(std::move(va));
return true;
}
} else {
im->logger.warn(
"Missing import local vertex id for vertex on "
"line: {}",
line_no);
}
return true;
}
static bool create_edge(CSVImporter *im, ElementSkeleton &es,
size_t line_no) {
auto o = es.add_edge();
if (!o.is_present()) {
return true;
} else {
im->logger.error("{} on line: {}", o.get(), line_no);
return false;
}
}
template <class TG>
typename PropertyFamily<TG>::PropertyType::PropertyFamilyKey property_key(
const char *name, Flags type) {
debug_assert(false, "Fail.");
}
// Returns filler for name:type in header_part. None if error occured.
template <class TG>
Option<unique_ptr<Filler>> get_filler(char *header_part,
vector<char *> &tmp_vec, bool vertex) {
tmp_vec.clear();
split(header_part, type_mark, tmp_vec);
const char *name = tmp_vec[0];
const char *type = tmp_vec[1];
if (tmp_vec.size() > 2) {
logger.error("To much sub parts in header part");
return make_option<unique_ptr<Filler>>();
} else if (tmp_vec.size() < 2) {
if (tmp_vec.size() == 1) {
logger.warn(
"Column: {} doesn't have specified type so string "
"type will be used",
tmp_vec[0]);
name = tmp_vec[0];
type = _string;
} else {
logger.warn("Empty colum definition, skiping column.");
std::unique_ptr<Filler> f(new SkipFiller());
return make_option(std::move(f));
}
} else {
name = tmp_vec[0];
type = tmp_vec[1];
}
// Create adequat filler
if (equal_str(type, "id")) {
std::unique_ptr<Filler> f(
name[0] == '\0' ? new IdFiller<TG>()
: new IdFiller<TG>(make_option(
property_key<TG>(name, Flags::Int64))));
return make_option(std::move(f));
} else if (equal_str(type, "start_id") || equal_str(type, "from_id") ||
equal_str(type, "from") || equal_str(type, "source")) {
std::unique_ptr<Filler> f(new FromFiller(*this));
return make_option(std::move(f));
} else if (equal_str(type, "label")) {
std::unique_ptr<Filler> f(new LabelFiller(*this));
return make_option(std::move(f));
} else if (equal_str(type, "end_id") || equal_str(type, "to_id") ||
equal_str(type, "to") || equal_str(type, "target")) {
std::unique_ptr<Filler> f(new ToFiller(*this));
return make_option(std::move(f));
} else if (equal_str(type, "type")) {
std::unique_ptr<Filler> f(new TypeFiller(*this));
return make_option(std::move(f));
} else if (name[0] == '\0') { // OTHER FILLERS REQUIRE NAME
logger.warn("Unnamed column of type: {} will be skipped.", type);
std::unique_ptr<Filler> f(new SkipFiller());
return make_option(std::move(f));
// *********************** PROPERTIES
} else if (equal_str(type, "bool")) {
std::unique_ptr<Filler> f(
new BoolFiller<TG>(property_key<TG>(name, Flags::Bool)));
return make_option(std::move(f));
} else if (equal_str(type, "double") ||
(UPLIFT_PRIMITIVES && equal_str(type, "float"))) {
std::unique_ptr<Filler> f(
new DoubleFiller<TG>(property_key<TG>(name, Flags::Double)));
return make_option(std::move(f));
} else if (equal_str(type, "float")) {
std::unique_ptr<Filler> f(
new FloatFiller<TG>(property_key<TG>(name, Flags::Float)));
return make_option(std::move(f));
} else if (equal_str(type, "long") ||
(UPLIFT_PRIMITIVES && equal_str(type, "int"))) {
std::unique_ptr<Filler> f(
new Int64Filler<TG>(property_key<TG>(name, Flags::Int64)));
return make_option(std::move(f));
} else if (equal_str(type, "int")) {
std::unique_ptr<Filler> f(
new Int32Filler<TG>(property_key<TG>(name, Flags::Int32)));
return make_option(std::move(f));
} else if (equal_str(type, "string")) {
std::unique_ptr<Filler> f(
new StringFiller<TG>(property_key<TG>(name, Flags::String)));
return make_option(std::move(f));
} else if (equal_str(type, "bool[]")) {
std::unique_ptr<Filler> f(make_array_filler<TG, bool, ArrayBool>(
*this, property_key<TG>(name, Flags::ArrayBool), to_bool));
return make_option(std::move(f));
} else if (equal_str(type, "double[]") ||
(UPLIFT_PRIMITIVES && equal_str(type, "float[]"))) {
std::unique_ptr<Filler> f(make_array_filler<TG, double, ArrayDouble>(
*this, property_key<TG>(name, Flags::ArrayDouble), to_double));
return make_option(std::move(f));
} else if (equal_str(type, "float[]")) {
std::unique_ptr<Filler> f(make_array_filler<TG, float, ArrayFloat>(
*this, property_key<TG>(name, Flags::ArrayFloat), to_float));
return make_option(std::move(f));
} else if (equal_str(type, "long[]") ||
(UPLIFT_PRIMITIVES && equal_str(type, "int[]"))) {
std::unique_ptr<Filler> f(make_array_filler<TG, int64_t, ArrayInt64>(
*this, property_key<TG>(name, Flags::ArrayInt64), to_int64));
return make_option(std::move(f));
} else if (equal_str(type, "int[]")) {
std::unique_ptr<Filler> f(make_array_filler<TG, int32_t, ArrayInt32>(
*this, property_key<TG>(name, Flags::ArrayInt32), to_int32));
return make_option(std::move(f));
} else if (equal_str(type, "string[]")) {
std::unique_ptr<Filler> f(make_array_filler<TG, std::string, ArrayString>(
*this, property_key<TG>(name, Flags::ArrayString), to_string));
return make_option(std::move(f));
} else {
logger.error("Unknown type: {}", type);
return make_option<unique_ptr<Filler>>();
}
}
void check_for_part_count(long diff, long line_no) {
if (diff != 0) {
if (diff < 0) {
logger.warn(
"Line no: {} has less parts then specified in "
"header. Missing: {} parts",
line_no, diff);
} else {
logger.warn(
"Line no: {} has more parts then specified in "
"header. Extra: {} parts",
line_no, diff);
}
}
}
};
template <>
PropertyFamily<TypeGroupVertex>::PropertyType::PropertyFamilyKey
CSVImporter::property_key<TypeGroupVertex>(const char *name, Flags type) {
return db.vertex_property_key(name, Type(type));
}
template <>
PropertyFamily<TypeGroupEdge>::PropertyType::PropertyFamilyKey
CSVImporter::property_key<TypeGroupEdge>(const char *name, Flags type) {
return db.edge_property_key(name, Type(type));
}
// Imports all -v "vertex_file_path.csv" vertices and -e "edge_file_path.csv"
// edges from specified files. Also defines arguments -d, -ad.
// -d delimiter => sets delimiter for parsing .csv files. Default is ,
// -ad delimiter => sets delimiter for parsing arrays in .csv. Default is
// Returns (no loaded vertices,no loaded edges)
std::pair<size_t, size_t> import_csv_from_arguments(
Db &db, std::vector<std::string> &para) {
DbAccessor t(db);
CSVImporter imp(t);
imp.parts_mark = get_argument(para, "-d", ",")[0];
imp.parts_array_mark = get_argument(para, "-ad", ",")[0];
// IMPORT VERTICES
size_t l_v = 0;
auto o = take_argument(para, "-v");
while (o.is_present()) {
std::fstream file(o.get());
imp.logger.info("Importing vertices from file: {}", o.get());
auto n = imp.import_vertices(file);
l_v = +n;
imp.logger.info("Loaded: {} vertices from {}", n, o.get());
o = take_argument(para, "-v");
}
// IMPORT EDGES
size_t l_e = 0;
o = take_argument(para, "-e");
while (o.is_present()) {
std::fstream file(o.get());
imp.logger.info("Importing edges from file: {}", o.get());
auto n = imp.import_edges(file);
l_e = +n;
imp.logger.info("Loaded: {} edges from {}", n, o.get());
o = take_argument(para, "-e");
}
t.commit();
return std::make_pair(l_v, l_e);
}

View File

@ -1,100 +0,0 @@
#pragma once
#include "database/db_accessor.hpp"
#include "storage/model/property_value.hpp"
#include "storage/model/property_value_store.hpp"
#include "storage/vertex_accessor.hpp"
#include "utils/assert.hpp"
// Holder for element data which he can then insert as a vertex or edge into the
// database depending on the available data and called add_* method.
class ElementSkeleton {
public:
ElementSkeleton(DbAccessor &db) : db(db){};
void add_property(StoredProperty<TypeGroupVertex> &&prop) {
properties_v.push_back(std::move(prop));
}
void add_property(StoredProperty<TypeGroupEdge> &&prop) {
properties_e.push_back(std::move(prop));
}
void set_element_id(size_t id) { el_id = make_option<size_t>(std::move(id)); }
void add_label(Label const &label) { labels.push_back(&label); }
void set_type(EdgeType const &type) { this->type = make_option(&type); }
void set_from(VertexAccessor &&va) {
from_va = make_option<VertexAccessor>(std::move(va));
}
void set_to(VertexAccessor &&va) {
to_va = make_option<VertexAccessor>(std::move(va));
}
VertexAccessor add_vertex() {
debug_assert(properties_e.empty(), "Properties aren't empty.");
auto va = db.vertex_insert();
for (auto l : labels) {
// std::cout << *l << std::endl;
va.add_label(*l);
}
for (auto prop : properties_v) {
va.set(std::move(prop));
}
return va;
}
// Return error msg if unsuccessful
Option<std::string> add_edge() {
if (!from_va.is_present()) {
return make_option(std::string("From field must be set"));
}
if (!to_va.is_present()) {
return make_option(std::string("To field must be set"));
}
if (!type.is_present()) {
return make_option(std::string("Type field must be set"));
}
debug_assert(properties_v.empty(), "Properties aren't empty.");
auto ve = db.edge_insert(from_va.get(), to_va.get());
ve.edge_type(*type.get());
for (auto prop : properties_e) {
ve.set(std::move(prop));
}
return make_option<std::string>();
}
void clear() {
el_id = make_option<size_t>();
to_va = make_option<VertexAccessor>();
from_va = make_option<VertexAccessor>();
type = make_option<EdgeType const *>();
labels.clear();
properties_v.clear();
properties_e.clear();
}
// Returns import local id.
Option<size_t> element_id() { return el_id; }
private:
DbAccessor &db;
Option<size_t> el_id;
Option<VertexAccessor> to_va;
Option<VertexAccessor> from_va;
Option<EdgeType const *> type;
std::vector<Label const *> labels;
PropertyValueStore properties_e;
PropertyValueStore properties_v;
};

View File

@ -1,29 +0,0 @@
#pragma once
#include "import/fillings/common.hpp"
#include "import/fillings/filler.hpp"
#include "storage/model/properties/all.hpp"
#include "storage/model/properties/flags.hpp"
#include "storage/model/properties/property_family.hpp"
// Parses boolean.
// TG - Type group
template <class TG>
class BoolFiller : public Filler {
public:
BoolFiller(typename PropertyFamily<TG>::PropertyType::PropertyFamilyKey key)
: key(key) {}
// Fills skeleton with data from str. Returns error description if
// error occurs.
Option<std::string> fill(ElementSkeleton &data, char *str) final {
if (str[0] != '\0') {
data.add_property(StoredProperty<TG>(Bool(to_bool(str)), key));
}
return make_option<std::string>();
}
private:
typename PropertyFamily<TG>::PropertyType::PropertyFamilyKey key;
};

View File

@ -1,24 +0,0 @@
#pragma once
#include <strings.h>
#include <cstdlib>
#include <cstdlib>
#include <iostream>
#include <string>
#include "storage/model/properties/all.hpp"
bool string2bool(const char *v) {
return strcasecmp(v, "true") == 0 || atoi(v) != 0;
}
bool to_bool(const char *str) { return string2bool(str); }
float to_float(const char *str) { return stof(str); }
double to_double(const char *str) { return atof(str); }
int32_t to_int32(const char *str) { return atoi(str); }
int64_t to_int64(const char *str) { return atoll(str); }
std::string to_string(const char *str) { return std::string(str); }

View File

@ -1,13 +0,0 @@
#pragma once
#include "import/element_skeleton.hpp"
#include "utils/option.hpp"
// Common class for varius classes which accept one part from data line in
// import, parses it and adds it into element skelleton.
class Filler {
public:
// Fills skeleton with data from str. Returns error description if
// error occurs.
virtual Option<std::string> fill(ElementSkeleton &data, char *str) = 0;
};

View File

@ -1,28 +0,0 @@
#pragma once
#include "import/fillings/common.hpp"
#include "import/fillings/filler.hpp"
#include "storage/model/properties/all.hpp"
#include "storage/model/properties/flags.hpp"
#include "storage/model/properties/property_family.hpp"
// Parses float.
// TG - Type group
template <class TG>
class FloatFiller : public Filler {
public:
FloatFiller(typename PropertyFamily<TG>::PropertyType::PropertyFamilyKey key)
: key(key) {}
// Fills skeleton with data from str. Returns error description if
// error occurs.
Option<std::string> fill(ElementSkeleton &data, char *str) final {
if (str[0] != '\0') {
data.add_property(StoredProperty<TG>(Float(to_float(str)), key));
}
return make_option<std::string>();
}
private:
typename PropertyFamily<TG>::PropertyType::PropertyFamilyKey key;
};

View File

@ -1,34 +0,0 @@
#pragma once
#include "import/fillings/common.hpp"
#include "import/fillings/filler.hpp"
#include "storage/model/properties/all.hpp"
#include "storage/model/properties/flags.hpp"
#include "storage/model/properties/property_family.hpp"
// Parses from id of vertex for edge.
class FromFiller : public Filler {
public:
FromFiller(BaseImporter &db) : bim(db) {}
// Fills skeleton with data from str. Returns error description if
// error occurs.
Option<std::string> fill(ElementSkeleton &data, char *str) final {
if (str[0] != '\0') {
auto id = atol(str);
Option<VertexAccessor> const &oav = bim.get_vertex(id);
if (oav.is_present()) {
data.set_from(VertexAccessor(oav.get()));
return make_option<std::string>();
} else {
return make_option(
std::string("Unknown vertex in from field with id: ") + str);
}
} else {
return make_option(std::string("From field must be spceified"));
}
}
private:
BaseImporter &bim;
};

View File

@ -1,38 +0,0 @@
#pragma once
#include "import/fillings/filler.hpp"
#include "utils/assert.hpp"
// Parses import local Id.
// TG - Type group
template <class TG>
class IdFiller : public Filler {
public:
IdFiller()
: key(make_option<
typename PropertyFamily<TG>::PropertyType::PropertyFamilyKey>()) {}
IdFiller(
Option<typename PropertyFamily<TG>::PropertyType::PropertyFamilyKey> key)
: key(key) {
debug_assert(
!key.is_present() || key.get().prop_type() == Type(Flags::Int64),
"Invalid key property type.");
}
// Fills skeleton with data from str. Returns error description if
// error occurs.
Option<std::string> fill(ElementSkeleton &data, char *str) final {
if (str[0] != '\0') {
data.set_element_id(atol(str));
if (key.is_present()) {
data.add_property(StoredProperty<TG>(Int64(to_int64(str)), key.get()));
}
}
return make_option<std::string>();
}
private:
Option<typename PropertyFamily<TG>::PropertyType::PropertyFamilyKey> key;
};

View File

@ -1,28 +0,0 @@
#pragma once
#include "import/fillings/common.hpp"
#include "import/fillings/filler.hpp"
#include "storage/model/properties/all.hpp"
#include "storage/model/properties/flags.hpp"
#include "storage/model/properties/property_family.hpp"
// Parses int64.
// TG - Type group
template <class TG>
class Int64Filler : public Filler {
public:
Int64Filler(typename PropertyFamily<TG>::PropertyType::PropertyFamilyKey key)
: key(key) {}
// Fills skeleton with data from str. Returns error description if
// error occurs.
Option<std::string> fill(ElementSkeleton &data, char *str) final {
if (str[0] != '\0') {
data.add_property(StoredProperty<TG>(Int64(to_int64(str)), key));
}
return make_option<std::string>();
}
private:
typename PropertyFamily<TG>::PropertyType::PropertyFamilyKey key;
};

View File

@ -1,27 +0,0 @@
#pragma once
#include "database/db_accessor.hpp"
#include "import/fillings/filler.hpp"
// Parses array of labels.
class LabelFiller : public Filler {
public:
LabelFiller(BaseImporter &db) : bim(db) {}
// Fills skeleton with data from str. Returns error description if
// error occurs.
Option<std::string> fill(ElementSkeleton &data, char *str) final {
sub_str.clear();
bim.extract(str, bim.parts_array_mark, sub_str);
for (auto s : sub_str) {
if (s[0] != '\0') {
data.add_label(bim.db.label_find_or_create(s));
}
}
return make_option<std::string>();
}
private:
BaseImporter &bim;
vector<char *> sub_str;
};

View File

@ -1,17 +0,0 @@
#pragma once
#include "import/fillings/common.hpp"
#include "import/fillings/filler.hpp"
#include "storage/model/properties/all.hpp"
#include "storage/model/properties/flags.hpp"
#include "storage/model/properties/property_family.hpp"
// Skips column.
class SkipFiller : public Filler {
public:
// Fills skeleton with data from str. Returns error description if
// error occurs.
Option<std::string> fill(ElementSkeleton &data, char *str) final {
return make_option<std::string>();
}
};

View File

@ -1,28 +0,0 @@
#pragma once
#include "import/fillings/common.hpp"
#include "import/fillings/filler.hpp"
#include "storage/model/properties/all.hpp"
#include "storage/model/properties/flags.hpp"
#include "storage/model/properties/property_family.hpp"
// Parses string.
// TG - Type group
template <class TG>
class StringFiller : public Filler {
public:
StringFiller(typename PropertyFamily<TG>::PropertyType::PropertyFamilyKey key)
: key(key) {}
// Fills skeleton with data from str. Returns error description if
// error occurs.
Option<std::string> fill(ElementSkeleton &data, char *str) final {
if (str[0] != '\0') {
data.add_property(StoredProperty<TG>(String(to_string(str)), key));
}
return make_option<std::string>();
}
private:
typename PropertyFamily<TG>::PropertyType::PropertyFamilyKey key;
};

View File

@ -1,34 +0,0 @@
#pragma once
#include "import/fillings/common.hpp"
#include "import/fillings/filler.hpp"
#include "storage/model/properties/all.hpp"
#include "storage/model/properties/flags.hpp"
#include "storage/model/properties/property_family.hpp"
// Parses to import local id of vertex for edge.
class ToFiller : public Filler {
public:
ToFiller(BaseImporter &db) : bim(db) {}
// Fills skeleton with data from str. Returns error description if
// error occurs.
Option<std::string> fill(ElementSkeleton &data, char *str) final {
if (str[0] != '\0') {
auto id = atol(str);
Option<VertexAccessor> const &oav = bim.get_vertex(id);
if (oav.is_present()) {
data.set_to(VertexAccessor(oav.get()));
return make_option<std::string>();
} else {
return make_option(std::string("Unknown vertex in to field with id: ") +
str);
}
} else {
return make_option(std::string("To field must be spceified"));
}
}
private:
BaseImporter &bim;
};

View File

@ -1,23 +0,0 @@
#pragma once
#include "database/db_accessor.hpp"
#include "import/fillings/filler.hpp"
// Parses type of edge.
class TypeFiller : public Filler {
public:
TypeFiller(BaseImporter &db) : bim(db) {}
// Fills skeleton with data from str. Returns error description if
// error occurs.
Option<std::string> fill(ElementSkeleton &data, char *str) final {
if (str[0] != '\0') {
data.set_type(bim.db.type_find_or_create(str));
}
return make_option<std::string>();
}
private:
BaseImporter &bim;
};

View File

@ -1,46 +0,0 @@
#pragma once
#include "utils/array_store.hpp"
#include "utils/void.hpp"
// Common menthods for translating Vertex/Edge representations from serialized
// form into database form.
// Implementor should override those methods which he needs, and ignore the
// rest.
// Caller is responisble to structure his calls as following:
//
//
// End goal would be to enforce these rules during compile time.
class GraphDecoder {
public:
// Starts reading vertex.
Id vertex_start();
// Returns number of stored labels.
size_t label_count();
// Wiil read label into given storage.
std::string const &label();
// Ends reading vertex
void vertex_end() {}
// Starts reading edge. Return from to ids of connected vertices.
std::pair<Id, Id> edge_start();
// Reads edge_type into given storage.
std::string const &edge_type();
// Ends reading edge.
void edge_end() {}
// Returns number of stored propertys.
size_t property_count();
// Reads property name into given storage.
std::string const &property_name();
// Reads property and calls T::handle for that property .
template <class T>
T property();
};

View File

@ -1,81 +0,0 @@
#pragma once
#include "utils/array_store.hpp"
#include "utils/void.hpp"
// Common menthods for translating Vertex/Edge representations in database to
// other format for extern usage.
// Implementor should override those methods which he needs, and ignore the
// rest.
// Caller is responisble to structure his calls as following:
// * start_vertex
// 1 label_count
// * label
// 1 property_count
// * property_name
// 1 handle
// 1 end_vertex
// or
// * start_edge
// 0-1 edge_type
// 1 property_count
// * property_name
// 1 handle
// 1 end_edge
//
// End goal would be to enforce these rules during compile time.
class GraphEncoder {
public:
// Starts writing vertex with given id.
void start_vertex(Id id) {}
// Number of following label calls.
void label_count(size_t n);
// Label of currently started vertex.
void label(std::string const &l) {}
// Ends writing vertex
void end_vertex() {}
// Starts writing edge from vertex to vertex
void start_edge(Id from, Id to) {}
// Type of currently started edge
void edge_type(std::string const &et) {}
// Ends writing edge
void end_edge() {}
// Number of following paired property_name,handle calls.
void property_count(size_t n);
// Property family name of next property for currently started element.
void property_name(std::string const &name) {}
void handle(const Void &v) {}
void handle(const bool &prop) {}
void handle(const float &prop) {}
void handle(const double &prop) {}
void handle(const int32_t &prop) {}
void handle(const int64_t &prop) {}
void handle(const std::string &value) {}
void handle(const ArrayStore<bool> &) {}
void handle(const ArrayStore<int32_t> &) {}
void handle(const ArrayStore<int64_t> &) {}
void handle(const ArrayStore<float> &) {}
void handle(const ArrayStore<double> &) {}
void handle(const ArrayStore<std::string> &) {}
};

View File

@ -1,107 +0,0 @@
#pragma once
#include "database/db_accessor.hpp"
#include "storage/edge_accessor.hpp"
#include "storage/edge_type/edge_type.hpp"
#include "storage/label/label.hpp"
#include "storage/vertex_accessor.hpp"
namespace serialization {
// Serializes Vertex to given writer which implements GraphEncoder.
template <class W>
void serialize_vertex(VertexAccessor const &v, W &writer) {
// Serialize vertex id
writer.start_vertex(v.id());
// Serialize labels
auto const &labels = v.labels();
writer.label_count(labels.size());
for (auto &label : labels) {
writer.label(label.get().str());
}
// Serialize propertys
auto const &propertys = v.properties();
writer.property_count(propertys.size());
for (auto &prop : propertys) {
writer.property_name(prop.key.family_name());
prop.accept_primitive(writer);
}
writer.end_vertex();
}
// Serializes Edge to given writer which implements GraphEncoder.
template <class W>
void serialize_edge(EdgeAccessor const &e, W &writer) {
// Serialize to and from vertices ids.
writer.start_edge(e.from().id(), e.to().id());
// Serialize type
writer.edge_type(e.edge_type().str());
// Serialize propertys
auto const &propertys = e.properties();
writer.property_count(propertys.size());
for (auto &prop : propertys) {
writer.property_name(prop.key.family_name());
prop.accept_primitive(writer);
}
writer.end_edge();
}
// Deserializes vertex from reader into database db. Returns Id which vertex had
// in the reader and VertexAccessor.
template <class D>
std::pair<Id, VertexAccessor> deserialize_vertex(DbAccessor &db, D &reader) {
auto v = db.vertex_insert();
auto old_id = reader.vertex_start();
// Deserialize labels
std::string s;
for (auto i = reader.label_count(); i > 0; i--) {
auto &label_key = db.label_find_or_create(reader.label().c_str());
v.add_label(label_key);
}
// Deserialize propertys
for (auto i = reader.property_count(); i > 0; i--) {
auto &family =
db.vertex_property_family_get(reader.property_name().c_str());
v.set(StoredProperty<TypeGroupVertex>(
family, reader.template property<Property>()));
}
reader.vertex_end();
return std::make_pair(old_id, v);
}
// Deserializes edge from reader into database db. Returns loaded EdgeAccessor.
// S - is the storage with at() method for accesing VertexAccessor under thers
// deserialization local id returnd from deserialize_vertex.
template <class D, class S>
EdgeAccessor deserialize_edge(DbAccessor &db, D &reader, S &store) {
auto ids = reader.edge_start();
// Deserialize from and to ids of vertices.
VertexAccessor &from = store.at(ids.first);
VertexAccessor &to = store.at(ids.second);
auto e = db.edge_insert(from, to);
// Deserialize type
auto &edge_type_key = db.type_find_or_create(reader.edge_type().c_str());
e.edge_type(edge_type_key);
// Deserialize properties
for (auto i = reader.property_count(); i > 0; i--) {
auto &family = db.edge_property_family_get(reader.property_name().c_str());
e.set(StoredProperty<TypeGroupEdge>(family,
reader.template property<Property>()));
}
reader.edge_end();
return e;
}
};

View File

@ -1,56 +0,0 @@
//
// Copyright 2017 Memgraph
// Created by Florijan Stamenkovic on 01.02.17.
//
#pragma once
#include <ostream>
#include "storage/property_value_store.hpp"
/**
* Writes all of the values from the given store in JSON format
* to the given output stream.
*
* @param store The store that should be serialized to JSON.
* @param ostream The stream to write to.
*/
void PropertyValuesToJson(const PropertyValueStore& store,
std::ostream& ostream = std::cout) {
bool first = true;
auto write_key =
[&ostream, &first](const PropertyValueStore::TKey& key) -> std::ostream& {
if (first) {
ostream << '{';
first = false;
} else
ostream << ',';
return ostream << '"' << key << "\":";
};
auto handler = [&ostream, &write_key](const PropertyValueStore::TKey& key,
const PropertyValue& value) {
switch (value.type_) {
case PropertyValue::Type::Null:
break;
case PropertyValue::Type::Bool:
write_key(key) << (value.Value<bool>() ? "true" : "false");
break;
case PropertyValue::Type::String:
write_key(key) << '"' << value.Value<std::string>() << '"';
break;
case PropertyValue::Type::Int:
write_key(key) << value.Value<int64_t>();
break;
case PropertyValue::Type::Float:
write_key(key) << value.Value<float>();
break;
}
};
auto finish = [&ostream]() { ostream << '}' << std::endl; };
store.Accept(handler, finish);
}

View File

@ -1,39 +0,0 @@
#pragma once
#include <memory>
#include "rapidjson/stringbuffer.h"
#include "rapidjson/writer.h"
#include "storage/model/properties/properties.hpp"
class RapidJsonStringWriter {
public:
// TODO: clear up naming
using sptr = std::shared_ptr<rapidjson::Writer<rapidjson::StringBuffer>>;
RapidJsonStringWriter(const sptr& writer) : writer(writer) {}
void handle(const std::string& key, Property& value, bool first) {
writer->String(key.c_str());
value.accept(*this);
}
void handle(Bool& b) { writer->String(b.value() ? "true" : "false"); }
void handle(String& s) { writer->String(s.value.c_str()); }
void handle(Int32& int32) {
writer->String(std::to_string(int32.value).c_str());
}
void handle(Int64& int64) {
writer->String(std::to_string(int64.value).c_str());
}
void handle(Float& f) { writer->String(std::to_string(f.value).c_str()); }
void handle(Double& d) { writer->String(std::to_string(d.value).c_str()); }
private:
sptr writer;
};