Raised artist/album/track limits when explorin the collection. fixes #237
This commit is contained in:
@@ -370,6 +370,7 @@ CoverService::getFromTrack(Database::Session& dbSession, Database::TrackId track
|
||||
std::shared_ptr<IEncodedImage>
|
||||
CoverService::getFromRelease(Database::ReleaseId releaseId, ImageSize width)
|
||||
{
|
||||
using namespace Database;
|
||||
const CacheEntryDesc cacheEntryDesc {releaseId, width};
|
||||
|
||||
std::shared_ptr<IEncodedImage> cover {loadFromCache(cacheEntryDesc)};
|
||||
@@ -378,11 +379,11 @@ CoverService::getFromRelease(Database::ReleaseId releaseId, ImageSize width)
|
||||
|
||||
struct ReleaseInfo
|
||||
{
|
||||
Database::TrackId firstTrackId;
|
||||
TrackId firstTrackId;
|
||||
std::filesystem::path releaseDirectory;
|
||||
};
|
||||
|
||||
Database::Session& session {_db.getTLSSession()};
|
||||
Session& session {_db.getTLSSession()};
|
||||
|
||||
auto getReleaseInfo {[&]
|
||||
{
|
||||
@@ -390,13 +391,15 @@ CoverService::getFromRelease(Database::ReleaseId releaseId, ImageSize width)
|
||||
|
||||
auto transaction {session.createSharedTransaction()};
|
||||
|
||||
if (const Database::Release::pointer release {Database::Release::find(session, releaseId)})
|
||||
const auto tracks {Track::find(session, Track::FindParameters {}.setRelease(releaseId).setRange({0, 1}).setSortMethod(TrackSortMethod::Release))};
|
||||
|
||||
if (!tracks.results.empty())
|
||||
{
|
||||
if (const auto firstTrack {release->getFirstTrack()})
|
||||
if (const Track::pointer track {Track::find(session, tracks.results.front())})
|
||||
{
|
||||
res = ReleaseInfo {};
|
||||
res->firstTrackId = firstTrack->getId();
|
||||
res->releaseDirectory = firstTrack->getPath().parent_path();
|
||||
res->firstTrackId = track->getId();
|
||||
res->releaseDirectory = track->getPath().parent_path();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -405,64 +405,12 @@ Release::hasVariousArtists() const
|
||||
return getArtists().size() > 1;
|
||||
}
|
||||
|
||||
std::vector<Track::pointer>
|
||||
Release::getTracks(const std::vector<ClusterId>& clusterIds) const
|
||||
{
|
||||
assert(session());
|
||||
|
||||
WhereClause where;
|
||||
|
||||
std::ostringstream oss;
|
||||
oss << "SELECT t FROM track t INNER JOIN release r ON t.release_id = r.id";
|
||||
|
||||
if (!clusterIds.empty())
|
||||
{
|
||||
oss << " INNER JOIN cluster c ON c.id = t_c.cluster_id INNER JOIN track_cluster t_c ON t_c.track_id = t.id";
|
||||
|
||||
WhereClause clusterClause;
|
||||
|
||||
for (auto id : clusterIds)
|
||||
clusterClause.Or(WhereClause("c.id = ?")).bind(id.toString());
|
||||
|
||||
where.And(clusterClause);
|
||||
}
|
||||
|
||||
where.And(WhereClause("r.id = ?")).bind(getId().toString());
|
||||
|
||||
oss << " " << where.get();
|
||||
|
||||
if (!clusterIds.empty())
|
||||
oss << " GROUP BY t.id HAVING COUNT(*) = " << clusterIds.size();
|
||||
|
||||
oss << " ORDER BY t.disc_number,t.track_number";
|
||||
|
||||
auto query {session()->query<Wt::Dbo::ptr<Track>>(oss.str())};
|
||||
for (const std::string& bindArg : where.getBindArgs())
|
||||
query.bind(bindArg);
|
||||
|
||||
auto res {query.resultList()};
|
||||
return std::vector<Track::pointer> (res.begin(), res.end());
|
||||
}
|
||||
|
||||
std::size_t
|
||||
Release::getTracksCount() const
|
||||
{
|
||||
return _tracks.size();
|
||||
}
|
||||
|
||||
Track::pointer
|
||||
Release::getFirstTrack() const
|
||||
{
|
||||
assert(session());
|
||||
|
||||
return session()->query<Wt::Dbo::ptr<Track>>("SELECT t from track t")
|
||||
.join("release r ON t.release_id = r.id")
|
||||
.where("r.id = ?").bind(getId())
|
||||
.orderBy("t.disc_number,t.track_number")
|
||||
.limit(1)
|
||||
.resultValue();
|
||||
}
|
||||
|
||||
std::chrono::milliseconds
|
||||
Release::getDuration() const
|
||||
{
|
||||
|
||||
@@ -103,8 +103,11 @@ createQuery(Session& session, const Track::FindParameters& params)
|
||||
}
|
||||
}
|
||||
|
||||
assert(!(params.nonRelease && params.release.isValid()));
|
||||
if (params.nonRelease)
|
||||
query.where("t.release_id IS NULL");
|
||||
else if (params.release.isValid())
|
||||
query.where("t.release_id = ?").bind(params.release);
|
||||
|
||||
switch (params.sortMethod)
|
||||
{
|
||||
@@ -126,6 +129,9 @@ createQuery(Session& session, const Track::FindParameters& params)
|
||||
case TrackSortMethod::DateDescAndRelease:
|
||||
query.orderBy("t.date DESC,t.release_id,t.disc_number,t.track_number");
|
||||
break;
|
||||
case TrackSortMethod::Release:
|
||||
query.orderBy("t.disc_number,t.track_number");
|
||||
break;
|
||||
}
|
||||
|
||||
return query;
|
||||
|
||||
@@ -91,9 +91,7 @@ class Release : public Object<Release, ReleaseId>
|
||||
static RangeResults<ReleaseId> findOrphans(Session& session, Range range); // no track related
|
||||
static RangeResults<ReleaseId> findOrderedByArtist(Session& session, Range range);
|
||||
|
||||
std::vector<ObjectPtr<Track>> getTracks(const std::vector<ClusterId>& clusters = {}) const;
|
||||
std::size_t getTracksCount() const;
|
||||
ObjectPtr<Track> getFirstTrack() const;
|
||||
|
||||
// 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)
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
#include "services/database/ArtistId.hpp"
|
||||
#include "services/database/ClusterId.hpp"
|
||||
#include "services/database/Object.hpp"
|
||||
#include "services/database/ReleaseId.hpp"
|
||||
#include "services/database/TrackId.hpp"
|
||||
#include "services/database/Types.hpp"
|
||||
#include "services/database/UserId.hpp"
|
||||
@@ -67,6 +68,7 @@ class Track : public Object<Track, TrackId>
|
||||
ArtistId artist; // only tracks that involve this user
|
||||
EnumSet<TrackArtistLinkType> trackArtistLinkTypes; // and for these link types
|
||||
bool nonRelease {}; // only tracks that do not belong to a release
|
||||
ReleaseId release; // matching this release
|
||||
|
||||
FindParameters& setClusters(const std::vector<ClusterId>& _clusters) { clusters = _clusters; return *this; }
|
||||
FindParameters& setKeywords(const std::vector<std::string_view>& _keywords) { keywords = _keywords; return *this; }
|
||||
@@ -76,6 +78,7 @@ class Track : public Object<Track, TrackId>
|
||||
FindParameters& setStarringUser(UserId _user, Scrobbler _scrobbler) { starringUser = _user; scrobbler = _scrobbler; return *this; }
|
||||
FindParameters& setArtist(ArtistId _artist, EnumSet<TrackArtistLinkType> _trackArtistLinkTypes = {}) { artist = _artist; trackArtistLinkTypes = _trackArtistLinkTypes; return *this; }
|
||||
FindParameters& setNonRelease(bool _nonRelease) { nonRelease = _nonRelease; return *this; }
|
||||
FindParameters& setRelease(ReleaseId _release) { release = _release; return *this; }
|
||||
};
|
||||
|
||||
struct PathResult
|
||||
|
||||
@@ -112,6 +112,7 @@ namespace Database
|
||||
StarredDateDesc,
|
||||
Name,
|
||||
DateDescAndRelease,
|
||||
Release, // order by disc/track number
|
||||
};
|
||||
|
||||
enum class TrackArtistLinkType
|
||||
|
||||
@@ -53,7 +53,8 @@ TEST_F(DatabaseFixture, MultiTracksSingleArtistSingleRelease)
|
||||
ASSERT_EQ(releases.results.size(), 1);
|
||||
EXPECT_EQ(releases.results.front(), release.getId());
|
||||
|
||||
EXPECT_EQ(release->getTracks().size(), nbTracks);
|
||||
const auto tracks {Track::find(session, Track::FindParameters {}.setRelease(release.getId()))};
|
||||
EXPECT_EQ(tracks.results.size(), nbTracks);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -70,9 +70,9 @@ TEST_F(DatabaseFixture, Release_singleTrack)
|
||||
auto transaction {session.createSharedTransaction()};
|
||||
EXPECT_TRUE(Release::findOrphans(session, Range {}).results.empty());
|
||||
|
||||
EXPECT_EQ(release->getTracksCount(), 1);
|
||||
ASSERT_EQ(release->getTracks().size(), 1);
|
||||
EXPECT_EQ(release->getTracks().front()->getId(), 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());
|
||||
}
|
||||
|
||||
{
|
||||
@@ -103,7 +103,8 @@ TEST_F(DatabaseFixture, Release_singleTrack)
|
||||
{
|
||||
auto transaction {session.createUniqueTransaction()};
|
||||
|
||||
EXPECT_TRUE(release->getTracks().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);
|
||||
@@ -279,8 +280,8 @@ TEST_F(DatabaseFixture, MultiTracksSingleReleaseFirstTrack)
|
||||
{
|
||||
auto transaction {session.createSharedTransaction()};
|
||||
|
||||
EXPECT_FALSE(release1->getFirstTrack());
|
||||
EXPECT_FALSE(release2->getFirstTrack());
|
||||
EXPECT_TRUE(Track::find(session, Track::FindParameters {}.setRelease(release1.getId())).results.empty());
|
||||
EXPECT_TRUE(Track::find(session, Track::FindParameters {}.setRelease(release2.getId())).results.empty());
|
||||
}
|
||||
|
||||
{
|
||||
@@ -303,11 +304,17 @@ TEST_F(DatabaseFixture, MultiTracksSingleReleaseFirstTrack)
|
||||
{
|
||||
auto transaction {session.createSharedTransaction()};
|
||||
|
||||
EXPECT_TRUE(release1->getFirstTrack());
|
||||
EXPECT_TRUE(release2->getFirstTrack());
|
||||
{
|
||||
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());
|
||||
}
|
||||
|
||||
EXPECT_EQ(release1->getFirstTrack()->getId(), track1A.getId());
|
||||
EXPECT_EQ(release2->getFirstTrack()->getId(), 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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user