From 451b0bbebb38104b73a30b8d556bf1a6e49c29f9 Mon Sep 17 00:00:00 2001 From: Bartosz Wieczorek Date: Fri, 9 Mar 2018 12:50:56 +0100 Subject: [PATCH] add value and values classes that holds all the data --- sql/schema.sql | 209 ++++++++++++------ .../db/postgresql_connector/CMakeLists.txt | 4 +- .../eedb/db/pg/ParametersRepository.hpp | 13 +- .../include/eedb/db/pg/model/all.hpp | 20 +- .../include/eedb/mock/db/pg/ParameterMock.hpp | 24 +- .../src/data/ParametersRepository.cpp | 19 ++ .../src/data/PgCategories.cpp | 4 +- .../src/data/PgCategory.cpp | 24 +- .../src/data/PgItemsRepository.cpp | 11 +- .../postgresql_connector/test/CMakeLists.txt | 2 +- .../test/test_eedb_data_PgItemsRepository.cpp | 27 ++- .../test_eedb_data_PgParametersRepository.cpp | 27 +++ src/libs/eedb/CMakeLists.txt | 1 + src/libs/eedb/include/eedb/Value.hpp | 195 ++++++++++++---- src/libs/eedb/include/eedb/db/Item.hpp | 15 +- src/libs/eedb/include/eedb/db/Parameter.hpp | 30 ++- src/libs/eedb/test/CMakeLists.txt | 17 ++ src/libs/eedb/test/test_Value.cpp | 78 +++++++ 18 files changed, 560 insertions(+), 160 deletions(-) create mode 100644 src/libs/eedb/test/CMakeLists.txt create mode 100644 src/libs/eedb/test/test_Value.cpp diff --git a/sql/schema.sql b/sql/schema.sql index 6ed2f06..6dab547 100644 --- a/sql/schema.sql +++ b/sql/schema.sql @@ -37,10 +37,15 @@ create table "system_info"( "when" timestamp, constraint "pk_system_info" primary key ("id") ); -create index "ix_system_info_name" on "system_info"("name") with ( FILLFACTOR=100 ); -comment on table "system_info" is 'table introduced to save information about system e.g. actual db version / application version etc'; -comment on column "system_info"."name" is ''; -comment on column "system_info"."value" is ''; +create index "ix_system_info_name" + on "system_info"("name") + with ( FILLFACTOR=100 ); +comment on table "system_info" + is 'table introduced to save information about system e.g. actual db version / application version etc'; +comment on column "system_info"."name" + is ''; +comment on column "system_info"."value" + is ''; create table "group" ( "gid" serial not null, @@ -51,7 +56,8 @@ create table "group" ( constraint "pk_group_gid" primary key ("gid"), constraint "ux_group_name" unique ("name") ); -create trigger "update_user_group_last_update" before update on "group" for each row execute PROCEDURE last_update_column(); +create trigger "update_user_group_last_update" + before update on "group" for each row execute procedure last_update_column(); insert into "group"("name") values ('nogroup'), ('admins'), ('moderators'), ('users'); create or replace function default_group_id() @@ -95,12 +101,18 @@ create table "auth_info" ( constraint "pk_auth_into_id" primary key("id"), constraint "ux_auth_info_email" unique ("email") ); -create trigger "update_auth_info_updated" before update on "auth_info" for each row execute PROCEDURE last_update_column(); -comment on table "auth_info" is ''; -comment on column "auth_info"."id" is ''; -comment on column "auth_info"."group" is 'default user group'; -comment on column "auth_info"."created" is 'time of created'; -comment on column "auth_info"."config" is 'user configuration'; +create trigger "update_auth_info_updated" + before update on "auth_info" for each row execute procedure last_update_column(); +comment on table "auth_info" + is ''; +comment on column "auth_info"."id" + is ''; +comment on column "auth_info"."group" + is 'default user group'; +comment on column "auth_info"."created" + is 'time of created'; +comment on column "auth_info"."config" + is 'user configuration'; create table "auth_identity" ( @@ -111,11 +123,16 @@ create table "auth_identity" ( constraint "pk_auth_identity_id" primary key("id"), constraint "fk_auth_identity_auth_info_id" foreign key ("auth_info_id") references "auth_info" ("id") on delete cascade deferrable initially immediate ); -comment on table "auth_identity" is ''; -comment on column "auth_identity"."id" is ''; -comment on column "auth_identity"."auth_info_id" is ''; -comment on column "auth_identity"."provider" is ''; -comment on column "auth_identity"."identity" is ''; +comment on table "auth_identity" + is ''; +comment on column "auth_identity"."id" + is ''; +comment on column "auth_identity"."auth_info_id" + is ''; +comment on column "auth_identity"."provider" + is ''; +comment on column "auth_identity"."identity" + is ''; create table "auth_token" ( "id" serial not null, @@ -126,12 +143,18 @@ create table "auth_token" ( constraint "pk_auth_token_id" primary key("id"), constraint "fk_auth_token_auth_info_id" foreign key ("auth_info_id") references "auth_info" ("id") on delete cascade deferrable initially immediate ); -create index "ix_auth_token_value" ON "auth_token" ("value"); -comment on table "auth_token" is ''; -comment on column "auth_token"."id" is ''; -comment on column "auth_token"."auth_info_id" is ''; -comment on column "auth_token"."value" is ''; -comment on column "auth_token"."expires" is ''; +create index "ix_auth_token_value" + on "auth_token"("value"); +comment on table "auth_token" + is ''; +comment on column "auth_token"."id" + is ''; +comment on column "auth_token"."auth_info_id" + is ''; +comment on column "auth_token"."value" + is ''; +comment on column "auth_token"."expires" + is ''; create table "user_audit_action" ( @@ -140,9 +163,12 @@ create table "user_audit_action" ( constraint "pk_user_audit_action_id" primary key ("id"), constraint "ux_user_audit_action_name" unique ("name" ) ); -comment on table "user_audit_action" is 'action that user can take (like login/logout/config change?)'; -comment on column "user_audit_action"."id" is ''; -comment on column "user_audit_action"."name" is 'action name'; +comment on table "user_audit_action" + is 'action that user can take (like login/logout/config change?)'; +comment on column "user_audit_action"."id" + is ''; +comment on column "user_audit_action"."name" + is 'action name'; insert into "user_audit_action"("name") values ('login'), ('logout'); @@ -158,11 +184,16 @@ create UNLOGGED table "user_audit" ( ); create index "ix_user_history_data" ON "user_audit" ((("data" ->> 'status')::text)) WHERE ("data" ->> 'status') IS not null; comment on table "user_audit" IS 'saves user actions like login/logout'; -comment on column "user_audit"."id" is ''; -comment on column "user_audit"."auth_info_id" is ''; -comment on column "user_audit"."action_id" is ''; -comment on column "user_audit"."data" is 'data column contains information about taken action (if login was successful? if not, from what ip this action was taken?)'; -comment on column "user_audit"."when_happened" is ''; +comment on column "user_audit"."id" + is ''; +comment on column "user_audit"."auth_info_id" + is ''; +comment on column "user_audit"."action_id" + is ''; +comment on column "user_audit"."data" + is 'data column contains information about taken action (if login was successful? if not, from what ip this action was taken?)'; +comment on column "user_audit"."when_happened" + is ''; --create table "user_groups"( @@ -186,16 +217,25 @@ create table "stat"( constraint "fk_stat_user" foreign key ("owner") references "auth_info" ("id") on delete cascade deferrable initially immediate, constraint "fk_stat_primary_group" foreign key ("group") references "group" ("gid") on delete cascade deferrable initially immediate ); -create trigger update_stat_last_update before update on stat for each row execute PROCEDURE last_update_column(); -comment on table "stat" is ''; -comment on column "stat"."id" is 'unique id for all objects in database'; -comment on column "stat"."owner" is 'uid of object''s owner'; -comment on column "stat"."group" is 'groups of object'; -comment on column "stat"."unixperms" is 'Unixpermissions'; -comment on column "stat"."status" is 'status in which object is in (login, logout, removed etc)'; -comment on column "stat"."name" is ''; -comment on column "stat"."created" is ''; -comment on column "stat"."updated" is ''; +create trigger update_stat_last_update before update on stat for each row execute procedure last_update_column(); +comment on table "stat" + is ''; +comment on column "stat"."id" + is 'unique id for all objects in database'; +comment on column "stat"."owner" + is 'uid of object''s owner'; +comment on column "stat"."group" + is 'groups of object'; +comment on column "stat"."unixperms" + is 'Unixpermissions'; +comment on column "stat"."status" + is 'status in which object is in (login, logout, removed etc)'; +comment on column "stat"."name" + is ''; +comment on column "stat"."created" + is ''; +comment on column "stat"."updated" + is ''; --create table "action"( @@ -276,11 +316,16 @@ create index "ix_category_parent_path" on "category" using GIST ("parent_path"); create unique index "ux_category_name" on "category"("parent_id", "name" ); create trigger "update_category_last_update" before update on "category" for each row execute procedure last_update_column(); create trigger "update_category_parent_path" before insert or update on "category" for each row execute procedure update_category_parent_path(); -comment on table "category" is 'categories of items'; -comment on column "category"."parent_id" is ''; -comment on column "category"."parent_path" is ''; -comment on column "category"."description" is ''; -comment on column "category"."thumbnail" is ''; +comment on table "category" + is 'categories of items'; +comment on column "category"."parent_id" + is ''; +comment on column "category"."parent_path" + is ''; +comment on column "category"."description" + is ''; +comment on column "category"."thumbnail" + is ''; create table "unit"( @@ -291,46 +336,71 @@ create table "unit"( constraint "pk_unit" primary key ("id") ) inherits(stat); create unique index "uk_unit_name" on "unit"("name", "symbol"); -create trigger update_unit_last_update before update on "unit" for each row execute PROCEDURE last_update_column(); -comment on table "unit" is 'categories of items'; -comment on column "unit"."symbol" is ''; -comment on column "unit"."description" is ''; -comment on column "unit"."dimension_symbol" is ''; +create trigger update_unit_last_update before update on "unit" for each row execute procedure last_update_column(); +comment on table "unit" + is 'categories of items'; +comment on column "unit"."symbol" + is ''; +comment on column "unit"."description" + is ''; +comment on column "unit"."dimension_symbol" + is ''; create table "parameter"( "unit_id" int, + "type" text, "description" text, constraint "pk_parameter" primary key ("id"), constraint "fk_parameter_unit" foreign key ("unit_id") references "unit"("id") on delete cascade deferrable initially immediate ) inherits(stat); create unique index "uk_parameter_name" on "parameter"("name"); -create trigger update_parameter_last_update before update on "parameter" for each row execute PROCEDURE last_update_column(); -comment on table "parameter" is 'Parameter'; -comment on column "parameter"."unit_id" is ''; -comment on column "parameter"."description" is ''; +create trigger update_parameter_last_update before update on "parameter" for each row execute procedure last_update_column(); +comment on table "parameter" + is 'Parameter data'; +comment on table "parameter"."name" + is 'name of parameter e.g. Max power'; +comment on column "parameter"."unit_id" + is 'id of assigned unit (for range types, unit/list types indicated type of single value)'; +comment on column "parameter"."type" + is 'Type ot the parameter numeric/text or some variations e.g. list->"numeric[]", range->"numeric..."'; +comment on column "parameter"."description" + is ''; +--create table "producer"( +--) inherits ("stat"); + +-- TODO create fulltext search on short_desc column +-- TODO create "producer" table to save producers there insted in items table create table "item"( - "symbol" text not null, - "original_symbol" text, + "producer_symbol" text, "producer" text, "attributes" jsonb not null DEFAULT('{}'), "short_desc" text, "description" text, constraint "pk_items" primary key ("id"), constraint "fk_item_auth_info" foreign key ("owner") references "auth_info"("id") deferrable initially immediate -) inherits (stat); +) inherits ("stat"); create index "ix_item_attributes" on "item" USING GIN ("attributes"); -create unique index "ux_item" on "item"("name", "symbol"); -create trigger update_item_last_update before update on item for each row execute PROCEDURE last_update_column(); -comment on table "item" is ''; -comment on column "item"."symbol" is ''; -comment on column "item"."original_symbol" is ''; -comment on column "item"."producer" is ''; -comment on column "item"."attributes" is ''; -comment on column "item"."short_desc" is ''; -comment on column "item"."description" is ''; +create index "ix_item_producer" on "item"("producer"); +create index "ix_item_producer_symbol" on "item"("producer_symbol"); +create unique index "ux_item_symbol" on "item"("name"); +create trigger update_item_last_update before update on item for each row execute procedure last_update_column(); +comment on table "item" + is ''; +comment on column "item"."name" + is 'Item symbol saved in database'; +comment on column "item"."producer_symbol" + is 'symbol of the producent'; +comment on column "item"."producer" + is 'producent'; +comment on column "item"."attributes" + is 'JSON list of values'; +comment on column "item"."short_desc" + is ''; +comment on column "item"."description" + is ''; create table "category_items"( @@ -340,7 +410,8 @@ create table "category_items"( constraint "fk_category_id" foreign key ("category_id") references "category"("id") on delete cascade deferrable initially immediate, constraint "fk_item_id" foreign key ("item_id") references "item"("id") on delete cascade deferrable initially immediate ); -comment on table "category_items" is ''; +comment on table "category_items" + is ''; --create table "inventory"( @@ -349,7 +420,7 @@ comment on table "category_items" is ''; -- constraint "fk_inventory_owner" foreign key ("owner") references "auth_info" ("id") deferrable initially immediate, -- constraint "chk_inventory_name_length" check (length(name) < 100) --) inherits (stat); ---create trigger update_inventory_last_update before update on inventory for each row execute PROCEDURE last_update_column(); +--create trigger update_inventory_last_update before update on inventory for each row execute procedure last_update_column(); --create table "user_inventory"( @@ -366,12 +437,14 @@ comment on table "category_items" is ''; --); --comment on table in_stock IS 'Table contains information about items being available in storage'; + --create table inventory_operations( -- constraint inventory_operations_pkey primary key (uid), -- constraint OperationOwner_fk foreign key (owner) references users (uid) deferrable initially IMMEDIATE, -- constraint inventory_operation_unique UNIQUE (name) --) inherits(stat); + --create table inventory_history( -- inventory_from_id INTEGER not null references inventory on DELETE CASCADE, -- inventory_to_id INTEGER not null references inventory on DELETE CASCADE, diff --git a/src/libs/db/postgresql_connector/CMakeLists.txt b/src/libs/db/postgresql_connector/CMakeLists.txt index 13ed12e..dbd8dac 100644 --- a/src/libs/db/postgresql_connector/CMakeLists.txt +++ b/src/libs/db/postgresql_connector/CMakeLists.txt @@ -1,12 +1,12 @@ set(LIB postgres_connector) -file(GLOB_RECURSE postgres_connector_SOURCE src/*) +file(GLOB_RECURSE ${LIB}_SOURCE src/*) # find packages find_package(Sqlpp-connector-postgresql REQUIRED) # create library -add_library(${LIB} ${postgres_connector_SOURCE}) +add_library(${LIB} ${${LIB}_SOURCE}) # link all target_include_directories (${LIB} diff --git a/src/libs/db/postgresql_connector/include/eedb/db/pg/ParametersRepository.hpp b/src/libs/db/postgresql_connector/include/eedb/db/pg/ParametersRepository.hpp index d0b7f94..a7e16cf 100644 --- a/src/libs/db/postgresql_connector/include/eedb/db/pg/ParametersRepository.hpp +++ b/src/libs/db/postgresql_connector/include/eedb/db/pg/ParametersRepository.hpp @@ -2,11 +2,22 @@ #include +#include + +namespace eedb::db{ +class PgConnection; +} + namespace eedb { class PgParametersRepository : public ParametersRepository { - // ParametersRepository interface public: + PgParametersRepository(db::PgConnection&db); + std::unique_ptr< Parameter > create(std::string name, std::string description) const override; std::unique_ptr< Parameter > search(std::string name) const override; + +private: + struct PgParametersRepositoryPriv; + spimpl::unique_impl_ptr< PgParametersRepositoryPriv > _priv; }; } // namespace eedb diff --git a/src/libs/db/postgresql_connector/include/eedb/db/pg/model/all.hpp b/src/libs/db/postgresql_connector/include/eedb/db/pg/model/all.hpp index 1f77c8e..71593f8 100644 --- a/src/libs/db/postgresql_connector/include/eedb/db/pg/model/all.hpp +++ b/src/libs/db/postgresql_connector/include/eedb/db/pg/model/all.hpp @@ -11,13 +11,13 @@ #include #include -constexpr eedb::auth_identity t_auth_identity; -constexpr eedb::auth_info t_auth_info; -constexpr eedb::auth_token t_auth_token; -constexpr eedb::category t_category; -constexpr eedb::group t_group; -constexpr eedb::parameter t_parameter; -constexpr eedb::stat t_stat; -constexpr eedb::system_info t_system_info; -constexpr eedb::unit t_unit; -constexpr eedb::user_audit t_user_audit; +static constexpr eedb::auth_identity t_auth_identity; +static constexpr eedb::auth_info t_auth_info; +static constexpr eedb::auth_token t_auth_token; +static constexpr eedb::category t_category; +static constexpr eedb::group t_group; +static constexpr eedb::parameter t_parameter; +static constexpr eedb::stat t_stat; +static constexpr eedb::system_info t_system_info; +static constexpr eedb::unit t_unit; +static constexpr eedb::user_audit t_user_audit; diff --git a/src/libs/db/postgresql_connector/mock/include/eedb/mock/db/pg/ParameterMock.hpp b/src/libs/db/postgresql_connector/mock/include/eedb/mock/db/pg/ParameterMock.hpp index 8639746..c721136 100644 --- a/src/libs/db/postgresql_connector/mock/include/eedb/mock/db/pg/ParameterMock.hpp +++ b/src/libs/db/postgresql_connector/mock/include/eedb/mock/db/pg/ParameterMock.hpp @@ -2,7 +2,29 @@ #include +#include +#include + +#include +#include + namespace eedb::db::pg { -class ParameterMock : public ::eedb::ParameterMock {}; +class ParameterMock : public ::eedb::ParameterMock { + public: + ParameterMock(db::PgConnection & db) : _db{db} {} + + void _init(std::string name) { + using namespace sqlpp; + _id = _db(sqlpp::postgresql::insert_into(t_parameter) // + .set(t_parameter.name = name) // + .returning(t_parameter.id)) + .front() + .id; + } + + private: + db::PgConnection & _db; + int64_t _id{0}; +}; } // namespace eedb::db::pg diff --git a/src/libs/db/postgresql_connector/src/data/ParametersRepository.cpp b/src/libs/db/postgresql_connector/src/data/ParametersRepository.cpp index e69de29..18ddd6d 100644 --- a/src/libs/db/postgresql_connector/src/data/ParametersRepository.cpp +++ b/src/libs/db/postgresql_connector/src/data/ParametersRepository.cpp @@ -0,0 +1,19 @@ +#include + +#include +#include + +namespace eedb{ +struct PgParametersRepository::PgParametersRepositoryPriv {}; + +PgParametersRepository::PgParametersRepository(db::PgConnection & db) : _priv{spimpl::make_unique_impl< PgParametersRepositoryPriv >()} {} + +std::unique_ptr PgParametersRepository::create(std::string name, std::string description) const +{ +} + +std::unique_ptr PgParametersRepository::search(std::string name) const +{ + +} +} // namespace eedb diff --git a/src/libs/db/postgresql_connector/src/data/PgCategories.cpp b/src/libs/db/postgresql_connector/src/data/PgCategories.cpp index e1fa7d7..69a4115 100644 --- a/src/libs/db/postgresql_connector/src/data/PgCategories.cpp +++ b/src/libs/db/postgresql_connector/src/data/PgCategories.cpp @@ -15,10 +15,10 @@ struct PgCategories::PgCategoriesPriv { return [](auto & cat) { return cat.get(); }; } - PgCategoriesPriv(std::unique_ptr > > data) : _cache{std::move(data)} {} + PgCategoriesPriv(std::unique_ptr< std::vector< std::unique_ptr< Category > > > data) : _cache{std::move(data)} {} private: - std::unique_ptr > > _cache; + std::unique_ptr< std::vector< std::unique_ptr< Category > > > _cache; }; PgCategories::PgCategories(std::unique_ptr< std::vector< std::unique_ptr< Category > > > data) diff --git a/src/libs/db/postgresql_connector/src/data/PgCategory.cpp b/src/libs/db/postgresql_connector/src/data/PgCategory.cpp index 103689d..7e15959 100644 --- a/src/libs/db/postgresql_connector/src/data/PgCategory.cpp +++ b/src/libs/db/postgresql_connector/src/data/PgCategory.cpp @@ -15,11 +15,11 @@ struct PgCategory::PgCategoryPrivate { private: // select constexpr auto stat_columns() const { - return std::make_tuple(t_category.name, t_category.status); + return std::tuple{t_category.name, t_category.status}; } constexpr auto category_columns() const { - return std::make_tuple(t_category.description, t_category.id, t_category.parent_path); + return std::tuple{t_category.description, t_category.id, t_category.parent_path}; } constexpr auto columns() const { @@ -41,12 +41,12 @@ struct PgCategory::PgCategoryPrivate { } // set - auto set_stat() const { - return std::make_tuple( // - t_category.owner = _owner->uid(), - t_category.status = 0, - t_category.unixperms = sqlpp::verbatim< sqlpp::integer >(R"(unix_to_numeric("764"))")); - } + // auto set_stat() const { + // return std::tuple{// + // t_category.owner = _owner->uid(), + // t_category.status = 0, + // t_category.unixperms = sqlpp::verbatim< sqlpp::integer >(R"(unix_to_numeric("764"))")}; + // } public: Category * _self{nullptr}; @@ -102,6 +102,10 @@ struct PgCategory::PgCategoryPrivate { return _parent; } + auto displayName() const { + return _name; + } + protected: template < typename Row > void init_data(Row & row) { @@ -130,7 +134,9 @@ PgCategory::PgCategory(spimpl::impl_ptr< PgCategoryPrivate > priv) : _priv{std:: _priv->_self = this; } -Category::string_view PgCategory::displayName() const {} +Category::string_view PgCategory::displayName() const { + return _priv->displayName(); +} Category * PgCategory::parent() const { return _priv->parent(); diff --git a/src/libs/db/postgresql_connector/src/data/PgItemsRepository.cpp b/src/libs/db/postgresql_connector/src/data/PgItemsRepository.cpp index b5a4f16..327c566 100644 --- a/src/libs/db/postgresql_connector/src/data/PgItemsRepository.cpp +++ b/src/libs/db/postgresql_connector/src/data/PgItemsRepository.cpp @@ -4,13 +4,22 @@ #include #include +#include +#include + namespace eedb { struct PgItemsRepository::PgItemsRepositoryPriv {}; PgItemsRepository::PgItemsRepository(db::PgConnection & db, User * owner) : _priv{spimpl::make_unique_impl< PgItemsRepositoryPriv >()} {} std::unique_ptr< Item > PgItemsRepository::create(item::Identyfier id, Values values, std::optional< item::Foto >) const { - // + auto attributes = nlohmann::json(); + + values.serialize(attributes); + + std::cout< PgItemsRepository::search(const ItemQueryFilters & filer) const { diff --git a/src/libs/db/postgresql_connector/test/CMakeLists.txt b/src/libs/db/postgresql_connector/test/CMakeLists.txt index 79b51b5..af234fe 100644 --- a/src/libs/db/postgresql_connector/test/CMakeLists.txt +++ b/src/libs/db/postgresql_connector/test/CMakeLists.txt @@ -4,7 +4,7 @@ cmake_minimum_required(VERSION 3.0.2) find_package(GMock CONFIG REQUIRED) -set(TEST_EXECUTABLE_NAME postgres_connector-test ) +set(TEST_EXECUTABLE_NAME test-postgres_connector) #add test files file(GLOB_RECURSE TEST_FILES test_*.cpp ) diff --git a/src/libs/db/postgresql_connector/test/test_eedb_data_PgItemsRepository.cpp b/src/libs/db/postgresql_connector/test/test_eedb_data_PgItemsRepository.cpp index 8e4002d..cbef3c2 100644 --- a/src/libs/db/postgresql_connector/test/test_eedb_data_PgItemsRepository.cpp +++ b/src/libs/db/postgresql_connector/test/test_eedb_data_PgItemsRepository.cpp @@ -14,11 +14,23 @@ class PgItemsRepositoryTest : public DbTestBase< PgItemsRepositoryTest > { public: - PgItemsRepositoryTest() : user{db()}, category{db()} { + PgItemsRepositoryTest() : user{db()}, category{db()}, numericParameter{db()}, textParameter{db()} { using namespace testing; db().native()->start_transaction(); user._init(); // create fake user category._init_simple("main"); + numericParameter._init("numeric"); + textParameter._init("text"); + + sut = std::make_unique< eedb::PgItemsRepository >(db(), &user); + } + + auto some_id() { + return eedb::item::Identyfier{"AM2DM-2415SH60", "AM2DM-2415SH60"}; + } + auto some_val() { + using namespace std::string_literals; + return eedb::Values(eedb::Value{5, &numericParameter}, eedb::Value{"some text"s, &textParameter}); } ~PgItemsRepositoryTest() { @@ -28,7 +40,7 @@ class PgItemsRepositoryTest : public DbTestBase< PgItemsRepositoryTest > { protected: eedb::db::pg::UserMock user; eedb::db::pg::CategoryMock category; - eedb::db::pg::ParameterMock parameter; + eedb::db::pg::ParameterMock numericParameter, textParameter; int64_t sutId; std::unique_ptr< eedb::PgItemsRepository > sut; @@ -37,4 +49,13 @@ class PgItemsRepositoryTest : public DbTestBase< PgItemsRepositoryTest > { template <> std::unique_ptr< PgTestDatabasePrepare > DbTestBase< PgItemsRepositoryTest >::_test_db = {}; -TEST_F(PgItemsRepositoryTest, getListOfParameters) {} +TEST_F(PgItemsRepositoryTest, createParameterDontfail) { + EXPECT_TRUE(sut->create(some_id(), some_val(), {})); +} + +TEST_F(PgItemsRepositoryTest, createReturnsValidParameter) { + auto item = sut->create(some_id(), some_val(), {}); + ASSERT_TRUE(item); + EXPECT_EQ(item->displayName(), "AM2DM-2415SH60"); + // EXPECT_EQ(item->values()) +} diff --git a/src/libs/db/postgresql_connector/test/test_eedb_data_PgParametersRepository.cpp b/src/libs/db/postgresql_connector/test/test_eedb_data_PgParametersRepository.cpp index 475c25d..0d32752 100644 --- a/src/libs/db/postgresql_connector/test/test_eedb_data_PgParametersRepository.cpp +++ b/src/libs/db/postgresql_connector/test/test_eedb_data_PgParametersRepository.cpp @@ -7,6 +7,17 @@ class PgParametersRepositoryTest : public DbTestBase< PgParametersRepositoryTest > { public: + PgParametersRepositoryTest() : user{db()}, parameter{db()} { + db().native()->start_transaction(); + user._init(); + parameter._init("paraemter"); + sut = std::make_unique< eedb::PgParametersRepository >(db()); + } + + ~PgParametersRepositoryTest() { + db().native()->rollback_transaction(false); + } + protected: eedb::db::pg::UserMock user; eedb::db::pg::ParameterMock parameter; @@ -16,3 +27,19 @@ class PgParametersRepositoryTest : public DbTestBase< PgParametersRepositoryTest template <> std::unique_ptr< PgTestDatabasePrepare > DbTestBase< PgParametersRepositoryTest >::_test_db = {}; + +TEST_F(PgParametersRepositoryTest, searchForParameterByName){ + EXPECT_TRUE(sut->search("parameter")); +} + +TEST_F(PgParametersRepositoryTest, searchForBadName){ + EXPECT_FALSE(sut->search("bad_parameter")); +} + +TEST_F(PgParametersRepositoryTest, init3){ + +} + +TEST_F(PgParametersRepositoryTest, init4){ + +} diff --git a/src/libs/eedb/CMakeLists.txt b/src/libs/eedb/CMakeLists.txt index 804d334..cb1b374 100644 --- a/src/libs/eedb/CMakeLists.txt +++ b/src/libs/eedb/CMakeLists.txt @@ -13,3 +13,4 @@ target_include_directories(${LIB} # add tests add_subdirectory(mock) +add_subdirectory(test) diff --git a/src/libs/eedb/include/eedb/Value.hpp b/src/libs/eedb/include/eedb/Value.hpp index 87ca93c..93c360e 100644 --- a/src/libs/eedb/include/eedb/Value.hpp +++ b/src/libs/eedb/include/eedb/Value.hpp @@ -6,71 +6,168 @@ #include +#include + namespace eedb { -class Value; +namespace details { + class ValueBase { + public: + virtual ~ValueBase() = default; + + virtual nlohmann::json serializeValue() const = 0; + }; + + template < typename T_ > + class Value : public ValueBase { + public: + template < typename T > + explicit Value(T t) : _value{static_cast< T_ >(t)} {} + + nlohmann::json serializeValue() const override { + return _value; + } + + private: + T_ _value; + }; + + template < typename V > + class Range : public ValueBase { + static_assert(std::is_base_of_v< ValueBase, V >); + + public: + template < class T, class U > + Range(std::pair< T, U > value) : _value{std::move(value)} {} + + nlohmann::json serializeValue() const override { + return {{"min", _value.first.serializeValue()}, {"max", _value.second.serializeValue()}}; + } + + private: + // min / max pair of values + std::pair< V, V > _value; + }; + + using NumericValue = Value< double >; + using TextValue = Value< std::string >; + + using NumericList = Value< std::vector< double > >; + using TextList = Value< std::vector< std::string > >; + + using NumericRange = Range< NumericValue >; + +} // namespace details + +class Value { + public: + template < typename T > + Value(T attribute, // + Parameter * parameter, + typename std::enable_if_t< std::is_same_v< std::string, T > > * = nullptr) + : _value{std::make_unique< details::TextValue >(std::move(attribute))}, _parameter{parameter} {} + + template < typename T > + Value(T number, + Parameter * parameter, + typename std::enable_if_t< std::is_integral_v< T > || std::is_floating_point_v< T > > * = nullptr) + : _value{std::make_unique< details::NumericValue >(number)}, _parameter{parameter} {} + + template < typename T > + Value(std::pair< T, T > range, + Parameter * parameter, + typename std::enable_if_t< std::is_integral_v< T > || std::is_floating_point_v< T > > * = nullptr) + : _value{std::make_unique< details::NumericRange >(range)}, _parameter{parameter} {} + + template < typename T > + Value(std::vector< T > attributes, // + Parameter * parameter, + typename std::enable_if_t< std::is_same_v< std::string, T > > * = nullptr) + : _value{std::make_unique< details::TextList >(std::move(attributes))}, _parameter{parameter} {} + + template < typename T > + Value(std::vector< T > numbers, + Parameter * parameter, + typename std::enable_if_t< std::is_integral_v< T > || std::is_floating_point_v< T > > * = nullptr) + : _value{std::make_unique< details::NumericList >(std::move(numbers))}, _parameter{parameter} {} + + Value(const Value &) = default; + Value & operator=(const Value &) = delete; + + Value(Value &&) = default; + Value & operator=(Value &&) = default; + + void serialize(nlohmann::json & json) const { + json["value"] = _value->serializeValue(); + + if(_parameter) + json["parameter"] = std::string{_parameter->name()}; + } + + nlohmann::json serialize() const { + nlohmann::json json; + serialize(json); + return json; + } + + Parameter * parameter() const { + return _parameter; + } + + private: + std::unique_ptr< details::ValueBase > _value; + Parameter * _parameter{nullptr}; +}; /** * @brief The Values class */ class Values { public: - virtual ~Values() = default; -}; + Values() {} -class NumericValue { - public: - explicit NumericValue(double t) : _value{t} {} - - std::string to_string() const { - return std::to_string(_value); + template < typename... VList > + Values(VList &&... vs) { + _values.reserve(sizeof...(vs)); + emplace_(std::forward< VList >(vs)...); } - double value() const { - return _value; + Values(std::vector< Value > values) : _values{std::move(values)} {} + + auto begin() { + return _values.begin(); + } + + auto begin() const { + return _values.begin(); + } + + auto end() { + return _values.end(); + } + + auto end() const { + return _values.end(); + } + + bool serialize(nlohmann::json & json) const { + json["values"] = nlohmann::json::array(); + for(const auto & value : *this) { + value.serialize(json); + } + return true; } private: - double _value; -}; - -class TextValue { - public: - explicit TextValue(std::string_view value) : _value{value} {} - - std::string to_string() const { - return _value; + template < typename V, typename... VList > + void emplace_(V && v, VList &&... vs) { + _values.emplace_back(std::forward< V >(v)); + if constexpr(sizeof...(vs)) { + emplace_(std::forward< VList >(vs)...); + } } - std::string_view value() const { - return _value; - } - - private: - std::string _value; -}; - -/** - * @brief The Value class - */ -class Value { - public: - enum class Type { Numeric, Text }; - - /** - * @brief to_string - * @return returns value as string - */ - std::string to_string() const; - - Type type() const { - return Type::Numeric; - } - - Parameter * parameter() const {} - - private: - std::variant< TextValue, NumericValue > _value; + std::vector< Value > _values; }; } // namespace eedb diff --git a/src/libs/eedb/include/eedb/db/Item.hpp b/src/libs/eedb/include/eedb/db/Item.hpp index 3b9533b..e4506ea 100644 --- a/src/libs/eedb/include/eedb/db/Item.hpp +++ b/src/libs/eedb/include/eedb/db/Item.hpp @@ -33,22 +33,19 @@ namespace item { class Identyfier { public: - std::string_view name() const { - return _name; - } - - std::string_view producerSymbol() const { - return _prod; - } + Identyfier(std::string symbol, std::string producer_symbol={}) : _sym{std::move(symbol)}, _prod{std::move(producer_symbol)} {} std::string_view symbol() const { return _sym; } + std::string_view producerSymbol() const { + return _prod.empty() ? _sym : _prod; + } + private: - std::string _name; - std::string _prod; std::string _sym; + std::string _prod; }; class Foto { diff --git a/src/libs/eedb/include/eedb/db/Parameter.hpp b/src/libs/eedb/include/eedb/db/Parameter.hpp index 21de7fb..f0b7c5f 100644 --- a/src/libs/eedb/include/eedb/db/Parameter.hpp +++ b/src/libs/eedb/include/eedb/db/Parameter.hpp @@ -37,6 +37,17 @@ namespace details { class Parameters : public details::ParameterPtrIteratorRange {}; +enum class Type { + Numeric = 0x1 << 0, + NumericList, + NumericRange, + + Text = 0x1 << 4, + TextList, + + Script = 0x1 << 8 +}; + /** * @brief The Parameter class */ @@ -45,21 +56,32 @@ class Parameter { virtual ~Parameter() = default; /** - * @brief unit - * @return + * @brief type + * @return supported type od data + */ + Type type() const noexcept(true) { + return _type; + } + + /** + * @brief unit of given parameter, probably make sanse to have it only for numeric types of parameter + * @return unit for given parameter e.g. If the Parameter is "Max current" the Unit can be "A" */ virtual std::optional< Unit > unit() const = 0; /** * @brief name - * @return + * @return display name of parameter e.g. "Max current" */ virtual std::string_view name() const = 0; /** * @brief description - * @return + * @return parameter description */ virtual std::string_view description() const = 0; + + protected: + Type _type; }; } // namespace eedb diff --git a/src/libs/eedb/test/CMakeLists.txt b/src/libs/eedb/test/CMakeLists.txt new file mode 100644 index 0000000..088fdb2 --- /dev/null +++ b/src/libs/eedb/test/CMakeLists.txt @@ -0,0 +1,17 @@ +cmake_minimum_required(VERSION 3.0.2) + +find_package(GMock CONFIG REQUIRED) + +set(TEST_EXECUTABLE_NAME test-eedb_api ) + +#add test files +file(GLOB_RECURSE TEST_FILES test_*.cpp ) + +add_executable( ${TEST_EXECUTABLE_NAME} ${TEST_FILES}) +target_link_libraries(${TEST_EXECUTABLE_NAME} + PRIVATE eedb-api + PRIVATE eedb-mock + PRIVATE GMock::main +) + +add_test( ${TEST_EXECUTABLE_NAME} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TEST_EXECUTABLE_NAME}) diff --git a/src/libs/eedb/test/test_Value.cpp b/src/libs/eedb/test/test_Value.cpp new file mode 100644 index 0000000..bf9655b --- /dev/null +++ b/src/libs/eedb/test/test_Value.cpp @@ -0,0 +1,78 @@ +#include + +#include + +#include + +class ValueTest : public testing::Test { + protected: + eedb::ParameterMock parameter; +}; + +using namespace testing; + +TEST_F(ValueTest, init) { + eedb::Value _int{int{1}, ¶meter}; + eedb::Value _flo{float{2}, ¶meter}; + eedb::Value _dou{double{3}, ¶meter}; +} + +TEST_F(ValueTest, serializeInt) { + EXPECT_CALL(parameter, name()).WillOnce(Return("parameter name")); + eedb::Value _int{4, ¶meter}; + + auto json = nlohmann::json{}; + _int.serialize(json); + + EXPECT_EQ(json, (nlohmann::json{{"value", 4.0}, {"parameter", "parameter name"}})); +} + +TEST_F(ValueTest, serializeDouble) { + EXPECT_CALL(parameter, name()).WillOnce(Return("parameter name")); + eedb::Value _double{4.0, ¶meter}; + + auto json = nlohmann::json{}; + _double.serialize(json); + + EXPECT_EQ(json, (nlohmann::json{{"value", 4.0}, {"parameter", "parameter name"}})); +} + +TEST_F(ValueTest, serializeString) { + EXPECT_CALL(parameter, name()).WillOnce(Return("parameter name")); + eedb::Value _string{std::string{"asdfghjkl"}, ¶meter}; + + auto json = nlohmann::json{}; + _string.serialize(json); + + EXPECT_EQ(json, (nlohmann::json{{"value", "asdfghjkl"}, {"parameter", "parameter name"}})); +} + +TEST_F(ValueTest, serializeListOfInts) { + EXPECT_CALL(parameter, name()).WillOnce(Return("parameter name")); + + eedb::Value _intList{std::vector{1, 2, 3, 4, 5, 6}, ¶meter}; + + EXPECT_EQ(_intList.serialize(), (nlohmann::json{{"value", {1, 2, 3, 4, 5, 6}}, {"parameter", "parameter name"}})); +} + +TEST_F(ValueTest, serializeListOfStrings) { + using namespace std::string_literals; + EXPECT_CALL(parameter, name()).WillOnce(Return("parameter name")); + eedb::Value _stringList{std::vector{"a"s, "b"s, "c"s}, ¶meter}; + + auto json = nlohmann::json{}; + _stringList.serialize(json); + + EXPECT_EQ(json, (nlohmann::json{{"value", {"a"s, "b"s, "c"s}}, {"parameter", "parameter name"}})); +} + +TEST_F(ValueTest, serializeListOfRange) { + EXPECT_CALL(parameter, name()).WillOnce(Return("parameter name")); + eedb::Value _range{std::pair{0.001, 1000.0}, ¶meter}; + + auto json = nlohmann::json{}; + _range.serialize(json); + + EXPECT_EQ(json, (nlohmann::json{{"value", {{"min", 0.001}, {"max", 1000.0}}}, {"parameter", "parameter name"}})); +} +