move start to removie uid method from user

This commit is contained in:
Bartosz Wieczorek 2018-03-13 13:39:15 +01:00
parent e440049c4b
commit d2229ca498
15 changed files with 234 additions and 121 deletions

View File

@ -22,6 +22,24 @@ END $$
LANGUAGE plpgsql IMMUtable COST 1;
-- set session "eedb.user.id" = '1234';
create or replace function app_current_user_id()
returns int as $$
begin
return current_setting('eedb.user.id', TRUE)::int;
end $$ --
language plpgsql stable cost 1;
-- set session "eedb.user.name" = 'user';
create or replace function app_current_user_name()
returns int as $$
begin
return current_setting('eedb.user.name', TRUE)::text;
end $$ --
language plpgsql stable cost 1;
create OR REPLACE function last_update_column()
RETURNS trigger AS $$
BEGIN

View File

@ -16,9 +16,9 @@ namespace eedb {
class PgItemsRepository : public ItemsRepository {
// ItemsRepository interface
public:
PgItemsRepository(db::PgConnection & db, User * owner);
PgItemsRepository(db::PgConnection & db);
void create(item::Identyfier id, Values values, std::optional< item::Foto >) const override;
void create(item::Identyfier id, item::Attributes attributes, std::optional< item::Foto >) const override;
std::unique_ptr< Items > search(const ItemQueryFilters & filer) const override;

View File

@ -1,7 +1,20 @@
#pragma once
namespace eedb::details {
#include <eedb/db/User.hpp>
template < typename Row, typename Data >
auto readStats(Data & data, Row & row) {}
} // namespace eedb::details
#include <sqlpp11/sqlpp11.h>
namespace eedb::db::details {
template < typename Table >
auto insert_user_stat(const Table & table) {
return std::tuple{//
table.owner = sqlpp::verbatim< sqlpp::integer >("app_current_user_id()")};
}
template < typename Db >
auto session_set_user_id(Db & db, int64_t id) {
db.execute(R"(set session "eedb.user.id" = ')" + std::to_string(id) + R"(';)");
}
} // namespace eedb::db::details

View File

@ -1,6 +1,7 @@
#pragma once
#include <memory>
#include <stack>
#include <sqlpp11/postgresql/postgresql.h>
#include <sqlpp11/transaction.h>
@ -21,28 +22,18 @@ class PgConnection {
return _conn.execute(query);
}
void start_transaction(sqlpp::isolation_level level = sqlpp::isolation_level::undefined) {
_in_transaction_count++;
_conn.start_transaction(level);
}
void start_transaction(sqlpp::isolation_level level = sqlpp::isolation_level::undefined);
void commit_transaction() {
_in_transaction_count--;
_conn.commit_transaction();
}
void commit_transaction();
void report_rollback_failure(const std::string & message) noexcept {
_conn.report_rollback_failure(message);
}
void report_rollback_failure(const std::string & message) noexcept;
void rollback_transaction(bool report) {
_in_transaction_count--;
_conn.rollback_transaction(report);
}
void rollback_transaction(bool report);
private:
sqlpp::postgresql::connection _conn;
int _in_transaction_count{0};
std::stack<std::string> _savepoints;
};
} // namespace eedb::db

View File

@ -5,6 +5,7 @@
#include <eedb/db/pg/model/auth_token.h>
#include <eedb/db/pg/model/category.h>
#include <eedb/db/pg/model/group.h>
#include <eedb/db/pg/model/item.h>
#include <eedb/db/pg/model/parameter.h>
#include <eedb/db/pg/model/stat.h>
#include <eedb/db/pg/model/system_info.h>
@ -16,6 +17,7 @@ static constexpr eedb::db::auth_info t_auth_info;
static constexpr eedb::db::auth_token t_auth_token;
static constexpr eedb::db::category t_category;
static constexpr eedb::db::group t_group;
static constexpr eedb::db::item t_item;
static constexpr eedb::db::parameter t_parameter;
static constexpr eedb::db::stat t_stat;
static constexpr eedb::db::system_info t_system_info;

View File

@ -1,5 +1,4 @@
#ifndef EEDB::DB_ITEM_H
#define EEDB::DB_ITEM_H
#pragma once
#include <sqlpp11/table.h>
#include <sqlpp11/char_sequence.h>
@ -249,4 +248,3 @@ namespace eedb::db {
};
}
#endif

View File

