diff --git a/src/libs/db/postgresql_connector/include/eedb/pg/Categories.hpp b/src/libs/db/postgresql_connector/include/eedb/pg/Categories.hpp index 4baa96e..4a4b76c 100644 --- a/src/libs/db/postgresql_connector/include/eedb/pg/Categories.hpp +++ b/src/libs/db/postgresql_connector/include/eedb/pg/Categories.hpp @@ -7,7 +7,7 @@ namespace eedb::pg { class Connection; -class CategoriesImpl : public Categories { +class CategoriesImpl : public CategoriesChildren { // Categories interface public: CategoriesImpl(std::unique_ptr< std::vector< std::unique_ptr< eedb::Category > > > data); diff --git a/src/libs/db/postgresql_connector/include/eedb/pg/Category.hpp b/src/libs/db/postgresql_connector/include/eedb/pg/Category.hpp index 04369d2..1bc680b 100644 --- a/src/libs/db/postgresql_connector/include/eedb/pg/Category.hpp +++ b/src/libs/db/postgresql_connector/include/eedb/pg/Category.hpp @@ -9,9 +9,24 @@ class User; } namespace eedb::pg { +namespace impl { + /** + * @brief The PgCategory class + * + * 'private part' of categories class + */ + class PgCategory : public ::eedb::Category { + /** + * @brief id + * @return id of object in database + */ + virtual int64_t id() const = 0; + }; +} // namespace impl + class Connection; -class CategoryImpl : public Category { +class CategoryImpl : public impl::PgCategory { private: struct CategoryImplPrivate; spimpl::impl_ptr< CategoryImplPrivate > _priv; @@ -22,13 +37,14 @@ class CategoryImpl : public Category { string_view displayName() const override; - string_view path() const override; - Category * parent() const override; - std::unique_ptr< Categories > children() const override; + std::unique_ptr< CategoriesChildren > children() const override; std::unique_ptr< Category > create(std::string name, std::string description) const override; + + public: + int64_t id() const override; }; -} // namespace eedb +} // namespace eedb::pg diff --git a/src/libs/db/postgresql_connector/mock/include/eedb/mock/db/pg/CategoryMock.hpp b/src/libs/db/postgresql_connector/mock/include/eedb/mock/db/pg/CategoryMock.hpp index 6848456..157578a 100644 --- a/src/libs/db/postgresql_connector/mock/include/eedb/mock/db/pg/CategoryMock.hpp +++ b/src/libs/db/postgresql_connector/mock/include/eedb/mock/db/pg/CategoryMock.hpp @@ -2,7 +2,7 @@ #include -#include +#include #include #include @@ -12,7 +12,8 @@ namespace eedb::pg { -class CategoryMock : public ::eedb::CategoryMock { +class CategoryMock : public impl::PgCategory { + public: auto _createChild(int64_t parentId, std::string name) { return _db(sqlpp::postgresql::insert_into(t_category) // .set(t_category.name = name, t_category.parent_id = parentId) @@ -22,39 +23,46 @@ class CategoryMock : public ::eedb::CategoryMock { } void _root_guard() { - if(!_root_id) + if(!_id) _initRoot(); } public: CategoryMock(Connection & db) : _db{db} {} + MOCK_CONST_METHOD0(displayName, std::string_view()); + MOCK_CONST_METHOD0(path, std::string_view()); + MOCK_CONST_METHOD0(parent, Category *()); + MOCK_CONST_METHOD2(create, std::unique_ptr< Category >(std::string, std::string)); + MOCK_CONST_METHOD0(children, std::unique_ptr< CategoriesChildren >()); + MOCK_CONST_METHOD0(id, int64_t()); + void _init_simple(std::string name) { _root_guard(); - _createChild(_root_id, name); + _createChild(_id, name); } void _initRoot() { using namespace testing; const auto & row = _db(sqlpp::postgresql::insert_into(t_category) // - .set(t_category.name = "root", // - t_category.parent_id = sqlpp::null, - t_category.owner = sqlpp::verbatim< sqlpp::integer >(" app_current_user_id() ")) - .returning(t_category.id, t_category.parent_path)) - .front(); + .set(t_category.name = "root", // + t_category.parent_id = sqlpp::null, + t_category.owner = sqlpp::verbatim< sqlpp::integer >(" app_current_user_id() ")) + .returning(t_category.id, t_category.parent_path)) + .front(); - _root_id = row.id; - _path = row.parent_path; + _id = row.id; + _path = row.parent_path; } - void _expect_call_path() { + void _expect_call_id() { using namespace testing; - EXPECT_CALL(*this, path()).WillRepeatedly(Return(_path)); + EXPECT_CALL(*this, id()).WillRepeatedly(Return(_id)); } private: Connection & _db; - int64_t _root_id{0}; + int64_t _id{0}; std::string _path; }; diff --git a/src/libs/db/postgresql_connector/src/Categories.cpp b/src/libs/db/postgresql_connector/src/Categories.cpp index 8e8b198..84d05aa 100644 --- a/src/libs/db/postgresql_connector/src/Categories.cpp +++ b/src/libs/db/postgresql_connector/src/Categories.cpp @@ -18,7 +18,7 @@ struct CategoriesImpl::CategoriesImplPriv { }; CategoriesImpl::CategoriesImpl(std::unique_ptr< std::vector< std::unique_ptr< Category > > > data) - : eedb::Categories(boost::make_transform_iterator(data->begin(), CategoriesImplPriv::getTransform()), + : eedb::CategoriesChildren(boost::make_transform_iterator(data->begin(), CategoriesImplPriv::getTransform()), boost::make_transform_iterator(data->end(), CategoriesImplPriv::getTransform())), _priv{spimpl::make_unique_impl< CategoriesImplPriv >(std::move(data))} {} diff --git a/src/libs/db/postgresql_connector/src/Category.cpp b/src/libs/db/postgresql_connector/src/Category.cpp index a2c1ee2..7a883d9 100644 --- a/src/libs/db/postgresql_connector/src/Category.cpp +++ b/src/libs/db/postgresql_connector/src/Category.cpp @@ -126,7 +126,7 @@ struct CategoryImpl::CategoryImplPrivate { std::string _description; }; -CategoryImpl::CategoryImpl(Connection &db) : _priv{spimpl::make_impl< CategoryImplPrivate >(db, nullptr)} { +CategoryImpl::CategoryImpl(Connection & db) : _priv{spimpl::make_impl< CategoryImplPrivate >(db, nullptr)} { _priv->_self = this; } @@ -138,15 +138,11 @@ Category::string_view CategoryImpl::displayName() const { return _priv->displayName(); } -Category::string_view CategoryImpl::path() const { - return _priv->path(); -} - Category * CategoryImpl::parent() const { return _priv->parent(); } -std::unique_ptr< Categories > CategoryImpl::children() const { +std::unique_ptr< CategoriesChildren > CategoryImpl::children() const { return std::make_unique< CategoriesImpl >(_priv->categories()); } @@ -154,4 +150,8 @@ std::unique_ptr< Category > CategoryImpl::create(std::string name, std::string d return _priv->create(std::move(name), std::move(description)); } +int64_t CategoryImpl::id() const { + return _priv->id(); +} + } // namespace eedb::pg diff --git a/src/libs/db/postgresql_connector/src/Item.cpp b/src/libs/db/postgresql_connector/src/Item.cpp index 19b0856..5bdc961 100644 --- a/src/libs/db/postgresql_connector/src/Item.cpp +++ b/src/libs/db/postgresql_connector/src/Item.cpp @@ -1,7 +1,7 @@ #include -#include #include +#include #include #include @@ -15,16 +15,12 @@ namespace eedb::pg { struct ItemImpl::ItemPriv { ItemPriv(Connection & db, int64_t uid, item::Attributes attributes) : _db{db}, _uid{uid}, _attributes{std::move(attributes)} {} - bool attachToCategory(const Category * category) { + bool attachToCategory(const Category * _category) { + auto category = dynamic_cast< const CategoryImpl * >(_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)); + .set(t_category_items.category_id = category->id(), t_category_items.item_id = _uid)); return true; } diff --git a/src/libs/db/postgresql_connector/src/ItemsRepository.cpp b/src/libs/db/postgresql_connector/src/ItemsRepository.cpp index feb6340..2306a45 100644 --- a/src/libs/db/postgresql_connector/src/ItemsRepository.cpp +++ b/src/libs/db/postgresql_connector/src/ItemsRepository.cpp @@ -38,10 +38,10 @@ struct ItemsRepositoryImpl::temsRepositoryImplPriv { return std::tuple_cat(insert(attributes.values()), insert_producer(attributes.producer())); } - auto insert(const item::Identyfier &id, item::Attributes attributes, const std::optional< item::Foto > & foto) { + auto insert(const item::Identyfier & id, item::Attributes attributes, const std::optional< item::Foto > & foto) { try { - auto uid = _db(sqlpp::postgresql::insert_into(t_item) // - .set(std::tuple_cat( // + auto uid = _db(sqlpp::postgresql::insert_into(t_item) // + .set(std::tuple_cat( // insert(id), insert(attributes))) // .returning(t_item.id)) @@ -84,14 +84,6 @@ struct ItemsRepositoryImpl::temsRepositoryImplPriv { } } - 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); } @@ -120,18 +112,16 @@ struct ItemsRepositoryImpl::temsRepositoryImplPriv { auto search(const ItemQueryFilters & filer) { using sqlpp::dynamic_select; - auto x = _cte_categoryIdByPath(filer); - auto s = dynamic_select(_db.native(), all_of(t_item)) // .dynamic_from(_titem()) // .dynamic_where() .limit(100u); - if(filer.category() != nullptr) { - s.where.add(t_category_items.category_id == select(x.parent_id).from(x)); + if(auto cat = dynamic_cast< const CategoryImpl * >(filer.category()); cat != nullptr) { + s.where.add(t_category_items.category_id == cat->id()); } - auto rows = _db(with(x)(s)); + auto rows = _db(s); _items.clear(); for(const auto & row : rows) { diff --git a/src/libs/db/postgresql_connector/test/test_CategoriesRepository.cpp b/src/libs/db/postgresql_connector/test/test_CategoriesRepository.cpp index bfaf2cc..efc4fc1 100644 --- a/src/libs/db/postgresql_connector/test/test_CategoriesRepository.cpp +++ b/src/libs/db/postgresql_connector/test/test_CategoriesRepository.cpp @@ -27,5 +27,4 @@ TEST_F(PgCategoriesRepositoryTest, rootNotNull) { auto root = sut->root(); ASSERT_TRUE(root); EXPECT_FALSE(root->parent()); - EXPECT_EQ(root->path(), "root"); } diff --git a/src/libs/db/postgresql_connector/test/test_Category.cpp b/src/libs/db/postgresql_connector/test/test_Category.cpp index 918313f..3d611ca 100644 --- a/src/libs/db/postgresql_connector/test/test_Category.cpp +++ b/src/libs/db/postgresql_connector/test/test_Category.cpp @@ -31,6 +31,11 @@ TEST_F(PgCategoryTest, rootCategoryHasNoParent) { EXPECT_FALSE(sut->parent()); } +TEST_F(PgCategoryTest, id) { + auto category = sut->create("name", "description"); + EXPECT_NE(dynamic_cast< eedb::pg::CategoryImpl * >(category.get())->id(), 0); +} + TEST_F(PgCategoryTest, createChild) { sut->create("name", "description"); auto children = sut->children(); @@ -54,8 +59,3 @@ TEST_F(PgCategoryTest, childHasParent) { EXPECT_EQ(child->parent(), sut.get()); } } - -TEST_F(PgCategoryTest, path) { - auto path = std::string{sut->create("name", "description")->create("name", "description")->path()}; - EXPECT_THAT(path, MatchesRegex(R"(root\.[0-9]*\.[0-9]*)")); -} diff --git a/src/libs/db/postgresql_connector/test/test_ItemsRepository.cpp b/src/libs/db/postgresql_connector/test/test_ItemsRepository.cpp index cc2de16..42330be 100644 --- a/src/libs/db/postgresql_connector/test/test_ItemsRepository.cpp +++ b/src/libs/db/postgresql_connector/test/test_ItemsRepository.cpp @@ -37,7 +37,8 @@ class PgItemsRepositoryTest : public DbTestBase< PgItemsRepositoryTest > { EXPECT_CALL(textParameter, name()).WillRepeatedly(Return(std::string_view{"text parameter"})); EXPECT_CALL(listParameter, name()).WillRepeatedly(Return(std::string_view{"list parameter"})); - return eedb::Values(eedb::Value{5, &numericParameter}, + return eedb::Values( // + eedb::Value{5, &numericParameter}, eedb::Value{"some text"s, &textParameter}, eedb::Value{std::vector{1.2, 3.4, 5.6, 7.8}, &listParameter}); } @@ -68,6 +69,6 @@ TEST_F(PgItemsRepositoryTest, createTwiceThrowsException) { TEST_F(PgItemsRepositoryTest, createReturnsValidParameter) { EXPECT_NO_THROW(sut->create(some_id(), some_attributes(), {})); - category._expect_call_path(); + category._expect_call_id(); auto items = sut->search(eedb::ItemQueryFilters{&category}); }