Added a sentinel when UI limit is hit + a message when nothing found, fixes #358
This commit is contained in:
@@ -128,29 +128,10 @@ namespace lms::db::utils
|
||||
}
|
||||
|
||||
template<typename ResultType, typename Query>
|
||||
RangeResults<ResultType> execRangeQuery(Query& query, const std::optional<Range> range)
|
||||
std::vector<ResultType> execRangeQuery(Query& query, const std::optional<Range> range)
|
||||
{
|
||||
RangeResults<ResultType> res;
|
||||
|
||||
if (range)
|
||||
{
|
||||
res.range.offset = range->offset;
|
||||
applyRange(query, Range{ range->offset, range->size + 1 });
|
||||
|
||||
res.results.reserve(range->size);
|
||||
}
|
||||
|
||||
// TODO optim useless last copy
|
||||
res.results = utils::fetchQueryResults<ResultType>(query);
|
||||
if (range && (res.results.size() == range->size + 1))
|
||||
{
|
||||
res.moreResults = true;
|
||||
res.results.pop_back();
|
||||
}
|
||||
|
||||
res.range.size = res.results.size();
|
||||
|
||||
return res;
|
||||
applyRange(query, range);
|
||||
return utils::fetchQueryResults<ResultType>(query);
|
||||
}
|
||||
|
||||
template<typename Query, typename UnaryFunc>
|
||||
@@ -162,35 +143,6 @@ namespace lms::db::utils
|
||||
forEachQueryResult(query, std::forward<UnaryFunc>(func));
|
||||
}
|
||||
|
||||
template<typename Query, typename UnaryFunc>
|
||||
void forEachQueryRangeResult(Query& query, std::optional<Range> range, bool& moreResults, UnaryFunc&& func)
|
||||
{
|
||||
using ResultType = typename QueryResultType<Query>::type;
|
||||
|
||||
if (range)
|
||||
applyRange(query, Range{ range->offset, range->size + 1 });
|
||||
|
||||
moreResults = false;
|
||||
|
||||
std::size_t count{};
|
||||
ScopedQueryProfiler queryProfiler{ query };
|
||||
const auto collection{ query.resultList() };
|
||||
auto it{ fetchFirstResult(collection) };
|
||||
while (it != collection.end())
|
||||
{
|
||||
if (range && (count++ == static_cast<std::size_t>(range->size)))
|
||||
{
|
||||
moreResults = true;
|
||||
break;
|
||||
}
|
||||
|
||||
queryProfiler.suspend();
|
||||
func(*it);
|
||||
queryProfiler.resume();
|
||||
fetchNextResult<ResultType>(it);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
void executeCommand(Wt::Dbo::Session& session, std::string_view command, const Args&... args)
|
||||
{
|
||||
|
||||
@@ -135,14 +135,13 @@ namespace lms::db
|
||||
|
||||
if (params.starringUser.isValid())
|
||||
{
|
||||
assert(params.feedbackBackend);
|
||||
query.join("starred_artist s_a ON s_a.artist_id = a.id")
|
||||
.join("user u ON u.id = s_a.user_id")
|
||||
.where("s_a.user_id = ?")
|
||||
.bind(params.starringUser)
|
||||
.where("s_a.backend = ?")
|
||||
.bind(*params.feedbackBackend)
|
||||
.where("s_a.sync_state <> ?")
|
||||
.bind(SyncState::PendingRemove);
|
||||
.bind(SyncState::PendingRemove)
|
||||
.where("s_a.backend = u.feedback_backend");
|
||||
}
|
||||
|
||||
if (params.filters.clusters.size() == 1)
|
||||
@@ -323,7 +322,7 @@ namespace lms::db
|
||||
return utils::fetchQuerySingleResult(session.getDboSession()->query<Wt::Dbo::ptr<Artist>>("SELECT a FROM artist a").where("a.id = ?").bind(id));
|
||||
}
|
||||
|
||||
RangeResults<ArtistId> Artist::findIds(Session& session, const FindParameters& params)
|
||||
std::vector<ArtistId> Artist::findIds(Session& session, const FindParameters& params)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
@@ -331,7 +330,7 @@ namespace lms::db
|
||||
return utils::execRangeQuery<ArtistId>(query, params.range);
|
||||
}
|
||||
|
||||
RangeResults<Artist::pointer> Artist::find(Session& session, const FindParameters& params)
|
||||
std::vector<Artist::pointer> Artist::find(Session& session, const FindParameters& params)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
@@ -357,7 +356,7 @@ namespace lms::db
|
||||
return IdRange<ArtistId>{ .first = std::get<0>(res), .last = std::get<1>(res) };
|
||||
}
|
||||
|
||||
RangeResults<ArtistId> Artist::findOrphanIds(Session& session, std::optional<Range> range)
|
||||
std::vector<ArtistId> Artist::findOrphanIds(Session& session, std::optional<Range> range)
|
||||
{
|
||||
// TODO extend with release artists
|
||||
session.checkReadTransaction();
|
||||
@@ -388,7 +387,7 @@ AND NOT EXISTS (
|
||||
return utils::fetchQuerySingleResult(session.getDboSession()->query<int>("SELECT 1 FROM artist").where("id = ?").bind(id)) == 1;
|
||||
}
|
||||
|
||||
RangeResults<Artist::pointer> Artist::findWithMBIDNameVariants(Session& session, ArtistId& lastRetrievedArtist, std::optional<Range> range)
|
||||
std::vector<Artist::pointer> Artist::findWithMBIDNameVariants(Session& session, ArtistId& lastRetrievedArtist, std::optional<Range> range)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
@@ -407,8 +406,8 @@ AND NOT EXISTS (
|
||||
|
||||
auto results{ utils::execRangeQuery<Artist::pointer>(query, range) };
|
||||
|
||||
if (!results.results.empty())
|
||||
lastRetrievedArtist = results.results.back()->getId();
|
||||
if (!results.empty())
|
||||
lastRetrievedArtist = results.back()->getId();
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
@@ -130,7 +130,7 @@ namespace lms::db
|
||||
return utils::fetchQuerySingleResult(session.getDboSession()->query<int>("SELECT COUNT(*) FROM cluster"));
|
||||
}
|
||||
|
||||
RangeResults<ClusterId> Cluster::findIds(Session& session, const FindParameters& params)
|
||||
std::vector<ClusterId> Cluster::findIds(Session& session, const FindParameters& params)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
auto query{ createQuery<ClusterId>(session, params) };
|
||||
@@ -138,7 +138,7 @@ namespace lms::db
|
||||
return utils::execRangeQuery<ClusterId>(query, params.range);
|
||||
}
|
||||
|
||||
RangeResults<Cluster::pointer> Cluster::find(Session& session, const FindParameters& params)
|
||||
std::vector<Cluster::pointer> Cluster::find(Session& session, const FindParameters& params)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
auto query{ createQuery<Wt::Dbo::ptr<Cluster>>(session, params) };
|
||||
@@ -154,7 +154,7 @@ namespace lms::db
|
||||
return utils::forEachQueryResult(query, _func);
|
||||
}
|
||||
|
||||
RangeResults<ClusterId> Cluster::findOrphanIds(Session& session, std::optional<Range> range)
|
||||
std::vector<ClusterId> Cluster::findOrphanIds(Session& session, std::optional<Range> range)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
auto query{ session.getDboSession()->query<ClusterId>("SELECT DISTINCT c.id FROM cluster c WHERE NOT EXISTS(SELECT 1 FROM track_cluster t_c WHERE t_c.cluster_id = c.id)") };
|
||||
@@ -188,7 +188,7 @@ namespace lms::db
|
||||
_tracks.insert(getDboPtr(track));
|
||||
}
|
||||
|
||||
RangeResults<TrackId> Cluster::getTracks(std::optional<Range> range) const
|
||||
std::vector<TrackId> Cluster::getTracks(std::optional<Range> range) const
|
||||
{
|
||||
assert(session());
|
||||
|
||||
@@ -217,7 +217,7 @@ namespace lms::db
|
||||
return utils::fetchQuerySingleResult(session.getDboSession()->query<int>("SELECT COUNT(*) FROM cluster_type"));
|
||||
}
|
||||
|
||||
RangeResults<ClusterTypeId> ClusterType::findOrphanIds(Session& session, std::optional<Range> range)
|
||||
std::vector<ClusterTypeId> ClusterType::findOrphanIds(Session& session, std::optional<Range> range)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
@@ -229,7 +229,7 @@ namespace lms::db
|
||||
return utils::execRangeQuery<ClusterTypeId>(query, range);
|
||||
}
|
||||
|
||||
RangeResults<ClusterTypeId> ClusterType::findUsed(Session& session, std::optional<Range> range)
|
||||
std::vector<ClusterTypeId> ClusterType::findUsed(Session& session, std::optional<Range> range)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
@@ -263,7 +263,7 @@ namespace lms::db
|
||||
return utils::fetchQuerySingleResult(session.getDboSession()->find<ClusterType>().where("id = ?").bind(id));
|
||||
}
|
||||
|
||||
RangeResults<ClusterTypeId> ClusterType::findIds(Session& session, std::optional<Range> range)
|
||||
std::vector<ClusterTypeId> ClusterType::findIds(Session& session, std::optional<Range> range)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
|
||||
@@ -173,7 +173,7 @@ namespace lms::db
|
||||
});
|
||||
}
|
||||
|
||||
RangeResults<Directory::pointer> Directory::find(Session& session, const FindParameters& params)
|
||||
std::vector<Directory::pointer> Directory::find(Session& session, const FindParameters& params)
|
||||
{
|
||||
auto query{ createQuery(session, params) };
|
||||
return utils::execRangeQuery<Directory::pointer>(query, params.range);
|
||||
@@ -187,7 +187,7 @@ namespace lms::db
|
||||
});
|
||||
}
|
||||
|
||||
RangeResults<DirectoryId> Directory::findOrphanIds(Session& session, std::optional<Range> range)
|
||||
std::vector<DirectoryId> Directory::findOrphanIds(Session& session, std::optional<Range> range)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
@@ -208,7 +208,7 @@ namespace lms::db
|
||||
return utils::execRangeQuery<DirectoryId>(query, range);
|
||||
}
|
||||
|
||||
RangeResults<DirectoryId> Directory::findMismatchedLibrary(Session& session, std::optional<Range> range, const std::filesystem::path& rootPath, MediaLibraryId expectedLibraryId)
|
||||
std::vector<DirectoryId> Directory::findMismatchedLibrary(Session& session, std::optional<Range> range, const std::filesystem::path& rootPath, MediaLibraryId expectedLibraryId)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
@@ -219,7 +219,7 @@ namespace lms::db
|
||||
return utils::execRangeQuery<DirectoryId>(query, range);
|
||||
}
|
||||
|
||||
RangeResults<Directory::pointer> Directory::findRootDirectories(Session& session, std::optional<Range> range)
|
||||
std::vector<Directory::pointer> Directory::findRootDirectories(Session& session, std::optional<Range> range)
|
||||
{
|
||||
auto query{ session.getDboSession()->query<Wt::Dbo::ptr<Directory>>("SELECT d from directory d").where("d.parent_directory_id IS NULL") };
|
||||
return utils::execRangeQuery<Directory::pointer>(query, range);
|
||||
|
||||
@@ -128,14 +128,14 @@ namespace lms::db
|
||||
return utils::fetchQuerySingleResult(session.getDboSession()->query<int>("SELECT COUNT(*) FROM genre"));
|
||||
}
|
||||
|
||||
RangeResults<GenreId> Genre::findIds(Session& session, const FindParameters& params)
|
||||
std::vector<GenreId> Genre::findIds(Session& session, const FindParameters& params)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
auto query{ createQuery<GenreId>(session, params) };
|
||||
return utils::execRangeQuery<GenreId>(query, params.range);
|
||||
}
|
||||
|
||||
RangeResults<Genre::pointer> Genre::find(Session& session, const FindParameters& params)
|
||||
std::vector<Genre::pointer> Genre::find(Session& session, const FindParameters& params)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
auto query{ createQuery<Wt::Dbo::ptr<Genre>>(session, params) };
|
||||
@@ -165,7 +165,7 @@ namespace lms::db
|
||||
return utils::fetchQuerySingleResult(session.getDboSession()->find<Genre>().where("name = ?").bind(name));
|
||||
}
|
||||
|
||||
RangeResults<GenreId> Genre::findOrphanIds(Session& session, std::optional<Range> range)
|
||||
std::vector<GenreId> Genre::findOrphanIds(Session& session, std::optional<Range> range)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
auto query{ session.getDboSession()->query<GenreId>("SELECT g.id FROM genre g WHERE NOT EXISTS (SELECT 1 FROM track_genre t_g WHERE t_g.genre_id = g.id)") };
|
||||
|
||||
@@ -128,14 +128,14 @@ namespace lms::db
|
||||
return utils::fetchQuerySingleResult(session.getDboSession()->query<int>("SELECT COUNT(*) FROM grouping"));
|
||||
}
|
||||
|
||||
RangeResults<GroupingId> Grouping::findIds(Session& session, const FindParameters& params)
|
||||
std::vector<GroupingId> Grouping::findIds(Session& session, const FindParameters& params)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
auto query{ createQuery<GroupingId>(session, params) };
|
||||
return utils::execRangeQuery<GroupingId>(query, params.range);
|
||||
}
|
||||
|
||||
RangeResults<Grouping::pointer> Grouping::find(Session& session, const FindParameters& params)
|
||||
std::vector<Grouping::pointer> Grouping::find(Session& session, const FindParameters& params)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
auto query{ createQuery<Wt::Dbo::ptr<Grouping>>(session, params) };
|
||||
@@ -165,7 +165,7 @@ namespace lms::db
|
||||
return utils::fetchQuerySingleResult(session.getDboSession()->find<Grouping>().where("name = ?").bind(name));
|
||||
}
|
||||
|
||||
RangeResults<GroupingId> Grouping::findOrphanIds(Session& session, std::optional<Range> range)
|
||||
std::vector<GroupingId> Grouping::findOrphanIds(Session& session, std::optional<Range> range)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
auto query{ session.getDboSession()->query<GroupingId>("SELECT g.id FROM grouping g WHERE NOT EXISTS (SELECT 1 FROM track_grouping t_gr WHERE t_gr.grouping_id = g.id)") };
|
||||
|
||||
@@ -105,7 +105,7 @@ namespace lms::db
|
||||
});
|
||||
}
|
||||
|
||||
RangeResults<Image::pointer> Image::find(Session& session, const FindParameters& params)
|
||||
std::vector<Image::pointer> Image::find(Session& session, const FindParameters& params)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
|
||||
@@ -128,14 +128,14 @@ namespace lms::db
|
||||
return utils::fetchQuerySingleResult(session.getDboSession()->query<int>("SELECT COUNT(*) FROM language"));
|
||||
}
|
||||
|
||||
RangeResults<LanguageId> Language::findIds(Session& session, const FindParameters& params)
|
||||
std::vector<LanguageId> Language::findIds(Session& session, const FindParameters& params)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
auto query{ createQuery<LanguageId>(session, params) };
|
||||
return utils::execRangeQuery<LanguageId>(query, params.range);
|
||||
}
|
||||
|
||||
RangeResults<Language::pointer> Language::find(Session& session, const FindParameters& params)
|
||||
std::vector<Language::pointer> Language::find(Session& session, const FindParameters& params)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
auto query{ createQuery<Wt::Dbo::ptr<Language>>(session, params) };
|
||||
@@ -165,7 +165,7 @@ namespace lms::db
|
||||
return utils::fetchQuerySingleResult(session.getDboSession()->find<Language>().where("name = ?").bind(name));
|
||||
}
|
||||
|
||||
RangeResults<LanguageId> Language::findOrphanIds(Session& session, std::optional<Range> range)
|
||||
std::vector<LanguageId> Language::findOrphanIds(Session& session, std::optional<Range> range)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
auto query{ session.getDboSession()->query<LanguageId>("SELECT l.id FROM language l WHERE NOT EXISTS (SELECT 1 FROM track_language t_l WHERE t_l.language_id = l.id)") };
|
||||
|
||||
@@ -23,10 +23,12 @@
|
||||
#include <Wt/Dbo/WtSqlTraits.h>
|
||||
|
||||
#include "database/Session.hpp"
|
||||
#include "database/objects/Artist.hpp"
|
||||
#include "database/objects/Genre.hpp"
|
||||
#include "database/objects/Grouping.hpp"
|
||||
#include "database/objects/Language.hpp"
|
||||
#include "database/objects/Mood.hpp"
|
||||
#include "database/objects/Release.hpp"
|
||||
#include "database/objects/Track.hpp"
|
||||
#include "database/objects/User.hpp"
|
||||
|
||||
@@ -46,10 +48,12 @@ namespace lms::db
|
||||
auto query{ session.getDboSession()->query<ArtistId>("SELECT a.id from artist a").join("track_artist_link t_a_l ON t_a_l.artist_id = a.id").join("listen l ON l.track_id = t_a_l.track_id") };
|
||||
|
||||
if (params.user.isValid())
|
||||
query.where("l.user_id = ?").bind(params.user);
|
||||
|
||||
if (params.backend)
|
||||
query.where("l.backend = ?").bind(*params.backend);
|
||||
{
|
||||
query.join("user u ON u.id = l.user_id")
|
||||
.where("l.user_id = ?")
|
||||
.bind(params.user)
|
||||
.where("l.backend = u.scrobbling_backend");
|
||||
}
|
||||
|
||||
assert(!params.artist.isValid()); // poor check
|
||||
|
||||
@@ -161,10 +165,12 @@ namespace lms::db
|
||||
auto query{ session.getDboSession()->query<ReleaseId>("SELECT r.id from release r").join("track t ON t.release_id = r.id").join("listen l ON l.track_id = t.id") };
|
||||
|
||||
if (params.user.isValid())
|
||||
query.where("l.user_id = ?").bind(params.user);
|
||||
|
||||
if (params.backend)
|
||||
query.where("l.backend = ?").bind(*params.backend);
|
||||
{
|
||||
query.join("user u ON u.id = l.user_id")
|
||||
.where("l.user_id = ?")
|
||||
.bind(params.user)
|
||||
.where("l.backend = u.scrobbling_backend");
|
||||
}
|
||||
|
||||
if (params.artist.isValid())
|
||||
{
|
||||
@@ -244,10 +250,12 @@ namespace lms::db
|
||||
auto query{ session.getDboSession()->query<TrackId>("SELECT t.id from track t").join("listen l ON l.track_id = t.id") };
|
||||
|
||||
if (params.user.isValid())
|
||||
query.where("l.user_id = ?").bind(params.user);
|
||||
|
||||
if (params.backend)
|
||||
query.where("l.backend = ?").bind(*params.backend);
|
||||
{
|
||||
query.join("user u ON u.id = l.user_id")
|
||||
.where("l.user_id = ?")
|
||||
.bind(params.user)
|
||||
.where("l.backend = u.scrobbling_backend");
|
||||
}
|
||||
|
||||
if (params.artist.isValid())
|
||||
{
|
||||
@@ -348,7 +356,7 @@ namespace lms::db
|
||||
return utils::fetchQuerySingleResult(session.getDboSession()->query<Wt::Dbo::ptr<Listen>>("SELECT l from listen l").where("l.id = ?").bind(id));
|
||||
}
|
||||
|
||||
RangeResults<ListenId> Listen::find(Session& session, const FindParameters& parameters)
|
||||
std::vector<ListenId> Listen::find(Session& session, const FindParameters& parameters)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
@@ -373,39 +381,88 @@ namespace lms::db
|
||||
return utils::fetchQuerySingleResult(session.getDboSession()->find<Listen>().where("user_id = ?").bind(userId).where("track_id = ?").bind(trackId).where("backend = ?").bind(backend).where("date_time = ?").bind(Wt::WDateTime::fromTime_t(dateTime.toTime_t())));
|
||||
}
|
||||
|
||||
RangeResults<ArtistId> Listen::getTopArtists(Session& session, const ArtistStatsFindParameters& params)
|
||||
std::vector<ArtistId> Listen::getTopArtists(Session& session, const ArtistStatsFindParameters& params)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
auto query{ createArtistsQuery(session, params) };
|
||||
|
||||
auto collection{ query
|
||||
.orderBy("COUNT(a.id) DESC")
|
||||
.groupBy("a.id") };
|
||||
|
||||
auto query{ createArtistsQuery(session, params).orderBy("COUNT(a.id) DESC").groupBy("a.id") };
|
||||
return utils::execRangeQuery<ArtistId>(query, params.range);
|
||||
}
|
||||
|
||||
RangeResults<ReleaseId> Listen::getTopReleases(Session& session, const StatsFindParameters& params)
|
||||
std::vector<ReleaseId> Listen::getTopReleases(Session& session, const StatsFindParameters& params)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
auto query{ createReleasesQuery(session, params).orderBy("COUNT(r.id) DESC").groupBy("r.id") };
|
||||
return utils::execRangeQuery<ReleaseId>(query, params.range);
|
||||
}
|
||||
|
||||
std::vector<TrackId> Listen::getTopTracks(Session& session, const StatsFindParameters& params)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
auto query{ createTracksQuery(session, params).orderBy("COUNT(t.id) DESC").groupBy("t.id") };
|
||||
return utils::execRangeQuery<TrackId>(query, params.range);
|
||||
}
|
||||
|
||||
std::vector<ArtistId> Listen::getRecentArtists(Session& session, const ArtistStatsFindParameters& params)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
auto query{ createArtistsQuery(session, params).groupBy("a.id").having("l.date_time = MAX(l.date_time)").orderBy("l.date_time DESC") };
|
||||
return utils::execRangeQuery<ArtistId>(query, params.range);
|
||||
}
|
||||
|
||||
std::vector<ReleaseId> Listen::getRecentReleases(Session& session, const StatsFindParameters& params)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
auto query{ createReleasesQuery(session, params).groupBy("r.id").having("l.date_time = MAX(l.date_time)").orderBy("l.date_time DESC") };
|
||||
return utils::execRangeQuery<ReleaseId>(query, params.range);
|
||||
}
|
||||
|
||||
std::vector<TrackId> Listen::getRecentTracks(Session& session, const StatsFindParameters& params)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
auto query{ createTracksQuery(session, params).groupBy("t.id").having("l.date_time = MAX(l.date_time)").orderBy("l.date_time DESC") };
|
||||
return utils::execRangeQuery<TrackId>(query, params.range);
|
||||
}
|
||||
|
||||
void Listen::getTopArtists(Session& session, const ArtistStatsFindParameters& params, const std::function<void(const ObjectPtr<Artist>&)>& func)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
auto query{ createArtistsQuery(session, params)
|
||||
.orderBy("COUNT(a.id) DESC")
|
||||
.groupBy("a.id") };
|
||||
|
||||
utils::forEachQueryRangeResult(query, params.range, [&](const ArtistId& id) {
|
||||
if (const auto artist{ Artist::find(session, id) })
|
||||
func(artist);
|
||||
});
|
||||
}
|
||||
|
||||
void Listen::getTopReleases(Session& session, const StatsFindParameters& params, const std::function<void(const ObjectPtr<Release>&)>& func)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
auto query{ createReleasesQuery(session, params)
|
||||
.orderBy("COUNT(r.id) DESC")
|
||||
.groupBy("r.id") };
|
||||
|
||||
return utils::execRangeQuery<ReleaseId>(query, params.range);
|
||||
utils::forEachQueryRangeResult(query, params.range, [&](const ReleaseId& id) {
|
||||
if (const auto release{ Release::find(session, id) })
|
||||
func(release);
|
||||
});
|
||||
}
|
||||
|
||||
RangeResults<TrackId> Listen::getTopTracks(Session& session, const StatsFindParameters& params)
|
||||
void Listen::getTopTracks(Session& session, const StatsFindParameters& params, const std::function<void(const ObjectPtr<Track>&)>& func)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
auto query{ createTracksQuery(session, params)
|
||||
.orderBy("COUNT(t.id) DESC")
|
||||
.groupBy("t.id") };
|
||||
|
||||
return utils::execRangeQuery<TrackId>(query, params.range);
|
||||
utils::forEachQueryRangeResult(query, params.range, [&](const TrackId& id) {
|
||||
if (const auto track{ Track::find(session, id) })
|
||||
func(track);
|
||||
});
|
||||
}
|
||||
|
||||
RangeResults<ArtistId> Listen::getRecentArtists(Session& session, const ArtistStatsFindParameters& params)
|
||||
void Listen::getRecentArtists(Session& session, const ArtistStatsFindParameters& params, const std::function<void(const ObjectPtr<Artist>&)>& func)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
auto query{ createArtistsQuery(session, params)
|
||||
@@ -413,10 +470,13 @@ namespace lms::db
|
||||
.having("l.date_time = MAX(l.date_time)")
|
||||
.orderBy("l.date_time DESC") };
|
||||
|
||||
return utils::execRangeQuery<ArtistId>(query, params.range);
|
||||
utils::forEachQueryRangeResult(query, params.range, [&](const ArtistId& id) {
|
||||
if (const auto artist{ Artist::find(session, id) })
|
||||
func(artist);
|
||||
});
|
||||
}
|
||||
|
||||
RangeResults<ReleaseId> Listen::getRecentReleases(Session& session, const StatsFindParameters& params)
|
||||
void Listen::getRecentReleases(Session& session, const StatsFindParameters& params, const std::function<void(const ObjectPtr<Release>&)>& func)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
auto query{ createReleasesQuery(session, params)
|
||||
@@ -424,10 +484,13 @@ namespace lms::db
|
||||
.having("l.date_time = MAX(l.date_time)")
|
||||
.orderBy("l.date_time DESC") };
|
||||
|
||||
return utils::execRangeQuery<ReleaseId>(query, params.range);
|
||||
utils::forEachQueryRangeResult(query, params.range, [&](const ReleaseId& id) {
|
||||
if (const auto release{ Release::find(session, id) })
|
||||
func(release);
|
||||
});
|
||||
}
|
||||
|
||||
RangeResults<TrackId> Listen::getRecentTracks(Session& session, const StatsFindParameters& params)
|
||||
void Listen::getRecentTracks(Session& session, const StatsFindParameters& params, const std::function<void(const ObjectPtr<Track>&)>& func)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
auto query{ createTracksQuery(session, params)
|
||||
@@ -435,7 +498,10 @@ namespace lms::db
|
||||
.having("l.date_time = MAX(l.date_time)")
|
||||
.orderBy("l.date_time DESC") };
|
||||
|
||||
return utils::execRangeQuery<TrackId>(query, params.range);
|
||||
utils::forEachQueryRangeResult(query, params.range, [&](const TrackId& id) {
|
||||
if (const auto track{ Track::find(session, id) })
|
||||
func(track);
|
||||
});
|
||||
}
|
||||
|
||||
std::size_t Listen::getCount(Session& session, UserId userId, TrackId trackId)
|
||||
|
||||
@@ -110,7 +110,7 @@ namespace lms::db
|
||||
return IdRange<MediumId>{ .first = std::get<0>(res), .last = std::get<1>(res) };
|
||||
}
|
||||
|
||||
RangeResults<MediumId> Medium::findOrphanIds(Session& session, std::optional<Range> range)
|
||||
std::vector<MediumId> Medium::findOrphanIds(Session& session, std::optional<Range> range)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
|
||||
@@ -128,14 +128,14 @@ namespace lms::db
|
||||
return utils::fetchQuerySingleResult(session.getDboSession()->query<int>("SELECT COUNT(*) FROM mood"));
|
||||
}
|
||||
|
||||
RangeResults<MoodId> Mood::findIds(Session& session, const FindParameters& params)
|
||||
std::vector<MoodId> Mood::findIds(Session& session, const FindParameters& params)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
auto query{ createQuery<MoodId>(session, params) };
|
||||
return utils::execRangeQuery<MoodId>(query, params.range);
|
||||
}
|
||||
|
||||
RangeResults<Mood::pointer> Mood::find(Session& session, const FindParameters& params)
|
||||
std::vector<Mood::pointer> Mood::find(Session& session, const FindParameters& params)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
auto query{ createQuery<Wt::Dbo::ptr<Mood>>(session, params) };
|
||||
@@ -165,7 +165,7 @@ namespace lms::db
|
||||
return utils::fetchQuerySingleResult(session.getDboSession()->find<Mood>().where("name = ?").bind(name));
|
||||
}
|
||||
|
||||
RangeResults<MoodId> Mood::findOrphanIds(Session& session, std::optional<Range> range)
|
||||
std::vector<MoodId> Mood::findOrphanIds(Session& session, std::optional<Range> range)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
auto query{ session.getDboSession()->query<MoodId>("SELECT m.id FROM mood m WHERE NOT EXISTS (SELECT 1 FROM track_mood t_m WHERE t_m.mood_id = m.id)") };
|
||||
|
||||
@@ -150,14 +150,13 @@ namespace lms::db
|
||||
|
||||
if (params.starringUser.isValid())
|
||||
{
|
||||
assert(params.feedbackBackend);
|
||||
query.join("starred_release s_r ON s_r.release_id = r.id")
|
||||
.join("user u ON u.id = s_r.user_id")
|
||||
.where("s_r.user_id = ?")
|
||||
.bind(params.starringUser)
|
||||
.where("s_r.backend = ?")
|
||||
.bind(*params.feedbackBackend)
|
||||
.where("s_r.sync_state <> ?")
|
||||
.bind(SyncState::PendingRemove);
|
||||
.bind(SyncState::PendingRemove)
|
||||
.where("s_r.backend = u.feedback_backend");
|
||||
}
|
||||
|
||||
if (params.artist.isValid())
|
||||
@@ -356,7 +355,7 @@ namespace lms::db
|
||||
return utils::fetchQuerySingleResult(session.getDboSession()->query<Wt::Dbo::ptr<Country>>("SELECT c from country c").where("c.name = ?").bind(name));
|
||||
}
|
||||
|
||||
RangeResults<CountryId> Country::findOrphanIds(Session& session, std::optional<Range> range)
|
||||
std::vector<CountryId> Country::findOrphanIds(Session& session, std::optional<Range> range)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
@@ -418,7 +417,7 @@ namespace lms::db
|
||||
});
|
||||
}
|
||||
|
||||
RangeResults<LabelId> Label::findOrphanIds(Session& session, std::optional<Range> range)
|
||||
std::vector<LabelId> Label::findOrphanIds(Session& session, std::optional<Range> range)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
@@ -480,7 +479,7 @@ namespace lms::db
|
||||
});
|
||||
}
|
||||
|
||||
RangeResults<ReleaseTypeId> ReleaseType::findOrphanIds(Session& session, std::optional<Range> range)
|
||||
std::vector<ReleaseTypeId> ReleaseType::findOrphanIds(Session& session, std::optional<Range> range)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
@@ -527,7 +526,7 @@ namespace lms::db
|
||||
return utils::fetchQuerySingleResult(session.getDboSession()->query<int>("SELECT COUNT(*) FROM release"));
|
||||
}
|
||||
|
||||
RangeResults<ReleaseId> Release::findOrphanIds(Session& session, std::optional<Range> range)
|
||||
std::vector<ReleaseId> Release::findOrphanIds(Session& session, std::optional<Range> range)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
@@ -574,7 +573,7 @@ namespace lms::db
|
||||
return IdRange<ReleaseId>{ .first = std::get<0>(res), .last = std::get<1>(res) };
|
||||
}
|
||||
|
||||
RangeResults<Release::pointer> Release::find(Session& session, const FindParameters& params)
|
||||
std::vector<Release::pointer> Release::find(Session& session, const FindParameters& params)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
@@ -590,7 +589,7 @@ namespace lms::db
|
||||
utils::forEachQueryRangeResult(query, params.range, func);
|
||||
}
|
||||
|
||||
RangeResults<ReleaseId> Release::findIds(Session& session, const FindParameters& params)
|
||||
std::vector<ReleaseId> Release::findIds(Session& session, const FindParameters& params)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
|
||||
@@ -78,7 +78,7 @@ namespace lms::db
|
||||
return utils::fetchQuerySingleResult(session.getDboSession()->query<int>("SELECT 1 from starred_track").where("track_id = ?").bind(trackId).where("user_id = ?").bind(userId).where("backend = ?").bind(backend));
|
||||
}
|
||||
|
||||
RangeResults<StarredTrackId> StarredTrack::find(Session& session, const FindParameters& params)
|
||||
std::vector<StarredTrackId> StarredTrack::find(Session& session, const FindParameters& params)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
|
||||
@@ -77,14 +77,13 @@ namespace lms::db
|
||||
|
||||
if (params.starringUser.isValid())
|
||||
{
|
||||
assert(params.feedbackBackend);
|
||||
query.join("starred_track s_t ON s_t.track_id = t.id")
|
||||
.join("user u ON u.id = s_t.user_id")
|
||||
.where("s_t.user_id = ?")
|
||||
.bind(params.starringUser)
|
||||
.where("s_t.backend = ?")
|
||||
.bind(*params.feedbackBackend)
|
||||
.where("s_t.sync_state <> ?")
|
||||
.bind(SyncState::PendingRemove);
|
||||
.bind(SyncState::PendingRemove)
|
||||
.where("s_t.backend = u.feedback_backend");
|
||||
}
|
||||
|
||||
if (params.filters.clusters.size() == 1)
|
||||
@@ -435,7 +434,7 @@ namespace lms::db
|
||||
return utils::fetchQueryResults<Track::pointer>(session.getDboSession()->query<Wt::Dbo::ptr<Track>>("SELECT t from track t").where("t.recording_mbid = ?").bind(mbid));
|
||||
}
|
||||
|
||||
RangeResults<TrackId> Track::findIdsTrackMBIDDuplicates(Session& session, std::optional<Range> range)
|
||||
std::vector<TrackId> Track::findIdsTrackMBIDDuplicates(Session& session, std::optional<Range> range)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
@@ -564,7 +563,7 @@ namespace lms::db
|
||||
return _preferredMediaArtwork.id();
|
||||
}
|
||||
|
||||
RangeResults<TrackId> Track::findIds(Session& session, const FindParameters& parameters)
|
||||
std::vector<TrackId> Track::findIds(Session& session, const FindParameters& parameters)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
@@ -572,7 +571,7 @@ namespace lms::db
|
||||
return utils::execRangeQuery<TrackId>(query, parameters.range);
|
||||
}
|
||||
|
||||
RangeResults<Track::pointer> Track::find(Session& session, const FindParameters& parameters)
|
||||
std::vector<Track::pointer> Track::find(Session& session, const FindParameters& parameters)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
@@ -588,14 +587,6 @@ namespace lms::db
|
||||
utils::forEachQueryRangeResult(query, params.range, func);
|
||||
}
|
||||
|
||||
void Track::find(Session& session, const FindParameters& params, bool& moreResults, const std::function<void(const Track::pointer&)>& func)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
auto query{ createQuery<Wt::Dbo::ptr<Track>>(session, params) };
|
||||
utils::forEachQueryRangeResult(query, params.range, moreResults, func);
|
||||
}
|
||||
|
||||
std::size_t Track::getCount(Session& session, const FindParameters& params)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
@@ -54,7 +54,7 @@ namespace lms::db
|
||||
return utils::fetchQuerySingleResult(session.getDboSession()->query<int>("SELECT COUNT(*) FROM track_bookmark"));
|
||||
}
|
||||
|
||||
RangeResults<TrackBookmarkId> TrackBookmark::find(Session& session, UserId userId, std::optional<Range> range)
|
||||
std::vector<TrackBookmarkId> TrackBookmark::find(Session& session, UserId userId, std::optional<Range> range)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
|
||||
@@ -150,7 +150,7 @@ namespace lms::db
|
||||
return utils::fetchQuerySingleResult(query);
|
||||
}
|
||||
|
||||
RangeResults<TrackEmbeddedImageId> TrackEmbeddedImage::findOrphanIds(Session& session, std::optional<Range> range)
|
||||
std::vector<TrackEmbeddedImageId> TrackEmbeddedImage::findOrphanIds(Session& session, std::optional<Range> range)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
|
||||
@@ -182,7 +182,7 @@ namespace lms::db
|
||||
return utils::fetchQuerySingleResult(session.getDboSession()->query<Wt::Dbo::ptr<TrackList>>("select t_l from tracklist t_l").where("t_l.name = ?").bind(name).where("t_l.type = ?").bind(type).where("t_l.user_id = ?").bind(userId));
|
||||
}
|
||||
|
||||
RangeResults<TrackListId> TrackList::find(Session& session, const FindParameters& params)
|
||||
std::vector<TrackListId> TrackList::find(Session& session, const FindParameters& params)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
auto query{ createQuery<TrackListId>(session, params) };
|
||||
@@ -218,13 +218,13 @@ namespace lms::db
|
||||
TrackListEntry::pointer res;
|
||||
|
||||
auto entries = getEntries(Range{ pos, 1 });
|
||||
if (!entries.results.empty())
|
||||
res = entries.results.front();
|
||||
if (!entries.empty())
|
||||
res = entries.front();
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
RangeResults<ObjectPtr<TrackListEntry>> TrackList::getEntries(std::optional<Range> range) const
|
||||
std::vector<ObjectPtr<TrackListEntry>> TrackList::getEntries(std::optional<Range> range) const
|
||||
{
|
||||
assert(session());
|
||||
|
||||
|
||||
@@ -121,7 +121,7 @@ namespace lms::db
|
||||
});
|
||||
}
|
||||
|
||||
RangeResults<TrackLyricsId> TrackLyrics::findOrphanIds(Session& session, std::optional<Range> range)
|
||||
std::vector<TrackLyricsId> TrackLyrics::findOrphanIds(Session& session, std::optional<Range> range)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
|
||||
@@ -66,7 +66,7 @@ namespace lms::db
|
||||
return utils::fetchQuerySingleResult(session.getDboSession()->find<TrackMusicNNEmbeddings>().where("track_id = ?").bind(trackId));
|
||||
}
|
||||
|
||||
RangeResults<TrackMusicNNEmbeddingsId> TrackMusicNNEmbeddings::find(Session& session, std::optional<Range> range)
|
||||
std::vector<TrackMusicNNEmbeddingsId> TrackMusicNNEmbeddings::find(Session& session, std::optional<Range> range)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
|
||||
@@ -61,7 +61,7 @@ namespace lms::db
|
||||
return utils::fetchQuerySingleResult(session.getDboSession()->query<int>("SELECT COUNT(*) FROM user"));
|
||||
}
|
||||
|
||||
RangeResults<UserId> User::find(Session& session, const FindParameters& params)
|
||||
std::vector<UserId> User::find(Session& session, const FindParameters& params)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user