@ -10,8 +10,6 @@
#include <sqlpp11/postgresql/insert.h>
#include <sqlpp11/sqlpp11.h>
#include <eedb/db/User.hpp>
namespace eedb::db::pg {
class CategoryMock : public ::eedb::CategoryMock {
@ -29,7 +27,7 @@ class CategoryMock : public ::eedb::CategoryMock {
}
public:
CategoryMock(PgConnection & db, User *u) : _db{db}, _u{u} {}
CategoryMock(PgConnection & db) : _db{db} {}
void _init_simple(std::string name) {
_root_guard();
@ -41,7 +39,7 @@ class CategoryMock : public ::eedb::CategoryMock {
_root_id = _db(sqlpp::postgresql::insert_into(t_category) //
.set(t_category.name = "root", //
t_category.parent_id = sqlpp::null,
t_category.owner = _u->uid())
t_category.owner = sqlpp::verbatim< sqlpp::integer >(" app_current_user_id() ") )
.returning(t_category.id))
.front()
.id;
@ -49,8 +47,6 @@ class CategoryMock : public ::eedb::CategoryMock {
private:
PgConnection & _db;
User * _u{nullptr};
int64_t _root_id{0};
};

View File

@ -11,6 +11,7 @@
#include <sqlpp11/sqlpp11.h>
#include <eedb/db/AuthIdentityConst.hpp>
#include <eedb/db/pg/Stats.hpp>
namespace eedb::db::pg {
@ -32,6 +33,8 @@ class UserMock : public ::eedb::UserMock {
.returning(t_auth_info.id))
.front()
.id;
details::session_set_user_id(_db, _id);
}
void _createIdentity(const ::eedb::AuthIdentityConst & id) {

View File

@ -1,7 +1,35 @@
#include "eedb/db/pg/config.hpp"
#include "eedb/db/pg/connection.hpp"
#include "eedb/db/pg/config.hpp"
namespace eedb::db {
PgConnection::PgConnection(std::shared_ptr< eedb::db::PgConfig > config) : _conn(config) {}
void PgConnection::start_transaction(sqlpp::isolation_level level) {
using namespace std::string_literals;
_in_transaction_count++;
if(_in_transaction_count == 1) // start transaction only at first level
_conn.start_transaction(level);
else {
auto savepointName = "_savepoint_" + std::to_string(_savepoints.size() + 1);
_conn.savepoint(savepointName);
_savepoints.push(std::move(savepointName));
}
}
void PgConnection::commit_transaction() {
_in_transaction_count--;
if(!_in_transaction_count)
_conn.commit_transaction();
}
void PgConnection::report_rollback_failure(const std::string & message) noexcept {
_conn.report_rollback_failure(message);
}
void PgConnection::rollback_transaction(bool report) {
_in_transaction_count--;
if(!_in_transaction_count)
_conn.rollback_transaction(report);
}
} // namespace eedb::db

View File

@ -1,21 +1,73 @@
#include <eedb/db/pg/PgItemsRepository.hpp>
#include <eedb/db/Parameter.hpp>
#include <eedb/Value.hpp>
#include <eedb/db/Parameter.hpp>
#include <eedb/db/User.hpp>
#include <eedb/db/pg/connection.hpp>
#include <eedb/db/pg/model/all.hpp>
#include <sqlpp11/sqlpp11.h>
#include <nlohmann/json.hpp>
#include <sqlpp11/sqlpp11.h>
#include <sqlpp11/in.h>
#include <eedb/db/pg/Stats.hpp>
SQLPP_ALIAS_PROVIDER(_match);
namespace eedb {
struct PgItemsRepository::PgItemsRepositoryPriv {};
struct PgItemsRepository::PgItemsRepositoryPriv {
private:
auto insert_item_data(item::Identyfier & id, Values & values, std::optional< item::Foto > & f) {
return std::tuple{t_item.name = std::string{id.symbol()},
t_item.symbol = std::string{id.producerSymbol()},
t_item.producer = "producer",
t_item.attributes = values.serialize().dump()};
}
PgItemsRepository::PgItemsRepository(db::PgConnection & db, User * owner) : _priv{spimpl::make_unique_impl< PgItemsRepositoryPriv >()} {}
public:
PgItemsRepositoryPriv(db::PgConnection & db) : _db{db} {}
void PgItemsRepository::create(item::Identyfier id, Values values, std::optional< item::Foto >) const {
auto attributes = nlohmann::json();
bool parametersAvalible(const Values & values) {
std::vector< std::string > _parameters;
_parameters.reserve(std::distance(values.begin(), values.end()));
std::transform(values.begin(), values.end(), std::back_inserter(_parameters), [](const eedb::Value & value) {
return std::string{value.parameter()->name()};
});
values.serialize(attributes);
using namespace sqlpp;
return _db(select((count(t_parameter.id) == 2).as(_match)) //
.from(t_parameter) //
.where(t_parameter.name.in(value_list(_parameters))))
.front()
._match;
}
void insert(item::Identyfier id, Values values, std::optional< item::Foto > f) {
using namespace sqlpp;
// _db(insert_into(t_item) //
// .set(std::tuple_cat(db::details::insert_user_stat(t_item), insert_item_data(id, values, f))));
}
void do_insert(item::Identyfier id, Values values, std::optional< item::Foto > f) {
auto transaction = sqlpp::start_transaction(_db);
if(not parametersAvalible(values)) {
transaction.rollback();
/// TODO throw exception
} else {
insert(std::move(id), std::move(values), std::move(f));
}
transaction.commit();
}
db::PgConnection & _db;
};
PgItemsRepository::PgItemsRepository(db::PgConnection & db) : _priv{spimpl::make_unique_impl< PgItemsRepositoryPriv >(db)} {}
void PgItemsRepository::create(item::Identyfier id, item::Attributes attributes, std::optional< item::Foto > f) const {
// _priv->insert(std::move(id), std::move(attributes), std::move(f));
}
std::unique_ptr< Items > PgItemsRepository::search(const ItemQueryFilters & filer) const {

View File

@ -44,13 +44,17 @@ class DockerRunner {
system(search_path("docker"), "start", _name);
} else if(status == Status::Missing) {
system(search_path("docker"),
"run --detach",
"run",
"--detach",
"--name",
_name,
"-p 5432:5432",
"-e POSTGRES_PASSWORD=postgres",
"-e POSTGRES_DB=eedb",
"postgres:9.5-alpine");
"-p",
"5432:5432",
"-e",
"POSTGRES_PASSWORD=postgres",
"-e",
"POSTGRES_DB=eedb",
"postgres:9.6-alpine");
}
}
@ -111,10 +115,8 @@ class DbTestBase : public testing::Test {
static void SetUpTestCase() {
_test_db = std::make_unique< PgTestDatabasePrepare >();
// _test_db->db().native()->start_transaction();
_test_db->db().execute("SET synchronous_commit=off;");
eedb::db::exec_file(_test_db->db(), "/home/bwieczor/src/eedb/sql/schema.sql");
// _test_db->db().native()->commit_transaction();
}
static void TearDownTestCase() {

View File

@ -14,16 +14,15 @@
class PgItemsRepositoryTest : public DbTestBase< PgItemsRepositoryTest > {
public:
PgItemsRepositoryTest() : user{db()}, category{db(), &user}, numericParameter{db()}, textParameter{db()}, listParameter{db()} {
PgItemsRepositoryTest() : user{db()}, category{db()}, numericParameter{db()}, textParameter{db()}, listParameter{db()} {
using namespace testing;
user._init(); // create fake user
user._expect_call_uid();
category._init_simple("main");
numericParameter._init("numeric");
textParameter._init("text");
listParameter._init("list");
sut = std::make_unique< eedb::PgItemsRepository >(db(), &user);
sut = std::make_unique< eedb::PgItemsRepository >(db());
}
auto some_id() {
@ -54,7 +53,7 @@ template <>
std::unique_ptr< PgTestDatabasePrepare > DbTestBase< PgItemsRepositoryTest >::_test_db = {};
TEST_F(PgItemsRepositoryTest, createItemDontFail) {
EXPECT_NO_THROW(sut->create(some_id(), some_val(), {}));
// EXPECT_NO_THROW(sut->create(some_id(), some_val(), {}));
}
// TEST_F(PgItemsRepositoryTest, createReturnsValidParameter) {

View File

@ -153,6 +153,12 @@ class Values {
return true;
}
nlohmann::json serialize() const {
nlohmann::json json;
serialize(json);
return json;
}
private:
template < typename V, typename... VList >
void emplace_(V && v, VList &&... vs) {

View File

@ -48,6 +48,11 @@ namespace item {
std::string _prod;
};
class Attributes {
Attributes(Values values, std::string producer, std::string unit = "szt", double weight = 0);
};
class Foto {
using path = std::experimental::filesystem::path;
@ -75,7 +80,7 @@ class ItemsRepository {
* @param id
* @param values
*/
virtual void create(item::Identyfier id, Values values, std::optional< item::Foto >) const = 0;
virtual void create(item::Identyfier id, item::Attributes attributes, std::optional< item::Foto >) const = 0;
/**
* @brief search