From 6438abef65597cdbbfe8b277da9ee5aa950cc968 Mon Sep 17 00:00:00 2001 From: Bartosz Wieczorek Date: Tue, 20 Mar 2018 12:19:03 +0100 Subject: [PATCH] modyfi items --- cmake/install_deps.sh | 22 +++-- .../include/eedb/db/pg/PgItem.hpp | 4 +- .../include/eedb/db/pg/PgItemsRepository.hpp | 2 +- .../postgresql_connector/src/data/PgItem.cpp | 49 +++++++++- .../postgresql_connector/src/data/PgItems.cpp | 0 .../src/data/PgItemsRepository.cpp | 96 ++++++++++++++----- .../test/test_eedb_data_PgItemsRepository.cpp | 13 ++- src/libs/eedb/include/eedb/db/Item.hpp | 15 ++- 8 files changed, 158 insertions(+), 43 deletions(-) delete mode 100644 src/libs/db/postgresql_connector/src/data/PgItems.cpp diff --git a/cmake/install_deps.sh b/cmake/install_deps.sh index ba6e3c2..d30f7a1 100755 --- a/cmake/install_deps.sh +++ b/cmake/install_deps.sh @@ -48,7 +48,7 @@ mkdir date-build; cd date-build ${CMAKE_COMMAND} -G${CMAKE_GENERATOR} ../date\ -DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}\ -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER} \ - -DCMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX}\ + -DCMAKE_INSTALL_PREFIX="${CMAKE_INSTALL_PREFIX}"\ -DTZ_CXX_STANDARD=14 ${CMAKE_COMMAND} --build . --target install cd ../ @@ -57,7 +57,7 @@ mkdir sqlpp11-build; cd sqlpp11-build ${CMAKE_COMMAND} -G${CMAKE_GENERATOR} ../sqlpp11\ -DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}\ -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER}\ - -DCMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX}\ + -DCMAKE_INSTALL_PREFIX="${CMAKE_INSTALL_PREFIX}"\ -DENABLE_TESTS=FALSE ${CMAKE_COMMAND} --build . --target install cd ../ @@ -66,8 +66,9 @@ mkdir sqlpp11-connector-postgresql-build; cd sqlpp11-connector-postgresql-build ${CMAKE_COMMAND} -G${CMAKE_GENERATOR} ../sqlpp11-connector-postgresql\ -DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}\ -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER}\ - -DCMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX}\ - -DCMAKE_PREFIX_PATH=${CMAKE_PREFIX_PATH}\ + -DCMAKE_INSTALL_PREFIX="${CMAKE_INSTALL_PREFIX}"\ + -DCMAKE_BUILD_TYPE="${CMAKE_BUILD_TYPE}"\ + -DCMAKE_PREFIX_PATH="${CMAKE_PREFIX_PATH}"\ -DENABLE_TESTS=FALSE ${CMAKE_COMMAND} --build . --target install cd ../ @@ -76,10 +77,10 @@ mkdir wt-build; cd wt-build ${CMAKE_COMMAND} -G${CMAKE_GENERATOR} ../wt\ -DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}\ -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER}\ - -DCMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX}\ - -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}\ - -DCMAKE_INSTALL_RPATH=${CMAKE_RPATH}\ - -DCMAKE_PREFIX_PATH=${CMAKE_PREFIX_PATH}\ + -DCMAKE_INSTALL_PREFIX="${CMAKE_INSTALL_PREFIX}"\ + -DCMAKE_BUILD_TYPE="${CMAKE_BUILD_TYPE}"\ + -DCMAKE_INSTALL_RPATH="${CMAKE_RPATH}"\ + -DCMAKE_PREFIX_PATH="${CMAKE_PREFIX_PATH}"\ -DBoost_NO_BOOST_CMAKE=FALSE\ -DBoost_NO_SYSTEM_PATHS=TRUE\ -DBUILD_EXAMPLES=OFF\ @@ -104,8 +105,9 @@ mkdir ChaiScript-build; cd ChaiScript-build ${CMAKE_COMMAND} -G${CMAKE_GENERATOR} ../ChaiScript\ -DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}\ -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER}\ - -DCMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX}\ - -DCMAKE_PREFIX_PATH=${CMAKE_PREFIX_PATH}\ + -DCMAKE_INSTALL_PREFIX="${CMAKE_INSTALL_PREFIX}"\ + -DCMAKE_BUILD_TYPE="${CMAKE_BUILD_TYPE}"\ + -DCMAKE_PREFIX_PATH="${CMAKE_PREFIX_PATH}"\ -DMULTITHREAD_SUPPORT_ENABLED=TRUE\ -DDYNLOAD_ENABLED=FALSE\ -DBUILD_MODULES=TRUE\ diff --git a/src/libs/db/postgresql_connector/include/eedb/db/pg/PgItem.hpp b/src/libs/db/postgresql_connector/include/eedb/db/pg/PgItem.hpp index 9f1dc21..168c72d 100644 --- a/src/libs/db/postgresql_connector/include/eedb/db/pg/PgItem.hpp +++ b/src/libs/db/postgresql_connector/include/eedb/db/pg/PgItem.hpp @@ -12,6 +12,8 @@ namespace eedb { class PgItem : public Item { // Item interface public: + PgItem(db::PgConnection & db, item::Attributes attributes); + PgItem(db::PgConnection & db, int64_t uid, item::Attributes attributes); std::string_view displayName() const override; @@ -24,6 +26,6 @@ class PgItem : public Item { private: struct ItemPriv; - spimpl::impl_ptr< ItemPriv > _priv; + spimpl::unique_impl_ptr< ItemPriv > _priv; }; } // namespace eedb diff --git a/src/libs/db/postgresql_connector/include/eedb/db/pg/PgItemsRepository.hpp b/src/libs/db/postgresql_connector/include/eedb/db/pg/PgItemsRepository.hpp index ec36dbb..7ff6c9e 100644 --- a/src/libs/db/postgresql_connector/include/eedb/db/pg/PgItemsRepository.hpp +++ b/src/libs/db/postgresql_connector/include/eedb/db/pg/PgItemsRepository.hpp @@ -18,7 +18,7 @@ class PgItemsRepository : public ItemsRepository { public: PgItemsRepository(db::PgConnection & db); - void create(item::Identyfier id, item::Attributes attributes, std::optional< item::Foto >) const override; + std::unique_ptr< Item > create(item::Identyfier id, item::Attributes attributes, std::optional< item::Foto >) const override; std::unique_ptr< Items > search(const ItemQueryFilters & filer) const override; diff --git a/src/libs/db/postgresql_connector/src/data/PgItem.cpp b/src/libs/db/postgresql_connector/src/data/PgItem.cpp index a13e3b8..45c87b9 100644 --- a/src/libs/db/postgresql_connector/src/data/PgItem.cpp +++ b/src/libs/db/postgresql_connector/src/data/PgItem.cpp @@ -1,13 +1,58 @@ #include #include +#include #include +#include + +#include + +using namespace sqlpp; namespace eedb { -struct PgItem::ItemPriv {}; +struct PgItem::ItemPriv { + ItemPriv(db::PgConnection & db, int64_t uid, item::Attributes attributes) : _db{db}, _uid{uid}, _attributes{std::move(attributes)} {} -PgItem::PgItem(db::PgConnection & db, int64_t uid, item::Attributes attributes) : _priv{spimpl::make_impl< ItemPriv >()} {} + bool attachToCategory(const Category * category) { + assert(category); + auto x = sqlpp::cte(sqlpp::alias::x) + .as(select(t_category.parent_id) // + .from(t_category) // + .where(t_category.parent_path == std::string{category->path()}) + .limit(1u)); + + _db(insert_into(t_category_items) // + .set(t_category_items.category_id = 1, t_category_items.item_id = _uid)); + return true; + } + + db::PgConnection & _db; + int64_t _uid; + item::Attributes _attributes; +}; + +PgItem::PgItem(db::PgConnection & db, item::Attributes attributes) + : _priv{spimpl::make_unique_impl< ItemPriv >(db, 0, std::move(attributes))} {} + +PgItem::PgItem(db::PgConnection & db, int64_t uid, item::Attributes attributes) + : _priv{spimpl::make_unique_impl< ItemPriv >(db, uid, std::move(attributes))} {} + +std::string_view PgItem::displayName() const { + return std::string_view{"item"}; +} + +Values PgItem::values() const { + return {}; +} + +Item::CategoriesIt PgItem::attachedToCategories() const { + return {}; +} + +bool PgItem::attach(const Category * category) { + return _priv->attachToCategory(category); +} } // namespace eedb diff --git a/src/libs/db/postgresql_connector/src/data/PgItems.cpp b/src/libs/db/postgresql_connector/src/data/PgItems.cpp deleted file mode 100644 index e69de29..0000000 diff --git a/src/libs/db/postgresql_connector/src/data/PgItemsRepository.cpp b/src/libs/db/postgresql_connector/src/data/PgItemsRepository.cpp index 17cfa08..837947a 100644 --- a/src/libs/db/postgresql_connector/src/data/PgItemsRepository.cpp +++ b/src/libs/db/postgresql_connector/src/data/PgItemsRepository.cpp @@ -3,7 +3,9 @@ #include #include #include +#include #include +#include #include #include @@ -14,6 +16,8 @@ #include +#include + SQLPP_ALIAS_PROVIDER(_match); namespace eedb { @@ -34,12 +38,20 @@ struct PgItemsRepository::PgItemsRepositoryPriv { return std::tuple_cat(insert(attributes.values()), insert_producer(attributes.producer())); } - void insert(item::Identyfier id, item::Attributes attributes, std::optional< item::Foto > f) { + auto insert(item::Identyfier id, item::Attributes attributes, std::optional< item::Foto > f) { using namespace sqlpp; - _db(insert_into(t_item) // - .set(std::tuple_cat( // - insert(id), - insert(attributes)))); + try { + auto uid = _db(sqlpp::postgresql::insert_into(t_item) // + .set(std::tuple_cat( // + insert(id), + insert(attributes))) // + .returning(t_item.id)) + .front() + .id; + return std::make_unique< PgItem >(_db, uid, std::move(attributes)); + } catch(const sqlpp::postgresql::unique_violation & e) { + throw item::UniqueSymbolValidation(e.what()); + } } bool parametersAvalible(const Values & values) { @@ -59,30 +71,60 @@ struct PgItemsRepository::PgItemsRepositoryPriv { } public: - PgItemsRepositoryPriv(db::PgConnection & db) : _db{db} {} + PgItemsRepositoryPriv(db::PgConnection & db) : _db{db}, _parameters{_db} {} - void do_insert(item::Identyfier id, item::Attributes attributes, std::optional< item::Foto > f) { + auto do_insert(item::Identyfier id, item::Attributes attributes, std::optional< item::Foto > f) { auto transaction = sqlpp::start_transaction(_db); if(not parametersAvalible(attributes.values())) { transaction.rollback(); /// TODO throw exception } else { - insert(std::move(id), std::move(attributes), std::move(f)); + auto new_item = insert(std::move(id), std::move(attributes), std::move(f)); + transaction.commit(); + return new_item; } - transaction.commit(); + } + + auto _cte_categoryIdByPath(const ItemQueryFilters & filer) const { + return sqlpp::cte(sqlpp::alias::x) + .as(select(t_category.parent_id) // + .from(t_category) // + .where(t_category.parent_path == std::string{filer.category() ? filer.category()->path() : std::string_view{""}}) + .limit(1u)); + } + + auto _titem() const { + return t_item.inner_join(t_category_items).on(t_item.id == t_category_items.item_id); + } + + auto parameterByName(const std::string & name) const { + // return eedb::Parameter{}; + } + + auto readAttribute(nlohmann::json & attribute) const { + // auto value = eedb::Value{0, parameterByName()}; + } + + template < typename Row > + auto readAttributes(Row & row) const { + const auto & attributes_raw = row.attributes.value(); + const auto & producer = row.producer; + + auto attributes = nlohmann::json::parse({attributes_raw.begin(), attributes_raw.end()}); + auto values = std::vector< eedb::Value >{}; + for(auto & attribute : attributes) { + readAttribute(attribute); + } + return eedb::item::Attributes{std::move(values), producer}; } auto search(const ItemQueryFilters & filer) { using namespace sqlpp; - auto x = sqlpp::cte(sqlpp::alias::x) - .as(select(t_category.parent_id) // - .from(t_category) // - .where(t_category.parent_path == std::string{filer.category() ? filer.category()->path() : std::string_view{""}}) - .limit(1u)); + auto x = _cte_categoryIdByPath(filer); - auto s = dynamic_select(_db.native(), all_of(t_item)) // - .dynamic_from(t_item.inner_join(t_category_items).on(t_item.id == t_category_items.item_id)) // + auto s = dynamic_select(_db.native(), all_of(t_item)) // + .dynamic_from(_titem()) // .dynamic_where() .limit(100u); @@ -91,24 +133,34 @@ struct PgItemsRepository::PgItemsRepositoryPriv { } auto rows = _db(with(x)(s)); + + _items.clear(); for(const auto & row : rows) { - std::cout << row.name << " "; - std::cout << row.attributes << "\n"; + const auto & uid = row.id; + _items.emplace_back(std::make_unique< eedb::PgItem >(_db, uid, readAttributes(row))); } + + auto transform = []( + std::unique_ptr< eedb::PgItem > & pgitem) { return static_cast< std::unique_ptr< eedb::Item > >(pgitem.get()); }; + auto begin = boost::make_transform_iterator(_items.begin(), transform); + auto end = boost::make_transform_iterator(_items.end(), transform); + + return std::make_unique< eedb::Items >(begin, end); } + std::vector< std::unique_ptr< eedb::PgItem > > _items; + eedb::PgParametersRepository _parameters; 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->do_insert(std::move(id), std::move(attributes), std::move(f)); +std::unique_ptr< Item > PgItemsRepository::create(item::Identyfier id, item::Attributes attributes, std::optional< item::Foto > f) const { + return _priv->do_insert(std::move(id), std::move(attributes), std::move(f)); } std::unique_ptr< Items > PgItemsRepository::search(const ItemQueryFilters & filer) const { - _priv->search(filer); - return {}; + return _priv->search(filer); } Parameters PgItemsRepository::listParameters(const Category *) const { 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 ba9f0b3..2b7269f 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 @@ -19,6 +19,10 @@ class PgItemsRepositoryTest : public DbTestBase< PgItemsRepositoryTest > { user._init(); category._init_simple("main"); + numericParameter._init("numeric parameter"); + textParameter._init("text parameter"); + listParameter._init("list parameter"); + sut = std::make_unique< eedb::PgItemsRepository >(db()); } @@ -29,10 +33,6 @@ class PgItemsRepositoryTest : public DbTestBase< PgItemsRepositoryTest > { using namespace std::string_literals; using namespace testing; - numericParameter._init("numeric parameter"); - textParameter._init("text parameter"); - listParameter._init("list parameter"); - EXPECT_CALL(numericParameter, name()).WillRepeatedly(Return(std::string_view{"numeric parameter"})); EXPECT_CALL(textParameter, name()).WillRepeatedly(Return(std::string_view{"text parameter"})); EXPECT_CALL(listParameter, name()).WillRepeatedly(Return(std::string_view{"list parameter"})); @@ -61,6 +61,11 @@ TEST_F(PgItemsRepositoryTest, createItemDontFail) { EXPECT_NO_THROW(sut->create(some_id(), some_attributes(), {})); } +TEST_F(PgItemsRepositoryTest, createTwiceThrowsException){ + EXPECT_NO_THROW(sut->create(some_id(), some_attributes(), {})); + EXPECT_THROW(sut->create(some_id(), some_attributes(), {}), eedb::item::UniqueSymbolValidation); +} + TEST_F(PgItemsRepositoryTest, createReturnsValidParameter) { EXPECT_NO_THROW(sut->create(some_id(), some_attributes(), {})); category._expect_call_path(); diff --git a/src/libs/eedb/include/eedb/db/Item.hpp b/src/libs/eedb/include/eedb/db/Item.hpp index 3683d28..5d448c6 100644 --- a/src/libs/eedb/include/eedb/db/Item.hpp +++ b/src/libs/eedb/include/eedb/db/Item.hpp @@ -46,7 +46,7 @@ class ItemQueryFilters { }; namespace item { - using Iterator = IteratorTypeErasure::any_iterator< Item *, std::forward_iterator_tag, Item * >; + using Iterator = IteratorTypeErasure::any_iterator< std::unique_ptr , std::forward_iterator_tag, std::unique_ptr >; using IteratorRange = boost::iterator_range< Iterator >; class Identyfier { @@ -106,6 +106,16 @@ namespace item { path _thumbnail; }; + class UniqueSymbolValidation : public std::exception { + public: + UniqueSymbolValidation(std::string what) : _what{std::move(what)} {} + const char * what() const noexcept override { + return _what.data(); + } + + private: + std::string _what; + }; } // namespace item /** @@ -120,7 +130,7 @@ class ItemsRepository { * @param id * @param values */ - virtual void create(item::Identyfier id, item::Attributes attributes, std::optional< item::Foto >) const = 0; + virtual std::unique_ptr< Item > create(item::Identyfier id, item::Attributes attributes, std::optional< item::Foto >) const = 0; /** * @brief search @@ -147,7 +157,6 @@ class Items : public item::IteratorRange { using _base::_base; }; - /** * @brief The Item class */