forked from blue/lmdbal
some more primitive specializations, counting rows, dropping tables, tests
This commit is contained in:
parent
047f96b54a
commit
2f34fa69e8
@ -44,6 +44,14 @@ set(HEADERS
|
|||||||
serializer_uint16.hpp
|
serializer_uint16.hpp
|
||||||
serializer_uint32.hpp
|
serializer_uint32.hpp
|
||||||
serializer_uint64.hpp
|
serializer_uint64.hpp
|
||||||
|
serializer_int8.hpp
|
||||||
|
serializer_int16.hpp
|
||||||
|
serializer_int32.hpp
|
||||||
|
serializer_int64.hpp
|
||||||
|
serializer_float.hpp
|
||||||
|
serializer_double.hpp
|
||||||
|
serializer_stdstring.hpp
|
||||||
|
serializer_qstring.hpp
|
||||||
)
|
)
|
||||||
|
|
||||||
if (BUILD_STATIC)
|
if (BUILD_STATIC)
|
||||||
|
24
database.cpp
24
database.cpp
@ -85,7 +85,7 @@ void DataBase::open()
|
|||||||
bool DataBase::removeDirectory()
|
bool DataBase::removeDirectory()
|
||||||
{
|
{
|
||||||
if (opened) {
|
if (opened) {
|
||||||
throw Opened(name, "");
|
throw Opened(name, "remove database directory");
|
||||||
}
|
}
|
||||||
QString path(QStandardPaths::writableLocation(QStandardPaths::CacheLocation));
|
QString path(QStandardPaths::writableLocation(QStandardPaths::CacheLocation));
|
||||||
path += "/" + getName();
|
path += "/" + getName();
|
||||||
@ -108,3 +108,25 @@ bool DataBase::ready() const
|
|||||||
return opened;
|
return opened;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DataBase::drop()
|
||||||
|
{
|
||||||
|
if (!opened) {
|
||||||
|
throw Closed("drop", name);
|
||||||
|
}
|
||||||
|
|
||||||
|
MDB_txn *txn;
|
||||||
|
int rc = mdb_txn_begin(environment, NULL, 0, &txn);
|
||||||
|
if (rc) {
|
||||||
|
throw Unknown(name, mdb_strerror(rc));
|
||||||
|
}
|
||||||
|
for (const std::pair<const std::string, _Table*>& pair : tables) {
|
||||||
|
rc = pair.second->drop(txn);
|
||||||
|
if (rc) {
|
||||||
|
throw Unknown(name, mdb_strerror(rc), pair.first);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mdb_txn_commit(txn);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -42,6 +42,7 @@ public:
|
|||||||
bool ready() const;
|
bool ready() const;
|
||||||
bool removeDirectory();
|
bool removeDirectory();
|
||||||
QString getName() const;
|
QString getName() const;
|
||||||
|
void drop();
|
||||||
|
|
||||||
template <class K, class V>
|
template <class K, class V>
|
||||||
Table<K, V>* addTable(const std::string& name);
|
Table<K, V>* addTable(const std::string& name);
|
||||||
@ -72,7 +73,7 @@ private:
|
|||||||
template <class K, class V>
|
template <class K, class V>
|
||||||
DataBase::Table<K, V>* DataBase::addTable(const std::string& p_name) {
|
DataBase::Table<K, V>* DataBase::addTable(const std::string& p_name) {
|
||||||
if (opened) {
|
if (opened) {
|
||||||
throw Opened(name, p_name);
|
throw Opened(name, "add table " + p_name);
|
||||||
}
|
}
|
||||||
DataBase::Table<K, V>* table = new DataBase::Table<K, V>(p_name, this);
|
DataBase::Table<K, V>* table = new DataBase::Table<K, V>(p_name, this);
|
||||||
tables.insert(std::make_pair(p_name, (_Table*)table));
|
tables.insert(std::make_pair(p_name, (_Table*)table));
|
||||||
|
@ -38,7 +38,7 @@ std::string DataBase::Directory::getMessage() const {
|
|||||||
DataBase::Closed::Closed(
|
DataBase::Closed::Closed(
|
||||||
const std::string& p_operation,
|
const std::string& p_operation,
|
||||||
const std::string& p_dbName,
|
const std::string& p_dbName,
|
||||||
const std::string& p_tableName
|
const std::optional<std::string>& p_tableName
|
||||||
):
|
):
|
||||||
Exception(),
|
Exception(),
|
||||||
operation(p_operation),
|
operation(p_operation),
|
||||||
@ -46,22 +46,25 @@ DataBase::Closed::Closed(
|
|||||||
tableName(p_tableName) {}
|
tableName(p_tableName) {}
|
||||||
|
|
||||||
std::string DataBase::Closed::getMessage() const {
|
std::string DataBase::Closed::getMessage() const {
|
||||||
return "An attempt to perform operation " + operation
|
std::string msg = "An attempt to perform operation " + operation
|
||||||
+ " on closed database " + dbName
|
+ " on closed database " + dbName;
|
||||||
+ " on table " + tableName;
|
if (tableName.has_value()) {
|
||||||
|
msg += + " on table " + tableName.value();
|
||||||
|
}
|
||||||
|
return msg;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DataBase::Opened::Opened(const std::string& p_dbName, const std::string& p_tableName):
|
DataBase::Opened::Opened(const std::string& p_dbName, const std::string& p_action):
|
||||||
Exception(),
|
Exception(),
|
||||||
dbName(p_dbName),
|
dbName(p_dbName),
|
||||||
tableName(p_tableName) {}
|
action(p_action) {}
|
||||||
|
|
||||||
|
|
||||||
std::string DataBase::Opened::getMessage() const {
|
std::string DataBase::Opened::getMessage() const {
|
||||||
return "An attempt to add table " + tableName
|
return "An attempt to " + action
|
||||||
+ " to the database " + dbName
|
+ " (the database " + dbName
|
||||||
+ " but it's can't be done because the DataBase is already opened."
|
+ ") but it's can't be done because the DataBase is already opened";
|
||||||
+ " Please add all tables before opening DataBase.";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DataBase::NotFound::NotFound(
|
DataBase::NotFound::NotFound(
|
||||||
|
@ -43,23 +43,23 @@ private:
|
|||||||
|
|
||||||
class DataBase::Closed : public DataBase::Exception {
|
class DataBase::Closed : public DataBase::Exception {
|
||||||
public:
|
public:
|
||||||
Closed(const std::string& p_operation, const std::string& dbName, const std::string& tableName);
|
Closed(const std::string& p_operation, const std::string& dbName, const std::optional<std::string>& tableName = std::nullopt);
|
||||||
|
|
||||||
std::string getMessage() const;
|
std::string getMessage() const;
|
||||||
private:
|
private:
|
||||||
std::string operation;
|
std::string operation;
|
||||||
std::string dbName;
|
std::string dbName;
|
||||||
std::string tableName;
|
std::optional<std::string> tableName;
|
||||||
};
|
};
|
||||||
|
|
||||||
class DataBase::Opened : public DataBase::Exception {
|
class DataBase::Opened : public DataBase::Exception {
|
||||||
public:
|
public:
|
||||||
Opened(const std::string& dbName, const std::string& tableName);
|
Opened(const std::string& dbName, const std::string& action);
|
||||||
|
|
||||||
std::string getMessage() const;
|
std::string getMessage() const;
|
||||||
private:
|
private:
|
||||||
std::string dbName;
|
std::string dbName;
|
||||||
std::string tableName;
|
std::string action;
|
||||||
};
|
};
|
||||||
|
|
||||||
class DataBase::NotFound : public DataBase::Exception {
|
class DataBase::NotFound : public DataBase::Exception {
|
||||||
|
@ -51,5 +51,13 @@ private:
|
|||||||
#include "serializer_uint32.hpp"
|
#include "serializer_uint32.hpp"
|
||||||
#include "serializer_uint16.hpp"
|
#include "serializer_uint16.hpp"
|
||||||
#include "serializer_uint8.hpp"
|
#include "serializer_uint8.hpp"
|
||||||
|
#include "serializer_int64.hpp"
|
||||||
|
#include "serializer_int32.hpp"
|
||||||
|
#include "serializer_int16.hpp"
|
||||||
|
#include "serializer_int8.hpp"
|
||||||
|
#include "serializer_float.hpp"
|
||||||
|
#include "serializer_double.hpp"
|
||||||
|
#include "serializer_stdstring.hpp"
|
||||||
|
#include "serializer_qstring.hpp"
|
||||||
|
|
||||||
#endif // CORE_DATABASE_SERIALIZER_H
|
#endif // CORE_DATABASE_SERIALIZER_H
|
||||||
|
53
serializer_double.hpp
Normal file
53
serializer_double.hpp
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
// Squawk messenger.
|
||||||
|
// Copyright (C) 2019 Yury Gubich <blue@macaw.me>
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef CORE_DATABASE_SERIALIZER_DOUBLE_HPP
|
||||||
|
#define CORE_DATABASE_SERIALIZER_DOUBLE_HPP
|
||||||
|
|
||||||
|
template<>
|
||||||
|
class DataBase::Serializer<double>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Serializer():value(0) {};
|
||||||
|
Serializer(const double& p_value):value(p_value) {};
|
||||||
|
~Serializer() {};
|
||||||
|
|
||||||
|
double deserialize(const MDB_val& data) {
|
||||||
|
std::memcpy(&value, data.mv_data, 8);
|
||||||
|
return value;
|
||||||
|
};
|
||||||
|
MDB_val setData(const double& data) {
|
||||||
|
value = data;
|
||||||
|
return getData();
|
||||||
|
};
|
||||||
|
MDB_val getData() {
|
||||||
|
MDB_val result;
|
||||||
|
result.mv_data = &value;
|
||||||
|
result.mv_size = 8;
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
void clear() {}; //not possible;
|
||||||
|
|
||||||
|
private:
|
||||||
|
double value;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif //CORE_DATABASE_SERIALIZER_DOUBLE_HPP
|
||||||
|
|
||||||
|
|
||||||
|
|
53
serializer_float.hpp
Normal file
53
serializer_float.hpp
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
// Squawk messenger.
|
||||||
|
// Copyright (C) 2019 Yury Gubich <blue@macaw.me>
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef CORE_DATABASE_SERIALIZER_FLOAT_HPP
|
||||||
|
#define CORE_DATABASE_SERIALIZER_FLOAT_HPP
|
||||||
|
|
||||||
|
template<>
|
||||||
|
class DataBase::Serializer<float>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Serializer():value(0) {};
|
||||||
|
Serializer(const float& p_value):value(p_value) {};
|
||||||
|
~Serializer() {};
|
||||||
|
|
||||||
|
float deserialize(const MDB_val& data) {
|
||||||
|
std::memcpy(&value, data.mv_data, 4);
|
||||||
|
return value;
|
||||||
|
};
|
||||||
|
MDB_val setData(const float& data) {
|
||||||
|
value = data;
|
||||||
|
return getData();
|
||||||
|
};
|
||||||
|
MDB_val getData() {
|
||||||
|
MDB_val result;
|
||||||
|
result.mv_data = &value;
|
||||||
|
result.mv_size = 4;
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
void clear() {}; //not possible;
|
||||||
|
|
||||||
|
private:
|
||||||
|
float value;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif //CORE_DATABASE_SERIALIZER_FLOAT_HPP
|
||||||
|
|
||||||
|
|
||||||
|
|
50
serializer_int16.hpp
Normal file
50
serializer_int16.hpp
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
// Squawk messenger.
|
||||||
|
// Copyright (C) 2019 Yury Gubich <blue@macaw.me>
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef CORE_DATABASE_SERIALIZER_INT16_HPP
|
||||||
|
#define CORE_DATABASE_SERIALIZER_INT16_HPP
|
||||||
|
|
||||||
|
template<>
|
||||||
|
class DataBase::Serializer<int16_t>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Serializer():value(0) {};
|
||||||
|
Serializer(const int16_t& p_value):value(p_value) {};
|
||||||
|
~Serializer() {};
|
||||||
|
|
||||||
|
int16_t deserialize(const MDB_val& data) {
|
||||||
|
std::memcpy(&value, data.mv_data, 2);
|
||||||
|
return value;
|
||||||
|
};
|
||||||
|
MDB_val setData(const int16_t& data) {
|
||||||
|
value = data;
|
||||||
|
return getData();
|
||||||
|
};
|
||||||
|
MDB_val getData() {
|
||||||
|
MDB_val result;
|
||||||
|
result.mv_data = &value;
|
||||||
|
result.mv_size = 2;
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
void clear() {}; //not possible;
|
||||||
|
|
||||||
|
private:
|
||||||
|
int16_t value;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif //CORE_DATABASE_SERIALIZER_INT16_HPP
|
53
serializer_int32.hpp
Normal file
53
serializer_int32.hpp
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
// Squawk messenger.
|
||||||
|
// Copyright (C) 2019 Yury Gubich <blue@macaw.me>
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef CORE_DATABASE_SERIALIZER_INT32_HPP
|
||||||
|
#define CORE_DATABASE_SERIALIZER_INT32_HPP
|
||||||
|
|
||||||
|
template<>
|
||||||
|
class DataBase::Serializer<int32_t>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Serializer():value(0) {};
|
||||||
|
Serializer(const int32_t& p_value):value(p_value) {};
|
||||||
|
~Serializer() {};
|
||||||
|
|
||||||
|
int32_t deserialize(const MDB_val& data) {
|
||||||
|
std::memcpy(&value, data.mv_data, 4);
|
||||||
|
return value;
|
||||||
|
};
|
||||||
|
MDB_val setData(const int32_t& data) {
|
||||||
|
value = data;
|
||||||
|
return getData();
|
||||||
|
};
|
||||||
|
MDB_val getData() {
|
||||||
|
MDB_val result;
|
||||||
|
result.mv_data = &value;
|
||||||
|
result.mv_size = 4;
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
void clear() {}; //not possible;
|
||||||
|
|
||||||
|
private:
|
||||||
|
int32_t value;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif //CORE_DATABASE_SERIALIZER_INT32_HPP
|
||||||
|
|
||||||
|
|
||||||
|
|
53
serializer_int64.hpp
Normal file
53
serializer_int64.hpp
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
// Squawk messenger.
|
||||||
|
// Copyright (C) 2019 Yury Gubich <blue@macaw.me>
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef CORE_DATABASE_SERIALIZER_INT64_HPP
|
||||||
|
#define CORE_DATABASE_SERIALIZER_INT64_HPP
|
||||||
|
|
||||||
|
template<>
|
||||||
|
class DataBase::Serializer<int64_t>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Serializer():value(0) {};
|
||||||
|
Serializer(const int64_t& p_value):value(p_value) {};
|
||||||
|
~Serializer() {};
|
||||||
|
|
||||||
|
int64_t deserialize(const MDB_val& data) {
|
||||||
|
std::memcpy(&value, data.mv_data, 8);
|
||||||
|
return value;
|
||||||
|
};
|
||||||
|
MDB_val setData(const int64_t& data) {
|
||||||
|
value = data;
|
||||||
|
return getData();
|
||||||
|
};
|
||||||
|
MDB_val getData() {
|
||||||
|
MDB_val result;
|
||||||
|
result.mv_data = &value;
|
||||||
|
result.mv_size = 8;
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
void clear() {}; //not possible;
|
||||||
|
|
||||||
|
private:
|
||||||
|
int64_t value;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif //CORE_DATABASE_SERIALIZER_INT64_HPP
|
||||||
|
|
||||||
|
|
||||||
|
|
53
serializer_int8.hpp
Normal file
53
serializer_int8.hpp
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
// Squawk messenger.
|
||||||
|
// Copyright (C) 2019 Yury Gubich <blue@macaw.me>
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef CORE_DATABASE_SERIALIZER_INT8_HPP
|
||||||
|
#define CORE_DATABASE_SERIALIZER_INT8_HPP
|
||||||
|
|
||||||
|
template<>
|
||||||
|
class DataBase::Serializer<int8_t>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Serializer():value(0) {};
|
||||||
|
Serializer(const int8_t& p_value):value(p_value) {};
|
||||||
|
~Serializer() {};
|
||||||
|
|
||||||
|
int8_t deserialize(const MDB_val& data) {
|
||||||
|
std::memcpy(&value, data.mv_data, 1);
|
||||||
|
return value;
|
||||||
|
};
|
||||||
|
MDB_val setData(const int8_t& data) {
|
||||||
|
value = data;
|
||||||
|
return getData();
|
||||||
|
};
|
||||||
|
MDB_val getData() {
|
||||||
|
MDB_val result;
|
||||||
|
result.mv_data = &value;
|
||||||
|
result.mv_size = 1;
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
void clear() {}; //not possible;
|
||||||
|
|
||||||
|
private:
|
||||||
|
int8_t value;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif //CORE_DATABASE_SERIALIZER_INT8_HPP
|
||||||
|
|
||||||
|
|
||||||
|
|
58
serializer_qstring.hpp
Normal file
58
serializer_qstring.hpp
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
// Squawk messenger.
|
||||||
|
// Copyright (C) 2019 Yury Gubich <blue@macaw.me>
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef CORE_DATABASE_SERIALIZER_QSTRING_HPP
|
||||||
|
#define CORE_DATABASE_SERIALIZER_QSTRING_HPP
|
||||||
|
|
||||||
|
#include <QString>
|
||||||
|
#include <QByteArray>
|
||||||
|
|
||||||
|
template<>
|
||||||
|
class DataBase::Serializer<QString>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Serializer():value() {};
|
||||||
|
Serializer(const QString& p_value):value(p_value.toUtf8()) {};
|
||||||
|
~Serializer() {};
|
||||||
|
|
||||||
|
QString deserialize(const MDB_val& data) {
|
||||||
|
value = QByteArray((char*)data.mv_data, data.mv_size);
|
||||||
|
return QString::fromUtf8(value);
|
||||||
|
};
|
||||||
|
MDB_val setData(const QString& data) {
|
||||||
|
value = data.toUtf8();
|
||||||
|
return getData();
|
||||||
|
};
|
||||||
|
MDB_val getData() {
|
||||||
|
MDB_val result;
|
||||||
|
result.mv_data = value.data();
|
||||||
|
result.mv_size = value.size();
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
void clear() {}; //not possible;
|
||||||
|
|
||||||
|
private:
|
||||||
|
QByteArray value;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif //CORE_DATABASE_SERIALIZER_QSTRING_HPP
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
54
serializer_stdstring.hpp
Normal file
54
serializer_stdstring.hpp
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
// Squawk messenger.
|
||||||
|
// Copyright (C) 2019 Yury Gubich <blue@macaw.me>
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef CORE_DATABASE_SERIALIZER_STDSTRING_HPP
|
||||||
|
#define CORE_DATABASE_SERIALIZER_STDSTRING_HPP
|
||||||
|
|
||||||
|
template<>
|
||||||
|
class DataBase::Serializer<std::string>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Serializer():value() {};
|
||||||
|
Serializer(const std::string& p_value):value(p_value) {};
|
||||||
|
~Serializer() {};
|
||||||
|
|
||||||
|
std::string deserialize(const MDB_val& data) {
|
||||||
|
value = std::string((char*)data.mv_data, data.mv_size);
|
||||||
|
return value;
|
||||||
|
};
|
||||||
|
MDB_val setData(const std::string& data) {
|
||||||
|
value = data;
|
||||||
|
return getData();
|
||||||
|
};
|
||||||
|
MDB_val getData() {
|
||||||
|
MDB_val result;
|
||||||
|
result.mv_data = (char*)value.c_str();
|
||||||
|
result.mv_size = value.size();
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
void clear() {}; //not possible;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string value;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif //CORE_DATABASE_SERIALIZER_STDSTRING_HPP
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -36,7 +36,7 @@ public:
|
|||||||
};
|
};
|
||||||
MDB_val getData() {
|
MDB_val getData() {
|
||||||
MDB_val result;
|
MDB_val result;
|
||||||
result.mv_data = &value,
|
result.mv_data = &value;
|
||||||
result.mv_size = 2;
|
result.mv_size = 2;
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
|
@ -36,7 +36,7 @@ public:
|
|||||||
};
|
};
|
||||||
MDB_val getData() {
|
MDB_val getData() {
|
||||||
MDB_val result;
|
MDB_val result;
|
||||||
result.mv_data = &value,
|
result.mv_data = &value;
|
||||||
result.mv_size = 4;
|
result.mv_size = 4;
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
|
@ -36,7 +36,7 @@ public:
|
|||||||
};
|
};
|
||||||
MDB_val getData() {
|
MDB_val getData() {
|
||||||
MDB_val result;
|
MDB_val result;
|
||||||
result.mv_data = &value,
|
result.mv_data = &value;
|
||||||
result.mv_size = 8;
|
result.mv_size = 8;
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
|
@ -36,7 +36,7 @@ public:
|
|||||||
};
|
};
|
||||||
MDB_val getData() {
|
MDB_val getData() {
|
||||||
MDB_val result;
|
MDB_val result;
|
||||||
result.mv_data = &value,
|
result.mv_data = &value;
|
||||||
result.mv_size = 1;
|
result.mv_size = 1;
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
|
43
table.cpp
43
table.cpp
@ -24,3 +24,46 @@ DataBase::_Table::_Table(const std::string& p_name, DataBase* parent):
|
|||||||
}
|
}
|
||||||
|
|
||||||
DataBase::_Table::~_Table() {}
|
DataBase::_Table::~_Table() {}
|
||||||
|
|
||||||
|
|
||||||
|
void DataBase::_Table::drop()
|
||||||
|
{
|
||||||
|
if (!db->opened) {
|
||||||
|
throw Closed("drop", db->name, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
MDB_txn *txn;
|
||||||
|
int rc = mdb_txn_begin(db->environment, NULL, 0, &txn);
|
||||||
|
if (rc) {
|
||||||
|
throw Unknown(db->name, mdb_strerror(rc), name);
|
||||||
|
}
|
||||||
|
rc = drop(txn);
|
||||||
|
if (rc) {
|
||||||
|
throw Unknown(db->name, mdb_strerror(rc), name);
|
||||||
|
}
|
||||||
|
|
||||||
|
mdb_txn_commit(txn);
|
||||||
|
}
|
||||||
|
|
||||||
|
int DataBase::_Table::drop(MDB_txn* transaction)
|
||||||
|
{
|
||||||
|
return mdb_drop(transaction, dbi, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t DataBase::_Table::count() const
|
||||||
|
{
|
||||||
|
if (!db->opened) {
|
||||||
|
throw Closed("count", db->name, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
MDB_txn *txn;
|
||||||
|
MDB_stat stat;
|
||||||
|
int rc = mdb_txn_begin(db->environment, NULL, 0, &txn);
|
||||||
|
rc = mdb_stat(txn, dbi, &stat);
|
||||||
|
if (rc) {
|
||||||
|
throw Unknown(db->name, mdb_strerror(rc), name);
|
||||||
|
}
|
||||||
|
uint32_t amount = stat.ms_entries;
|
||||||
|
mdb_txn_abort(txn);
|
||||||
|
return amount;
|
||||||
|
}
|
||||||
|
11
table.h
11
table.h
@ -21,12 +21,19 @@
|
|||||||
#include "serializer.h"
|
#include "serializer.h"
|
||||||
|
|
||||||
class DataBase::_Table {
|
class DataBase::_Table {
|
||||||
public:
|
friend class DataBase;
|
||||||
|
protected:
|
||||||
_Table(const std::string& name, DataBase* parent);
|
_Table(const std::string& name, DataBase* parent);
|
||||||
virtual ~_Table();
|
virtual ~_Table();
|
||||||
|
|
||||||
virtual int createTable(MDB_txn * transaction) = 0;
|
virtual int createTable(MDB_txn * transaction) = 0;
|
||||||
|
virtual int drop(MDB_txn * transaction);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
virtual void drop();
|
||||||
|
virtual uint32_t count() const;
|
||||||
|
|
||||||
|
protected:
|
||||||
MDB_dbi dbi;
|
MDB_dbi dbi;
|
||||||
DataBase* db;
|
DataBase* db;
|
||||||
const std::string name;
|
const std::string name;
|
||||||
@ -40,7 +47,7 @@ protected:
|
|||||||
};
|
};
|
||||||
|
|
||||||
template <class K, class V>
|
template <class K, class V>
|
||||||
class DataBase::Table : private DataBase::_Table {
|
class DataBase::Table : public DataBase::_Table {
|
||||||
friend class DataBase;
|
friend class DataBase;
|
||||||
private:
|
private:
|
||||||
Table(const std::string& name, DataBase* parent);
|
Table(const std::string& name, DataBase* parent);
|
||||||
|
20
table.hpp
20
table.hpp
@ -164,6 +164,26 @@ inline int DataBase::_Table::makeTable<uint8_t>(MDB_txn* transaction) {
|
|||||||
return mdb_dbi_open(transaction, name.c_str(), MDB_CREATE | MDB_INTEGERKEY, &dbi);
|
return mdb_dbi_open(transaction, name.c_str(), MDB_CREATE | MDB_INTEGERKEY, &dbi);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
inline int DataBase::_Table::makeTable<int64_t>(MDB_txn* transaction) {
|
||||||
|
return mdb_dbi_open(transaction, name.c_str(), MDB_CREATE | MDB_INTEGERKEY, &dbi);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
inline int DataBase::_Table::makeTable<int32_t>(MDB_txn* transaction) {
|
||||||
|
return mdb_dbi_open(transaction, name.c_str(), MDB_CREATE | MDB_INTEGERKEY, &dbi);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
inline int DataBase::_Table::makeTable<int16_t>(MDB_txn* transaction) {
|
||||||
|
return mdb_dbi_open(transaction, name.c_str(), MDB_CREATE | MDB_INTEGERKEY, &dbi);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
inline int DataBase::_Table::makeTable<int8_t>(MDB_txn* transaction) {
|
||||||
|
return mdb_dbi_open(transaction, name.c_str(), MDB_CREATE | MDB_INTEGERKEY, &dbi);
|
||||||
|
}
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
inline std::string DataBase::_Table::toString(const T& value) {
|
inline std::string DataBase::_Table::toString(const T& value) {
|
||||||
return std::to_string(value);
|
return std::to_string(value);
|
||||||
|
112
test/basic.cpp
112
test/basic.cpp
@ -12,8 +12,7 @@ protected:
|
|||||||
t1(db->getTable<uint32_t, uint32_t>("table1")),
|
t1(db->getTable<uint32_t, uint32_t>("table1")),
|
||||||
t2(db->getTable<QString, QString>("table2")) {}
|
t2(db->getTable<QString, QString>("table2")) {}
|
||||||
|
|
||||||
~DataBaseTest() {
|
~DataBaseTest() {}
|
||||||
}
|
|
||||||
|
|
||||||
static void SetUpTestSuite() {
|
static void SetUpTestSuite() {
|
||||||
if (db == nullptr) {
|
if (db == nullptr) {
|
||||||
@ -43,7 +42,12 @@ TEST_F(DataBaseTest, RemovingDirectory) {
|
|||||||
EXPECT_EQ(db->removeDirectory(), true);
|
EXPECT_EQ(db->removeDirectory(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(DataBaseTest, OpeningDatabase) {
|
TEST_F(DataBaseTest, OpeningClosingDatabase) {
|
||||||
|
EXPECT_EQ(db->ready(), false);
|
||||||
|
db->open();
|
||||||
|
EXPECT_EQ(db->ready(), true);
|
||||||
|
db->close();
|
||||||
|
EXPECT_EQ(db->ready(), false);
|
||||||
db->open();
|
db->open();
|
||||||
EXPECT_EQ(db->ready(), true);
|
EXPECT_EQ(db->ready(), true);
|
||||||
}
|
}
|
||||||
@ -51,16 +55,112 @@ TEST_F(DataBaseTest, OpeningDatabase) {
|
|||||||
TEST_F(DataBaseTest, AddingIntegerKey) {
|
TEST_F(DataBaseTest, AddingIntegerKey) {
|
||||||
EXPECT_EQ(db->ready(), true);
|
EXPECT_EQ(db->ready(), true);
|
||||||
t1->addRecord(1, 2);
|
t1->addRecord(1, 2);
|
||||||
|
t1->addRecord(2, 2);
|
||||||
|
t1->addRecord(3, 15);
|
||||||
EXPECT_EQ(t1->getRecord(1), 2);
|
EXPECT_EQ(t1->getRecord(1), 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(DataBaseTest, AddingQStringKey) {
|
TEST_F(DataBaseTest, AddingQStringKey) {
|
||||||
EXPECT_EQ(db->ready(), true);
|
EXPECT_EQ(db->ready(), true);
|
||||||
t2->addRecord("hello", "world");
|
t2->addRecord("hello", "world");
|
||||||
|
t2->addRecord("aaa", "gagdfsdf");
|
||||||
|
t2->addRecord("sdfhga", "DSFFDG");
|
||||||
|
t2->addRecord("sdfsda", "shgsdgfa");
|
||||||
EXPECT_EQ(t2->getRecord("hello"), "world");
|
EXPECT_EQ(t2->getRecord("hello"), "world");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(DataBaseTest, ClosingDatabase) {
|
TEST_F(DataBaseTest, AddingRepeatingIntegerKey) {
|
||||||
db->close();
|
EXPECT_EQ(db->ready(), true);
|
||||||
EXPECT_EQ(db->ready(), false);
|
bool thrown = false;
|
||||||
|
try {
|
||||||
|
t1->addRecord(3, 24);
|
||||||
|
} catch (const DataBase::Exist e) {
|
||||||
|
thrown = true;
|
||||||
|
}
|
||||||
|
ASSERT_EQ(thrown, true) << "The expected behaviour is to throw exception on duplicate, but it didn't happened";
|
||||||
|
EXPECT_EQ(t1->getRecord(3), 15);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(DataBaseTest, AddingRepeatingStringKey) {
|
||||||
|
EXPECT_EQ(db->ready(), true);
|
||||||
|
bool thrown = false;
|
||||||
|
try {
|
||||||
|
t2->addRecord("sdfhga", "world");
|
||||||
|
} catch (const DataBase::Exist e) {
|
||||||
|
thrown = true;
|
||||||
|
}
|
||||||
|
ASSERT_EQ(thrown, true) << "The expected behaviour is to throw exception on duplicate, but it didn't happened";
|
||||||
|
EXPECT_EQ(t2->getRecord("sdfhga"), "DSFFDG");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(DataBaseTest, GettingNotExistingKeys) {
|
||||||
|
EXPECT_EQ(db->ready(), true);
|
||||||
|
bool thrown = false;
|
||||||
|
try {
|
||||||
|
QString wrong = t2->getRecord("almonds");
|
||||||
|
} catch (const DataBase::NotFound e) {
|
||||||
|
thrown = true;
|
||||||
|
}
|
||||||
|
ASSERT_EQ(thrown, true) << "The expected behaviour is to throw exception on duplicate, but it didn't happened";
|
||||||
|
|
||||||
|
thrown = false;
|
||||||
|
try {
|
||||||
|
uint32_t wrong = t1->getRecord(64);
|
||||||
|
} catch (const DataBase::NotFound e) {
|
||||||
|
thrown = true;
|
||||||
|
}
|
||||||
|
ASSERT_EQ(thrown, true) << "The expected behaviour is to throw exception on duplicate, but it didn't happened";
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(DataBaseTest, Persistence) {
|
||||||
|
EXPECT_EQ(db->ready(), true);
|
||||||
|
db->close();
|
||||||
|
delete db;
|
||||||
|
|
||||||
|
db = new DataBase("testBase");
|
||||||
|
t1 = db->addTable<uint32_t, uint32_t>("table1");
|
||||||
|
t2 = db->addTable<QString, QString>("table2");
|
||||||
|
db->open();
|
||||||
|
|
||||||
|
EXPECT_EQ(t1->getRecord(3), 15);
|
||||||
|
EXPECT_EQ(t1->getRecord(1), 2);
|
||||||
|
EXPECT_EQ(t1->getRecord(2), 2);
|
||||||
|
EXPECT_EQ(t2->getRecord("hello"), "world");
|
||||||
|
EXPECT_EQ(t2->getRecord("aaa"), "gagdfsdf");
|
||||||
|
EXPECT_EQ(t2->getRecord("sdfhga"), "DSFFDG");
|
||||||
|
EXPECT_EQ(t2->getRecord("sdfsda"), "shgsdgfa");
|
||||||
|
|
||||||
|
bool thrown = false;
|
||||||
|
try {
|
||||||
|
QString wrong = t2->getRecord("cats");
|
||||||
|
} catch (const DataBase::NotFound e) {
|
||||||
|
thrown = true;
|
||||||
|
}
|
||||||
|
ASSERT_EQ(thrown, true) << "The expected behaviour is to throw exception on duplicate, but it didn't happened";
|
||||||
|
|
||||||
|
thrown = false;
|
||||||
|
try {
|
||||||
|
uint32_t wrong = t1->getRecord(7893);
|
||||||
|
} catch (const DataBase::NotFound e) {
|
||||||
|
thrown = true;
|
||||||
|
}
|
||||||
|
ASSERT_EQ(thrown, true) << "The expected behaviour is to throw exception on duplicate, but it didn't happened";
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(DataBaseTest, CountAndDrop) {
|
||||||
|
EXPECT_EQ(db->ready(), true);
|
||||||
|
EXPECT_EQ(t1->count(), 3);
|
||||||
|
EXPECT_EQ(t2->count(), 4);
|
||||||
|
|
||||||
|
db->drop();
|
||||||
|
|
||||||
|
EXPECT_EQ(t1->count(), 0);
|
||||||
|
EXPECT_EQ(t2->count(), 0);
|
||||||
|
|
||||||
|
t1->addRecord(2, 2);
|
||||||
|
t2->addRecord("sdfhga", "world");
|
||||||
|
|
||||||
|
EXPECT_EQ(t1->count(), 1);
|
||||||
|
EXPECT_EQ(t2->count(), 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user