Deleted storage/model/properties, started refactoring
This commit is contained in:
parent
b329225322
commit
e508482ab9
@ -18,77 +18,76 @@ class Indexes;
|
||||
/**
|
||||
* Main class which represents Database concept in code.
|
||||
*/
|
||||
class Db
|
||||
{
|
||||
class Db {
|
||||
public:
|
||||
using sptr = std::shared_ptr<Db>;
|
||||
using sptr = std::shared_ptr<Db>;
|
||||
|
||||
/**
|
||||
* This constructor will create a database with the name "default"
|
||||
*
|
||||
* NOTE: explicit is here to prevent compiler from evaluating const char *
|
||||
* into a bool.
|
||||
*
|
||||
* @param import_snapshot will in constructor import latest snapshot
|
||||
* into the db.
|
||||
*/
|
||||
explicit Db(bool import_snapshot = true);
|
||||
/**
|
||||
* This constructor will create a database with the name "default"
|
||||
*
|
||||
* NOTE: explicit is here to prevent compiler from evaluating const char *
|
||||
* into a bool.
|
||||
*
|
||||
* @param import_snapshot will in constructor import latest snapshot
|
||||
* into the db.
|
||||
*/
|
||||
explicit Db(bool import_snapshot = true);
|
||||
|
||||
/**
|
||||
* Construct database with a custom name.
|
||||
*
|
||||
* @param name database name
|
||||
* @param import_snapshot will in constructor import latest snapshot
|
||||
* into the db.
|
||||
*/
|
||||
Db(const char *name, bool import_snapshot = true);
|
||||
/**
|
||||
* Construct database with a custom name.
|
||||
*
|
||||
* @param name database name
|
||||
* @param import_snapshot will in constructor import latest snapshot
|
||||
* into the db.
|
||||
*/
|
||||
Db(const char *name, bool import_snapshot = true);
|
||||
|
||||
/**
|
||||
* Construct database with a custom name.
|
||||
*
|
||||
* @param name database name
|
||||
* @param import_snapshot will in constructor import latest snapshot
|
||||
* into the db.
|
||||
*/
|
||||
Db(const std::string &name, bool import_snapshot = true);
|
||||
/**
|
||||
* Construct database with a custom name.
|
||||
*
|
||||
* @param name database name
|
||||
* @param import_snapshot will in constructor import latest snapshot
|
||||
* into the db.
|
||||
*/
|
||||
Db(const std::string &name, bool import_snapshot = true);
|
||||
|
||||
/**
|
||||
* Database object can't be copied.
|
||||
*/
|
||||
Db(const Db &db) = delete;
|
||||
/**
|
||||
* Database object can't be copied.
|
||||
*/
|
||||
Db(const Db &db) = delete;
|
||||
|
||||
private:
|
||||
/** database name */
|
||||
const std::string name_;
|
||||
/** database name */
|
||||
const std::string name_;
|
||||
|
||||
public:
|
||||
/** transaction engine related to this database */
|
||||
tx::Engine tx_engine;
|
||||
/** transaction engine related to this database */
|
||||
tx::Engine tx_engine;
|
||||
|
||||
/** graph related to this database */
|
||||
Graph graph;
|
||||
/** graph related to this database */
|
||||
Graph graph;
|
||||
|
||||
/** garbage collector related to this database*/
|
||||
Garbage garbage = {tx_engine};
|
||||
/** garbage collector related to this database*/
|
||||
Garbage garbage = {tx_engine};
|
||||
|
||||
/**
|
||||
* snapshot engine related to this database
|
||||
*
|
||||
* \b IMPORTANT: has to be initialized after name
|
||||
* */
|
||||
SnapshotEngine snap_engine = {*this};
|
||||
/**
|
||||
* snapshot engine related to this database
|
||||
*
|
||||
* \b IMPORTANT: has to be initialized after name
|
||||
* */
|
||||
SnapshotEngine snap_engine = {*this};
|
||||
|
||||
/**
|
||||
* Creates Indexes for this database.
|
||||
*/
|
||||
Indexes indexes();
|
||||
// TODO: Indexes should be created only once somwhere Like Db or layer
|
||||
// between Db and Dbms.
|
||||
/**
|
||||
* Creates Indexes for this database.
|
||||
*/
|
||||
Indexes indexes();
|
||||
// TODO: Indexes should be created only once somwhere Like Db or layer
|
||||
// between Db and Dbms.
|
||||
|
||||
/**
|
||||
* Returns a name of the database.
|
||||
*
|
||||
* @return database name
|
||||
*/
|
||||
std::string const &name() const;
|
||||
/**
|
||||
* Returns a name of the database.
|
||||
*
|
||||
* @return database name
|
||||
*/
|
||||
std::string const &name() const;
|
||||
};
|
||||
|
@ -2,17 +2,17 @@
|
||||
|
||||
#include "database/db.hpp"
|
||||
#include "database/db_transaction.hpp"
|
||||
#include "storage/model/properties/property_family.hpp"
|
||||
#include "utils/border.hpp"
|
||||
#include "utils/iterator/iterator.hpp"
|
||||
#include "utils/option.hpp"
|
||||
#include "storage/model/typed_value_store.hpp"
|
||||
|
||||
namespace tx
|
||||
{
|
||||
class Transaction;
|
||||
namespace tx {
|
||||
class Transaction;
|
||||
}
|
||||
|
||||
class Label;
|
||||
|
||||
class EdgeType;
|
||||
|
||||
using EdgePropertyFamily = PropertyFamily<TypeGroupEdge>;
|
||||
@ -44,119 +44,119 @@ using VertexPropertyFamily = PropertyFamily<TypeGroupVertex>;
|
||||
* which
|
||||
* returns by default filled EdgeAccessor.
|
||||
*/
|
||||
class DbAccessor
|
||||
{
|
||||
class DbAccessor {
|
||||
|
||||
public:
|
||||
DbAccessor(Db &db);
|
||||
DbAccessor(Db &db, tx::Transaction &t);
|
||||
DbAccessor(Db &db);
|
||||
|
||||
DbAccessor(const DbAccessor& other) = delete;
|
||||
DbAccessor(DbAccessor&& other) = delete;
|
||||
DbAccessor(Db &db, tx::Transaction &t);
|
||||
|
||||
//*******************VERTEX METHODS
|
||||
// Returns iterator of VertexAccessor for all vertices.
|
||||
// TODO: Implement class specaily for this return
|
||||
// NOTE: This implementation must be here to be able to infere return type.
|
||||
auto vertex_access()
|
||||
{
|
||||
return iter::make_map(
|
||||
iter::make_iter(this->db_transaction.db.graph.vertices.access()),
|
||||
[&](auto e) -> auto {
|
||||
return VertexAccessor(&(e->second), db_transaction);
|
||||
});
|
||||
}
|
||||
DbAccessor(const DbAccessor &other) = delete;
|
||||
|
||||
// Optionaly return vertex with given internal Id.
|
||||
Option<const VertexAccessor> vertex_find(const Id &id);
|
||||
DbAccessor(DbAccessor &&other) = delete;
|
||||
|
||||
// Creates new Vertex and returns filled VertexAccessor.
|
||||
VertexAccessor vertex_insert();
|
||||
//*******************VERTEX METHODS
|
||||
// Returns iterator of VertexAccessor for all vertices.
|
||||
// TODO: Implement class specaily for this return
|
||||
// NOTE: This implementation must be here to be able to infere return type.
|
||||
auto vertex_access() {
|
||||
return iter::make_map(
|
||||
iter::make_iter(this->db_transaction.db.graph.vertices.access()),
|
||||
[&](auto e) -> auto {
|
||||
return VertexAccessor(&(e->second), db_transaction);
|
||||
});
|
||||
}
|
||||
|
||||
// ******************* EDGE METHODS
|
||||
// Returns iterator of EdgeAccessor for all edges.
|
||||
// TODO: Implement class specaily for this return
|
||||
// NOTE: This implementation must be here to be able to infere return type.
|
||||
auto edge_access()
|
||||
{
|
||||
return iter::make_map(
|
||||
iter::make_iter(this->db_transaction.db.graph.edges.access()),
|
||||
[&](auto e) -> auto {
|
||||
return EdgeAccessor(&(e->second), db_transaction);
|
||||
});
|
||||
}
|
||||
// Optionaly return vertex with given internal Id.
|
||||
Option<const VertexAccessor> vertex_find(const Id &id);
|
||||
|
||||
// Optionally return Edge with given internal Id.
|
||||
Option<const EdgeAccessor> edge_find(const Id &id);
|
||||
// Creates new Vertex and returns filled VertexAccessor.
|
||||
VertexAccessor vertex_insert();
|
||||
|
||||
// Creates new Edge and returns filled EdgeAccessor.
|
||||
// Slighlty faster than const version.
|
||||
EdgeAccessor edge_insert(VertexAccessor &from, VertexAccessor &to);
|
||||
// ******************* EDGE METHODS
|
||||
// Returns iterator of EdgeAccessor for all edges.
|
||||
// TODO: Implement class specaily for this return
|
||||
// NOTE: This implementation must be here to be able to infere return type.
|
||||
auto edge_access() {
|
||||
return iter::make_map(
|
||||
iter::make_iter(this->db_transaction.db.graph.edges.access()),
|
||||
[&](auto e) -> auto {
|
||||
return EdgeAccessor(&(e->second), db_transaction);
|
||||
});
|
||||
}
|
||||
|
||||
// Creates new Edge and returns filled EdgeAccessor.
|
||||
EdgeAccessor edge_insert(VertexAccessor const &from,
|
||||
VertexAccessor const &to);
|
||||
// Optionally return Edge with given internal Id.
|
||||
Option<const EdgeAccessor> edge_find(const Id &id);
|
||||
|
||||
// ******************* LABEL METHODS
|
||||
// Finds or crated label with given name.
|
||||
const Label &label_find_or_create(const char *name);
|
||||
// Creates new Edge and returns filled EdgeAccessor.
|
||||
// Slighlty faster than const version.
|
||||
EdgeAccessor edge_insert(VertexAccessor &from, VertexAccessor &to);
|
||||
|
||||
// True if label with name exists.
|
||||
bool label_contains(const char *name);
|
||||
// Creates new Edge and returns filled EdgeAccessor.
|
||||
EdgeAccessor edge_insert(VertexAccessor const &from,
|
||||
VertexAccessor const &to);
|
||||
|
||||
// ******************** TYPE METHODS
|
||||
// Finds or creates edge_type with given name.
|
||||
const EdgeType &type_find_or_create(const char *name);
|
||||
// ******************* LABEL METHODS
|
||||
// Finds or crated label with given name.
|
||||
const Label &label_find_or_create(const char *name);
|
||||
|
||||
// True if edge_type with given name exists.
|
||||
bool type_contains(const char *name);
|
||||
// True if label with name exists.
|
||||
bool label_contains(const char *name);
|
||||
|
||||
// ******************** PROPERTY METHODS
|
||||
// ******************** TYPE METHODS
|
||||
// Finds or creates edge_type with given name.
|
||||
const EdgeType &type_find_or_create(const char *name);
|
||||
|
||||
VertexPropertyFamily &vertex_property_family_get(const std::string &name);
|
||||
// True if edge_type with given name exists.
|
||||
bool type_contains(const char *name);
|
||||
|
||||
EdgePropertyFamily &edge_property_family_get(const std::string &name);
|
||||
// ******************** PROPERTY METHODS
|
||||
|
||||
// ******************** PROPERTY HELPER METHODS
|
||||
VertexPropertyFamily::PropertyType::PropertyFamilyKey
|
||||
vertex_property_key(const std::string &name, Type type);
|
||||
VertexPropertyFamily &vertex_property_family_get(const std::string &name);
|
||||
|
||||
EdgePropertyFamily::PropertyType::PropertyFamilyKey
|
||||
edge_property_key(const std::string &name, Type type);
|
||||
EdgePropertyFamily &edge_property_family_get(const std::string &name);
|
||||
|
||||
template <class T>
|
||||
VertexPropertyFamily::PropertyType::PropertyTypeKey<T>
|
||||
vertex_property_key(const std::string &name)
|
||||
{
|
||||
return vertex_property_family_get(name)
|
||||
.get(T::type)
|
||||
.template type_key<T>();
|
||||
}
|
||||
// ******************** PROPERTY HELPER METHODS
|
||||
VertexPropertyFamily::PropertyType::PropertyFamilyKey
|
||||
vertex_property_key(const std::string &name, Type type);
|
||||
|
||||
template <class T>
|
||||
EdgePropertyFamily::PropertyType::PropertyTypeKey<T>
|
||||
edge_property_key(const std::string &name)
|
||||
{
|
||||
return edge_property_family_get(name)
|
||||
.get(T::type)
|
||||
.template type_key<T>();
|
||||
}
|
||||
EdgePropertyFamily::PropertyType::PropertyFamilyKey
|
||||
edge_property_key(const std::string &name, Type type);
|
||||
|
||||
bool update_indexes();
|
||||
// ******************** TRANSACTION METHODS
|
||||
template<class T>
|
||||
VertexPropertyFamily::PropertyType::PropertyTypeKey <T>
|
||||
vertex_property_key(const std::string &name) {
|
||||
return vertex_property_family_get(name)
|
||||
.get(T::type)
|
||||
.template type_key<T>();
|
||||
}
|
||||
|
||||
// True if commit was successful, or false if transaction was aborted.
|
||||
bool commit();
|
||||
template<class T>
|
||||
EdgePropertyFamily::PropertyType::PropertyTypeKey <T>
|
||||
edge_property_key(const std::string &name) {
|
||||
return edge_property_family_get(name)
|
||||
.get(T::type)
|
||||
.template type_key<T>();
|
||||
}
|
||||
|
||||
// Aborts transaction.
|
||||
void abort();
|
||||
bool update_indexes();
|
||||
// ******************** TRANSACTION METHODS
|
||||
|
||||
// True if commit was successful, or false if transaction was aborted.
|
||||
bool commit();
|
||||
|
||||
// Aborts transaction.
|
||||
void abort();
|
||||
|
||||
private:
|
||||
// TODO: make this friend generic for all indexes.
|
||||
template <class T, class K>
|
||||
friend class NonUniqueUnorderedIndex;
|
||||
template <class T, class K>
|
||||
friend class UniqueOrderedIndex;
|
||||
// TODO: make this friend generic for all indexes.
|
||||
template<class T, class K>
|
||||
friend
|
||||
class NonUniqueUnorderedIndex;
|
||||
|
||||
DbTransaction db_transaction;
|
||||
template<class T, class K>
|
||||
friend
|
||||
class UniqueOrderedIndex;
|
||||
|
||||
DbTransaction db_transaction;
|
||||
};
|
||||
|
@ -1,111 +1,104 @@
|
||||
#pragma once
|
||||
|
||||
#include <cassert>
|
||||
|
||||
#include "database/db_accessor.hpp"
|
||||
#include "storage/model/properties/property_family.hpp"
|
||||
#include "storage/vertex_accessor.hpp"
|
||||
#include "storage/model/typed_value.hpp"
|
||||
#include "storage/model/typed_value_store.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
|
||||
{
|
||||
class ElementSkeleton {
|
||||
|
||||
public:
|
||||
ElementSkeleton(DbAccessor &db) : db(db){};
|
||||
ElementSkeleton(DbAccessor &db) : db(db) {};
|
||||
|
||||
void add_property(StoredProperty<TypeGroupVertex> &&prop)
|
||||
{
|
||||
properties_v.push_back(std::move(prop));
|
||||
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() {
|
||||
assert(properties_e.empty());
|
||||
|
||||
auto va = db.vertex_insert();
|
||||
|
||||
for (auto l : labels) {
|
||||
// std::cout << *l << std::endl;
|
||||
va.add_label(*l);
|
||||
}
|
||||
|
||||
void add_property(StoredProperty<TypeGroupEdge> &&prop)
|
||||
{
|
||||
properties_e.push_back(std::move(prop));
|
||||
for (auto prop : properties_v) {
|
||||
va.set(std::move(prop));
|
||||
}
|
||||
|
||||
void set_element_id(size_t id)
|
||||
{
|
||||
el_id = make_option<size_t>(std::move(id));
|
||||
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 seted"));
|
||||
}
|
||||
if (!to_va.is_present()) {
|
||||
return make_option(std::string("To field must be seted"));
|
||||
}
|
||||
if (!type.is_present()) {
|
||||
return make_option(std::string("Type field must be seted"));
|
||||
}
|
||||
assert(properties_v.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));
|
||||
}
|
||||
|
||||
void add_label(Label const &label) { labels.push_back(&label); }
|
||||
return make_option<std::string>();
|
||||
}
|
||||
|
||||
void set_type(EdgeType const &type) { this->type = make_option(&type); }
|
||||
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();
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
assert(properties_e.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 seted"));
|
||||
}
|
||||
if (!to_va.is_present()) {
|
||||
return make_option(std::string("To field must be seted"));
|
||||
}
|
||||
if (!type.is_present()) {
|
||||
return make_option(std::string("Type field must be seted"));
|
||||
}
|
||||
assert(properties_v.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; }
|
||||
// Returns import local id.
|
||||
Option<size_t> element_id() { return el_id; }
|
||||
|
||||
private:
|
||||
DbAccessor &db;
|
||||
DbAccessor &db;
|
||||
|
||||
Option<size_t> el_id;
|
||||
Option<VertexAccessor> to_va;
|
||||
Option<VertexAccessor> from_va;
|
||||
Option<EdgeType const *> type;
|
||||
std::vector<Label const *> labels;
|
||||
std::vector<StoredProperty<TypeGroupEdge>> properties_e;
|
||||
std::vector<StoredProperty<TypeGroupVertex>> properties_v;
|
||||
Option<size_t> el_id;
|
||||
Option<VertexAccessor> to_va;
|
||||
Option<VertexAccessor> from_va;
|
||||
Option<EdgeType const *> type;
|
||||
std::vector<Label const *> labels;
|
||||
TypedValueStore properties_e;
|
||||
TypedValueStore properties_v;
|
||||
};
|
||||
|
@ -1,57 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "database/db_accessor.hpp"
|
||||
#include "import/fillings/common.hpp"
|
||||
#include "import/fillings/filler.hpp"
|
||||
#include "utils/array_store.hpp"
|
||||
|
||||
// Parses Array of elements type T.
|
||||
// TG - Type group
|
||||
// T - type of element in array.
|
||||
// A - property type in database for holding arrays.
|
||||
template <class TG, class T, class A>
|
||||
class ArrayFiller : public Filler
|
||||
{
|
||||
|
||||
public:
|
||||
ArrayFiller(
|
||||
BaseImporter &db,
|
||||
typename PropertyFamily<TG>::PropertyType::PropertyFamilyKey key,
|
||||
T (*f)(const char *))
|
||||
: bim(db), key(key), f(f)
|
||||
{
|
||||
}
|
||||
|
||||
// Fills skeleton with data from str. Returns error description if
|
||||
// error occurs.
|
||||
Option<std::string> fill(ElementSkeleton &data, char *str) final
|
||||
{
|
||||
sub_str.clear();
|
||||
std::vector<T> vec;
|
||||
bim.extract(str, bim.parts_array_mark, sub_str);
|
||||
for (auto s : sub_str) {
|
||||
if (s[0] != '\0') {
|
||||
vec.push_back(f(s));
|
||||
}
|
||||
}
|
||||
if (vec.size() > 0) {
|
||||
data.add_property(StoredProperty<TG>(A(std::move(vec)), key));
|
||||
}
|
||||
return make_option<std::string>();
|
||||
}
|
||||
|
||||
private:
|
||||
BaseImporter &bim;
|
||||
typename PropertyFamily<TG>::PropertyType::PropertyFamilyKey key;
|
||||
vector<char *> sub_str;
|
||||
T (*f)(const char *);
|
||||
};
|
||||
|
||||
template <class TG, class T, class A>
|
||||
auto make_array_filler(
|
||||
BaseImporter &db,
|
||||
typename PropertyFamily<TG>::PropertyType::PropertyFamilyKey key,
|
||||
T (*f)(const char *))
|
||||
{
|
||||
return new ArrayFiller<TG, T, A>(db, key, f);
|
||||
}
|
@ -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 double.
|
||||
// TG - Type group
|
||||
template <class TG>
|
||||
class DoubleFiller : public Filler
|
||||
{
|
||||
|
||||
public:
|
||||
DoubleFiller(
|
||||
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>(Double(to_double(str)), key));
|
||||
}
|
||||
|
||||
return make_option<std::string>();
|
||||
}
|
||||
|
||||
private:
|
||||
typename PropertyFamily<TG>::PropertyType::PropertyFamilyKey key;
|
||||
};
|
@ -1,35 +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 int32.
|
||||
// TG - Type group
|
||||
template <class TG>
|
||||
class Int32Filler : public Filler
|
||||
{
|
||||
|
||||
public:
|
||||
Int32Filler(
|
||||
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>(Int32(to_int32(str)), key));
|
||||
}
|
||||
|
||||
return make_option<std::string>();
|
||||
}
|
||||
|
||||
private:
|
||||
typename PropertyFamily<TG>::PropertyType::PropertyFamilyKey key;
|
||||
};
|
@ -7,46 +7,43 @@
|
||||
#include "mvcc/serialization_error.hpp"
|
||||
#include "storage/locking/record_lock.hpp"
|
||||
|
||||
namespace mvcc
|
||||
{
|
||||
namespace mvcc {
|
||||
|
||||
template <class T>
|
||||
class VersionList
|
||||
{
|
||||
template<class T>
|
||||
class VersionList {
|
||||
friend class Accessor;
|
||||
|
||||
public:
|
||||
public:
|
||||
using uptr = std::unique_ptr<VersionList<T>>;
|
||||
using item_t = T;
|
||||
|
||||
VersionList(Id id) : id(id) {}
|
||||
|
||||
VersionList(const VersionList &) = delete;
|
||||
|
||||
/* @brief Move constructs the version list
|
||||
* Note: use only at the beginning of the "other's" lifecycle since this
|
||||
* constructor doesn't move the RecordLock, but only the head pointer
|
||||
*/
|
||||
VersionList(VersionList &&other) : id(other.id)
|
||||
{
|
||||
this->head = other.head.load();
|
||||
other.head = nullptr;
|
||||
VersionList(VersionList &&other) : id(other.id) {
|
||||
this->head = other.head.load();
|
||||
other.head = nullptr;
|
||||
}
|
||||
|
||||
~VersionList() { delete head.load(); }
|
||||
|
||||
friend std::ostream &operator<<(std::ostream &stream,
|
||||
const VersionList<T> &vlist)
|
||||
{
|
||||
stream << "VersionList" << std::endl;
|
||||
const VersionList<T> &vlist) {
|
||||
stream << "VersionList" << std::endl;
|
||||
|
||||
auto record = vlist.head.load();
|
||||
auto record = vlist.head.load();
|
||||
|
||||
while (record != nullptr) {
|
||||
stream << "-- " << *record << std::endl;
|
||||
record = record->next();
|
||||
}
|
||||
while (record != nullptr) {
|
||||
stream << "-- " << *record << std::endl;
|
||||
record = record->next();
|
||||
}
|
||||
|
||||
return stream;
|
||||
return stream;
|
||||
}
|
||||
|
||||
auto gc_lock_acquire() { return std::unique_lock<RecordLock>(lock); }
|
||||
@ -59,156 +56,148 @@ public:
|
||||
// possibilty that someone is reading it at this moment but he cant change
|
||||
// it or get anything from it.
|
||||
// TODO: Validate this method
|
||||
bool gc_deleted(const Id &id)
|
||||
{
|
||||
auto r = head.load(std::memory_order_seq_cst);
|
||||
T *bef = nullptr;
|
||||
bool gc_deleted(const Id &id) {
|
||||
auto r = head.load(std::memory_order_seq_cst);
|
||||
T *bef = nullptr;
|
||||
|
||||
// nullptr
|
||||
// |
|
||||
// [v1] ...
|
||||
// |
|
||||
// [v2] <------+
|
||||
// | |
|
||||
// [v3] <------+
|
||||
// | | Jump backwards until you find a first old deleted
|
||||
// [VerList] ----+ version, or you reach the end of the list
|
||||
//
|
||||
while (r != nullptr && !r->is_deleted_before(id)) {
|
||||
bef = r;
|
||||
r = r->next(std::memory_order_seq_cst);
|
||||
// nullptr
|
||||
// |
|
||||
// [v1] ...
|
||||
// |
|
||||
// [v2] <------+
|
||||
// | |
|
||||
// [v3] <------+
|
||||
// | | Jump backwards until you find a first old deleted
|
||||
// [VerList] ----+ version, or you reach the end of the list
|
||||
//
|
||||
while (r != nullptr && !r->is_deleted_before(id)) {
|
||||
bef = r;
|
||||
r = r->next(std::memory_order_seq_cst);
|
||||
}
|
||||
|
||||
if (bef == nullptr) {
|
||||
// if r==nullptr he is needed and it is expecting insert.
|
||||
// if r!=nullptr vertex has been explicitly deleted. It can't be
|
||||
// updated because for update, visible record is needed and at this
|
||||
// point whe know that there is no visible record for any
|
||||
// transaction. Also it cant be inserted because head isn't nullptr.
|
||||
// Remove also requires visible record. Find wont return any record
|
||||
// because none is visible.
|
||||
return r != nullptr;
|
||||
} else {
|
||||
if (r != nullptr) {
|
||||
// Bef is possible visible to some transaction but r is not and
|
||||
// the implementation of this version list guarantees that
|
||||
// record r and older records aren't accessed.
|
||||
bef->next(nullptr, std::memory_order_seq_cst);
|
||||
delete r; // THIS IS ISSUE IF MULTIPLE THREADS TRY TO DO THIS
|
||||
}
|
||||
|
||||
if (bef == nullptr) {
|
||||
// if r==nullptr he is needed and it is expecting insert.
|
||||
// if r!=nullptr vertex has been explicitly deleted. It can't be
|
||||
// updated because for update, visible record is needed and at this
|
||||
// point whe know that there is no visible record for any
|
||||
// transaction. Also it cant be inserted because head isn't nullptr.
|
||||
// Remove also requires visible record. Find wont return any record
|
||||
// because none is visible.
|
||||
return r != nullptr;
|
||||
} else {
|
||||
if (r != nullptr) {
|
||||
// Bef is possible visible to some transaction but r is not and
|
||||
// the implementation of this version list guarantees that
|
||||
// record r and older records aren't accessed.
|
||||
bef->next(nullptr, std::memory_order_seq_cst);
|
||||
delete r; // THIS IS ISSUE IF MULTIPLE THREADS TRY TO DO THIS
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void vacuum() {}
|
||||
|
||||
T *find(const tx::TransactionRead &t) const
|
||||
{
|
||||
auto r = head.load(std::memory_order_seq_cst);
|
||||
T *find(const tx::TransactionRead &t) const {
|
||||
auto r = head.load(std::memory_order_seq_cst);
|
||||
|
||||
// nullptr
|
||||
// |
|
||||
// [v1] ...
|
||||
// |
|
||||
// [v2] <------+
|
||||
// | |
|
||||
// [v3] <------+
|
||||
// | | Jump backwards until you find a first visible
|
||||
// [VerList] ----+ version, or you reach the end of the list
|
||||
//
|
||||
while (r != nullptr && !r->visible(t))
|
||||
r = r->next(std::memory_order_seq_cst);
|
||||
// nullptr
|
||||
// |
|
||||
// [v1] ...
|
||||
// |
|
||||
// [v2] <------+
|
||||
// | |
|
||||
// [v3] <------+
|
||||
// | | Jump backwards until you find a first visible
|
||||
// [VerList] ----+ version, or you reach the end of the list
|
||||
//
|
||||
while (r != nullptr && !r->visible(t))
|
||||
r = r->next(std::memory_order_seq_cst);
|
||||
|
||||
return r;
|
||||
return r;
|
||||
}
|
||||
|
||||
T *insert(tx::Transaction &t)
|
||||
{
|
||||
assert(head == nullptr);
|
||||
T *insert(tx::Transaction &t) {
|
||||
assert(head == nullptr);
|
||||
|
||||
// create a first version of the record
|
||||
// TODO replace 'new' with something better
|
||||
auto v1 = new T();
|
||||
// create a first version of the record
|
||||
// TODO replace 'new' with something better
|
||||
auto v1 = new T();
|
||||
|
||||
// mark the record as created by the transaction t
|
||||
v1->mark_created(t);
|
||||
// mark the record as created by the transaction t
|
||||
v1->mark_created(t);
|
||||
|
||||
head.store(v1, std::memory_order_seq_cst);
|
||||
head.store(v1, std::memory_order_seq_cst);
|
||||
|
||||
return v1;
|
||||
return v1;
|
||||
}
|
||||
|
||||
T *update(tx::Transaction &t)
|
||||
{
|
||||
assert(head != nullptr);
|
||||
auto record = find(t);
|
||||
T *update(tx::Transaction &t) {
|
||||
assert(head != nullptr);
|
||||
auto record = find(t);
|
||||
|
||||
// check if we found any visible records
|
||||
if (!record) return nullptr;
|
||||
// check if we found any visible records
|
||||
if (!record) return nullptr;
|
||||
|
||||
return update(record, t);
|
||||
return update(record, t);
|
||||
}
|
||||
|
||||
T *update(T *record, tx::Transaction &t)
|
||||
{
|
||||
assert(record != nullptr);
|
||||
lock_and_validate(record, t);
|
||||
T *update(T *record, tx::Transaction &t) {
|
||||
assert(record != nullptr);
|
||||
lock_and_validate(record, t);
|
||||
|
||||
// It could be done with unique_ptr but while this could mean memory
|
||||
// leak on exception, unique_ptr could mean use after free. Memory
|
||||
// leak is less dangerous.
|
||||
auto updated = new T();
|
||||
updated->data = record->data;
|
||||
// It could be done with unique_ptr but while this could mean memory
|
||||
// leak on exception, unique_ptr could mean use after free. Memory
|
||||
// leak is less dangerous.
|
||||
auto updated = new T();
|
||||
updated->data = record->data;
|
||||
|
||||
updated->mark_created(t);
|
||||
record->mark_deleted(t);
|
||||
updated->mark_created(t);
|
||||
record->mark_deleted(t);
|
||||
|
||||
updated->next(record, std::memory_order_seq_cst);
|
||||
head.store(updated, std::memory_order_seq_cst);
|
||||
updated->next(record, std::memory_order_seq_cst);
|
||||
head.store(updated, std::memory_order_seq_cst);
|
||||
|
||||
return updated;
|
||||
return updated;
|
||||
}
|
||||
|
||||
bool remove(tx::Transaction &t)
|
||||
{
|
||||
assert(head != nullptr);
|
||||
auto record = find(t);
|
||||
bool remove(tx::Transaction &t) {
|
||||
assert(head != nullptr);
|
||||
auto record = find(t);
|
||||
|
||||
if (!record) return false;
|
||||
if (!record) return false;
|
||||
|
||||
// TODO: Is this lock and validate necessary
|
||||
lock_and_validate(record, t);
|
||||
return remove(record, t), true;
|
||||
// TODO: Is this lock and validate necessary
|
||||
lock_and_validate(record, t);
|
||||
return remove(record, t), true;
|
||||
}
|
||||
|
||||
void remove(T *record, tx::Transaction &t)
|
||||
{
|
||||
assert(record != nullptr);
|
||||
lock_and_validate(record, t);
|
||||
record->mark_deleted(t);
|
||||
void remove(T *record, tx::Transaction &t) {
|
||||
assert(record != nullptr);
|
||||
lock_and_validate(record, t);
|
||||
record->mark_deleted(t);
|
||||
}
|
||||
|
||||
const Id id;
|
||||
|
||||
private:
|
||||
void lock_and_validate(T *record, tx::Transaction &t)
|
||||
{
|
||||
assert(record != nullptr);
|
||||
private:
|
||||
void lock_and_validate(T *record, tx::Transaction &t) {
|
||||
assert(record != nullptr);
|
||||
|
||||
// take a lock on this node
|
||||
t.take_lock(lock);
|
||||
// take a lock on this node
|
||||
t.take_lock(lock);
|
||||
|
||||
// if the record hasn't been deleted yet or the deleting transaction
|
||||
// has aborted, it's ok to modify it
|
||||
if (!record->tx.exp() || !record->exp_committed(t)) return;
|
||||
// if the record hasn't been deleted yet or the deleting transaction
|
||||
// has aborted, it's ok to modify it
|
||||
if (!record->tx.exp() || !record->exp_committed(t)) return;
|
||||
|
||||
// if it committed, then we have a serialization conflict
|
||||
assert(record->hints.load().exp.is_committed());
|
||||
throw SerializationError();
|
||||
// if it committed, then we have a serialization conflict
|
||||
assert(record->hints.load().exp.is_committed());
|
||||
throw SerializationError();
|
||||
}
|
||||
|
||||
std::atomic<T *> head{nullptr};
|
||||
RecordLock lock;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
@ -1,10 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "storage/model/properties/array.hpp"
|
||||
#include "storage/model/properties/bool.hpp"
|
||||
#include "storage/model/properties/double.hpp"
|
||||
#include "storage/model/properties/float.hpp"
|
||||
#include "storage/model/properties/int32.hpp"
|
||||
#include "storage/model/properties/int64.hpp"
|
||||
#include "storage/model/properties/null.hpp"
|
||||
#include "storage/model/properties/string.hpp"
|
@ -1,77 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "storage/model/properties/flags.hpp"
|
||||
#include "utils/array_store.hpp"
|
||||
|
||||
template <class T, Flags flag_t>
|
||||
class Array
|
||||
{
|
||||
public:
|
||||
const static Type type;
|
||||
|
||||
using Arr = ArrayStore<T>;
|
||||
|
||||
Array(Arr &&value) : data(std::make_shared<Arr>(std::move(value))) {}
|
||||
|
||||
Arr &value() { return *data.get(); }
|
||||
|
||||
Arr const &value() const { return *data.get(); }
|
||||
|
||||
std::ostream &print(std::ostream &stream) const
|
||||
{
|
||||
stream << "[";
|
||||
for (auto e : value()) {
|
||||
stream << e << ",";
|
||||
}
|
||||
stream << "]";
|
||||
return stream;
|
||||
}
|
||||
|
||||
friend std::ostream &operator<<(std::ostream &stream, const Array &prop)
|
||||
{
|
||||
return prop.print(stream);
|
||||
}
|
||||
|
||||
bool operator==(const Array &other) const { return *this == other.value(); }
|
||||
|
||||
bool operator==(const Arr &other) const
|
||||
{
|
||||
auto arr = value();
|
||||
if (arr.size() != other.size()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto n = arr.size();
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
if (arr[i] != other[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// NOTE: OTHER METHODS WILL AUTOMATICALLY USE THIS IN CERTAIN SITUATIONS TO
|
||||
// MOVE ARR OUT OF SHARED_PTR WHICH IS BAD
|
||||
// operator const Arr &() const { return value(); };
|
||||
|
||||
private:
|
||||
// TODO: PropertyHolder can be 8B smaller if this uses custom shared_ptr
|
||||
// which has only one ptr here.
|
||||
std::shared_ptr<Arr> data;
|
||||
};
|
||||
|
||||
using ArrayString = Array<std::string, Flags::ArrayString>;
|
||||
|
||||
using ArrayBool = Array<bool, Flags::ArrayBool>;
|
||||
|
||||
using ArrayInt32 = Array<int32_t, Flags::ArrayInt32>;
|
||||
|
||||
using ArrayInt64 = Array<int64_t, Flags::ArrayInt64>;
|
||||
|
||||
using ArrayFloat = Array<float, Flags::ArrayFloat>;
|
||||
|
||||
using ArrayDouble = Array<double, Flags::ArrayDouble>;
|
@ -1,37 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "storage/model/properties/flags.hpp"
|
||||
|
||||
class Bool
|
||||
{
|
||||
public:
|
||||
const static Type type;
|
||||
|
||||
Bool(bool d) : data(d) {}
|
||||
|
||||
bool &value() { return data; }
|
||||
|
||||
bool const &value() const { return data; }
|
||||
|
||||
std::ostream &print(std::ostream &stream) const
|
||||
{
|
||||
return operator<<(stream, *this);
|
||||
}
|
||||
|
||||
friend std::ostream &operator<<(std::ostream &stream, const Bool &prop)
|
||||
{
|
||||
return stream << prop.data;
|
||||
}
|
||||
|
||||
bool operator==(const Bool &other) const
|
||||
{
|
||||
return other.value() == value();
|
||||
}
|
||||
|
||||
bool operator==(bool v) const { return value() == v; }
|
||||
|
||||
explicit operator bool() const { return value(); }
|
||||
|
||||
private:
|
||||
bool data;
|
||||
};
|
@ -1,19 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "storage/model/properties/flags.hpp"
|
||||
#include "storage/model/properties/floating.hpp"
|
||||
|
||||
struct Double : public Floating<Double>
|
||||
{
|
||||
public:
|
||||
const static Type type;
|
||||
|
||||
Double(double d) : data(d) {}
|
||||
|
||||
double &value() { return data; }
|
||||
|
||||
double const &value() const { return data; }
|
||||
|
||||
private:
|
||||
double data;
|
||||
};
|
@ -1,151 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <cassert>
|
||||
#include <ostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "utils/total_ordering.hpp"
|
||||
#include "utils/underlying_cast.hpp"
|
||||
|
||||
// TODO: Revise this
|
||||
// NOTE: Why not just count all the types?
|
||||
enum class Flags : unsigned
|
||||
{
|
||||
// Type | Mask
|
||||
// -----------+----------------------------------------
|
||||
// Null | 0000 0000 0000 0000 0000 0000 0000 0000
|
||||
// -----------+----------------------------------------
|
||||
// Bool | 0000 0000 0000 0000 0000 0000 0000 0001
|
||||
// + True | 0000 0000 0000 0000 0000 0000 0000 0011
|
||||
// + False | 0000 0000 0000 0000 0000 0000 0000 0101
|
||||
// -----------+----------------------------------------
|
||||
// String | 0000 0000 0000 0000 0000 0000 0000 1000
|
||||
// -----------+----------------------------------------
|
||||
// Number | 0000 0000 0000 0000 0000 0000 0001 0000
|
||||
// + Integral | 0000 0000 0000 0000 0000 0000 0011 0000
|
||||
// + Int32 | 0000 0000 0000 0000 0000 0000 0111 0000
|
||||
// + Int64 | 0000 0000 0000 0000 0000 0000 1011 0000
|
||||
// + Floating | 0000 0000 0000 0000 0000 0001 0001 0000
|
||||
// + Float | 0000 0000 0000 0000 0000 0011 0001 0000
|
||||
// + Double | 0000 0000 0000 0000 0000 0101 0001 0000
|
||||
// -----------+----------------------------------------
|
||||
// Array | 0000 0000 0000 0000 0001 0000 0000 0000
|
||||
// -----------+----------------------------------------
|
||||
|
||||
Null = 0x0,
|
||||
Bool = 0x1,
|
||||
|
||||
// TODO remove this two values
|
||||
True = 0x2 | Bool,
|
||||
False = 0x4 | Bool,
|
||||
|
||||
String = 0x8,
|
||||
|
||||
Number = 0x10,
|
||||
Integral = 0x20 | Number,
|
||||
Int32 = 0x40 | Integral,
|
||||
Int64 = 0x80 | Integral,
|
||||
|
||||
Floating = 0x100 | Number,
|
||||
Float = 0x200 | Floating,
|
||||
Double = 0x400 | Floating,
|
||||
|
||||
Array = 0x1000,
|
||||
ArrayBool = (Bool << 13) | Array,
|
||||
ArrayString = (String << 13) | Array,
|
||||
ArrayInt32 = (Int32 << 13) | Array,
|
||||
ArrayInt64 = (Int64 << 13) | Array,
|
||||
ArrayFloat = (Float << 13) | Array,
|
||||
ArrayDouble = (Double << 13) | Array,
|
||||
|
||||
type_mask = 0xFFFFFF
|
||||
};
|
||||
|
||||
// Mask to turn flags into type. It passes all bits except 0x2 and 0x4 which
|
||||
// correspond
|
||||
// to True and False.
|
||||
const unsigned flags_equal_mask = 0xFF3FF9;
|
||||
|
||||
class Type : public TotalOrdering<Type>
|
||||
{
|
||||
public:
|
||||
constexpr Type(Flags f) : value(underlying_cast(f) & flags_equal_mask)
|
||||
{
|
||||
Flags o = Flags(value);
|
||||
assert(o == Flags::Null || o == Flags::Bool || o == Flags::String ||
|
||||
o == Flags::Int32 || o == Flags::Int64 || o == Flags::Float ||
|
||||
o == Flags::Double || o == Flags::ArrayBool ||
|
||||
o == Flags::ArrayString || o == Flags::ArrayInt32 ||
|
||||
o == Flags::ArrayInt64 || o == Flags::ArrayFloat ||
|
||||
o == Flags::ArrayDouble);
|
||||
}
|
||||
|
||||
const std::string to_str() const
|
||||
{
|
||||
switch (flags()) {
|
||||
case Flags::Null:
|
||||
return "null";
|
||||
case Flags::Bool:
|
||||
return "bool";
|
||||
case Flags::String:
|
||||
return "str";
|
||||
case Flags::Int32:
|
||||
return "int32";
|
||||
case Flags::Int64:
|
||||
return "int64";
|
||||
case Flags::Float:
|
||||
return "float";
|
||||
case Flags::Double:
|
||||
return "double";
|
||||
case Flags::ArrayBool:
|
||||
return "array_bool";
|
||||
case Flags::ArrayString:
|
||||
return "array_string";
|
||||
case Flags::ArrayInt64:
|
||||
return "array_int64";
|
||||
case Flags::ArrayInt32:
|
||||
return "array_int32";
|
||||
case Flags::ArrayFloat:
|
||||
return "array_float";
|
||||
case Flags::ArrayDouble:
|
||||
return "array_double";
|
||||
|
||||
default:
|
||||
assert(false);
|
||||
return "err_unknown_type_" + std::to_string(value);
|
||||
}
|
||||
}
|
||||
|
||||
Flags flags() const { return Flags(value); }
|
||||
|
||||
Type get_type() const { return *this; }
|
||||
|
||||
bool is_array() const
|
||||
{
|
||||
return (value & underlying_cast(Flags::Array)) != 0;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
bool is() const
|
||||
{
|
||||
return *this == T::type;
|
||||
}
|
||||
|
||||
bool operator==(Flags other) const { return *this == Type(other); }
|
||||
|
||||
bool operator!=(Flags other) const { return *this != Type(other); }
|
||||
|
||||
friend bool operator<(const Type &lhs, const Type &rhs)
|
||||
{
|
||||
return lhs.value < rhs.value;
|
||||
}
|
||||
|
||||
friend bool operator==(const Type &lhs, const Type &rhs)
|
||||
{
|
||||
return lhs.value == rhs.value;
|
||||
}
|
||||
|
||||
private:
|
||||
const unsigned value; // TODO: turn this to flags
|
||||
};
|
@ -1,23 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "storage/model/properties/double.hpp"
|
||||
#include "storage/model/properties/flags.hpp"
|
||||
#include "storage/model/properties/floating.hpp"
|
||||
|
||||
class Float : public Floating<Float>
|
||||
{
|
||||
|
||||
public:
|
||||
const static Type type;
|
||||
|
||||
Float(float d) : data(d) {}
|
||||
|
||||
operator Double() const { return Double(value()); }
|
||||
|
||||
float &value() { return data; }
|
||||
|
||||
float const &value() const { return data; }
|
||||
|
||||
private:
|
||||
float data;
|
||||
};
|
@ -1,9 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "storage/model/properties/number.hpp"
|
||||
|
||||
template <class Derived>
|
||||
struct Floating : public Number<Derived>
|
||||
{
|
||||
using Number<Derived>::Number;
|
||||
};
|
@ -1,22 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "storage/model/properties/flags.hpp"
|
||||
#include "storage/model/properties/int64.hpp"
|
||||
#include "storage/model/properties/integral.hpp"
|
||||
|
||||
class Int32 : public Integral<Int32>
|
||||
{
|
||||
public:
|
||||
const static Type type;
|
||||
|
||||
Int32(int32_t d) : data(d) {}
|
||||
|
||||
operator Int64() const { return Int64(value()); }
|
||||
|
||||
int32_t &value() { return data; }
|
||||
|
||||
int32_t const &value() const { return data; }
|
||||
|
||||
private:
|
||||
int32_t data;
|
||||
};
|
@ -1,18 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "storage/model/properties/flags.hpp"
|
||||
#include "storage/model/properties/integral.hpp"
|
||||
|
||||
class Int64 : public Integral<Int64>
|
||||
{
|
||||
public:
|
||||
const static Type type;
|
||||
|
||||
Int64(int64_t d) : data(d) {}
|
||||
|
||||
int64_t &value() { return data; }
|
||||
|
||||
int64_t const &value() const { return data; }
|
||||
private:
|
||||
int64_t data;
|
||||
};
|
@ -1,18 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "storage/model/properties/floating.hpp"
|
||||
#include "storage/model/properties/number.hpp"
|
||||
#include "storage/model/properties/utils/modulo.hpp"
|
||||
|
||||
template <class Derived>
|
||||
struct Integral : public Number<Derived>, public Modulo<Derived>
|
||||
{
|
||||
using Number<Derived>::Number;
|
||||
|
||||
template <class T, typename = std::enable_if_t<
|
||||
std::is_base_of<Floating<T>, T>::value>>
|
||||
operator T() const
|
||||
{
|
||||
return T(this->derived().value);
|
||||
}
|
||||
};
|
@ -1,72 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "storage/model/properties/properties.hpp"
|
||||
#include "storage/type_group_edge.hpp"
|
||||
#include "storage/type_group_vertex.hpp"
|
||||
|
||||
template <class Buffer>
|
||||
struct JsonWriter
|
||||
{
|
||||
public:
|
||||
JsonWriter(Buffer &buffer) : buffer(buffer) { buffer << '{'; };
|
||||
|
||||
void handle(const StoredProperty<TypeGroupEdge> &prop)
|
||||
{
|
||||
handle<TypeGroupEdge>(prop);
|
||||
}
|
||||
|
||||
void handle(const StoredProperty<TypeGroupVertex> &prop)
|
||||
{
|
||||
handle<TypeGroupVertex>(prop);
|
||||
}
|
||||
|
||||
template <class TG>
|
||||
void handle(const StoredProperty<TG> &prop)
|
||||
{
|
||||
if (!first) buffer << ',';
|
||||
|
||||
if (first) first = false;
|
||||
|
||||
buffer << '"' << prop.key.family_name() << "\":";
|
||||
|
||||
prop.accept(*this);
|
||||
}
|
||||
|
||||
void handle(const Null &v) { buffer << "NULL"; }
|
||||
|
||||
void handle(const Bool &b) { buffer << (b ? "true" : "false"); }
|
||||
|
||||
void handle(const String &s) { buffer << '"' << s.value() << '"'; }
|
||||
|
||||
void handle(const Int32 &int32) { buffer << std::to_string(int32.value()); }
|
||||
|
||||
void handle(const Int64 &int64) { buffer << std::to_string(int64.value()); }
|
||||
|
||||
void handle(const Float &f) { buffer << std::to_string(f.value()); }
|
||||
|
||||
void handle(const Double &d) { buffer << std::to_string(d.value()); }
|
||||
|
||||
// Not yet implemented
|
||||
void handle(const ArrayBool &) { assert(false); }
|
||||
|
||||
// Not yet implemented
|
||||
void handle(const ArrayInt32 &) { assert(false); }
|
||||
|
||||
// Not yet implemented
|
||||
void handle(const ArrayInt64 &) { assert(false); }
|
||||
|
||||
// Not yet implemented
|
||||
void handle(const ArrayFloat &) { assert(false); }
|
||||
|
||||
// Not yet implemented
|
||||
void handle(const ArrayDouble &) { assert(false); }
|
||||
|
||||
// Not yet implemented
|
||||
void handle(const ArrayString &) { assert(false); }
|
||||
|
||||
void finish() { buffer << '}'; }
|
||||
|
||||
private:
|
||||
bool first{true};
|
||||
Buffer &buffer;
|
||||
};
|
@ -1,23 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <ostream>
|
||||
#include <string>
|
||||
#include "storage/model/properties/flags.hpp"
|
||||
#include "utils/void.hpp"
|
||||
|
||||
class Null
|
||||
{
|
||||
public:
|
||||
const static Type type;
|
||||
|
||||
Void &value() { return _void; }
|
||||
Void const &value() const { return _void; }
|
||||
|
||||
std::ostream &print(std::ostream &stream) const;
|
||||
|
||||
friend std::ostream &operator<<(std::ostream &stream, const Null &prop);
|
||||
|
||||
bool operator==(const Null &) const;
|
||||
|
||||
explicit operator bool();
|
||||
};
|
@ -1,33 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "storage/model/properties/utils/math_operations.hpp"
|
||||
#include "storage/model/properties/utils/unary_negation.hpp"
|
||||
#include "utils/total_ordering.hpp"
|
||||
|
||||
template <class Derived>
|
||||
class Number : public TotalOrdering<Derived>,
|
||||
public MathOperations<Derived>,
|
||||
public UnaryNegation<Derived>
|
||||
{
|
||||
|
||||
public:
|
||||
std::ostream &print(std::ostream &stream) const
|
||||
{
|
||||
return operator<<(stream, this->derived());
|
||||
}
|
||||
|
||||
friend std::ostream &operator<<(std::ostream &s, const Derived &number)
|
||||
{
|
||||
return s << number.value();
|
||||
}
|
||||
|
||||
friend bool operator==(const Derived &lhs, const Derived &rhs)
|
||||
{
|
||||
return lhs.value() == rhs.value();
|
||||
}
|
||||
|
||||
friend bool operator<(const Derived &lhs, const Derived &rhs)
|
||||
{
|
||||
return lhs.value() == rhs.value();
|
||||
}
|
||||
};
|
@ -1,99 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <unordered_set>
|
||||
|
||||
#include "utils/option.hpp"
|
||||
#include "utils/option_ptr.hpp"
|
||||
|
||||
#include "storage/model/properties/property_family.hpp"
|
||||
#include "storage/model/properties/stored_property.hpp"
|
||||
|
||||
// TG - type group (TypeGroupEntity)
|
||||
|
||||
// TODO: think about a better place
|
||||
template <class TG, class T>
|
||||
using type_key_t =
|
||||
typename PropertyFamily<TG>::PropertyType::template PropertyTypeKey<T>;
|
||||
|
||||
// Collection of stored properties.
|
||||
// NOTE: Currently underlying strucutre is a vector which is fine for smaller
|
||||
// number of properties.
|
||||
template <class TG>
|
||||
class Properties
|
||||
{
|
||||
public:
|
||||
using property_key =
|
||||
typename PropertyFamily<TG>::PropertyType::PropertyFamilyKey;
|
||||
|
||||
template <class T>
|
||||
using type_key_t =
|
||||
typename PropertyFamily<TG>::PropertyType::template PropertyTypeKey<T>;
|
||||
|
||||
auto begin() const { return props.begin(); }
|
||||
auto cbegin() const { return props.cbegin(); }
|
||||
|
||||
auto end() const { return props.end(); }
|
||||
auto cend() const { return props.cend(); }
|
||||
|
||||
size_t size() const { return props.size(); }
|
||||
|
||||
const bool contains(property_key &key) const;
|
||||
|
||||
const StoredProperty<TG> &at(PropertyFamily<TG> &key) const;
|
||||
|
||||
const StoredProperty<TG> &at(property_key &key) const;
|
||||
|
||||
template <class T>
|
||||
OptionPtr<const T> at(type_key_t<T> &key) const
|
||||
{
|
||||
for (auto &prop : props) {
|
||||
if (prop.key == key) {
|
||||
if (prop.template is<T>()) {
|
||||
return OptionPtr<const T>(&(prop.template as<T>()));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return OptionPtr<const T>();
|
||||
}
|
||||
|
||||
void set(StoredProperty<TG> &&value);
|
||||
|
||||
void clear(property_key &key);
|
||||
|
||||
void clear(PropertyFamily<TG> &key);
|
||||
|
||||
template <class Handler>
|
||||
void accept(Handler &handler) const
|
||||
{
|
||||
for (auto &kv : props)
|
||||
kv.accept(handler);
|
||||
|
||||
handler.finish();
|
||||
}
|
||||
|
||||
template <class Handler>
|
||||
void handle(Handler &handler) const
|
||||
{
|
||||
for (auto &kv : props)
|
||||
handler.handle(kv);
|
||||
|
||||
handler.finish();
|
||||
}
|
||||
|
||||
template <class Handler>
|
||||
void for_all(Handler handler) const
|
||||
{
|
||||
for (auto &kv : props)
|
||||
handler(kv);
|
||||
}
|
||||
|
||||
private:
|
||||
using props_t = std::vector<StoredProperty<TG>>;
|
||||
// TODO: more bytes can be saved if this is array with exact size as number
|
||||
// of elements.
|
||||
// TODO: even more bytes can be saved if this is one ptr to structure which
|
||||
// holds len followed by len sized array.
|
||||
props_t props;
|
||||
};
|
@ -1,47 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <cassert>
|
||||
#include <memory>
|
||||
#include <ostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "storage/model/properties/flags.hpp"
|
||||
#include "storage/model/properties/property_holder.hpp"
|
||||
|
||||
class Null;
|
||||
|
||||
// Property Class designated for creation outside the database.
|
||||
class Property : public PropertyHolder<Type>
|
||||
{
|
||||
public:
|
||||
using PropertyHolder<Type>::PropertyHolder;
|
||||
|
||||
static Property handle(Void &&v);
|
||||
|
||||
static Property handle(bool &&prop);
|
||||
|
||||
static Property handle(float &&prop);
|
||||
|
||||
static Property handle(double &&prop);
|
||||
|
||||
static Property handle(int32_t &&prop);
|
||||
|
||||
static Property handle(int64_t &&prop);
|
||||
|
||||
static Property handle(std::string &&value);
|
||||
|
||||
static Property handle(ArrayStore<bool> &&);
|
||||
|
||||
static Property handle(ArrayStore<int32_t> &&);
|
||||
|
||||
static Property handle(ArrayStore<int64_t> &&);
|
||||
|
||||
static Property handle(ArrayStore<float> &&);
|
||||
|
||||
static Property handle(ArrayStore<double> &&);
|
||||
|
||||
static Property handle(ArrayStore<std::string> &&);
|
||||
};
|
||||
|
||||
using properties_t = std::vector<Property>;
|
@ -1,246 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "data_structures/concurrent/concurrent_map.hpp"
|
||||
#include "storage/indexes/index_holder.hpp"
|
||||
#include "storage/model/properties/flags.hpp"
|
||||
#include "storage/type_group_edge.hpp"
|
||||
#include "storage/type_group_vertex.hpp"
|
||||
#include "utils/option.hpp"
|
||||
#include "utils/total_ordering.hpp"
|
||||
#include "utils/underlying_cast.hpp"
|
||||
|
||||
// #include "storage/indexes/index_base.hpp"
|
||||
|
||||
// Family of properties with the same name but different types.
|
||||
// Ordered on name.
|
||||
// TG - group of types Edge/Vertex
|
||||
template <class TG>
|
||||
class PropertyFamily : public TotalOrdering<PropertyFamily<TG>>
|
||||
{
|
||||
friend class PropertyType;
|
||||
friend class PropertyFamilyKey;
|
||||
friend class PropertyTypeKey;
|
||||
|
||||
public:
|
||||
// Type of property defined with his family and his type.
|
||||
// Ordered on PropertyFamily and Type.
|
||||
class PropertyType : public TotalOrdering<PropertyType>
|
||||
{
|
||||
friend class PropertyFamilyKey;
|
||||
friend class PropertyTypeKey;
|
||||
friend class PropertyFamily;
|
||||
|
||||
public:
|
||||
// Ordered on POINTERS to PropertyFamily
|
||||
class PropertyFamilyKey
|
||||
: public TotalOrdering<PropertyFamilyKey>,
|
||||
public TotalOrdering<PropertyFamilyKey, PropertyFamily>,
|
||||
public TotalOrdering<PropertyFamily, PropertyFamilyKey>
|
||||
{
|
||||
friend class PropertyType;
|
||||
friend class PropertyTypeKey;
|
||||
|
||||
PropertyFamilyKey(const PropertyType &type) : type(&type) {}
|
||||
|
||||
public:
|
||||
friend bool operator==(const PropertyFamilyKey &lhs,
|
||||
const PropertyFamilyKey &rhs)
|
||||
{
|
||||
return &(lhs.type->family) == &(rhs.type->family);
|
||||
}
|
||||
|
||||
friend bool operator<(const PropertyFamilyKey &lhs,
|
||||
const PropertyFamilyKey &rhs)
|
||||
{
|
||||
return &(lhs.type->family) < &(rhs.type->family);
|
||||
}
|
||||
|
||||
friend bool operator==(const PropertyFamilyKey &lhs,
|
||||
const PropertyFamily &rhs)
|
||||
{
|
||||
return &(lhs.type->family) == &(rhs);
|
||||
}
|
||||
|
||||
friend bool operator<(const PropertyFamilyKey &lhs,
|
||||
const PropertyFamily &rhs)
|
||||
{
|
||||
return &(lhs.type->family) < &(rhs);
|
||||
}
|
||||
|
||||
friend bool operator==(const PropertyFamily &lhs,
|
||||
const PropertyFamilyKey &rhs)
|
||||
{
|
||||
return &(lhs) == &(rhs.type->family);
|
||||
}
|
||||
|
||||
friend bool operator<(const PropertyFamily &lhs,
|
||||
const PropertyFamilyKey &rhs)
|
||||
{
|
||||
return &(lhs) < &(rhs.type->family);
|
||||
}
|
||||
|
||||
Type get_type() const { return type->type; }
|
||||
|
||||
Type prop_type() const { return type->type; }
|
||||
|
||||
std::string const &family_name() const
|
||||
{
|
||||
return type->family.name();
|
||||
}
|
||||
|
||||
const PropertyFamily &get_family() const { return type->family; }
|
||||
|
||||
const std::string to_str() const
|
||||
{
|
||||
return std::string(family_name());
|
||||
}
|
||||
|
||||
private:
|
||||
const PropertyType *type;
|
||||
};
|
||||
|
||||
// Ordered on POINTERS to PropertyType.
|
||||
// When compared with PropertyFamilyKey behaves as PropertyFamilyKey.
|
||||
template <class T>
|
||||
class PropertyTypeKey
|
||||
: public TotalOrdering<PropertyTypeKey<T>>,
|
||||
public TotalOrdering<PropertyFamilyKey, PropertyTypeKey<T>>,
|
||||
public TotalOrdering<PropertyTypeKey<T>, PropertyFamilyKey>
|
||||
{
|
||||
friend class PropertyType;
|
||||
|
||||
PropertyTypeKey(const PropertyType &type) : type(type) {}
|
||||
public:
|
||||
PropertyFamilyKey family_key() const
|
||||
{
|
||||
return PropertyFamilyKey(type);
|
||||
}
|
||||
|
||||
Type const &prop_type() const { return type.type; }
|
||||
|
||||
friend bool operator==(const PropertyTypeKey &lhs,
|
||||
const PropertyTypeKey &rhs)
|
||||
{
|
||||
return &(lhs.type) == &(rhs.type);
|
||||
}
|
||||
|
||||
friend bool operator<(const PropertyTypeKey &lhs,
|
||||
const PropertyTypeKey &rhs)
|
||||
{
|
||||
return &(lhs.type) < &(rhs.type);
|
||||
}
|
||||
|
||||
friend bool operator==(const PropertyFamilyKey &lhs,
|
||||
const PropertyTypeKey &rhs)
|
||||
{
|
||||
return lhs == rhs.family_key();
|
||||
}
|
||||
|
||||
friend bool operator<(const PropertyFamilyKey &lhs,
|
||||
const PropertyTypeKey &rhs)
|
||||
{
|
||||
return lhs < rhs.family_key();
|
||||
}
|
||||
|
||||
friend bool operator==(const PropertyTypeKey &lhs,
|
||||
const PropertyFamilyKey &rhs)
|
||||
{
|
||||
return lhs.family_key() == rhs;
|
||||
}
|
||||
|
||||
friend bool operator<(const PropertyTypeKey &lhs,
|
||||
const PropertyFamilyKey &rhs)
|
||||
{
|
||||
return lhs.family_key() < rhs;
|
||||
}
|
||||
|
||||
private:
|
||||
const PropertyType &type;
|
||||
};
|
||||
|
||||
private:
|
||||
PropertyType(PropertyFamily &family, Type type);
|
||||
PropertyType(PropertyFamily &other) = delete;
|
||||
PropertyType(PropertyFamily &&other) = delete;
|
||||
|
||||
public:
|
||||
template <class T>
|
||||
bool is() const
|
||||
{
|
||||
return type == T::type;
|
||||
}
|
||||
|
||||
bool is(Type &t) const;
|
||||
|
||||
// Returns key ordered on POINTERS to PropertyType.
|
||||
// When compared with PropertyFamilyKey behaves as PropertyFamilyKey.
|
||||
template <class T>
|
||||
PropertyTypeKey<T> type_key()
|
||||
{
|
||||
assert(this->is<T>());
|
||||
return PropertyTypeKey<T>(*this);
|
||||
}
|
||||
|
||||
// Returns key ordered on POINTERS to PropertyFamily
|
||||
PropertyFamilyKey family_key();
|
||||
|
||||
friend bool operator<(const PropertyType &lhs, const PropertyType &rhs)
|
||||
{
|
||||
return lhs.family < rhs.family ||
|
||||
(lhs.family == rhs.family && lhs.type < rhs.type);
|
||||
}
|
||||
|
||||
friend bool operator==(const PropertyType &lhs, const PropertyType &rhs)
|
||||
{
|
||||
return lhs.family == rhs.family && lhs.type == rhs.type;
|
||||
}
|
||||
|
||||
private:
|
||||
const PropertyFamily &family;
|
||||
const Type type;
|
||||
};
|
||||
|
||||
PropertyFamily(std::string const &name_v);
|
||||
PropertyFamily(std::string &&name_v);
|
||||
PropertyFamily(PropertyFamily &other) = delete;
|
||||
PropertyFamily(PropertyFamily &&other) = delete;
|
||||
|
||||
std::string const &name() const;
|
||||
|
||||
// Returns type if it exists otherwise creates it.
|
||||
PropertyType &get(Type type);
|
||||
|
||||
// Return pointer for NULL type. Extremly fast.
|
||||
PropertyType &getNull() const { return *null_type; }
|
||||
|
||||
friend bool operator<(const PropertyFamily &lhs, const PropertyFamily &rhs);
|
||||
|
||||
friend bool operator==(const PropertyFamily &lhs,
|
||||
const PropertyFamily &rhs);
|
||||
|
||||
// Place for index of TG::elements which have property from this family.
|
||||
IndexHolder<TG, std::nullptr_t> index;
|
||||
|
||||
private:
|
||||
const std::string name_v;
|
||||
|
||||
// This is exclusivly for getNull method.
|
||||
PropertyType *null_type{nullptr};
|
||||
|
||||
// TODO: Because types wont be removed this could be done with more efficent
|
||||
// data structure.
|
||||
ConcurrentMap<Type, std::unique_ptr<PropertyType>> types;
|
||||
};
|
||||
|
||||
using VertexPropertyKey =
|
||||
PropertyFamily<TypeGroupVertex>::PropertyType::PropertyFamilyKey;
|
||||
using EdgePropertyKey =
|
||||
PropertyFamily<TypeGroupEdge>::PropertyType::PropertyFamilyKey;
|
||||
template <class T>
|
||||
using VertexPropertyType =
|
||||
PropertyFamily<TypeGroupVertex>::PropertyType::PropertyTypeKey<T>;
|
||||
template <class T>
|
||||
using EdgePropertyType =
|
||||
PropertyFamily<TypeGroupEdge>::PropertyType::PropertyTypeKey<T>;
|
@ -1,291 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "storage/model/properties/all.hpp"
|
||||
|
||||
// Generates constructor by value which accepts type_name object and stores them
|
||||
// in union_name field.
|
||||
#define GENERATE_CONSTRUCTOR_FOR_DATA(type_name, union_name) \
|
||||
PropertyHolder(type_name &&data, T k) \
|
||||
: union_name(std::move(data)), key(k) \
|
||||
{ \
|
||||
assert(type_name::type == key.get_type()); \
|
||||
}
|
||||
|
||||
// Genrates case claus for Flags::type_name to construct type_name object in
|
||||
// place of union_name field by a move from other
|
||||
#define GENERATE_CASE_CLAUSE_FOR_CONSTRUCTOR_MOVE(type_name, union_name) \
|
||||
case Flags::type_name: { \
|
||||
new (&(this->union_name)) type_name(std::move(other.union_name)); \
|
||||
break; \
|
||||
}
|
||||
|
||||
// Genrates case claus for Flags::type_name to construct type_name object in
|
||||
// place of union_name field by a copy from other
|
||||
#define GENERATE_CASE_CLAUSE_FOR_CONSTRUCTOR_COPY(type_name, union_name) \
|
||||
case Flags::type_name: { \
|
||||
new (&(this->union_name)) type_name(other.union_name); \
|
||||
break; \
|
||||
}
|
||||
|
||||
// Genrates case claus for Flags::type_name to destruct type_name object in
|
||||
// place of union_name field
|
||||
#define GENERATE_CASE_CLAUSE_FOR_DESTRUCTOR(type_name, union_name) \
|
||||
case Flags::type_name: { \
|
||||
this->union_name.~type_name(); \
|
||||
break; \
|
||||
}
|
||||
|
||||
// Genrates case claus for Flags::type_name to handle type_name object from
|
||||
// field of union_name
|
||||
#define GENERATE_CASE_CLAUSE_FOR_HANDLER(type_name, union_name) \
|
||||
case Flags::type_name: { \
|
||||
h.handle(this->union_name); \
|
||||
break; \
|
||||
}
|
||||
|
||||
// Genrates case claus for Flags::type_name to handle primitives of type_name
|
||||
// object from field of union_name
|
||||
#define GENERATE_CASE_CLAUSE_FOR_HANDLER_PRIMITIVE(type_name, union_name) \
|
||||
case Flags::type_name: { \
|
||||
h.handle(this->union_name.value()); \
|
||||
break; \
|
||||
}
|
||||
|
||||
// Genrates case claus for Flags::type_name to print type_name object from
|
||||
// field of union_name
|
||||
#define GENERATE_CASE_CLAUSE_FOR_PRINT(type_name, union_name) \
|
||||
case Flags::type_name: { \
|
||||
return this->union_name.print(stream); \
|
||||
}
|
||||
|
||||
// Genrates case claus for Flags::type_name to comapre type_name object from
|
||||
// field of union_name with same named and field from other holder.
|
||||
#define GENERATE_CASE_CLAUSE_FOR_COMPARISON(type_name, union_name) \
|
||||
case Flags::type_name: { \
|
||||
return this->union_name == other.union_name; \
|
||||
}
|
||||
|
||||
// Generates field in a union with a given type and name
|
||||
#define GENERATE_UNION_FIELD(type_name, union_name) type_name union_name
|
||||
|
||||
// Generates signatures define_generator(type_name, union_name );
|
||||
// for every pair type,property
|
||||
#define GENERATE_FOR_ALL_PROPERTIES(define_generator) \
|
||||
define_generator(Null, null_v); \
|
||||
define_generator(Bool, bool_v); \
|
||||
define_generator(Int32, int32_v); \
|
||||
define_generator(Int64, int64_v); \
|
||||
define_generator(Float, float_V); \
|
||||
define_generator(Double, double_v); \
|
||||
define_generator(String, string_v); \
|
||||
define_generator(ArrayBool, array_bool); \
|
||||
define_generator(ArrayInt32, array_int32); \
|
||||
define_generator(ArrayInt64, array_int64); \
|
||||
define_generator(ArrayFloat, array_float); \
|
||||
define_generator(ArrayDouble, array_double); \
|
||||
define_generator(ArrayString, array_string);
|
||||
|
||||
// Holds property and has some means of determining its type.
|
||||
// T must have method get_type() const which returns Type.
|
||||
template <class T>
|
||||
class PropertyHolder
|
||||
{
|
||||
// He is his own best friend.
|
||||
template <class O>
|
||||
friend class PropertyHolder;
|
||||
|
||||
public:
|
||||
PropertyHolder() = delete;
|
||||
|
||||
GENERATE_FOR_ALL_PROPERTIES(GENERATE_CONSTRUCTOR_FOR_DATA);
|
||||
|
||||
PropertyHolder(PropertyHolder const &other) : key(other.key)
|
||||
{
|
||||
switch (other.key.get_type().flags()) {
|
||||
GENERATE_FOR_ALL_PROPERTIES(
|
||||
GENERATE_CASE_CLAUSE_FOR_CONSTRUCTOR_COPY);
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
assert(key.get_type().flags() == Flags::Int64 || this->int64_v != 0);
|
||||
}
|
||||
|
||||
PropertyHolder(PropertyHolder &&other) : key(other.key)
|
||||
{
|
||||
switch (other.key.get_type().flags()) {
|
||||
GENERATE_FOR_ALL_PROPERTIES(
|
||||
GENERATE_CASE_CLAUSE_FOR_CONSTRUCTOR_MOVE);
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
|
||||
template <class O>
|
||||
PropertyHolder(PropertyHolder<O> &&other, T const &key) : key(key)
|
||||
{
|
||||
assert(other.key.get_type() == key.get_type());
|
||||
switch (key.get_type().flags()) {
|
||||
GENERATE_FOR_ALL_PROPERTIES(
|
||||
GENERATE_CASE_CLAUSE_FOR_CONSTRUCTOR_MOVE);
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
assert(key.get_type().flags() == Flags::Int64 || this->int64_v != 0);
|
||||
}
|
||||
|
||||
~PropertyHolder()
|
||||
{
|
||||
switch (key.get_type().flags()) {
|
||||
GENERATE_FOR_ALL_PROPERTIES(GENERATE_CASE_CLAUSE_FOR_DESTRUCTOR);
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
|
||||
PropertyHolder &operator=(PropertyHolder const &other)
|
||||
{
|
||||
this->~PropertyHolder();
|
||||
new (this) PropertyHolder(other);
|
||||
assert(key.get_type().flags() == Flags::Int64 || this->int64_v != 0);
|
||||
return *this;
|
||||
}
|
||||
|
||||
PropertyHolder &operator=(PropertyHolder &&other)
|
||||
{
|
||||
this->~PropertyHolder();
|
||||
new (this) PropertyHolder(std::move(other));
|
||||
assert(key.get_type().flags() == Flags::Int64 || this->int64_v != 0);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Calls appropiate handler with a database property.
|
||||
// (String,Int64,ArrayBool,...)
|
||||
template <class Handler>
|
||||
void accept(Handler &h) const
|
||||
{
|
||||
switch (key.get_type().flags()) {
|
||||
GENERATE_FOR_ALL_PROPERTIES(GENERATE_CASE_CLAUSE_FOR_HANDLER);
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
|
||||
// Calls appropiate handler with a primitive.(std::string,bool,int64_t,...)
|
||||
template <class Handler>
|
||||
void accept_primitive(Handler &h) const
|
||||
{
|
||||
switch (key.get_type().flags()) {
|
||||
GENERATE_FOR_ALL_PROPERTIES(
|
||||
GENERATE_CASE_CLAUSE_FOR_HANDLER_PRIMITIVE);
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
|
||||
std::ostream &print(std::ostream &stream) const
|
||||
{
|
||||
switch (key.get_type().flags()) {
|
||||
GENERATE_FOR_ALL_PROPERTIES(GENERATE_CASE_CLAUSE_FOR_PRINT);
|
||||
default:
|
||||
// TODO: custom error
|
||||
throw std::runtime_error("PropertyHolder::print -> unknown flag");
|
||||
}
|
||||
}
|
||||
|
||||
friend std::ostream &operator<<(std::ostream &stream,
|
||||
const PropertyHolder &prop)
|
||||
{
|
||||
return prop.print(stream);
|
||||
}
|
||||
|
||||
bool operator==(const PropertyHolder &other) const
|
||||
{
|
||||
if (key == other.key) {
|
||||
switch (key.get_type().flags()) {
|
||||
GENERATE_FOR_ALL_PROPERTIES(GENERATE_CASE_CLAUSE_FOR_COMPARISON);
|
||||
default:
|
||||
assert(false);
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
template <class O>
|
||||
bool operator==(const PropertyHolder<O> &other) const
|
||||
{
|
||||
if (key.get_type() == other.key.get_type()) {
|
||||
switch (key.get_type().flags()) {
|
||||
GENERATE_FOR_ALL_PROPERTIES(GENERATE_CASE_CLAUSE_FOR_COMPARISON);
|
||||
default:
|
||||
assert(false);
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
template <class O, Flags f = O::type.flags()>
|
||||
bool operator==(const O &other) const
|
||||
{
|
||||
if (key.get_type() == O::type) {
|
||||
return other == as<O>();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool operator!=(const PropertyHolder &other) const
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
// True if NULL
|
||||
bool is_empty() const { return is<Null>(); }
|
||||
|
||||
// True if contains T property
|
||||
template <class D>
|
||||
bool is() const
|
||||
{
|
||||
return D::type == key.get_type();
|
||||
}
|
||||
|
||||
// T MUST be type with which this holder was constructed.
|
||||
template <class D>
|
||||
D &as()
|
||||
{
|
||||
assert(is<D>());
|
||||
return *reinterpret_cast<D *>(&array_string);
|
||||
}
|
||||
|
||||
// T MUST be type with which this PropertyData was constructed.
|
||||
// Specialized after this class
|
||||
template <class D>
|
||||
D const &as() const
|
||||
{
|
||||
assert(is<D>());
|
||||
return *reinterpret_cast<D const *>(&array_string);
|
||||
}
|
||||
|
||||
// Knows type
|
||||
const T key;
|
||||
|
||||
private:
|
||||
// Stored data.
|
||||
union
|
||||
{
|
||||
GENERATE_FOR_ALL_PROPERTIES(GENERATE_UNION_FIELD);
|
||||
};
|
||||
};
|
||||
|
||||
#undef GENERATE_CONSTRUCTOR_FOR_DATA
|
||||
#undef GENERATE_CASE_CLAUSE_FOR_CONSTRUCTOR_MOVE
|
||||
#undef GENERATE_CASE_CLAUSE_FOR_CONSTRUCTOR_COPY
|
||||
#undef GENERATE_CASE_CLAUSE_FOR_DESTRUCTOR
|
||||
#undef GENERATE_CASE_CLAUSE_FOR_HANDLER
|
||||
#undef GENERATE_CASE_CLAUSE_FOR_PRINT
|
||||
#undef GENERATE_CASE_CLAUSE_FOR_COMPARISON
|
||||
#undef GENERATE_UNION_FIELD
|
||||
#undef GENERATE_FOR_ALL_PROPERTIES
|
@ -1,28 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "storage/model/properties/flags.hpp"
|
||||
#include "storage/model/properties/property_family.hpp"
|
||||
#include "storage/model/properties/property_holder.hpp"
|
||||
|
||||
template <class TG>
|
||||
using property_key =
|
||||
typename PropertyFamily<TG>::PropertyType::PropertyFamilyKey;
|
||||
|
||||
// Property Class designated for creation inside the database. Meant for
|
||||
// storage.
|
||||
template <class TG>
|
||||
class StoredProperty : public PropertyHolder<property_key<TG>>
|
||||
{
|
||||
// null property family
|
||||
const static class PropertyFamily<TG> null_family;
|
||||
|
||||
public:
|
||||
// NOTE: Needed for properties to return reference on stored property when
|
||||
// they don't cointain searched property.
|
||||
const static class StoredProperty<TG> null;
|
||||
|
||||
using PropertyHolder<property_key<TG>>::PropertyHolder;
|
||||
|
||||
template <class P>
|
||||
StoredProperty(PropertyFamily<TG> &family, P &&property);
|
||||
};
|
@ -1,37 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <ostream>
|
||||
#include <string>
|
||||
|
||||
#include "storage/model/properties/flags.hpp"
|
||||
|
||||
class String
|
||||
{
|
||||
public:
|
||||
const static Type type;
|
||||
|
||||
String(std::string const &d) : data(std::make_shared<std::string>(d)) {}
|
||||
String(std::string &&d) : data(std::make_shared<std::string>(std::move(d)))
|
||||
{
|
||||
}
|
||||
|
||||
std::string &value() { return *data.get(); }
|
||||
|
||||
std::string const &value() const { return *data.get(); }
|
||||
|
||||
std::ostream &print(std::ostream &stream) const;
|
||||
|
||||
friend std::ostream &operator<<(std::ostream &stream, const String &prop);
|
||||
|
||||
bool operator==(const String &other) const;
|
||||
|
||||
bool operator==(const std::string &other) const;
|
||||
|
||||
// NOTE: OTHER METHODS WILL AUTOMATICALLY USE THIS IN CERTAIN SITUATIONS
|
||||
// TO MOVE STD::STRING OUT OF SHARED_PTR WHICH IS BAD.
|
||||
// operator const std::string &() const;
|
||||
|
||||
private:
|
||||
std::shared_ptr<std::string> data;
|
||||
};
|
@ -1,25 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
template <class Derived>
|
||||
struct MathOperations
|
||||
{
|
||||
friend Derived operator+(const Derived& lhs, const Derived& rhs)
|
||||
{
|
||||
return Derived(lhs.value + rhs.value);
|
||||
}
|
||||
|
||||
friend Derived operator-(const Derived& lhs, const Derived& rhs)
|
||||
{
|
||||
return Derived(lhs.value - rhs.value);
|
||||
}
|
||||
|
||||
friend Derived operator*(const Derived& lhs, const Derived& rhs)
|
||||
{
|
||||
return Derived(lhs.value * rhs.value);
|
||||
}
|
||||
|
||||
friend Derived operator/(const Derived& lhs, const Derived& rhs)
|
||||
{
|
||||
return Derived(lhs.value / rhs.value);
|
||||
}
|
||||
};
|
@ -1,10 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
template <class Derived>
|
||||
struct Modulo
|
||||
{
|
||||
friend Derived operator%(const Derived& lhs, const Derived& rhs)
|
||||
{
|
||||
return Derived(lhs.value % rhs.value);
|
||||
}
|
||||
};
|
@ -1,12 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "utils/crtp.hpp"
|
||||
|
||||
template <class Derived>
|
||||
struct UnaryNegation : public Crtp<Derived>
|
||||
{
|
||||
Derived operator-() const
|
||||
{
|
||||
return Derived(-this->derived().value);
|
||||
}
|
||||
};
|
@ -1,125 +1,108 @@
|
||||
#include "database/db.hpp"
|
||||
#include "database/db_accessor.hpp"
|
||||
#include "utils/iterator/iterator.hpp"
|
||||
|
||||
DbAccessor::DbAccessor(Db &db)
|
||||
: db_transaction(std::move(DbTransaction(db, db.tx_engine.begin())))
|
||||
{
|
||||
: db_transaction(std::move(DbTransaction(db, db.tx_engine.begin()))) {
|
||||
}
|
||||
|
||||
DbAccessor::DbAccessor(Db &db, tx::Transaction &t)
|
||||
: db_transaction(std::move(DbTransaction(db, t)))
|
||||
{
|
||||
: db_transaction(std::move(DbTransaction(db, t))) {
|
||||
}
|
||||
|
||||
// VERTEX METHODS
|
||||
|
||||
Option<const VertexAccessor> DbAccessor::vertex_find(const Id &id)
|
||||
{
|
||||
return this->db_transaction.db.graph.vertices.find(db_transaction, id);
|
||||
Option<const VertexAccessor> DbAccessor::vertex_find(const Id &id) {
|
||||
return this->db_transaction.db.graph.vertices.find(db_transaction, id);
|
||||
}
|
||||
|
||||
VertexAccessor DbAccessor::vertex_insert()
|
||||
{
|
||||
return this->db_transaction.db.graph.vertices.insert(db_transaction);
|
||||
VertexAccessor DbAccessor::vertex_insert() {
|
||||
return this->db_transaction.db.graph.vertices.insert(db_transaction);
|
||||
}
|
||||
|
||||
// EDGE METHODS
|
||||
|
||||
Option<const EdgeAccessor> DbAccessor::edge_find(const Id &id)
|
||||
{
|
||||
return db_transaction.db.graph.edges.find(db_transaction, id);
|
||||
Option<const EdgeAccessor> DbAccessor::edge_find(const Id &id) {
|
||||
return db_transaction.db.graph.edges.find(db_transaction, id);
|
||||
}
|
||||
|
||||
EdgeAccessor DbAccessor::edge_insert(VertexAccessor &from, VertexAccessor &to)
|
||||
{
|
||||
auto edge_accessor = db_transaction.db.graph.edges.insert(
|
||||
db_transaction, from.vlist, to.vlist);
|
||||
EdgeAccessor DbAccessor::edge_insert(VertexAccessor &from, VertexAccessor &to) {
|
||||
auto edge_accessor = db_transaction.db.graph.edges.insert(
|
||||
db_transaction, from.vlist, to.vlist);
|
||||
|
||||
// Connect edge with from,to vertices.
|
||||
from->data.out.add(edge_accessor.vlist);
|
||||
to->data.in.add(edge_accessor.vlist);
|
||||
// Connect edge with from,to vertices.
|
||||
from->data.out.add(edge_accessor.vlist);
|
||||
to->data.in.add(edge_accessor.vlist);
|
||||
|
||||
return edge_accessor;
|
||||
return edge_accessor;
|
||||
}
|
||||
|
||||
EdgeAccessor DbAccessor::edge_insert(VertexAccessor const &from,
|
||||
VertexAccessor const &to)
|
||||
{
|
||||
auto edge_accessor = db_transaction.db.graph.edges.insert(
|
||||
db_transaction, from.vlist, to.vlist);
|
||||
VertexAccessor const &to) {
|
||||
auto edge_accessor = db_transaction.db.graph.edges.insert(
|
||||
db_transaction, from.vlist, to.vlist);
|
||||
|
||||
// Connect edge with updated from,to vertices.
|
||||
from.update()->data.out.add(edge_accessor.vlist);
|
||||
to.update()->data.in.add(edge_accessor.vlist);
|
||||
// Connect edge with updated from,to vertices.
|
||||
from.update()->data.out.add(edge_accessor.vlist);
|
||||
to.update()->data.in.add(edge_accessor.vlist);
|
||||
|
||||
return edge_accessor;
|
||||
return edge_accessor;
|
||||
}
|
||||
|
||||
// LABEL METHODS
|
||||
const Label &DbAccessor::label_find_or_create(const char *name)
|
||||
{
|
||||
return db_transaction.db.graph.label_store.find_or_create(name);
|
||||
const Label &DbAccessor::label_find_or_create(const char *name) {
|
||||
return db_transaction.db.graph.label_store.find_or_create(name);
|
||||
}
|
||||
|
||||
bool DbAccessor::label_contains(const char *name)
|
||||
{
|
||||
return db_transaction.db.graph.label_store.contains(name);
|
||||
bool DbAccessor::label_contains(const char *name) {
|
||||
return db_transaction.db.graph.label_store.contains(name);
|
||||
}
|
||||
|
||||
// TYPE METHODS
|
||||
const EdgeType &DbAccessor::type_find_or_create(const char *name)
|
||||
{
|
||||
return db_transaction.db.graph.edge_type_store.find_or_create(name);
|
||||
const EdgeType &DbAccessor::type_find_or_create(const char *name) {
|
||||
return db_transaction.db.graph.edge_type_store.find_or_create(name);
|
||||
}
|
||||
|
||||
bool DbAccessor::type_contains(const char *name)
|
||||
{
|
||||
return db_transaction.db.graph.edge_type_store.contains(name);
|
||||
bool DbAccessor::type_contains(const char *name) {
|
||||
return db_transaction.db.graph.edge_type_store.contains(name);
|
||||
}
|
||||
|
||||
// PROPERTY METHODS
|
||||
VertexPropertyFamily &
|
||||
DbAccessor::vertex_property_family_get(const std::string &name)
|
||||
{
|
||||
return db_transaction.db.graph.vertices.property_family_find_or_create(
|
||||
name);
|
||||
DbAccessor::vertex_property_family_get(const std::string &name) {
|
||||
return db_transaction.db.graph.vertices.property_family_find_or_create(
|
||||
name);
|
||||
}
|
||||
|
||||
EdgePropertyFamily &
|
||||
DbAccessor::edge_property_family_get(const std::string &name)
|
||||
{
|
||||
return db_transaction.db.graph.edges.property_family_find_or_create(name);
|
||||
DbAccessor::edge_property_family_get(const std::string &name) {
|
||||
return db_transaction.db.graph.edges.property_family_find_or_create(name);
|
||||
}
|
||||
|
||||
// PROPERTY HELPER METHODS
|
||||
VertexPropertyFamily::PropertyType::PropertyFamilyKey
|
||||
DbAccessor::vertex_property_key(const std::string &name, Type type)
|
||||
{
|
||||
return vertex_property_family_get(name).get(type).family_key();
|
||||
DbAccessor::vertex_property_key(const std::string &name, Type type) {
|
||||
return vertex_property_family_get(name).get(type).family_key();
|
||||
}
|
||||
|
||||
EdgePropertyFamily::PropertyType::PropertyFamilyKey
|
||||
DbAccessor::edge_property_key(const std::string &name, Type type)
|
||||
{
|
||||
return edge_property_family_get(name).get(type).family_key();
|
||||
DbAccessor::edge_property_key(const std::string &name, Type type) {
|
||||
return edge_property_family_get(name).get(type).family_key();
|
||||
}
|
||||
|
||||
bool DbAccessor::update_indexes()
|
||||
{
|
||||
return db_transaction.update_indexes();
|
||||
bool DbAccessor::update_indexes() {
|
||||
return db_transaction.update_indexes();
|
||||
}
|
||||
|
||||
// TRANSACTION METHODS
|
||||
bool DbAccessor::commit()
|
||||
{
|
||||
if (db_transaction.update_indexes()) {
|
||||
db_transaction.trans.commit();
|
||||
return true;
|
||||
} else {
|
||||
// Index update wasn't successfull so whe are aborting transaction.
|
||||
db_transaction.trans.abort();
|
||||
return false;
|
||||
}
|
||||
bool DbAccessor::commit() {
|
||||
if (db_transaction.update_indexes()) {
|
||||
db_transaction.trans.commit();
|
||||
return true;
|
||||
} else {
|
||||
// Index update wasn't successfull so whe are aborting transaction.
|
||||
db_transaction.trans.abort();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void DbAccessor::abort() { db_transaction.trans.abort(); }
|
||||
|
@ -1,16 +0,0 @@
|
||||
#include "storage/model/properties/array.hpp"
|
||||
|
||||
template <class T, Flags flag_t>
|
||||
const Type Array<T, flag_t>::type = Type(flag_t);
|
||||
|
||||
template class Array<std::string, Flags::ArrayString>;
|
||||
|
||||
template class Array<bool, Flags::ArrayBool>;
|
||||
|
||||
template class Array<int32_t, Flags::ArrayInt32>;
|
||||
|
||||
template class Array<int64_t, Flags::ArrayInt64>;
|
||||
|
||||
template class Array<float, Flags::ArrayFloat>;
|
||||
|
||||
template class Array<double, Flags::ArrayDouble>;
|
@ -1,3 +0,0 @@
|
||||
#include "storage/model/properties/bool.hpp"
|
||||
|
||||
const Type Bool::type = Type(Flags::Bool);
|
@ -1,3 +0,0 @@
|
||||
#include "storage/model/properties/double.hpp"
|
||||
|
||||
const Type Double::type = Type(Flags::Double);
|
@ -1,3 +0,0 @@
|
||||
#include "storage/model/properties/float.hpp"
|
||||
|
||||
const Type Float::type = Type(Flags::Float);
|
@ -1,3 +0,0 @@
|
||||
#include "storage/model/properties/int32.hpp"
|
||||
|
||||
const Type Int32::type = Type(Flags::Int32);
|
@ -1,3 +0,0 @@
|
||||
#include "storage/model/properties/int64.hpp"
|
||||
|
||||
const Type Int64::type = Type(Flags::Int64);
|
@ -1,17 +0,0 @@
|
||||
#include "storage/model/properties/null.hpp"
|
||||
|
||||
const Type Null::type = Type(Flags::Null);
|
||||
|
||||
bool Null::operator==(const Null &) const { return true; }
|
||||
|
||||
Null::operator bool() { return false; }
|
||||
|
||||
std::ostream &operator<<(std::ostream &stream, const Null &)
|
||||
{
|
||||
return stream << "NULL";
|
||||
}
|
||||
|
||||
std::ostream &Null::print(std::ostream &stream) const
|
||||
{
|
||||
return operator<<(stream, *this);
|
||||
}
|
@ -1,86 +0,0 @@
|
||||
#include "storage/model/properties/properties.hpp"
|
||||
|
||||
#include "storage/model/properties/null.hpp"
|
||||
#include "storage/model/properties/property_family.hpp"
|
||||
#include "utils/option.hpp"
|
||||
|
||||
#include "storage/type_group_edge.hpp"
|
||||
#include "storage/type_group_vertex.hpp"
|
||||
|
||||
template <class TG>
|
||||
const bool Properties<TG>::contains(property_key &key) const
|
||||
{
|
||||
for (auto &prop : props)
|
||||
{
|
||||
if (prop.key == key)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
template <class TG>
|
||||
const StoredProperty<TG> &Properties<TG>::at(PropertyFamily<TG> &fam) const
|
||||
{
|
||||
// It doesn't matter whit which type
|
||||
// compare is done, thats why getNull
|
||||
// method is here to give fast access
|
||||
// to such key.
|
||||
auto f_key = fam.getNull().family_key();
|
||||
return at(f_key);
|
||||
}
|
||||
|
||||
template <class TG>
|
||||
const StoredProperty<TG> &Properties<TG>::at(property_key &key) const
|
||||
{
|
||||
for (auto &prop : props) {
|
||||
if (prop.key == key) {
|
||||
return prop;
|
||||
}
|
||||
}
|
||||
return StoredProperty<TG>::null;
|
||||
}
|
||||
|
||||
template <class TG>
|
||||
void Properties<TG>::set(StoredProperty<TG> &&value)
|
||||
{
|
||||
for (auto &prop : props) {
|
||||
if (prop.key == value.key) {
|
||||
// It is necessary to change key because the types from before and
|
||||
// now could be different.
|
||||
StoredProperty<TG> &sp = const_cast<StoredProperty<TG> &>(prop);
|
||||
sp = std::move(value);
|
||||
return;
|
||||
}
|
||||
}
|
||||
props.push_back(std::move(value));
|
||||
}
|
||||
|
||||
template <class TG>
|
||||
void Properties<TG>::clear(property_key &key)
|
||||
{
|
||||
auto end = props.end();
|
||||
for (auto it = props.begin(); it != end; it++) {
|
||||
if (it->key == key) {
|
||||
props.erase(it);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class TG>
|
||||
void Properties<TG>::clear(PropertyFamily<TG> &fam)
|
||||
{
|
||||
// It doesn't matter whit which type
|
||||
// find is called, thats why getNull
|
||||
// method is here to give fast access
|
||||
// to such key.
|
||||
auto f_key = fam.getNull().family_key();
|
||||
clear(f_key);
|
||||
}
|
||||
|
||||
template class Properties<TypeGroupEdge>;
|
||||
|
||||
template class Properties<TypeGroupVertex>;
|
@ -1,68 +0,0 @@
|
||||
#include "storage/model/properties/property.hpp"
|
||||
|
||||
#include "storage/model/properties/all.hpp"
|
||||
|
||||
Property Property::handle(Void &&v)
|
||||
{
|
||||
return Property(Null(), Type(Flags::Null));
|
||||
}
|
||||
|
||||
Property Property::handle(bool &&prop)
|
||||
{
|
||||
return Property(Bool(prop), Type(Flags::Bool));
|
||||
}
|
||||
|
||||
Property Property::handle(float &&prop)
|
||||
{
|
||||
return Property(Float(prop), Type(Flags::Float));
|
||||
}
|
||||
|
||||
Property Property::handle(double &&prop)
|
||||
{
|
||||
return Property(Double(prop), Type(Flags::Double));
|
||||
}
|
||||
|
||||
Property Property::handle(int32_t &&prop)
|
||||
{
|
||||
return Property(Int32(prop), Type(Flags::Int32));
|
||||
}
|
||||
|
||||
Property Property::handle(int64_t &&prop)
|
||||
{
|
||||
return Property(Int64(prop), Type(Flags::Int64));
|
||||
}
|
||||
|
||||
Property Property::handle(std::string &&value)
|
||||
{
|
||||
return Property(String(std::move(value)), Type(Flags::String));
|
||||
}
|
||||
|
||||
Property Property::handle(ArrayStore<bool> &&a)
|
||||
{
|
||||
return Property(ArrayBool(std::move(a)), Type(Flags::ArrayBool));
|
||||
}
|
||||
|
||||
Property Property::handle(ArrayStore<int32_t> &&a)
|
||||
{
|
||||
return Property(ArrayInt32(std::move(a)), Type(Flags::ArrayInt32));
|
||||
}
|
||||
|
||||
Property Property::handle(ArrayStore<int64_t> &&a)
|
||||
{
|
||||
return Property(ArrayInt64(std::move(a)), Type(Flags::ArrayInt64));
|
||||
}
|
||||
|
||||
Property Property::handle(ArrayStore<float> &&a)
|
||||
{
|
||||
return Property(ArrayFloat(std::move(a)), Type(Flags::ArrayFloat));
|
||||
}
|
||||
|
||||
Property Property::handle(ArrayStore<double> &&a)
|
||||
{
|
||||
return Property(ArrayDouble(std::move(a)), Type(Flags::ArrayDouble));
|
||||
}
|
||||
|
||||
Property Property::handle(ArrayStore<std::string> &&a)
|
||||
{
|
||||
return Property(ArrayString(std::move(a)), Type(Flags::ArrayString));
|
||||
}
|
@ -1,62 +0,0 @@
|
||||
#include "storage/model/properties/property_family.hpp"
|
||||
|
||||
#include "storage/type_group_edge.hpp"
|
||||
#include "storage/type_group_vertex.hpp"
|
||||
|
||||
template <class T>
|
||||
PropertyFamily<T>::PropertyFamily(std::string const &name_v)
|
||||
: name_v(std::forward<const std::string>(name_v))
|
||||
{
|
||||
null_type = &get(Flags::Null);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
PropertyFamily<T>::PropertyFamily(std::string &&name_v)
|
||||
: name_v(std::move(name_v))
|
||||
{
|
||||
null_type = &get(Flags::Null);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
std::string const &PropertyFamily<T>::name() const
|
||||
{
|
||||
return name_v;
|
||||
}
|
||||
|
||||
// Returns type if it exists otherwise creates it.
|
||||
template <class T>
|
||||
typename PropertyFamily<T>::PropertyType &PropertyFamily<T>::get(Type type)
|
||||
{
|
||||
auto acc = types.access();
|
||||
auto it = acc.find(type);
|
||||
if (it == acc.end()) {
|
||||
auto value =
|
||||
std::unique_ptr<PropertyType>(new PropertyType(*this, type));
|
||||
auto res = acc.insert(type, std::move(value));
|
||||
it = res.first;
|
||||
}
|
||||
return *(it->second);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
PropertyFamily<T>::PropertyType::PropertyType(PropertyFamily &family, Type type)
|
||||
: family(family), type(std::move(type))
|
||||
{
|
||||
}
|
||||
|
||||
template <class T>
|
||||
bool PropertyFamily<T>::PropertyType::is(Type &t) const
|
||||
{
|
||||
return type == t;
|
||||
}
|
||||
|
||||
// Returns key ordered on POINTERS to PropertyFamily
|
||||
template <class T>
|
||||
typename PropertyFamily<T>::PropertyType::PropertyFamilyKey
|
||||
PropertyFamily<T>::PropertyType::family_key()
|
||||
{
|
||||
return PropertyFamilyKey(*this);
|
||||
}
|
||||
|
||||
template class PropertyFamily<TypeGroupEdge>;
|
||||
template class PropertyFamily<TypeGroupVertex>;
|
@ -1,26 +0,0 @@
|
||||
#include "storage/model/properties/property.hpp"
|
||||
#include "storage/model/properties/stored_property.hpp"
|
||||
|
||||
template <class TG>
|
||||
const PropertyFamily<TG> StoredProperty<TG>::null_family("NULL");
|
||||
|
||||
template <class TG>
|
||||
const StoredProperty<TG> StoredProperty<TG>::null = {
|
||||
Null(), StoredProperty<TG>::null_family.getNull().family_key()};
|
||||
|
||||
template <class TG>
|
||||
template <class P>
|
||||
StoredProperty<TG>::StoredProperty(PropertyFamily<TG> &family, P &&property)
|
||||
: StoredProperty(std::move(property),
|
||||
family.get(property.key.get_type()).family_key())
|
||||
{
|
||||
}
|
||||
|
||||
template class StoredProperty<TypeGroupVertex>;
|
||||
template class StoredProperty<TypeGroupEdge>;
|
||||
|
||||
template StoredProperty<TypeGroupVertex>::StoredProperty(
|
||||
PropertyFamily<TypeGroupVertex> &family, Property &&property);
|
||||
|
||||
template StoredProperty<TypeGroupEdge>::StoredProperty(
|
||||
PropertyFamily<TypeGroupEdge> &family, Property &&property);
|
@ -1,23 +0,0 @@
|
||||
#include "storage/model/properties/string.hpp"
|
||||
|
||||
const Type String::type = Type(Flags::String);
|
||||
|
||||
bool String::operator==(const String &other) const
|
||||
{
|
||||
return value() == other.value();
|
||||
}
|
||||
|
||||
bool String::operator==(const std::string &other) const
|
||||
{
|
||||
return value() == other;
|
||||
}
|
||||
|
||||
std::ostream &operator<<(std::ostream &stream, const String &prop)
|
||||
{
|
||||
return stream << prop.value();
|
||||
}
|
||||
|
||||
std::ostream &String::print(std::ostream &stream) const
|
||||
{
|
||||
return operator<<(stream, *this);
|
||||
}
|
Loading…
Reference in New Issue
Block a user