From c4d2d20447cb95b4b82b166589d0f558df82d248 Mon Sep 17 00:00:00 2001 From: emeric Date: Sat, 4 Nov 2023 16:15:39 +0100 Subject: [PATCH] SubsonicAPI: optimized search for albums --- src/libs/services/database/impl/Release.cpp | 279 +++--- .../include/services/database/Release.hpp | 7 +- src/libs/services/database/test/Cluster.cpp | 18 +- .../services/database/test/DatabaseTest.cpp | 6 +- src/libs/services/database/test/Release.cpp | 874 +++++++++--------- .../services/database/test/StarredRelease.cpp | 6 +- .../feedback/impl/FeedbackService.cpp | 2 +- .../impl/ScanStepRemoveOrphanDbFiles.cpp | 3 +- .../impl/entrypoints/AlbumSongLists.cpp | 12 +- .../subsonic/impl/entrypoints/Browsing.cpp | 10 +- .../subsonic/impl/entrypoints/Searching.cpp | 9 +- src/lms/ui/explore/ArtistView.cpp | 4 +- src/lms/ui/explore/ReleaseCollector.cpp | 17 +- .../recommendation/LmsRecommendation.cpp | 206 ++--- 14 files changed, 735 insertions(+), 718 deletions(-) diff --git a/src/libs/services/database/impl/Release.cpp b/src/libs/services/database/impl/Release.cpp index 801b4720..8021dc98 100644 --- a/src/libs/services/database/impl/Release.cpp +++ b/src/libs/services/database/impl/Release.cpp @@ -34,152 +34,170 @@ namespace Database { - - Wt::Dbo::Query createQuery(Session& session, const Release::FindParameters& params) + namespace { - auto query{ session.getDboSession().query("SELECT DISTINCT r.id from release r") }; - - if (params.sortMethod == ReleaseSortMethod::LastWritten - || params.sortMethod == ReleaseSortMethod::Date - || params.sortMethod == ReleaseSortMethod::OriginalDate - || params.sortMethod == ReleaseSortMethod::OriginalDateDesc - || params.writtenAfter.isValid() - || params.dateRange - || params.artist.isValid() - || params.clusters.size() == 1) + template + Wt::Dbo::Query createQuery(Session& session, std::string_view itemToSelect, const Release::FindParameters& params) { - query.join("track t ON t.release_id = r.id"); - } + auto query{ session.getDboSession().query("SELECT DISTINCT " + std::string{ itemToSelect } + " from release r") }; - if (params.writtenAfter.isValid()) - query.where("t.file_last_write > ?").bind(params.writtenAfter); - - if (params.dateRange) - { - query.where("t.date >= ?").bind(params.dateRange->begin); - query.where("t.date <= ?").bind(params.dateRange->end); - } - - for (std::string_view keyword : params.keywords) - query.where("r.name LIKE ? ESCAPE '" ESCAPE_CHAR_STR "'").bind("%" + Utils::escapeLikeKeyword(keyword) + "%"); - - if (params.starringUser.isValid()) - { - assert(params.feedbackBackend); - query.join("starred_release s_r ON s_r.release_id = r.id") - .where("s_r.user_id = ?").bind(params.starringUser) - .where("s_r.backend = ?").bind(*params.feedbackBackend) - .where("s_r.sync_state <> ?").bind(SyncState::PendingRemove); - } - - if (params.artist.isValid()) - { - query.join("artist a ON a.id = t_a_l.artist_id") - .join("track_artist_link t_a_l ON t_a_l.track_id = t.id") - .where("a.id = ?").bind(params.artist); - - if (!params.trackArtistLinkTypes.empty()) + if (params.sortMethod == ReleaseSortMethod::LastWritten + || params.sortMethod == ReleaseSortMethod::Date + || params.sortMethod == ReleaseSortMethod::OriginalDate + || params.sortMethod == ReleaseSortMethod::OriginalDateDesc + || params.writtenAfter.isValid() + || params.dateRange + || params.artist.isValid() + || params.clusters.size() == 1) { - std::ostringstream oss; - - bool first{ true }; - for (TrackArtistLinkType linkType : params.trackArtistLinkTypes) - { - if (!first) - oss << " OR "; - oss << "t_a_l.type = ?"; - query.bind(linkType); - - first = false; - } - query.where(oss.str()); + query.join("track t ON t.release_id = r.id"); } - if (!params.excludedTrackArtistLinkTypes.empty()) + if (params.writtenAfter.isValid()) + query.where("t.file_last_write > ?").bind(params.writtenAfter); + + if (params.dateRange) + { + query.where("t.date >= ?").bind(params.dateRange->begin); + query.where("t.date <= ?").bind(params.dateRange->end); + } + + for (std::string_view keyword : params.keywords) + query.where("r.name LIKE ? ESCAPE '" ESCAPE_CHAR_STR "'").bind("%" + Utils::escapeLikeKeyword(keyword) + "%"); + + if (params.starringUser.isValid()) + { + assert(params.feedbackBackend); + query.join("starred_release s_r ON s_r.release_id = r.id") + .where("s_r.user_id = ?").bind(params.starringUser) + .where("s_r.backend = ?").bind(*params.feedbackBackend) + .where("s_r.sync_state <> ?").bind(SyncState::PendingRemove); + } + + if (params.artist.isValid()) + { + query.join("artist a ON a.id = t_a_l.artist_id") + .join("track_artist_link t_a_l ON t_a_l.track_id = t.id") + .where("a.id = ?").bind(params.artist); + + if (!params.trackArtistLinkTypes.empty()) + { + std::ostringstream oss; + + bool first{ true }; + for (TrackArtistLinkType linkType : params.trackArtistLinkTypes) + { + if (!first) + oss << " OR "; + oss << "t_a_l.type = ?"; + query.bind(linkType); + + first = false; + } + query.where(oss.str()); + } + + if (!params.excludedTrackArtistLinkTypes.empty()) + { + std::ostringstream oss; + oss << "r.id NOT IN (SELECT DISTINCT r.id FROM release r" + " INNER JOIN artist a ON a.id = t_a_l.artist_id" + " INNER JOIN track_artist_link t_a_l ON t_a_l.track_id = t.id" + " INNER JOIN track t ON t.release_id = r.id" + " WHERE (a.id = ? AND ("; + + query.bind(params.artist); + + bool first{ true }; + for (const TrackArtistLinkType linkType : params.excludedTrackArtistLinkTypes) + { + if (!first) + oss << " OR "; + oss << "t_a_l.type = ?"; + query.bind(linkType); + + first = false; + } + oss << ")))"; + query.where(oss.str()); + } + } + + if (params.clusters.size() == 1) + { + query.join("track_cluster t_c ON t_c.track_id = t.id") + .where("t_c.cluster_id = ?").bind(params.clusters.front()); + } + else if (params.clusters.size() > 1) { std::ostringstream oss; - oss << "r.id NOT IN (SELECT DISTINCT r.id FROM release r" - " INNER JOIN artist a ON a.id = t_a_l.artist_id" - " INNER JOIN track_artist_link t_a_l ON t_a_l.track_id = t.id" + oss << "r.id IN (SELECT DISTINCT r.id FROM release r" " INNER JOIN track t ON t.release_id = r.id" - " WHERE (a.id = ? AND ("; + " INNER JOIN track_cluster t_c ON t_c.track_id = t.id"; - query.bind(params.artist); - - bool first{ true }; - for (const TrackArtistLinkType linkType : params.excludedTrackArtistLinkTypes) + WhereClause clusterClause; + for (const ClusterId clusterId : params.clusters) { - if (!first) - oss << " OR "; - oss << "t_a_l.type = ?"; - query.bind(linkType); - - first = false; + clusterClause.Or(WhereClause("t_c.cluster_id = ?")); + query.bind(clusterId); } - oss << ")))"; + + oss << " " << clusterClause.get(); + oss << " GROUP BY t.id HAVING COUNT(*) = " << params.clusters.size() << ")"; + query.where(oss.str()); } - } - if (params.clusters.size() == 1) - { - query.join("track_cluster t_c ON t_c.track_id = t.id") - .where("t_c.cluster_id = ?").bind(params.clusters.front()); - } - else if (params.clusters.size() > 1) - { - std::ostringstream oss; - oss << "r.id IN (SELECT DISTINCT r.id FROM release r" - " INNER JOIN track t ON t.release_id = r.id" - " INNER JOIN track_cluster t_c ON t_c.track_id = t.id"; + if (params.primaryType) + query.where("primary_type = ?").bind(*params.primaryType); + if (!params.secondaryTypes.empty()) + query.where("secondary_type = ?").bind(params.secondaryTypes); - WhereClause clusterClause; - for (const ClusterId clusterId : params.clusters) + switch (params.sortMethod) { - clusterClause.Or(WhereClause("t_c.cluster_id = ?")); - query.bind(clusterId); + case ReleaseSortMethod::None: + break; + case ReleaseSortMethod::Name: + query.orderBy("r.name COLLATE NOCASE"); + break; + case ReleaseSortMethod::Random: + query.orderBy("RANDOM()"); + break; + case ReleaseSortMethod::LastWritten: + query.orderBy("t.file_last_write DESC"); + break; + case ReleaseSortMethod::Date: + query.orderBy("t.date, r.name COLLATE NOCASE"); + break; + case ReleaseSortMethod::OriginalDate: + query.orderBy("CASE WHEN t.original_date IS NULL THEN t.date ELSE t.original_date END, t.date, r.name COLLATE NOCASE"); + break; + case ReleaseSortMethod::OriginalDateDesc: + query.orderBy("CASE WHEN t.original_date IS NULL THEN t.date ELSE t.original_date END DESC, t.date, r.name COLLATE NOCASE"); + break; + case ReleaseSortMethod::StarredDateDesc: + assert(params.starringUser.isValid()); + query.orderBy("s_r.date_time DESC"); + break; } - oss << " " << clusterClause.get(); - oss << " GROUP BY t.id HAVING COUNT(*) = " << params.clusters.size() << ")"; - - query.where(oss.str()); + return query; } - if (params.primaryType) - query.where("primary_type = ?").bind(*params.primaryType); - if (!params.secondaryTypes.empty()) - query.where("secondary_type = ?").bind(params.secondaryTypes); - - switch (params.sortMethod) + template + Wt::Dbo::Query createQuery(Session& session, const Release::FindParameters& params) { - case ReleaseSortMethod::None: - break; - case ReleaseSortMethod::Name: - query.orderBy("r.name COLLATE NOCASE"); - break; - case ReleaseSortMethod::Random: - query.orderBy("RANDOM()"); - break; - case ReleaseSortMethod::LastWritten: - query.orderBy("t.file_last_write DESC"); - break; - case ReleaseSortMethod::Date: - query.orderBy("t.date, r.name COLLATE NOCASE"); - break; - case ReleaseSortMethod::OriginalDate: - query.orderBy("CASE WHEN t.original_date IS NULL THEN t.date ELSE t.original_date END, t.date, r.name COLLATE NOCASE"); - break; - case ReleaseSortMethod::OriginalDateDesc: - query.orderBy("CASE WHEN t.original_date IS NULL THEN t.date ELSE t.original_date END DESC, t.date, r.name COLLATE NOCASE"); - break; - case ReleaseSortMethod::StarredDateDesc: - assert(params.starringUser.isValid()); - query.orderBy("s_r.date_time DESC"); - break; - } + std::string_view itemToSelect; + + if constexpr (std::is_same_v) + itemToSelect = "r.id"; + else if constexpr (std::is_same_v>) + itemToSelect = "r"; + else + static_assert("Unhandled type"); - return query; + return createQuery(session, itemToSelect, params); + } } Release::Release(const std::string& name, const std::optional& MBID) @@ -238,7 +256,7 @@ namespace Database return session.getDboSession().query("SELECT COUNT(*) FROM release"); } - RangeResults Release::findOrderedByArtist(Session& session, Range range) + RangeResults Release::findIdsOrderedByArtist(Session& session, Range range) { session.checkSharedLocked(); @@ -253,7 +271,7 @@ namespace Database return Utils::execQuery(query, range); } - RangeResults Release::findOrphans(Session& session, Range range) + RangeResults Release::findOrphanIds(Session& session, Range range) { session.checkSharedLocked(); @@ -261,12 +279,19 @@ namespace Database return Utils::execQuery(query, range); } - RangeResults Release::find(Session& session, const FindParameters& params) + RangeResults Release::find(Session& session, const FindParameters& params) { session.checkSharedLocked(); - auto query{ createQuery(session, params) }; + auto query{ createQuery>(session, params) }; + return Utils::execQuery(query, params.range); + } + RangeResults Release::findIds(Session& session, const FindParameters& params) + { + session.checkSharedLocked(); + + auto query{ createQuery(session, params) }; return Utils::execQuery(query, params.range); } diff --git a/src/libs/services/database/include/services/database/Release.hpp b/src/libs/services/database/include/services/database/Release.hpp index dce8f4f3..28035a38 100644 --- a/src/libs/services/database/include/services/database/Release.hpp +++ b/src/libs/services/database/include/services/database/Release.hpp @@ -88,9 +88,10 @@ namespace Database static pointer find(Session& session, const UUID& MBID); static std::vector find(Session& session, const std::string& name); static pointer find(Session& session, ReleaseId id); - static RangeResults find(Session& session, const FindParameters& parameters); - static RangeResults findOrphans(Session& session, Range range); // no track related - static RangeResults findOrderedByArtist(Session& session, Range range); + static RangeResults find(Session& session, const FindParameters& parameters); + static RangeResults findIds(Session& session, const FindParameters& parameters); + static RangeResults findOrphanIds(Session& session, Range range); // not track related + static RangeResults findIdsOrderedByArtist(Session& session, Range range); // Get the cluster of the tracks that belong to this release // Each clusters are grouped by cluster type, sorted by the number of occurence (max to min) diff --git a/src/libs/services/database/test/Cluster.cpp b/src/libs/services/database/test/Cluster.cpp index b3fa9373..5e0cbcd0 100644 --- a/src/libs/services/database/test/Cluster.cpp +++ b/src/libs/services/database/test/Cluster.cpp @@ -374,7 +374,7 @@ TEST_F(DatabaseFixture, Cluster_singleTrackSingleReleaseSingleCluster) { auto transaction{ session.createSharedTransaction() }; - auto releases{ Release::find(session, Release::FindParameters {}.setClusters({cluster.getId()})) }; + const auto releases{ Release::findIds(session, Release::FindParameters {}.setClusters({cluster.getId()})) }; ASSERT_EQ(releases.results.size(), 1); EXPECT_EQ(releases.results.front(), release.getId()); } @@ -382,7 +382,7 @@ TEST_F(DatabaseFixture, Cluster_singleTrackSingleReleaseSingleCluster) { auto transaction{ session.createSharedTransaction() }; - auto releases{ Release::find(session, Release::FindParameters {}.setClusters({unusedCluster.getId()})) }; + const auto releases{ Release::findIds(session, Release::FindParameters {}.setClusters({unusedCluster.getId()})) }; EXPECT_EQ(releases.results.size(), 0); } @@ -415,7 +415,7 @@ TEST_F(DatabaseFixture, SingleTrackSingleArtistMultiClusters) auto transaction{ session.createSharedTransaction() }; EXPECT_TRUE(ClusterType::findOrphans(session, Range{}).results.empty()); EXPECT_EQ(Cluster::findOrphans(session, Range{}).results.size(), 2); - EXPECT_TRUE(Release::findOrphans(session, Range{}).results.empty()); + EXPECT_TRUE(Release::findOrphanIds(session, Range{}).results.empty()); EXPECT_TRUE(Artist::findAllOrphans(session, Range{}).results.empty()); } @@ -475,7 +475,7 @@ TEST_F(DatabaseFixture, SingleTrackSingleArtistMultiRolesMultiClusters) { auto transaction{ session.createSharedTransaction() }; EXPECT_TRUE(Cluster::findOrphans(session, Range{}).results.empty()); - EXPECT_TRUE(Release::findOrphans(session, Range{}).results.empty()); + EXPECT_TRUE(Release::findOrphanIds(session, Range{}).results.empty()); EXPECT_TRUE(Artist::findAllOrphans(session, Range{}).results.empty()); } @@ -628,7 +628,7 @@ TEST_F(DatabaseFixture, SingleTrackSingleReleaseSingleArtistSingleCluster) EXPECT_TRUE(Cluster::findOrphans(session, Range{}).results.empty()); EXPECT_TRUE(ClusterType::findOrphans(session, Range{}).results.empty()); EXPECT_TRUE(Artist::findAllOrphans(session, Range{}).results.empty()); - EXPECT_TRUE(Release::findOrphans(session, Range{}).results.empty()); + EXPECT_TRUE(Release::findOrphanIds(session, Range{}).results.empty()); } { @@ -638,11 +638,11 @@ TEST_F(DatabaseFixture, SingleTrackSingleReleaseSingleArtistSingleCluster) ASSERT_EQ(artists.results.size(), 1); EXPECT_EQ(artists.results.front(), artist.getId()); - auto releases{ Release::find(session, Release::FindParameters {}.setArtist(artist.getId())) }; + auto releases{ Release::findIds(session, Release::FindParameters {}.setArtist(artist.getId())) }; ASSERT_EQ(releases.results.size(), 1); EXPECT_EQ(releases.results.front(), release.getId()); - releases = Release::find(session, Release::FindParameters{}.setArtist(artist.getId()).setClusters({ cluster.getId() })); + releases = Release::findIds(session, Release::FindParameters{}.setArtist(artist.getId()).setClusters({ cluster.getId() })); ASSERT_EQ(releases.results.size(), 1); EXPECT_EQ(releases.results.front(), release.getId()); } @@ -669,11 +669,11 @@ TEST_F(DatabaseFixture, SingleTrackSingleReleaseSingleArtistMultiClusters) { auto transaction{ session.createSharedTransaction() }; - auto releases{ Release::find(session, Release::FindParameters {}.setArtist(artist.getId())) }; + auto releases{ Release::findIds(session, Release::FindParameters {}.setArtist(artist.getId())) }; ASSERT_EQ(releases.results.size(), 1); EXPECT_EQ(releases.results.front(), release.getId()); - releases = Release::find(session, Release::FindParameters{}.setArtist(artist.getId()).setClusters({ cluster1.getId(), cluster2.getId() })); + releases = Release::findIds(session, Release::FindParameters{}.setArtist(artist.getId()).setClusters({ cluster1.getId(), cluster2.getId() })); ASSERT_EQ(releases.results.size(), 1); EXPECT_EQ(releases.results.front(), release.getId()); } diff --git a/src/libs/services/database/test/DatabaseTest.cpp b/src/libs/services/database/test/DatabaseTest.cpp index 8e20b757..65844bf8 100644 --- a/src/libs/services/database/test/DatabaseTest.cpp +++ b/src/libs/services/database/test/DatabaseTest.cpp @@ -42,14 +42,14 @@ TEST_F(DatabaseFixture, MultiTracksSingleArtistSingleRelease) { auto transaction {session.createSharedTransaction()}; - EXPECT_TRUE(Release::findOrphans(session, Range {}).results.empty()); + EXPECT_TRUE(Release::findOrphanIds(session, Range {}).results.empty()); EXPECT_TRUE(Artist::findAllOrphans(session, Range {}).results.empty()); } { auto transaction {session.createSharedTransaction()}; - auto releases {Release::find(session, Release::FindParameters {}.setArtist(artist.getId()))}; + auto releases {Release::findIds(session, Release::FindParameters {}.setArtist(artist.getId()))}; ASSERT_EQ(releases.results.size(), 1); EXPECT_EQ(releases.results.front(), release.getId()); @@ -74,7 +74,7 @@ TEST_F(DatabaseFixture, SingleTrackSingleReleaseSingleArtist) { auto transaction {session.createUniqueTransaction()}; - auto releases {Release::find(session, Release::FindParameters {}.setArtist(artist.getId()))}; + auto releases {Release::findIds(session, Release::FindParameters {}.setArtist(artist.getId()))}; ASSERT_EQ(releases.results.size(), 1); EXPECT_EQ(releases.results.front(), release.getId()); diff --git a/src/libs/services/database/test/Release.cpp b/src/libs/services/database/test/Release.cpp index 9c153fc4..f3b400ea 100644 --- a/src/libs/services/database/test/Release.cpp +++ b/src/libs/services/database/test/Release.cpp @@ -23,580 +23,586 @@ using namespace Database; TEST_F(DatabaseFixture, Release) { - { - auto transaction {session.createSharedTransaction()}; + { + auto transaction{ session.createSharedTransaction() }; - EXPECT_EQ(Release::getCount(session), 0); - EXPECT_FALSE(Release::exists(session, 0)); - EXPECT_FALSE(Release::exists(session, 1)); - } + EXPECT_EQ(Release::getCount(session), 0); + EXPECT_FALSE(Release::exists(session, 0)); + EXPECT_FALSE(Release::exists(session, 1)); + } - ScopedRelease release {session, "MyRelease"}; + ScopedRelease release{ session, "MyRelease" }; - { - auto transaction {session.createSharedTransaction()}; + { + auto transaction{ session.createSharedTransaction() }; - EXPECT_EQ(Release::getCount(session), 1); - EXPECT_TRUE(Release::exists(session, release.getId())); + EXPECT_EQ(Release::getCount(session), 1); + EXPECT_TRUE(Release::exists(session, release.getId())); - { - auto releases {Release::findOrphans(session, Range {})}; - ASSERT_EQ(releases.results.size(), 1); - EXPECT_EQ(releases.results.front(), release.getId()); - } + { + const auto releases{ Release::findOrphanIds(session, Range {}) }; + ASSERT_EQ(releases.results.size(), 1); + EXPECT_EQ(releases.results.front(), release.getId()); + } - { - auto releases {Release::find(session, Release::FindParameters {})}; - ASSERT_EQ(releases.results.size(), 1); - EXPECT_EQ(releases.results.front(), release.getId()); - EXPECT_EQ(release->getDuration(), std::chrono::seconds {0}); - } - } + { + const auto releases{ Release::findIds(session, Release::FindParameters {}) }; + ASSERT_EQ(releases.results.size(), 1); + EXPECT_EQ(releases.results.front(), release.getId()); + EXPECT_EQ(release->getDuration(), std::chrono::seconds{ 0 }); + } + + { + const auto releases{ Release::find(session, Release::FindParameters {}) }; + ASSERT_EQ(releases.results.size(), 1); + EXPECT_EQ(releases.results.front()->getId(), release.getId()); + } + } } TEST_F(DatabaseFixture, Release_singleTrack) { - ScopedRelease release {session, "MyRelease"}; + ScopedRelease release{ session, "MyRelease" }; - { - ScopedTrack track {session, "MyTrack"}; - { - auto transaction {session.createUniqueTransaction()}; + { + ScopedTrack track{ session, "MyTrack" }; + { + auto transaction{ session.createUniqueTransaction() }; - track.get().modify()->setRelease(release.get()); - track.get().modify()->setName("MyTrackName"); - release.get().modify()->setName("MyReleaseName"); - } + track.get().modify()->setRelease(release.get()); + track.get().modify()->setName("MyTrackName"); + release.get().modify()->setName("MyReleaseName"); + } - { - auto transaction {session.createSharedTransaction()}; - EXPECT_TRUE(Release::findOrphans(session, Range {}).results.empty()); + { + auto transaction{ session.createSharedTransaction() }; + EXPECT_TRUE(Release::findOrphanIds(session, Range{}).results.empty()); - const auto tracks {Track::find(session, Track::FindParameters {}.setRelease(release.getId()))}; - ASSERT_EQ(tracks.results.size(), 1); - EXPECT_EQ(tracks.results.front(), track.getId()); - } + const auto tracks{ Track::find(session, Track::FindParameters {}.setRelease(release.getId())) }; + ASSERT_EQ(tracks.results.size(), 1); + EXPECT_EQ(tracks.results.front(), track.getId()); + } - { - auto transaction {session.createUniqueTransaction()}; + { + auto transaction{ session.createUniqueTransaction() }; - ASSERT_TRUE(track->getRelease()); - EXPECT_EQ(track->getRelease()->getId(), release.getId()); - } + ASSERT_TRUE(track->getRelease()); + EXPECT_EQ(track->getRelease()->getId(), release.getId()); + } - { - auto transaction {session.createUniqueTransaction()}; - auto tracks {Track::find(session, Track::FindParameters{}.setName("MyTrackName").setReleaseName("MyReleaseName"))}; - ASSERT_EQ(tracks.results.size(), 1); - EXPECT_EQ(tracks.results.front(), track.getId()); - } - { - auto transaction {session.createUniqueTransaction()}; - auto tracks {Track::find(session, Track::FindParameters{}.setName("MyTrackName").setReleaseName("MyReleaseFoo"))}; - EXPECT_EQ(tracks.results.size(), 0); - } - { - auto transaction {session.createUniqueTransaction()}; - auto tracks {Track::find(session, Track::FindParameters{}.setName("MyTrackFoo").setReleaseName("MyReleaseName"))}; - EXPECT_EQ(tracks.results.size(), 0); - } - } + { + auto transaction{ session.createUniqueTransaction() }; + auto tracks{ Track::find(session, Track::FindParameters{}.setName("MyTrackName").setReleaseName("MyReleaseName")) }; + ASSERT_EQ(tracks.results.size(), 1); + EXPECT_EQ(tracks.results.front(), track.getId()); + } + { + auto transaction{ session.createUniqueTransaction() }; + auto tracks{ Track::find(session, Track::FindParameters{}.setName("MyTrackName").setReleaseName("MyReleaseFoo")) }; + EXPECT_EQ(tracks.results.size(), 0); + } + { + auto transaction{ session.createUniqueTransaction() }; + auto tracks{ Track::find(session, Track::FindParameters{}.setName("MyTrackFoo").setReleaseName("MyReleaseName")) }; + EXPECT_EQ(tracks.results.size(), 0); + } + } - { - auto transaction {session.createUniqueTransaction()}; + { + auto transaction{ session.createUniqueTransaction() }; - const auto tracks {Track::find(session, Track::FindParameters {}.setRelease(release.getId()))}; - EXPECT_TRUE(tracks.results.empty()); + const auto tracks{ Track::find(session, Track::FindParameters {}.setRelease(release.getId())) }; + EXPECT_TRUE(tracks.results.empty()); - auto releases {Release::findOrphans(session, Range {})}; - ASSERT_EQ(releases.results.size(), 1); - EXPECT_EQ(releases.results.front(), release.getId()); - } + auto releases{ Release::findOrphanIds(session, Range {}) }; + ASSERT_EQ(releases.results.size(), 1); + EXPECT_EQ(releases.results.front(), release.getId()); + } } TEST_F(DatabaseFixture, MulitpleReleaseSearchByName) { - ScopedRelease release1 {session, "MyRelease"}; - ScopedRelease release2 {session, "MyRelease%"}; - ScopedRelease release3 {session, "%MyRelease"}; - ScopedRelease release4 {session, "MyRelease%Foo"}; - ScopedRelease release5 {session, "Foo%MyRelease"}; - ScopedRelease release6 {session, "_yRelease"}; + ScopedRelease release1{ session, "MyRelease" }; + ScopedRelease release2{ session, "MyRelease%" }; + ScopedRelease release3{ session, "%MyRelease" }; + ScopedRelease release4{ session, "MyRelease%Foo" }; + ScopedRelease release5{ session, "Foo%MyRelease" }; + ScopedRelease release6{ session, "_yRelease" }; - // filters does not work on orphans - ScopedTrack track1 {session, "MyTrack"}; - ScopedTrack track2 {session, "MyTrack"}; - ScopedTrack track3 {session, "MyTrack"}; - ScopedTrack track4 {session, "MyTrack"}; - ScopedTrack track5 {session, "MyTrack"}; - ScopedTrack track6 {session, "MyTrack"}; + // filters does not work on orphans + ScopedTrack track1{ session, "MyTrack" }; + ScopedTrack track2{ session, "MyTrack" }; + ScopedTrack track3{ session, "MyTrack" }; + ScopedTrack track4{ session, "MyTrack" }; + ScopedTrack track5{ session, "MyTrack" }; + ScopedTrack track6{ session, "MyTrack" }; - { - auto transaction {session.createUniqueTransaction()}; + { + auto transaction{ session.createUniqueTransaction() }; - track1.get().modify()->setRelease(release1.get()); - track2.get().modify()->setRelease(release2.get()); - track3.get().modify()->setRelease(release3.get()); - track4.get().modify()->setRelease(release4.get()); - track5.get().modify()->setRelease(release5.get()); - track6.get().modify()->setRelease(release6.get()); - } + track1.get().modify()->setRelease(release1.get()); + track2.get().modify()->setRelease(release2.get()); + track3.get().modify()->setRelease(release3.get()); + track4.get().modify()->setRelease(release4.get()); + track5.get().modify()->setRelease(release5.get()); + track6.get().modify()->setRelease(release6.get()); + } - { - auto transaction {session.createSharedTransaction()}; + { + auto transaction{ session.createSharedTransaction() }; - { - const auto releases {Release::find(session, Release::FindParameters {}.setKeywords({"Release"}))}; - EXPECT_EQ(releases.results.size(), 6); - } + { + const auto releases{ Release::findIds(session, Release::FindParameters {}.setKeywords({"Release"})) }; + EXPECT_EQ(releases.results.size(), 6); + } - { - const auto releases {Release::find(session, Release::FindParameters {}.setKeywords({"MyRelease"}))}; - ASSERT_EQ(releases.results.size(), 5); - EXPECT_TRUE(std::none_of(std::cbegin(releases.results), std::cend(releases.results), [&](const ReleaseId releaseId) { return releaseId == release6.getId(); })); - } - { - const auto releases {Release::find(session, Release::FindParameters {}.setKeywords({"MyRelease%"}))}; - ASSERT_EQ(releases.results.size(), 2); - EXPECT_EQ(releases.results[0], release2.getId()); - EXPECT_EQ(releases.results[1], release4.getId()); - } - { - const auto releases {Release::find(session, Release::FindParameters {}.setKeywords({"%MyRelease"}))}; - ASSERT_EQ(releases.results.size(), 2); - EXPECT_EQ(releases.results[0], release3.getId()); - EXPECT_EQ(releases.results[1], release5.getId()); - } - { - const auto releases {Release::find(session, Release::FindParameters {}.setKeywords({"Foo%MyRelease"}))}; - ASSERT_EQ(releases.results.size(), 1); - EXPECT_EQ(releases.results[0], release5.getId()); - } - { - const auto releases {Release::find(session, Release::FindParameters {}.setKeywords({"MyRelease%Foo"}))}; - ASSERT_EQ(releases.results.size(), 1); - EXPECT_EQ(releases.results[0], release4.getId()); - } - } + { + const auto releases{ Release::findIds(session, Release::FindParameters {}.setKeywords({"MyRelease"})) }; + ASSERT_EQ(releases.results.size(), 5); + EXPECT_TRUE(std::none_of(std::cbegin(releases.results), std::cend(releases.results), [&](const ReleaseId releaseId) { return releaseId == release6.getId(); })); + } + { + const auto releases{ Release::findIds(session, Release::FindParameters {}.setKeywords({"MyRelease%"})) }; + ASSERT_EQ(releases.results.size(), 2); + EXPECT_EQ(releases.results[0], release2.getId()); + EXPECT_EQ(releases.results[1], release4.getId()); + } + { + const auto releases{ Release::findIds(session, Release::FindParameters {}.setKeywords({"%MyRelease"})) }; + ASSERT_EQ(releases.results.size(), 2); + EXPECT_EQ(releases.results[0], release3.getId()); + EXPECT_EQ(releases.results[1], release5.getId()); + } + { + const auto releases{ Release::findIds(session, Release::FindParameters {}.setKeywords({"Foo%MyRelease"})) }; + ASSERT_EQ(releases.results.size(), 1); + EXPECT_EQ(releases.results[0], release5.getId()); + } + { + const auto releases{ Release::findIds(session, Release::FindParameters {}.setKeywords({"MyRelease%Foo"})) }; + ASSERT_EQ(releases.results.size(), 1); + EXPECT_EQ(releases.results[0], release4.getId()); + } + } } TEST_F(DatabaseFixture, MultiTracksSingleReleaseTotalDiscTrack) { - ScopedRelease release1 {session, "MyRelease"}; + ScopedRelease release1{ session, "MyRelease" }; - { - auto transaction {session.createSharedTransaction()}; + { + auto transaction{ session.createSharedTransaction() }; - EXPECT_FALSE(release1->getTotalDisc()); - } + EXPECT_FALSE(release1->getTotalDisc()); + } - ScopedTrack track1 {session, "MyTrack"}; - { - auto transaction {session.createUniqueTransaction()}; + ScopedTrack track1{ session, "MyTrack" }; + { + auto transaction{ session.createUniqueTransaction() }; - track1.get().modify()->setRelease(release1.get()); - } + track1.get().modify()->setRelease(release1.get()); + } - { - auto transaction {session.createSharedTransaction()}; + { + auto transaction{ session.createSharedTransaction() }; - EXPECT_FALSE(release1->getTotalDisc()); - } + EXPECT_FALSE(release1->getTotalDisc()); + } - { - auto transaction {session.createUniqueTransaction()}; + { + auto transaction{ session.createUniqueTransaction() }; - track1.get().modify()->setTotalTrack(36); - release1.get().modify()->setTotalDisc(6); - } + track1.get().modify()->setTotalTrack(36); + release1.get().modify()->setTotalDisc(6); + } - { - auto transaction {session.createSharedTransaction()}; + { + auto transaction{ session.createSharedTransaction() }; - ASSERT_TRUE(track1->getTotalTrack()); - EXPECT_EQ(*track1->getTotalTrack(), 36); - ASSERT_TRUE(release1->getTotalDisc()); - EXPECT_EQ(*release1->getTotalDisc(), 6); - } + ASSERT_TRUE(track1->getTotalTrack()); + EXPECT_EQ(*track1->getTotalTrack(), 36); + ASSERT_TRUE(release1->getTotalDisc()); + EXPECT_EQ(*release1->getTotalDisc(), 6); + } - ScopedTrack track2 {session, "MyTrack2"}; - { - auto transaction {session.createUniqueTransaction()}; + ScopedTrack track2{ session, "MyTrack2" }; + { + auto transaction{ session.createUniqueTransaction() }; - track2.get().modify()->setRelease(release1.get()); - track2.get().modify()->setTotalTrack(37); - release1.get().modify()->setTotalDisc(67); - } + track2.get().modify()->setRelease(release1.get()); + track2.get().modify()->setTotalTrack(37); + release1.get().modify()->setTotalDisc(67); + } - { - auto transaction {session.createSharedTransaction()}; + { + auto transaction{ session.createSharedTransaction() }; - ASSERT_TRUE(track1->getTotalTrack()); - EXPECT_EQ(*track1->getTotalTrack(), 36); - ASSERT_TRUE(release1->getTotalDisc()); - EXPECT_EQ(*release1->getTotalDisc(), 67); - } + ASSERT_TRUE(track1->getTotalTrack()); + EXPECT_EQ(*track1->getTotalTrack(), 36); + ASSERT_TRUE(release1->getTotalDisc()); + EXPECT_EQ(*release1->getTotalDisc(), 67); + } - ScopedRelease release2 {session, "MyRelease2"}; - { - auto transaction {session.createSharedTransaction()}; + ScopedRelease release2{ session, "MyRelease2" }; + { + auto transaction{ session.createSharedTransaction() }; - EXPECT_FALSE(release2->getTotalDisc()); - } + EXPECT_FALSE(release2->getTotalDisc()); + } - ScopedTrack track3 {session, "MyTrack3"}; - { - auto transaction {session.createUniqueTransaction()}; + ScopedTrack track3{ session, "MyTrack3" }; + { + auto transaction{ session.createUniqueTransaction() }; - track3.get().modify()->setRelease(release2.get()); - track3.get().modify()->setTotalTrack(7); - release2.get().modify()->setTotalDisc(5); - } - { - auto transaction {session.createSharedTransaction()}; + track3.get().modify()->setRelease(release2.get()); + track3.get().modify()->setTotalTrack(7); + release2.get().modify()->setTotalDisc(5); + } + { + auto transaction{ session.createSharedTransaction() }; - ASSERT_TRUE(track1->getTotalTrack()); - EXPECT_EQ(*track1->getTotalTrack(), 36); - ASSERT_TRUE(release1->getTotalDisc()); - EXPECT_EQ(*release2->getTotalDisc(), 5); - ASSERT_TRUE(track3->getTotalTrack()); - EXPECT_EQ(*track3->getTotalTrack(), 7); - ASSERT_TRUE(release2->getTotalDisc()); - EXPECT_EQ(*release2->getTotalDisc(), 5); - } + ASSERT_TRUE(track1->getTotalTrack()); + EXPECT_EQ(*track1->getTotalTrack(), 36); + ASSERT_TRUE(release1->getTotalDisc()); + EXPECT_EQ(*release2->getTotalDisc(), 5); + ASSERT_TRUE(track3->getTotalTrack()); + EXPECT_EQ(*track3->getTotalTrack(), 7); + ASSERT_TRUE(release2->getTotalDisc()); + EXPECT_EQ(*release2->getTotalDisc(), 5); + } } TEST_F(DatabaseFixture, MultiTracksSingleReleaseFirstTrack) { - ScopedRelease release1 {session, "MyRelease1"}; - ScopedRelease release2 {session, "MyRelease2"}; + ScopedRelease release1{ session, "MyRelease1" }; + ScopedRelease release2{ session, "MyRelease2" }; - ScopedTrack track1A {session, "MyTrack1A"}; - ScopedTrack track1B {session, "MyTrack1B"}; - ScopedTrack track2A {session, "MyTrack2A"}; - ScopedTrack track2B {session, "MyTrack2B"}; + ScopedTrack track1A{ session, "MyTrack1A" }; + ScopedTrack track1B{ session, "MyTrack1B" }; + ScopedTrack track2A{ session, "MyTrack2A" }; + ScopedTrack track2B{ session, "MyTrack2B" }; - { - auto transaction {session.createSharedTransaction()}; + { + auto transaction{ session.createSharedTransaction() }; - EXPECT_TRUE(Track::find(session, Track::FindParameters {}.setRelease(release1.getId())).results.empty()); - EXPECT_TRUE(Track::find(session, Track::FindParameters {}.setRelease(release2.getId())).results.empty()); - } + EXPECT_TRUE(Track::find(session, Track::FindParameters{}.setRelease(release1.getId())).results.empty()); + EXPECT_TRUE(Track::find(session, Track::FindParameters{}.setRelease(release2.getId())).results.empty()); + } - { - auto transaction {session.createUniqueTransaction()}; + { + auto transaction{ session.createUniqueTransaction() }; - track1A.get().modify()->setRelease(release1.get()); - track1B.get().modify()->setRelease(release1.get()); - track2A.get().modify()->setRelease(release2.get()); - track2B.get().modify()->setRelease(release2.get()); + track1A.get().modify()->setRelease(release1.get()); + track1B.get().modify()->setRelease(release1.get()); + track2A.get().modify()->setRelease(release2.get()); + track2B.get().modify()->setRelease(release2.get()); - track1A.get().modify()->setTrackNumber(1); - track1B.get().modify()->setTrackNumber(2); + track1A.get().modify()->setTrackNumber(1); + track1B.get().modify()->setTrackNumber(2); - track2A.get().modify()->setDiscNumber(2); - track2A.get().modify()->setTrackNumber(1); - track2B.get().modify()->setTrackNumber(2); - track2B.get().modify()->setDiscNumber(1); - } + track2A.get().modify()->setDiscNumber(2); + track2A.get().modify()->setTrackNumber(1); + track2B.get().modify()->setTrackNumber(2); + track2B.get().modify()->setDiscNumber(1); + } - { - auto transaction {session.createSharedTransaction()}; + { + auto transaction{ session.createSharedTransaction() }; - { - const auto tracks {Track::find(session, Track::FindParameters {}.setRelease(release1.getId()).setSortMethod(TrackSortMethod::Release))}; - ASSERT_FALSE(tracks.results.empty()); - EXPECT_EQ(tracks.results.front(), track1A.getId()); - } + { + const auto tracks{ Track::find(session, Track::FindParameters {}.setRelease(release1.getId()).setSortMethod(TrackSortMethod::Release)) }; + ASSERT_FALSE(tracks.results.empty()); + EXPECT_EQ(tracks.results.front(), track1A.getId()); + } - { - const auto tracks {Track::find(session, Track::FindParameters {}.setRelease(release2.getId()).setSortMethod(TrackSortMethod::Release))}; - ASSERT_FALSE(tracks.results.empty()); - EXPECT_EQ(tracks.results.front(), track2B.getId()); - } - } + { + const auto tracks{ Track::find(session, Track::FindParameters {}.setRelease(release2.getId()).setSortMethod(TrackSortMethod::Release)) }; + ASSERT_FALSE(tracks.results.empty()); + EXPECT_EQ(tracks.results.front(), track2B.getId()); + } + } } TEST_F(DatabaseFixture, MultiTracksSingleReleaseDate) { - ScopedRelease release1 {session, "MyRelease1"}; - ScopedRelease release2 {session, "MyRelease2"}; - const Wt::WDate release1Date {Wt::WDate {1994, 2, 3}}; - const Wt::WDate release1OriginalDate {Wt::WDate {1993, 4, 5}}; + ScopedRelease release1{ session, "MyRelease1" }; + ScopedRelease release2{ session, "MyRelease2" }; + const Wt::WDate release1Date{ Wt::WDate {1994, 2, 3} }; + const Wt::WDate release1OriginalDate{ Wt::WDate {1993, 4, 5} }; - ScopedTrack track1A {session, "MyTrack1A"}; - ScopedTrack track1B {session, "MyTrack1B"}; - ScopedTrack track2A {session, "MyTrack2A"}; - ScopedTrack track2B {session, "MyTrack2B"}; + ScopedTrack track1A{ session, "MyTrack1A" }; + ScopedTrack track1B{ session, "MyTrack1B" }; + ScopedTrack track2A{ session, "MyTrack2A" }; + ScopedTrack track2B{ session, "MyTrack2B" }; - { - auto transaction {session.createSharedTransaction()}; + { + auto transaction{ session.createSharedTransaction() }; - const auto releases {Release::find(session, Release::FindParameters {}.setDateRange(DateRange::fromYearRange(0, 3000)))}; - EXPECT_EQ(releases.results.size(), 0); - } + const auto releases{ Release::findIds(session, Release::FindParameters {}.setDateRange(DateRange::fromYearRange(0, 3000))) }; + EXPECT_EQ(releases.results.size(), 0); + } - { - auto transaction {session.createUniqueTransaction()}; + { + auto transaction{ session.createUniqueTransaction() }; - track1A.get().modify()->setRelease(release1.get()); - track1B.get().modify()->setRelease(release1.get()); - track2A.get().modify()->setRelease(release2.get()); - track2B.get().modify()->setRelease(release2.get()); + track1A.get().modify()->setRelease(release1.get()); + track1B.get().modify()->setRelease(release1.get()); + track2A.get().modify()->setRelease(release2.get()); + track2B.get().modify()->setRelease(release2.get()); - track1A.get().modify()->setDate(release1Date); - track1B.get().modify()->setDate(release1Date); - track1A.get().modify()->setOriginalDate(release1OriginalDate); - track1B.get().modify()->setOriginalDate(release1OriginalDate); + track1A.get().modify()->setDate(release1Date); + track1B.get().modify()->setDate(release1Date); + track1A.get().modify()->setOriginalDate(release1OriginalDate); + track1B.get().modify()->setOriginalDate(release1OriginalDate); - EXPECT_EQ(release1.get()->getReleaseDate(), release1Date); - EXPECT_EQ(release1.get()->getOriginalReleaseDate(), release1OriginalDate); - } + EXPECT_EQ(release1.get()->getReleaseDate(), release1Date); + EXPECT_EQ(release1.get()->getOriginalReleaseDate(), release1OriginalDate); + } - { - auto transaction {session.createSharedTransaction()}; + { + auto transaction{ session.createSharedTransaction() }; - auto releases {Release::find(session, Release::FindParameters {}.setDateRange(DateRange::fromYearRange(1950, 2000)))}; - ASSERT_EQ(releases.results.size(), 1); - EXPECT_EQ(releases.results.front(), release1.getId()); + auto releases{ Release::findIds(session, Release::FindParameters {}.setDateRange(DateRange::fromYearRange(1950, 2000))) }; + ASSERT_EQ(releases.results.size(), 1); + EXPECT_EQ(releases.results.front(), release1.getId()); - releases = Release::find(session, Release::FindParameters {}.setDateRange(DateRange::fromYearRange(1994, 1994))); - ASSERT_EQ(releases.results.size(), 1); - EXPECT_EQ(releases.results.front(), release1.getId()); + releases = Release::findIds(session, Release::FindParameters{}.setDateRange(DateRange::fromYearRange(1994, 1994))); + ASSERT_EQ(releases.results.size(), 1); + EXPECT_EQ(releases.results.front(), release1.getId()); - releases = Release::find(session, Release::FindParameters {}.setDateRange(DateRange::fromYearRange(1993, 1993))); - ASSERT_EQ(releases.results.size(), 0); - } + releases = Release::findIds(session, Release::FindParameters{}.setDateRange(DateRange::fromYearRange(1993, 1993))); + ASSERT_EQ(releases.results.size(), 0); + } } TEST_F(DatabaseFixture, Release_writtenAfter) { - ScopedRelease release {session, "MyRelease"}; - ScopedTrack track {session, "MyTrack"}; + ScopedRelease release{ session, "MyRelease" }; + ScopedTrack track{ session, "MyTrack" }; - const Wt::WDateTime dateTime {Wt::WDate {1950, 1, 1}, Wt::WTime {12, 30, 20}}; + const Wt::WDateTime dateTime{ Wt::WDate {1950, 1, 1}, Wt::WTime {12, 30, 20} }; - { - auto transaction {session.createUniqueTransaction()}; - track.get().modify()->setLastWriteTime(dateTime); - track.get().modify()->setRelease(release.get()); - } + { + auto transaction{ session.createUniqueTransaction() }; + track.get().modify()->setLastWriteTime(dateTime); + track.get().modify()->setRelease(release.get()); + } - { - auto transaction {session.createSharedTransaction()}; - const auto releases {Release::find(session, Release::FindParameters {})}; - EXPECT_EQ(releases.results.size(), 1); - } + { + auto transaction{ session.createSharedTransaction() }; + const auto releases{ Release::findIds(session, Release::FindParameters {}) }; + EXPECT_EQ(releases.results.size(), 1); + } - { - auto transaction {session.createSharedTransaction()}; - const auto releases {Release::find(session, Release::FindParameters {}.setWrittenAfter(dateTime.addSecs(-1)))}; - EXPECT_EQ(releases.results.size(), 1); - } + { + auto transaction{ session.createSharedTransaction() }; + const auto releases{ Release::findIds(session, Release::FindParameters {}.setWrittenAfter(dateTime.addSecs(-1))) }; + EXPECT_EQ(releases.results.size(), 1); + } - { - auto transaction {session.createSharedTransaction()}; - const auto releases {Release::find(session, Release::FindParameters {}.setWrittenAfter(dateTime.addSecs(+1)))}; - EXPECT_EQ(releases.results.size(), 0); - } + { + auto transaction{ session.createSharedTransaction() }; + const auto releases{ Release::findIds(session, Release::FindParameters {}.setWrittenAfter(dateTime.addSecs(+1))) }; + EXPECT_EQ(releases.results.size(), 0); + } } TEST_F(DatabaseFixture, Release_artist) { - ScopedRelease release {session, "MyRelease"}; - ScopedTrack track {session, "MyTrack"}; - ScopedArtist artist {session, "MyArtist"}; - ScopedArtist artist2 {session, "MyArtist2"}; - { - auto transaction {session.createUniqueTransaction()}; - track.get().modify()->setRelease(release.get()); - } + ScopedRelease release{ session, "MyRelease" }; + ScopedTrack track{ session, "MyTrack" }; + ScopedArtist artist{ session, "MyArtist" }; + ScopedArtist artist2{ session, "MyArtist2" }; + { + auto transaction{ session.createUniqueTransaction() }; + track.get().modify()->setRelease(release.get()); + } - { - auto transaction {session.createSharedTransaction()}; + { + auto transaction{ session.createSharedTransaction() }; - auto releases {Release::find(session, Release::FindParameters {}.setArtist(artist.getId(), {TrackArtistLinkType::Artist}))}; - EXPECT_EQ(releases.results.size(), 0); + auto releases{ Release::findIds(session, Release::FindParameters {}.setArtist(artist.getId(), {TrackArtistLinkType::Artist})) }; + EXPECT_EQ(releases.results.size(), 0); - releases = Release::find(session, Release::FindParameters {}.setArtist(artist2.getId(), {TrackArtistLinkType::Artist})); - EXPECT_EQ(releases.results.size(), 0); - } + releases = Release::findIds(session, Release::FindParameters{}.setArtist(artist2.getId(), { TrackArtistLinkType::Artist })); + EXPECT_EQ(releases.results.size(), 0); + } - { - auto transaction {session.createUniqueTransaction()}; - TrackArtistLink::create(session, track.get(), artist.get(), TrackArtistLinkType::Artist); + { + auto transaction{ session.createUniqueTransaction() }; + TrackArtistLink::create(session, track.get(), artist.get(), TrackArtistLinkType::Artist); - auto releases {Release::find(session, Release::FindParameters {}.setArtist(artist.getId(), {TrackArtistLinkType::Artist}))}; - ASSERT_EQ(releases.results.size(), 1); - EXPECT_EQ(releases.results.front(), release.getId()); + auto releases{ Release::findIds(session, Release::FindParameters {}.setArtist(artist.getId(), {TrackArtistLinkType::Artist})) }; + ASSERT_EQ(releases.results.size(), 1); + EXPECT_EQ(releases.results.front(), release.getId()); - releases = Release::find(session, Release::FindParameters {}.setArtist(artist.getId(), {TrackArtistLinkType::Artist, TrackArtistLinkType::Mixer})); - EXPECT_EQ(releases.results.size(), 1); - EXPECT_EQ(releases.results.front(), release.getId()); + releases = Release::findIds(session, Release::FindParameters{}.setArtist(artist.getId(), { TrackArtistLinkType::Artist, TrackArtistLinkType::Mixer })); + EXPECT_EQ(releases.results.size(), 1); + EXPECT_EQ(releases.results.front(), release.getId()); - releases = Release::find(session, Release::FindParameters {}.setArtist(artist2.getId(), {TrackArtistLinkType::Artist})); - EXPECT_EQ(releases.results.size(), 0); + releases = Release::findIds(session, Release::FindParameters{}.setArtist(artist2.getId(), { TrackArtistLinkType::Artist })); + EXPECT_EQ(releases.results.size(), 0); - releases = Release::find(session, Release::FindParameters {}.setArtist(artist2.getId())); - EXPECT_EQ(releases.results.size(), 0); + releases = Release::findIds(session, Release::FindParameters{}.setArtist(artist2.getId())); + EXPECT_EQ(releases.results.size(), 0); - releases = Release::find(session, Release::FindParameters {}.setArtist(artist.getId(), {TrackArtistLinkType::ReleaseArtist, TrackArtistLinkType::Artist})); - ASSERT_EQ(releases.results.size(), 1); - EXPECT_EQ(releases.results.front(), release.getId()); + releases = Release::findIds(session, Release::FindParameters{}.setArtist(artist.getId(), { TrackArtistLinkType::ReleaseArtist, TrackArtistLinkType::Artist })); + ASSERT_EQ(releases.results.size(), 1); + EXPECT_EQ(releases.results.front(), release.getId()); - releases = Release::find(session, Release::FindParameters {}.setArtist(artist.getId())); - ASSERT_EQ(releases.results.size(), 1); - EXPECT_EQ(releases.results.front(), release.getId()); + releases = Release::findIds(session, Release::FindParameters{}.setArtist(artist.getId())); + ASSERT_EQ(releases.results.size(), 1); + EXPECT_EQ(releases.results.front(), release.getId()); - releases = Release::find(session, Release::FindParameters {}.setArtist(artist.getId(), {TrackArtistLinkType::Composer})); - EXPECT_EQ(releases.results.size(), 0); + releases = Release::findIds(session, Release::FindParameters{}.setArtist(artist.getId(), { TrackArtistLinkType::Composer })); + EXPECT_EQ(releases.results.size(), 0); - releases = Release::find(session, Release::FindParameters {}.setArtist(artist.getId(), {TrackArtistLinkType::Composer, TrackArtistLinkType::Mixer})); - EXPECT_EQ(releases.results.size(), 0); + releases = Release::findIds(session, Release::FindParameters{}.setArtist(artist.getId(), { TrackArtistLinkType::Composer, TrackArtistLinkType::Mixer })); + EXPECT_EQ(releases.results.size(), 0); - releases = Release::find(session, Release::FindParameters {}.setArtist(artist.getId(), {}, {TrackArtistLinkType::Artist})); - EXPECT_EQ(releases.results.size(), 0); + releases = Release::findIds(session, Release::FindParameters{}.setArtist(artist.getId(), {}, { TrackArtistLinkType::Artist })); + EXPECT_EQ(releases.results.size(), 0); - releases = Release::find(session, Release::FindParameters {}.setArtist(artist.getId(), {}, {TrackArtistLinkType::Artist, TrackArtistLinkType::Composer})); - EXPECT_EQ(releases.results.size(), 0); - } + releases = Release::findIds(session, Release::FindParameters{}.setArtist(artist.getId(), {}, { TrackArtistLinkType::Artist, TrackArtistLinkType::Composer })); + EXPECT_EQ(releases.results.size(), 0); + } } TEST_F(DatabaseFixture, Release_getDiscCount) { - ScopedRelease release {session, "MyRelease"}; - ScopedTrack track {session, "MyTrack"}; - ScopedTrack track2 {session, "MyTrack2"}; + ScopedRelease release{ session, "MyRelease" }; + ScopedTrack track{ session, "MyTrack" }; + ScopedTrack track2{ session, "MyTrack2" }; - { - auto transaction {session.createSharedTransaction()}; - EXPECT_EQ(release.get()->getDiscCount(), 0); - } - { - auto transaction {session.createUniqueTransaction()}; - track.get().modify()->setRelease(release.get()); - } - { - auto transaction {session.createSharedTransaction()}; - EXPECT_EQ(release.get()->getDiscCount(), 0); - } - { - auto transaction {session.createUniqueTransaction()}; - track.get().modify()->setDiscNumber(5); - } - { - auto transaction {session.createSharedTransaction()}; - EXPECT_EQ(release.get()->getDiscCount(), 1); - } - { - auto transaction {session.createUniqueTransaction()}; - track2.get().modify()->setRelease(release.get()); - track2.get().modify()->setDiscNumber(5); - } - { - auto transaction {session.createSharedTransaction()}; - EXPECT_EQ(release.get()->getDiscCount(), 1); - } - { - auto transaction {session.createUniqueTransaction()}; - track2.get().modify()->setDiscNumber(6); - } - { - auto transaction {session.createSharedTransaction()}; - EXPECT_EQ(release.get()->getDiscCount(), 2); - } + { + auto transaction{ session.createSharedTransaction() }; + EXPECT_EQ(release.get()->getDiscCount(), 0); + } + { + auto transaction{ session.createUniqueTransaction() }; + track.get().modify()->setRelease(release.get()); + } + { + auto transaction{ session.createSharedTransaction() }; + EXPECT_EQ(release.get()->getDiscCount(), 0); + } + { + auto transaction{ session.createUniqueTransaction() }; + track.get().modify()->setDiscNumber(5); + } + { + auto transaction{ session.createSharedTransaction() }; + EXPECT_EQ(release.get()->getDiscCount(), 1); + } + { + auto transaction{ session.createUniqueTransaction() }; + track2.get().modify()->setRelease(release.get()); + track2.get().modify()->setDiscNumber(5); + } + { + auto transaction{ session.createSharedTransaction() }; + EXPECT_EQ(release.get()->getDiscCount(), 1); + } + { + auto transaction{ session.createUniqueTransaction() }; + track2.get().modify()->setDiscNumber(6); + } + { + auto transaction{ session.createSharedTransaction() }; + EXPECT_EQ(release.get()->getDiscCount(), 2); + } } TEST_F(DatabaseFixture, Release_releaseType) { - ScopedRelease release {session, "MyRelease"}; + ScopedRelease release{ session, "MyRelease" }; - { - auto transaction {session.createSharedTransaction()}; - EXPECT_EQ(release.get()->getPrimaryType(), std::nullopt); - EXPECT_EQ(release.get()->getSecondaryTypes(), EnumSet {}); - } + { + auto transaction{ session.createSharedTransaction() }; + EXPECT_EQ(release.get()->getPrimaryType(), std::nullopt); + EXPECT_EQ(release.get()->getSecondaryTypes(), EnumSet {}); + } - { - auto transaction {session.createUniqueTransaction()}; - release.get().modify()->setPrimaryType({ ReleaseTypePrimary::Album }); - release.get().modify()->setSecondaryTypes({ ReleaseTypeSecondary::Compilation }); - } + { + auto transaction{ session.createUniqueTransaction() }; + release.get().modify()->setPrimaryType({ ReleaseTypePrimary::Album }); + release.get().modify()->setSecondaryTypes({ ReleaseTypeSecondary::Compilation }); + } - { - auto transaction {session.createSharedTransaction()}; - EXPECT_EQ(release.get()->getPrimaryType(), ReleaseTypePrimary::Album); - EXPECT_TRUE(release.get()->getSecondaryTypes().contains(ReleaseTypeSecondary::Compilation)); - } + { + auto transaction{ session.createSharedTransaction() }; + EXPECT_EQ(release.get()->getPrimaryType(), ReleaseTypePrimary::Album); + EXPECT_TRUE(release.get()->getSecondaryTypes().contains(ReleaseTypeSecondary::Compilation)); + } } TEST_F(DatabaseFixture, ReleaseSortOrder) { - ScopedRelease release1 {session, "MyRelease1"}; - const Wt::WDate release1Date {Wt::WDate {2000, 2, 3}}; - const Wt::WDate release1OriginalDate {Wt::WDate {1993, 4, 5}}; + ScopedRelease release1{ session, "MyRelease1" }; + const Wt::WDate release1Date{ Wt::WDate {2000, 2, 3} }; + const Wt::WDate release1OriginalDate{ Wt::WDate {1993, 4, 5} }; - ScopedRelease release2 {session, "MyRelease2"}; - const Wt::WDate release2Date {Wt::WDate {1994, 2, 3}}; + ScopedRelease release2{ session, "MyRelease2" }; + const Wt::WDate release2Date{ Wt::WDate {1994, 2, 3} }; - ScopedTrack track1 {session, "MyTrack1"}; - ScopedTrack track2 {session, "MyTrack2"}; + ScopedTrack track1{ session, "MyTrack1" }; + ScopedTrack track2{ session, "MyTrack2" }; - ASSERT_LT(release2Date, release1Date); - ASSERT_GT(release2Date, release1OriginalDate); + ASSERT_LT(release2Date, release1Date); + ASSERT_GT(release2Date, release1OriginalDate); - { - auto transaction {session.createUniqueTransaction()}; + { + auto transaction{ session.createUniqueTransaction() }; - track1.get().modify()->setRelease(release1.get()); - track1.get().modify()->setOriginalDate(release1OriginalDate); - track1.get().modify()->setDate(release1Date); + track1.get().modify()->setRelease(release1.get()); + track1.get().modify()->setOriginalDate(release1OriginalDate); + track1.get().modify()->setDate(release1Date); - track2.get().modify()->setRelease(release2.get()); - track2.get().modify()->setDate(release2Date); - } + track2.get().modify()->setRelease(release2.get()); + track2.get().modify()->setDate(release2Date); + } - { - auto transaction {session.createSharedTransaction()}; + { + auto transaction{ session.createSharedTransaction() }; - const auto releases {Release::find(session, Release::FindParameters {}.setSortMethod(ReleaseSortMethod::Name) )}; - ASSERT_EQ(releases.results.size(), 2); - EXPECT_EQ(releases.results.front(), release1.getId()); - EXPECT_EQ(releases.results.back(), release2.getId()); - } + const auto releases{ Release::findIds(session, Release::FindParameters {}.setSortMethod(ReleaseSortMethod::Name)) }; + ASSERT_EQ(releases.results.size(), 2); + EXPECT_EQ(releases.results.front(), release1.getId()); + EXPECT_EQ(releases.results.back(), release2.getId()); + } - { - auto transaction {session.createSharedTransaction()}; + { + auto transaction{ session.createSharedTransaction() }; - const auto releases {Release::find(session, Release::FindParameters {}.setSortMethod(ReleaseSortMethod::Random) )}; - ASSERT_EQ(releases.results.size(), 2); - } + const auto releases{ Release::findIds(session, Release::FindParameters {}.setSortMethod(ReleaseSortMethod::Random)) }; + ASSERT_EQ(releases.results.size(), 2); + } - { - auto transaction {session.createSharedTransaction()}; + { + auto transaction{ session.createSharedTransaction() }; - const auto releases {Release::find(session, Release::FindParameters {}.setSortMethod(ReleaseSortMethod::Date) )}; - ASSERT_EQ(releases.results.size(), 2); - EXPECT_EQ(releases.results.front(), release2.getId()); - EXPECT_EQ(releases.results.back(), release1.getId()); - } + const auto releases{ Release::findIds(session, Release::FindParameters {}.setSortMethod(ReleaseSortMethod::Date)) }; + ASSERT_EQ(releases.results.size(), 2); + EXPECT_EQ(releases.results.front(), release2.getId()); + EXPECT_EQ(releases.results.back(), release1.getId()); + } - { - auto transaction {session.createSharedTransaction()}; + { + auto transaction{ session.createSharedTransaction() }; - const auto releases {Release::find(session, Release::FindParameters {}.setSortMethod(ReleaseSortMethod::OriginalDate) )}; - ASSERT_EQ(releases.results.size(), 2); - EXPECT_EQ(releases.results.front(), release1.getId()); - EXPECT_EQ(releases.results.back(), release2.getId()); - } - { - auto transaction {session.createSharedTransaction()}; + const auto releases{ Release::findIds(session, Release::FindParameters {}.setSortMethod(ReleaseSortMethod::OriginalDate)) }; + ASSERT_EQ(releases.results.size(), 2); + EXPECT_EQ(releases.results.front(), release1.getId()); + EXPECT_EQ(releases.results.back(), release2.getId()); + } + { + auto transaction{ session.createSharedTransaction() }; - const auto releases {Release::find(session, Release::FindParameters {}.setSortMethod(ReleaseSortMethod::OriginalDateDesc) )}; - ASSERT_EQ(releases.results.size(), 2); - EXPECT_EQ(releases.results.front(), release2.getId()); - EXPECT_EQ(releases.results.back(), release1.getId()); - } + const auto releases{ Release::findIds(session, Release::FindParameters {}.setSortMethod(ReleaseSortMethod::OriginalDateDesc)) }; + ASSERT_EQ(releases.results.size(), 2); + EXPECT_EQ(releases.results.front(), release2.getId()); + EXPECT_EQ(releases.results.back(), release1.getId()); + } } diff --git a/src/libs/services/database/test/StarredRelease.cpp b/src/libs/services/database/test/StarredRelease.cpp index ba0e5cb5..e595a416 100644 --- a/src/libs/services/database/test/StarredRelease.cpp +++ b/src/libs/services/database/test/StarredRelease.cpp @@ -96,7 +96,7 @@ TEST_F(DatabaseFixture, StarredRelease_dateTime) { auto transaction{ session.createSharedTransaction() }; - auto releases{ Release::find(session, Release::FindParameters {}.setStarringUser(user.getId(), FeedbackBackend::Internal)) }; + auto releases{ Release::findIds(session, Release::FindParameters {}.setStarringUser(user.getId(), FeedbackBackend::Internal)) }; EXPECT_EQ(releases.results.size(), 2); } @@ -106,7 +106,7 @@ TEST_F(DatabaseFixture, StarredRelease_dateTime) starredRelease1.get().modify()->setDateTime(dateTime); starredRelease2.get().modify()->setDateTime(dateTime.addSecs(-1)); - auto releases{ Release::find(session, Release::FindParameters {}.setStarringUser(user.getId(), FeedbackBackend::Internal).setSortMethod(ReleaseSortMethod::StarredDateDesc)) }; + auto releases{ Release::findIds(session, Release::FindParameters {}.setStarringUser(user.getId(), FeedbackBackend::Internal).setSortMethod(ReleaseSortMethod::StarredDateDesc)) }; ASSERT_EQ(releases.results.size(), 2); EXPECT_EQ(releases.results[0], starredRelease1->getRelease()->getId()); EXPECT_EQ(releases.results[1], starredRelease2->getRelease()->getId()); @@ -117,7 +117,7 @@ TEST_F(DatabaseFixture, StarredRelease_dateTime) starredRelease1.get().modify()->setDateTime(dateTime); starredRelease2.get().modify()->setDateTime(dateTime.addSecs(1)); - auto releases{ Release::find(session, Release::FindParameters {}.setStarringUser(user.getId(), FeedbackBackend::Internal).setSortMethod(ReleaseSortMethod::StarredDateDesc)) }; + auto releases{ Release::findIds(session, Release::FindParameters {}.setStarringUser(user.getId(), FeedbackBackend::Internal).setSortMethod(ReleaseSortMethod::StarredDateDesc)) }; ASSERT_EQ(releases.results.size(), 2); EXPECT_EQ(releases.results[0], starredRelease2->getRelease()->getId()); EXPECT_EQ(releases.results[1], starredRelease1->getRelease()->getId()); diff --git a/src/libs/services/feedback/impl/FeedbackService.cpp b/src/libs/services/feedback/impl/FeedbackService.cpp index 4a5297ac..30981a8b 100644 --- a/src/libs/services/feedback/impl/FeedbackService.cpp +++ b/src/libs/services/feedback/impl/FeedbackService.cpp @@ -141,7 +141,7 @@ namespace Feedback Session& session{ _db.getTLSSession() }; auto transaction{ session.createSharedTransaction() }; - return Release::find(session, params); + return Release::findIds(session, params); } void FeedbackService::star(UserId userId, TrackId trackId) diff --git a/src/libs/services/scanner/impl/ScanStepRemoveOrphanDbFiles.cpp b/src/libs/services/scanner/impl/ScanStepRemoveOrphanDbFiles.cpp index 5b57416d..f3731f2b 100644 --- a/src/libs/services/scanner/impl/ScanStepRemoveOrphanDbFiles.cpp +++ b/src/libs/services/scanner/impl/ScanStepRemoveOrphanDbFiles.cpp @@ -153,10 +153,11 @@ namespace Scanner LMS_LOG(DBUPDATER, DEBUG) << "Checking orphan releases..."; + // TODO, by batch Session& session {_db.getTLSSession()}; auto transaction {session.createUniqueTransaction()}; - auto releases {Release::findOrphans(session, Range {})}; + auto releases {Release::findOrphanIds(session, Range {})}; for (const ReleaseId releaseId : releases.results) { Release::pointer release {Release::find(session, releaseId)}; diff --git a/src/libs/subsonic/impl/entrypoints/AlbumSongLists.cpp b/src/libs/subsonic/impl/entrypoints/AlbumSongLists.cpp index 7eac8606..f1634147 100644 --- a/src/libs/subsonic/impl/entrypoints/AlbumSongLists.cpp +++ b/src/libs/subsonic/impl/entrypoints/AlbumSongLists.cpp @@ -66,11 +66,11 @@ namespace API::Subsonic params.setSortMethod(ReleaseSortMethod::Name); params.setRange(range); - releases = Release::find(context.dbSession, params); + releases = Release::findIds(context.dbSession, params); } else if (type == "alphabeticalByArtist") { - releases = Release::findOrderedByArtist(context.dbSession, range); + releases = Release::findIdsOrderedByArtist(context.dbSession, range); } else if (type == "byGenre") { @@ -86,7 +86,7 @@ namespace API::Subsonic params.setSortMethod(ReleaseSortMethod::Name); params.setRange(range); - releases = Release::find(context.dbSession, params); + releases = Release::findIds(context.dbSession, params); } } } @@ -100,7 +100,7 @@ namespace API::Subsonic params.setRange(range); params.setDateRange(DateRange::fromYearRange(fromYear, toYear)); - releases = Release::find(context.dbSession, params); + releases = Release::findIds(context.dbSession, params); } else if (type == "frequent") { @@ -112,7 +112,7 @@ namespace API::Subsonic params.setSortMethod(ReleaseSortMethod::LastWritten); params.setRange(range); - releases = Release::find(context.dbSession, params); + releases = Release::findIds(context.dbSession, params); } else if (type == "random") { @@ -122,7 +122,7 @@ namespace API::Subsonic params.setSortMethod(ReleaseSortMethod::Random); params.setRange({ 0, size }); - releases = Release::find(context.dbSession, params); + releases = Release::findIds(context.dbSession, params); } else if (type == "recent") { diff --git a/src/libs/subsonic/impl/entrypoints/Browsing.cpp b/src/libs/subsonic/impl/entrypoints/Browsing.cpp index 14c32236..87b750dd 100644 --- a/src/libs/subsonic/impl/entrypoints/Browsing.cpp +++ b/src/libs/subsonic/impl/entrypoints/Browsing.cpp @@ -335,11 +335,8 @@ namespace API::Subsonic directoryNode.setAttribute("name", Utils::makeNameFilesystemCompatible(artist->getName())); const auto artistReleases{ Release::find(context.dbSession, Release::FindParameters {}.setArtist(*artistId)) }; - for (const ReleaseId artistReleaseId : artistReleases.results) - { - const Release::pointer release{ Release::find(context.dbSession, artistReleaseId) }; + for (const Release::pointer& release : artistReleases.results) directoryNode.addArrayChild("child", createAlbumNode(context, release, user, false /* no id3 */)); - } } else if (releaseId) { @@ -408,11 +405,8 @@ namespace API::Subsonic Response::Node artistNode{ createArtistNode(context, artist, user, true /* id3 */) }; const auto releases{ Release::find(context.dbSession, Release::FindParameters {}.setArtist(artist->getId())) }; - for (const ReleaseId releaseId : releases.results) - { - const Release::pointer release{ Release::find(context.dbSession, releaseId) }; + for (const Release::pointer& release : releases.results) artistNode.addArrayChild("album", createAlbumNode(context, release, user, true /* id3 */)); - } response.addNode("artist", std::move(artistNode)); diff --git a/src/libs/subsonic/impl/entrypoints/Searching.cpp b/src/libs/subsonic/impl/entrypoints/Searching.cpp index de4b18f9..5d609795 100644 --- a/src/libs/subsonic/impl/entrypoints/Searching.cpp +++ b/src/libs/subsonic/impl/entrypoints/Searching.cpp @@ -70,7 +70,6 @@ namespace API::Subsonic { Artist::FindParameters params; params.setKeywords(keywords); - params.setSortMethod(ArtistSortMethod::BySortName); params.setRange({ artistOffset, artistCount }); RangeResults artistIds{ Artist::find(context.dbSession, params) }; @@ -85,15 +84,11 @@ namespace API::Subsonic { Release::FindParameters params; params.setKeywords(keywords); - params.setSortMethod(ReleaseSortMethod::Name); params.setRange({ albumOffset, albumCount }); - RangeResults releaseIds{ Release::find(context.dbSession, params) }; - for (const ReleaseId releaseId : releaseIds.results) - { - const auto release{ Release::find(context.dbSession, releaseId) }; + RangeResults releases{ Release::find(context.dbSession, params) }; + for (const Release::pointer& release : releases.results) searchResult2Node.addArrayChild("album", createAlbumNode(context, release, user, id3)); - } } if (songCount > 0) diff --git a/src/lms/ui/explore/ArtistView.cpp b/src/lms/ui/explore/ArtistView.cpp index 9d9f7626..8df53080 100644 --- a/src/lms/ui/explore/ArtistView.cpp +++ b/src/lms/ui/explore/ArtistView.cpp @@ -216,7 +216,7 @@ Artist::refreshReleases() params.setArtist(_artistId, {TrackArtistLinkType::ReleaseArtist}, {}); params.setSortMethod(ReleaseSortMethod::OriginalDateDesc); - const auto releases {Release::find(LmsApp->getDbSession(), params)}; + const auto releases {Release::findIds(LmsApp->getDbSession(), params)}; if (!releases.results.empty()) { // first pass: gather all ids and sort by type @@ -276,7 +276,7 @@ Artist::refreshAppearsOnReleases() params.setArtist(_artistId, types, {TrackArtistLinkType::ReleaseArtist}); params.setSortMethod(ReleaseSortMethod::OriginalDateDesc); - const auto releases {Release::find(LmsApp->getDbSession(), params)}; + const auto releases {Release::findIds(LmsApp->getDbSession(), params)}; if (!releases.results.empty()) { Wt::WTemplate* releaseContainer {bindNew("appears-on-releases", Wt::WString::tr("Lms.Explore.Artist.template.release-container"))}; diff --git a/src/lms/ui/explore/ReleaseCollector.cpp b/src/lms/ui/explore/ReleaseCollector.cpp index f892bbd8..4a421d4c 100644 --- a/src/lms/ui/explore/ReleaseCollector.cpp +++ b/src/lms/ui/explore/ReleaseCollector.cpp @@ -19,12 +19,9 @@ #include "ReleaseCollector.hpp" -#include - #include "services/database/Release.hpp" #include "services/database/Session.hpp" #include "services/database/User.hpp" -#include "services/database/TrackList.hpp" #include "services/feedback/IFeedbackService.hpp" #include "services/scrobbling/IScrobblingService.hpp" #include "utils/Service.hpp" @@ -35,8 +32,7 @@ namespace UserInterface { using namespace Database; - RangeResults - ReleaseCollector::get(Database::Range range) + RangeResults ReleaseCollector::get(Database::Range range) { Feedback::IFeedbackService& feedbackService{ *Service::get() }; Scrobbling::IScrobblingService& scrobblingService{ *Service::get() }; @@ -73,7 +69,7 @@ namespace UserInterface { auto transaction{ LmsApp->getDbSession().createSharedTransaction() }; - releases = Release::find(LmsApp->getDbSession(), params); + releases = Release::findIds(LmsApp->getDbSession(), params); } break; } @@ -87,7 +83,7 @@ namespace UserInterface { auto transaction{ LmsApp->getDbSession().createSharedTransaction() }; - releases = Release::find(LmsApp->getDbSession(), params); + releases = Release::findIds(LmsApp->getDbSession(), params); } break; } @@ -101,7 +97,7 @@ namespace UserInterface { auto transaction{ LmsApp->getDbSession().createSharedTransaction() }; - releases = Release::find(LmsApp->getDbSession(), params); + releases = Release::findIds(LmsApp->getDbSession(), params); } break; } @@ -113,8 +109,7 @@ namespace UserInterface return releases; } - RangeResults - ReleaseCollector::getRandomReleases(Range range) + RangeResults ReleaseCollector::getRandomReleases(Range range) { assert(getMode() == Mode::Random); @@ -127,7 +122,7 @@ namespace UserInterface { auto transaction{ LmsApp->getDbSession().createSharedTransaction() }; - _randomReleases = Release::find(LmsApp->getDbSession(), params); + _randomReleases = Release::findIds(LmsApp->getDbSession(), params); } } diff --git a/src/tools/recommendation/LmsRecommendation.cpp b/src/tools/recommendation/LmsRecommendation.cpp index 5dec1cb3..eaf876f9 100644 --- a/src/tools/recommendation/LmsRecommendation.cpp +++ b/src/tools/recommendation/LmsRecommendation.cpp @@ -42,154 +42,154 @@ static void dumpTracksRecommendation(Session session, Recommendation::IRecommendationService& recommendationService, unsigned maxSimilarityCount) { - const RangeResults trackIds {[&]() - { - auto transaction {session.createSharedTransaction()}; - return Track::find(session, Track::FindParameters {}); - }()}; + const RangeResults trackIds{ [&] + { + auto transaction {session.createSharedTransaction()}; + return Track::find(session, Track::FindParameters {}); + }() }; - std::cout << "*** Tracks (" << trackIds.results.size() << ") ***" << std::endl; - for (const TrackId trackId : trackIds.results) - { - auto trackToString = [&](const TrackId trackId) - { - std::string res; - auto transaction {session.createSharedTransaction()}; - const Track::pointer track {Track::find(session, trackId)}; + std::cout << "*** Tracks (" << trackIds.results.size() << ") ***" << std::endl; + for (const TrackId trackId : trackIds.results) + { + auto trackToString = [&](const TrackId trackId) + { + std::string res; + auto transaction{ session.createSharedTransaction() }; + const Track::pointer track{ Track::find(session, trackId) }; - res += track->getName(); - if (track->getRelease()) - res += " [" + track->getRelease()->getName() + "]"; - for (auto artist : track->getArtists({TrackArtistLinkType::Artist})) - res += " - " + artist->getName(); - for (auto cluster : track->getClusters()) - res += " {" + cluster->getType()->getName() + "-"+ cluster->getName() + "}"; + res += track->getName(); + if (track->getRelease()) + res += " [" + track->getRelease()->getName() + "]"; + for (auto artist : track->getArtists({ TrackArtistLinkType::Artist })) + res += " - " + artist->getName(); + for (auto cluster : track->getClusters()) + res += " {" + cluster->getType()->getName() + "-" + cluster->getName() + "}"; - return res; - }; + return res; + }; - std::cout << "Processing track '" << trackToString(trackId) << std::endl; - for (TrackId similarTrackId : recommendationService.findSimilarTracks({trackId}, maxSimilarityCount)) - std::cout << "\t- Similar track '" << trackToString(similarTrackId) << std::endl; - } + std::cout << "Processing track '" << trackToString(trackId) << std::endl; + for (TrackId similarTrackId : recommendationService.findSimilarTracks({ trackId }, maxSimilarityCount)) + std::cout << "\t- Similar track '" << trackToString(similarTrackId) << std::endl; + } } static void dumpReleasesRecommendation(Session session, Recommendation::IRecommendationService& recommendationService, unsigned maxSimilarityCount) { - const RangeResults releaseIds {std::invoke([&]() - { - auto transaction {session.createSharedTransaction()}; - return Release::find(session, Release::FindParameters {}); - })}; + const RangeResults releaseIds{ std::invoke([&] + { + auto transaction {session.createSharedTransaction()}; + return Release::findIds(session, Release::FindParameters {}); + }) }; - std::cout << "*** Releases ***" << std::endl; - for (ReleaseId releaseId : releaseIds.results) - { - auto releaseToString = [&](ReleaseId releaseId) -> std::string - { - auto transaction {session.createSharedTransaction()}; + std::cout << "*** Releases ***" << std::endl; + for (const ReleaseId releaseId : releaseIds.results) + { + auto releaseToString = [&](ReleaseId releaseId) -> std::string + { + auto transaction{ session.createSharedTransaction() }; - Release::pointer release {Release::find(session, releaseId)}; - return release->getName(); - }; + Release::pointer release{ Release::find(session, releaseId) }; + return release->getName(); + }; - std::cout << "Processing release '" << releaseToString(releaseId) << "'" << std::endl; - for (ReleaseId similarReleaseId : recommendationService.getSimilarReleases(releaseId, maxSimilarityCount)) - std::cout << "\t- Similar release '" << releaseToString(similarReleaseId) << "'" << std::endl; - } + std::cout << "Processing release '" << releaseToString(releaseId) << "'" << std::endl; + for (const ReleaseId similarReleaseId : recommendationService.getSimilarReleases(releaseId, maxSimilarityCount)) + std::cout << "\t- Similar release '" << releaseToString(similarReleaseId) << "'" << std::endl; + } } static void dumpArtistsRecommendation(Session session, Recommendation::IRecommendationService& recommendationService, unsigned maxSimilarityCount) { - const RangeResults artistIds = std::invoke([&]() - { - auto transaction {session.createSharedTransaction()}; - return Artist::find(session, Artist::FindParameters {}); - }); + const RangeResults artistIds = std::invoke([&]() + { + auto transaction{ session.createSharedTransaction() }; + return Artist::find(session, Artist::FindParameters{}); + }); - std::cout << "*** Artists ***" << std::endl; - for (ArtistId artistId : artistIds.results) - { - auto artistToString = [&](ArtistId artistId) - { - auto transaction {session.createSharedTransaction()}; + std::cout << "*** Artists ***" << std::endl; + for (ArtistId artistId : artistIds.results) + { + auto artistToString = [&](ArtistId artistId) + { + auto transaction{ session.createSharedTransaction() }; - Artist::pointer artist {Artist::find(session, artistId)}; - return artist->getName(); - }; + Artist::pointer artist{ Artist::find(session, artistId) }; + return artist->getName(); + }; - std::cout << "Processing artist '" << artistToString(artistId) << "'" << std::endl; - for (ArtistId similarArtistId : recommendationService.getSimilarArtists(artistId, {TrackArtistLinkType::Artist, TrackArtistLinkType::ReleaseArtist}, maxSimilarityCount)) - { - std::cout << "\t- Similar artist '" << artistToString(similarArtistId) << "'" << std::endl; - } - } + std::cout << "Processing artist '" << artistToString(artistId) << "'" << std::endl; + for (ArtistId similarArtistId : recommendationService.getSimilarArtists(artistId, { TrackArtistLinkType::Artist, TrackArtistLinkType::ReleaseArtist }, maxSimilarityCount)) + { + std::cout << "\t- Similar artist '" << artistToString(similarArtistId) << "'" << std::endl; + } + } } -int main(int argc, char *argv[]) +int main(int argc, char* argv[]) { - try - { - namespace po = boost::program_options; + try + { + namespace po = boost::program_options; - // log to stdout - Service logger {std::make_unique(std::cout)}; + // log to stdout + Service logger{ std::make_unique(std::cout) }; - po::options_description desc{"Allowed options"}; + po::options_description desc{ "Allowed options" }; desc.add_options() - ("help,h", "print usage message") - ("conf,c", po::value()->default_value("/etc/lms.conf"), "LMS config file") - ("artists,a", "Display recommendation for artists") - ("releases,r", "Display recommendation for releases") - ("tracks,t", "Display recommendation for tracks") - ("max,m", po::value()->default_value(3), "Max similarity result count") - ; + ("help,h", "print usage message") + ("conf,c", po::value()->default_value("/etc/lms.conf"), "LMS config file") + ("artists,a", "Display recommendation for artists") + ("releases,r", "Display recommendation for releases") + ("tracks,t", "Display recommendation for tracks") + ("max,m", po::value()->default_value(3), "Max similarity result count") + ; po::variables_map vm; po::store(po::parse_command_line(argc, argv, desc), vm); if (vm.count("help")) - { - std::cout << desc << std::endl; + { + std::cout << desc << std::endl; return EXIT_SUCCESS; } - Service config {createConfig(vm["conf"].as())}; + Service config{ createConfig(vm["conf"].as()) }; - Db db {config->getPath("working-dir") / "lms.db"}; - Session session {db}; + Db db{ config->getPath("working-dir") / "lms.db" }; + Session session{ db }; - std::cout << "Creating recommendation recommendationService..." << std::endl; - const auto recommendationService {Recommendation::createRecommendationService(db)}; - std::cout << "Recommendation recommendationService created!" << std::endl; + std::cout << "Creating recommendation recommendationService..." << std::endl; + const auto recommendationService{ Recommendation::createRecommendationService(db) }; + std::cout << "Recommendation recommendationService created!" << std::endl; - std::cout << "Loading recommendation recommendationService..." << std::endl; - recommendationService->load(false); + std::cout << "Loading recommendation recommendationService..." << std::endl; + recommendationService->load(false); - unsigned maxSimilarityCount {vm["max"].as()}; + unsigned maxSimilarityCount{ vm["max"].as() }; - std::cout << "Recommendation recommendationService loaded!" << std::endl; + std::cout << "Recommendation recommendationService loaded!" << std::endl; - if (vm.count("tracks")) - dumpTracksRecommendation(db, *recommendationService, maxSimilarityCount); + if (vm.count("tracks")) + dumpTracksRecommendation(db, *recommendationService, maxSimilarityCount); - if (vm.count("releases")) - dumpReleasesRecommendation(db, *recommendationService, maxSimilarityCount); + if (vm.count("releases")) + dumpReleasesRecommendation(db, *recommendationService, maxSimilarityCount); - if (vm.count("artists")) - dumpArtistsRecommendation(db, *recommendationService, maxSimilarityCount); - } - catch( std::exception& e) - { - std::cerr << "Caught exception: " << e.what() << std::endl; - return EXIT_FAILURE; - } + if (vm.count("artists")) + dumpArtistsRecommendation(db, *recommendationService, maxSimilarityCount); + } + catch (std::exception& e) + { + std::cerr << "Caught exception: " << e.what() << std::endl; + return EXIT_FAILURE; + } - return EXIT_SUCCESS; + return EXIT_SUCCESS; }