Chaned the way the inner dbo session is accessed + added exec wrappers for queries
This commit is contained in:
@@ -41,7 +41,7 @@ namespace lms::db
|
||||
session.checkReadTransaction();
|
||||
|
||||
// TODO remove distinct and use group by
|
||||
auto query{ session.getDboSession().query<ResultType>("SELECT DISTINCT " + std::string{ itemToSelect } + " FROM artist a") };
|
||||
auto query{ session.getDboSession()->query<ResultType>("SELECT DISTINCT " + std::string{ itemToSelect } + " FROM artist a") };
|
||||
if (params.sortMethod == ArtistSortMethod::LastWritten
|
||||
|| params.writtenAfter.isValid()
|
||||
|| params.linkType
|
||||
@@ -175,21 +175,21 @@ namespace lms::db
|
||||
|
||||
Artist::pointer Artist::create(Session& session, const std::string& name, const std::optional<core::UUID>& MBID)
|
||||
{
|
||||
return session.getDboSession().add(std::unique_ptr<Artist>{ new Artist{ name, MBID } });
|
||||
return session.getDboSession()->add(std::unique_ptr<Artist>{ new Artist{ name, MBID } });
|
||||
}
|
||||
|
||||
std::size_t Artist::getCount(Session& session)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
return session.getDboSession().query<int>("SELECT COUNT(*) FROM artist");
|
||||
return utils::execSingleResultQuery(session.getDboSession()->query<int>("SELECT COUNT(*) FROM artist"));
|
||||
}
|
||||
|
||||
void Artist::find(Session& session, ArtistId& lastRetrievedArtist, std::size_t count, const std::function<void(const Artist::pointer&)>& func, MediaLibraryId library)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
auto query{ session.getDboSession().query<Wt::Dbo::ptr<Artist>>("SELECT a FROM artist a")
|
||||
auto query{ session.getDboSession()->query<Wt::Dbo::ptr<Artist>>("SELECT a FROM artist a")
|
||||
.orderBy("a.id")
|
||||
.where("a.id > ?").bind(lastRetrievedArtist)
|
||||
.limit(static_cast<int>(count)) };
|
||||
@@ -201,7 +201,7 @@ namespace lms::db
|
||||
query.where("t.media_library_id = ?").bind(library);
|
||||
}
|
||||
|
||||
auto collection{ query.resultList() };
|
||||
auto collection{ utils::execMultiResultQuery(query) };
|
||||
|
||||
for (auto itResult{ collection.begin() }; itResult != collection.end(); ++itResult)
|
||||
{
|
||||
@@ -214,9 +214,9 @@ namespace lms::db
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
Wt::Dbo::collection<Wt::Dbo::ptr<Artist>> res = session.getDboSession().find<Artist>()
|
||||
Wt::Dbo::collection<Wt::Dbo::ptr<Artist>> res{ utils::execMultiResultQuery(session.getDboSession()->find<Artist>()
|
||||
.where("name = ?").bind(std::string{ name, 0, _maxNameLength })
|
||||
.orderBy("LENGTH(mbid) DESC"); // put mbid entries first
|
||||
.orderBy("LENGTH(mbid) DESC")) }; // put mbid entries first
|
||||
|
||||
return std::vector<Artist::pointer>(res.begin(), res.end());
|
||||
}
|
||||
@@ -224,27 +224,26 @@ namespace lms::db
|
||||
Artist::pointer Artist::find(Session& session, const core::UUID& mbid)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
return session.getDboSession().find<Artist>().where("mbid = ?").bind(std::string{ mbid.getAsString() }).resultValue();
|
||||
return utils::execSingleResultQuery(session.getDboSession()->find<Artist>().where("mbid = ?").bind(std::string{ mbid.getAsString() }));
|
||||
}
|
||||
|
||||
Artist::pointer Artist::find(Session& session, ArtistId id)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
return session.getDboSession().find<Artist>().where("id = ?").bind(id).resultValue();
|
||||
return utils::execSingleResultQuery(session.getDboSession()->find<Artist>().where("id = ?").bind(id));
|
||||
}
|
||||
|
||||
bool Artist::exists(Session& session, ArtistId id)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
return session.getDboSession().query<int>("SELECT 1 FROM artist").where("id = ?").bind(id).resultValue() == 1;
|
||||
return utils::execSingleResultQuery(session.getDboSession()->query<int>("SELECT 1 FROM artist").where("id = ?").bind(id)) == 1;
|
||||
}
|
||||
|
||||
|
||||
RangeResults<ArtistId> Artist::findOrphanIds(Session& session, std::optional<Range> range)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
auto query{ session.getDboSession().query<ArtistId>("SELECT DISTINCT a.id FROM artist a WHERE NOT EXISTS(SELECT 1 FROM track t INNER JOIN track_artist_link t_a_l ON t_a_l.artist_id = a.id WHERE t.id = t_a_l.track_id)") };
|
||||
return utils::execQuery<ArtistId>(query, range);
|
||||
auto query{ session.getDboSession()->query<ArtistId>("SELECT DISTINCT a.id FROM artist a WHERE NOT EXISTS(SELECT 1 FROM track t INNER JOIN track_artist_link t_a_l ON t_a_l.artist_id = a.id WHERE t.id = t_a_l.track_id)") };
|
||||
return utils::execRangeQuery<ArtistId>(query, range);
|
||||
}
|
||||
|
||||
RangeResults<ArtistId> Artist::findIds(Session& session, const FindParameters& params)
|
||||
@@ -252,7 +251,7 @@ namespace lms::db
|
||||
session.checkReadTransaction();
|
||||
|
||||
auto query{ createQuery<ArtistId>(session, params) };
|
||||
return utils::execQuery<ArtistId>(query, params.range);
|
||||
return utils::execRangeQuery<ArtistId>(query, params.range);
|
||||
}
|
||||
|
||||
RangeResults<Artist::pointer> Artist::find(Session& session, const FindParameters& params)
|
||||
@@ -260,7 +259,7 @@ namespace lms::db
|
||||
session.checkReadTransaction();
|
||||
|
||||
auto query{ createQuery<Wt::Dbo::ptr<Artist>>(session, params) };
|
||||
return utils::execQuery<Artist::pointer>(query, params.range);
|
||||
return utils::execRangeQuery<Artist::pointer>(query, params.range);
|
||||
}
|
||||
|
||||
void Artist::find(Session& session, const FindParameters& params, std::function<void(const pointer&)> func)
|
||||
@@ -268,7 +267,7 @@ namespace lms::db
|
||||
session.checkReadTransaction();
|
||||
|
||||
auto query{ createQuery<Wt::Dbo::ptr<Artist>>(session, params) };
|
||||
utils::execQuery(query, params.range, func);
|
||||
utils::execRangeQuery(query, params.range, func);
|
||||
}
|
||||
|
||||
RangeResults<ArtistId> Artist::findSimilarArtistIds(core::EnumSet<TrackArtistLinkType> artistLinkTypes, std::optional<Range> range) const
|
||||
@@ -315,7 +314,7 @@ namespace lms::db
|
||||
for (const TrackArtistLinkType type : artistLinkTypes)
|
||||
query.bind(type);
|
||||
|
||||
return utils::execQuery<ArtistId>(query, range);
|
||||
return utils::execRangeQuery<ArtistId>(query, range);
|
||||
}
|
||||
|
||||
std::vector<std::vector<Cluster::pointer>> Artist::getClusterGroups(std::vector<ClusterTypeId> clusterTypeIds, std::size_t size) const
|
||||
@@ -338,12 +337,12 @@ namespace lms::db
|
||||
oss << " " << where.get();
|
||||
oss << "GROUP BY c.id ORDER BY COUNT(DISTINCT c.id) DESC";
|
||||
|
||||
Wt::Dbo::Query<Wt::Dbo::ptr<Cluster>> query = session()->query<Wt::Dbo::ptr<Cluster>>(oss.str());
|
||||
Wt::Dbo::Query<Wt::Dbo::ptr<Cluster>> query{ session()->query<Wt::Dbo::ptr<Cluster>>(oss.str()) };
|
||||
|
||||
for (const std::string& bindArg : where.getBindArgs())
|
||||
query.bind(bindArg);
|
||||
|
||||
Wt::Dbo::collection<Wt::Dbo::ptr<Cluster>> queryRes = query;
|
||||
Wt::Dbo::collection<Wt::Dbo::ptr<Cluster>> queryRes{ utils::execMultiResultQuery(query) };
|
||||
|
||||
std::map<ClusterTypeId, std::vector<Cluster::pointer>> clustersByType;
|
||||
for (const Cluster::pointer& cluster : queryRes)
|
||||
|
||||
@@ -24,38 +24,34 @@
|
||||
#include "database/User.hpp"
|
||||
#include "StringViewTraits.hpp"
|
||||
#include "IdTypeTraits.hpp"
|
||||
#include "Utils.hpp"
|
||||
|
||||
namespace lms::db
|
||||
{
|
||||
|
||||
AuthToken::AuthToken(std::string_view value, const Wt::WDateTime& expiry, ObjectPtr<User> user)
|
||||
: _value {value}
|
||||
, _expiry {expiry}
|
||||
, _user {getDboPtr(user)}
|
||||
{
|
||||
}
|
||||
AuthToken::AuthToken(std::string_view value, const Wt::WDateTime& expiry, ObjectPtr<User> user)
|
||||
: _value{ value }
|
||||
, _expiry{ expiry }
|
||||
, _user{ getDboPtr(user) }
|
||||
{
|
||||
}
|
||||
|
||||
AuthToken::pointer
|
||||
AuthToken::create(Session& session, std::string_view value, const Wt::WDateTime& expiry, ObjectPtr<User> user)
|
||||
{
|
||||
return session.getDboSession().add(std::unique_ptr<AuthToken> {new AuthToken {value, expiry, user}});
|
||||
}
|
||||
AuthToken::pointer AuthToken::create(Session& session, std::string_view value, const Wt::WDateTime& expiry, ObjectPtr<User> user)
|
||||
{
|
||||
return session.getDboSession()->add(std::unique_ptr<AuthToken> {new AuthToken{ value, expiry, user }});
|
||||
}
|
||||
|
||||
void
|
||||
AuthToken::removeExpiredTokens(Session& session, const Wt::WDateTime& now)
|
||||
{
|
||||
session.checkWriteTransaction();
|
||||
void AuthToken::removeExpiredTokens(Session& session, const Wt::WDateTime& now)
|
||||
{
|
||||
session.checkWriteTransaction();
|
||||
|
||||
session.getDboSession().execute("DELETE FROM auth_token WHERE expiry < ?").bind(now);
|
||||
}
|
||||
session.getDboSession()->execute("DELETE FROM auth_token WHERE expiry < ?").bind(now);
|
||||
}
|
||||
|
||||
AuthToken::pointer
|
||||
AuthToken::find(Session& session, std::string_view value)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
AuthToken::pointer AuthToken::find(Session& session, std::string_view value)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
return session.getDboSession().find<AuthToken>()
|
||||
.where("value = ?").bind(value)
|
||||
.resultValue();
|
||||
}
|
||||
return utils::execSingleResultQuery(session.getDboSession()->find<AuthToken>().where("value = ?").bind(value));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ namespace lms::db
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
auto query{ session.getDboSession().query<ResultType>("SELECT DISTINCT " + std::string{ itemToSelect } + " FROM cluster c") };
|
||||
auto query{ session.getDboSession()->query<ResultType>("SELECT DISTINCT " + std::string{ itemToSelect } + " FROM cluster c") };
|
||||
|
||||
if (params.track.isValid() || params.release.isValid())
|
||||
{
|
||||
@@ -86,14 +86,14 @@ namespace lms::db
|
||||
|
||||
Cluster::pointer Cluster::create(Session& session, ObjectPtr<ClusterType> type, std::string_view name)
|
||||
{
|
||||
return session.getDboSession().add(std::unique_ptr<Cluster> {new Cluster{ type, name }});
|
||||
return session.getDboSession()->add(std::unique_ptr<Cluster> {new Cluster{ type, name }});
|
||||
}
|
||||
|
||||
std::size_t Cluster::getCount(Session& session)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
return session.getDboSession().query<int>("SELECT COUNT(*) FROM cluster");
|
||||
return utils::execSingleResultQuery(session.getDboSession()->query<int>("SELECT COUNT(*) FROM cluster"));
|
||||
}
|
||||
|
||||
RangeResults<ClusterId> Cluster::findIds(Session& session, const FindParameters& params)
|
||||
@@ -101,7 +101,7 @@ namespace lms::db
|
||||
session.checkReadTransaction();
|
||||
auto query{ createQuery<ClusterId>(session, params) };
|
||||
|
||||
return utils::execQuery<ClusterId>(query, params.range);
|
||||
return utils::execRangeQuery<ClusterId>(query, params.range);
|
||||
}
|
||||
|
||||
RangeResults<Cluster::pointer> Cluster::find(Session& session, const FindParameters& params)
|
||||
@@ -109,38 +109,38 @@ namespace lms::db
|
||||
session.checkReadTransaction();
|
||||
auto query{ createQuery<Wt::Dbo::ptr<Cluster>>(session, params) };
|
||||
|
||||
return utils::execQuery<Cluster::pointer>(query, params.range);
|
||||
return utils::execRangeQuery<Cluster::pointer>(query, params.range);
|
||||
}
|
||||
|
||||
RangeResults<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)") };
|
||||
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)") };
|
||||
|
||||
return utils::execQuery<ClusterId>(query, range);
|
||||
return utils::execRangeQuery<ClusterId>(query, range);
|
||||
}
|
||||
|
||||
Cluster::pointer Cluster::find(Session& session, ClusterId id)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
return session.getDboSession().find<Cluster>().where("id = ?").bind(id).resultValue();
|
||||
return session.getDboSession()->find<Cluster>().where("id = ?").bind(id).resultValue();
|
||||
}
|
||||
|
||||
std::size_t Cluster::computeTrackCount(Session& session, ClusterId id)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
return session.getDboSession().query<int>("SELECT COUNT(t.id) FROM track t INNER JOIN track_cluster t_c ON t_c.track_id = t.id")
|
||||
.where("t_c.cluster_id = ?").bind(id).resultValue();
|
||||
return utils::execSingleResultQuery(session.getDboSession()->query<int>("SELECT COUNT(t.id) FROM track t INNER JOIN track_cluster t_c ON t_c.track_id = t.id")
|
||||
.where("t_c.cluster_id = ?").bind(id));
|
||||
}
|
||||
|
||||
std::size_t Cluster::computeReleaseCount(Session& session, ClusterId id)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
return session.getDboSession().query<int>("SELECT COUNT(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")
|
||||
.where("t_c.cluster_id = ?").bind(id).resultValue();
|
||||
return utils::execSingleResultQuery(session.getDboSession()->query<int>("SELECT COUNT(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")
|
||||
.where("t_c.cluster_id = ?").bind(id));
|
||||
}
|
||||
|
||||
void Cluster::addTrack(ObjectPtr<Track> track)
|
||||
@@ -155,7 +155,7 @@ namespace lms::db
|
||||
auto query{ session()->query<TrackId>("SELECT t.id FROM track t INNER JOIN cluster c ON c.id = t_c.cluster_id INNER JOIN track_cluster t_c ON t_c.track_id = t.id")
|
||||
.where("c.id = ?").bind(getId()) };
|
||||
|
||||
return utils::execQuery<TrackId>(query, range);
|
||||
return utils::execRangeQuery<TrackId>(query, range);
|
||||
}
|
||||
|
||||
ClusterType::ClusterType(std::string_view name)
|
||||
@@ -165,61 +165,60 @@ namespace lms::db
|
||||
|
||||
ClusterType::pointer ClusterType::create(Session& session, std::string_view name)
|
||||
{
|
||||
return session.getDboSession().add(std::unique_ptr<ClusterType> {new ClusterType{ name }});
|
||||
return session.getDboSession()->add(std::unique_ptr<ClusterType> {new ClusterType{ name }});
|
||||
}
|
||||
|
||||
std::size_t ClusterType::getCount(Session& session)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
return session.getDboSession().query<int>("SELECT COUNT(*) FROM cluster_type");
|
||||
return utils::execSingleResultQuery(session.getDboSession()->query<int>("SELECT COUNT(*) FROM cluster_type"));
|
||||
}
|
||||
|
||||
|
||||
RangeResults<ClusterTypeId> ClusterType::findOrphanIds(Session& session, std::optional<Range> range)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
auto query{ session.getDboSession().query<ClusterTypeId>(
|
||||
auto query{ session.getDboSession()->query<ClusterTypeId>(
|
||||
"SELECT c_t.id from cluster_type c_t"
|
||||
" LEFT OUTER JOIN cluster c ON c_t.id = c.cluster_type_id")
|
||||
.where("c.id IS NULL") };
|
||||
|
||||
return utils::execQuery<ClusterTypeId>(query, range);
|
||||
return utils::execRangeQuery<ClusterTypeId>(query, range);
|
||||
}
|
||||
|
||||
RangeResults<ClusterTypeId> ClusterType::findUsed(Session& session, std::optional<Range> range)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
auto query{ session.getDboSession().query<ClusterTypeId>(
|
||||
auto query{ session.getDboSession()->query<ClusterTypeId>(
|
||||
"SELECT DISTINCT c_t.id from cluster_type c_t")
|
||||
.join("cluster c ON c_t.id = c.cluster_type_id") };
|
||||
|
||||
return utils::execQuery<ClusterTypeId>(query, range);
|
||||
return utils::execRangeQuery<ClusterTypeId>(query, range);
|
||||
}
|
||||
|
||||
ClusterType::pointer ClusterType::find(Session& session, std::string_view name)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
return session.getDboSession().find<ClusterType>().where("name = ?").bind(std::string{ name }).resultValue();
|
||||
return utils::execSingleResultQuery(session.getDboSession()->find<ClusterType>().where("name = ?").bind(std::string{ name }));
|
||||
}
|
||||
|
||||
ClusterType::pointer ClusterType::find(Session& session, ClusterTypeId id)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
return session.getDboSession().find<ClusterType>().where("id = ?").bind(id).resultValue();
|
||||
return utils::execSingleResultQuery(session.getDboSession()->find<ClusterType>().where("id = ?").bind(id));
|
||||
}
|
||||
|
||||
RangeResults<ClusterTypeId> ClusterType::findIds(Session& session, std::optional<Range> range)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
auto query{ session.getDboSession().query<ClusterTypeId>("SELECT id from cluster_type") };
|
||||
auto query{ session.getDboSession()->query<ClusterTypeId>("SELECT id from cluster_type") };
|
||||
|
||||
return utils::execQuery<ClusterTypeId>(query, range);
|
||||
return utils::execRangeQuery<ClusterTypeId>(query, range);
|
||||
}
|
||||
|
||||
Cluster::pointer ClusterType::getCluster(const std::string& name) const
|
||||
@@ -227,9 +226,9 @@ namespace lms::db
|
||||
assert(self());
|
||||
assert(session());
|
||||
|
||||
return session()->find<Cluster>()
|
||||
return utils::execSingleResultQuery(session()->find<Cluster>()
|
||||
.where("name = ?").bind(name)
|
||||
.where("cluster_type_id = ?").bind(getId()).resultValue();
|
||||
.where("cluster_type_id = ?").bind(getId()));
|
||||
}
|
||||
|
||||
std::vector<Cluster::pointer> ClusterType::getClusters() const
|
||||
@@ -237,10 +236,9 @@ namespace lms::db
|
||||
assert(self());
|
||||
assert(session());
|
||||
|
||||
auto res = session()->find<Cluster>()
|
||||
auto res {utils::execMultiResultQuery(session()->find<Cluster>()
|
||||
.where("cluster_type_id = ?").bind(getId())
|
||||
.orderBy("name")
|
||||
.resultList();
|
||||
.orderBy("name"))};
|
||||
|
||||
return std::vector<Cluster::pointer>(res.begin(), res.end());
|
||||
}
|
||||
|
||||
@@ -29,9 +29,9 @@ namespace lms::db
|
||||
{
|
||||
namespace
|
||||
{
|
||||
Wt::Dbo::Query<ArtistId> createArtistsQuery(Wt::Dbo::Session& session, const Listen::ArtistStatsFindParameters& params)
|
||||
Wt::Dbo::Query<ArtistId> createArtistsQuery(Session& session, const Listen::ArtistStatsFindParameters& params)
|
||||
{
|
||||
auto query{ session.query<ArtistId>("SELECT a.id from artist a")
|
||||
auto query{ session.getDboSession()->query<ArtistId>("SELECT a.id from artist a")
|
||||
.join("track t ON t.id = t_a_l.track_id")
|
||||
.join("track_artist_link t_a_l ON t_a_l.artist_id = a.id")
|
||||
.join("listen l ON l.track_id = t.id") };
|
||||
@@ -75,9 +75,9 @@ namespace lms::db
|
||||
return query;
|
||||
}
|
||||
|
||||
Wt::Dbo::Query<ReleaseId> createReleasesQuery(Wt::Dbo::Session& session, const Listen::StatsFindParameters& params)
|
||||
Wt::Dbo::Query<ReleaseId> createReleasesQuery(Session& session, const Listen::StatsFindParameters& params)
|
||||
{
|
||||
auto query{ session.query<ReleaseId>("SELECT r.id from release r")
|
||||
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") };
|
||||
|
||||
@@ -120,9 +120,9 @@ namespace lms::db
|
||||
return query;
|
||||
}
|
||||
|
||||
Wt::Dbo::Query<TrackId> createTracksQuery(Wt::Dbo::Session& session, const Listen::StatsFindParameters& params)
|
||||
Wt::Dbo::Query<TrackId> createTracksQuery(Session& session, const Listen::StatsFindParameters& params)
|
||||
{
|
||||
auto query{ session.query<TrackId>("SELECT t.id from track t")
|
||||
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())
|
||||
@@ -174,26 +174,26 @@ namespace lms::db
|
||||
Listen::pointer Listen::create(Session& session, ObjectPtr<User> user, ObjectPtr<Track> track, ScrobblingBackend backend, const Wt::WDateTime& dateTime)
|
||||
{
|
||||
session.checkWriteTransaction();
|
||||
return session.getDboSession().add(std::unique_ptr<Listen> {new Listen{ user, track, backend, dateTime }});
|
||||
return session.getDboSession()->add(std::unique_ptr<Listen> {new Listen{ user, track, backend, dateTime }});
|
||||
}
|
||||
|
||||
std::size_t Listen::getCount(Session& session)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
return session.getDboSession().query<int>("SELECT COUNT(*) FROM listen");
|
||||
return utils::execSingleResultQuery(session.getDboSession()->query<int>("SELECT COUNT(*) FROM listen"));
|
||||
}
|
||||
|
||||
Listen::pointer Listen::find(Session& session, ListenId id)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
return session.getDboSession().find<Listen>().where("id = ?").bind(id).resultValue();
|
||||
return utils::execSingleResultQuery(session.getDboSession()->find<Listen>().where("id = ?").bind(id));
|
||||
}
|
||||
|
||||
RangeResults<ListenId> Listen::find(Session& session, const FindParameters& parameters)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
auto query{ session.getDboSession().query<ListenId>("SELECT id FROM listen")
|
||||
auto query{ session.getDboSession()->query<ListenId>("SELECT id FROM listen")
|
||||
.orderBy("date_time") };
|
||||
|
||||
if (parameters.user.isValid())
|
||||
@@ -205,100 +205,98 @@ namespace lms::db
|
||||
if (parameters.syncState)
|
||||
query.where("sync_state = ?").bind(*parameters.syncState);
|
||||
|
||||
return utils::execQuery<ListenId>(query, parameters.range);
|
||||
return utils::execRangeQuery<ListenId>(query, parameters.range);
|
||||
}
|
||||
|
||||
Listen::pointer Listen::find(Session& session, UserId userId, TrackId trackId, ScrobblingBackend backend, const Wt::WDateTime& dateTime)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
return session.getDboSession().find<Listen>()
|
||||
return utils::execSingleResultQuery(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()))
|
||||
.resultValue();
|
||||
.where("date_time = ?").bind(Wt::WDateTime::fromTime_t(dateTime.toTime_t())));
|
||||
}
|
||||
|
||||
RangeResults<ArtistId> Listen::getTopArtists(Session& session, const ArtistStatsFindParameters& params)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
auto query{ createArtistsQuery(session.getDboSession(), params) };
|
||||
auto query{ createArtistsQuery(session, params) };
|
||||
|
||||
auto collection{ query
|
||||
.orderBy("COUNT(a.id) DESC")
|
||||
.groupBy("a.id") };
|
||||
|
||||
return utils::execQuery<ArtistId>(query, params.range);
|
||||
return utils::execRangeQuery<ArtistId>(query, params.range);
|
||||
}
|
||||
|
||||
RangeResults<ReleaseId> Listen::getTopReleases(Session& session, const StatsFindParameters& params)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
auto query{ createReleasesQuery(session.getDboSession(), params)
|
||||
auto query{ createReleasesQuery(session, params)
|
||||
.orderBy("COUNT(r.id) DESC")
|
||||
.groupBy("r.id") };
|
||||
|
||||
return utils::execQuery<ReleaseId>(query, params.range);
|
||||
return utils::execRangeQuery<ReleaseId>(query, params.range);
|
||||
}
|
||||
|
||||
RangeResults<TrackId> Listen::getTopTracks(Session& session, const StatsFindParameters& params)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
auto query{ createTracksQuery(session.getDboSession(), params)
|
||||
auto query{ createTracksQuery(session, params)
|
||||
.orderBy("COUNT(t.id) DESC")
|
||||
.groupBy("t.id") };
|
||||
|
||||
return utils::execQuery<TrackId>(query, params.range);
|
||||
return utils::execRangeQuery<TrackId>(query, params.range);
|
||||
}
|
||||
|
||||
RangeResults<ArtistId> Listen::getRecentArtists(Session& session, const ArtistStatsFindParameters& params)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
auto query{ createArtistsQuery(session.getDboSession(), params)
|
||||
auto query{ createArtistsQuery(session, params)
|
||||
.groupBy("a.id").having("l.date_time = MAX(l.date_time)")
|
||||
.orderBy("l.date_time DESC") };
|
||||
|
||||
return utils::execQuery<ArtistId>(query, params.range);
|
||||
return utils::execRangeQuery<ArtistId>(query, params.range);
|
||||
}
|
||||
|
||||
RangeResults<ReleaseId> Listen::getRecentReleases(Session& session, const StatsFindParameters& params)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
auto query{ createReleasesQuery(session.getDboSession(), params)
|
||||
auto query{ createReleasesQuery(session, params)
|
||||
.groupBy("r.id").having("l.date_time = MAX(l.date_time)")
|
||||
.orderBy("l.date_time DESC") };
|
||||
|
||||
return utils::execQuery<ReleaseId>(query, params.range);
|
||||
return utils::execRangeQuery<ReleaseId>(query, params.range);
|
||||
}
|
||||
|
||||
RangeResults<TrackId> Listen::getRecentTracks(Session& session, const StatsFindParameters& params)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
auto query{ createTracksQuery(session.getDboSession(), params)
|
||||
auto query{ createTracksQuery(session, params)
|
||||
.groupBy("t.id").having("l.date_time = MAX(l.date_time)")
|
||||
.orderBy("l.date_time DESC") };
|
||||
|
||||
return utils::execQuery<TrackId>(query, params.range);
|
||||
return utils::execRangeQuery<TrackId>(query, params.range);
|
||||
}
|
||||
|
||||
std::size_t Listen::getCount(Session& session, UserId userId, TrackId trackId)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
return session.getDboSession().query<int>("SELECT COUNT(*) from listen l")
|
||||
return utils::execSingleResultQuery(session.getDboSession()->query<int>("SELECT COUNT(*) from listen l")
|
||||
.join("user u ON u.id = l.user_id")
|
||||
.where("l.track_id = ?").bind(trackId)
|
||||
.where("l.user_id = ?").bind(userId)
|
||||
.where("l.backend = u.scrobbling_backend")
|
||||
.resultValue();
|
||||
.where("l.backend = u.scrobbling_backend"));
|
||||
}
|
||||
|
||||
std::size_t Listen::getCount(Session& session, UserId userId, ReleaseId releaseId)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
return session.getDboSession().query<int>(
|
||||
return utils::execSingleResultQuery(session.getDboSession()->query<int>(
|
||||
"SELECT IFNULL(MIN(count_result), 0)"
|
||||
" FROM ("
|
||||
" SELECT COUNT(l.track_id) AS count_result"
|
||||
@@ -308,8 +306,7 @@ namespace lms::db
|
||||
" GROUP BY t.id)")
|
||||
.bind(userId)
|
||||
.bind(userId)
|
||||
.bind(releaseId)
|
||||
.resultValue();
|
||||
.bind(releaseId));
|
||||
}
|
||||
|
||||
Listen::pointer Listen::getMostRecentListen(Session& session, UserId userId, ScrobblingBackend backend, ReleaseId releaseId)
|
||||
@@ -317,26 +314,24 @@ namespace lms::db
|
||||
session.checkReadTransaction();
|
||||
|
||||
// TODO not pending remove?
|
||||
return session.getDboSession().query<Wt::Dbo::ptr<Listen>>("SELECT l from listen l")
|
||||
return utils::execSingleResultQuery(session.getDboSession()->query<Wt::Dbo::ptr<Listen>>("SELECT l from listen l")
|
||||
.join("track t ON l.track_id = t.id")
|
||||
.where("t.release_id = ?").bind(releaseId)
|
||||
.where("l.user_id = ?").bind(userId)
|
||||
.where("l.backend = ?").bind(backend)
|
||||
.orderBy("l.date_time DESC")
|
||||
.limit(1)
|
||||
.resultValue();
|
||||
.limit(1));
|
||||
}
|
||||
|
||||
Listen::pointer Listen::getMostRecentListen(Session& session, UserId userId, ScrobblingBackend backend, TrackId trackId)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
// TODO not pending remove?
|
||||
return session.getDboSession().query<Wt::Dbo::ptr<Listen>>("SELECT l from listen l")
|
||||
return utils::execSingleResultQuery(session.getDboSession()->query<Wt::Dbo::ptr<Listen>>("SELECT l from listen l")
|
||||
.where("l.track_id = ?").bind(trackId)
|
||||
.where("l.user_id = ?").bind(userId)
|
||||
.where("l.backend = ?").bind(backend)
|
||||
.orderBy("l.date_time DESC")
|
||||
.limit(1)
|
||||
.resultValue();
|
||||
.limit(1));
|
||||
}
|
||||
} // namespace lms::db
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include "IdTypeTraits.hpp"
|
||||
#include "PathTraits.hpp"
|
||||
#include "StringViewTraits.hpp"
|
||||
#include "Utils.hpp"
|
||||
|
||||
namespace lms::db
|
||||
{
|
||||
@@ -36,42 +37,42 @@ namespace lms::db
|
||||
|
||||
MediaLibrary::pointer MediaLibrary::create(Session& session, const std::filesystem::path& p, std::string_view name)
|
||||
{
|
||||
return session.getDboSession().add(std::unique_ptr<MediaLibrary>{ new MediaLibrary{ p, name } });
|
||||
return session.getDboSession()->add(std::unique_ptr<MediaLibrary>{ new MediaLibrary{ p, name } });
|
||||
}
|
||||
|
||||
std::size_t MediaLibrary::getCount(Session& session)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
return session.getDboSession().query<int>("SELECT COUNT(*) FROM media_library");
|
||||
return utils::execSingleResultQuery(session.getDboSession()->query<int>("SELECT COUNT(*) FROM media_library"));
|
||||
}
|
||||
|
||||
MediaLibrary::pointer MediaLibrary::find(Session& session, MediaLibraryId id)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
return session.getDboSession().find<MediaLibrary>().where("id = ?").bind(id).resultValue();
|
||||
return utils::execSingleResultQuery(session.getDboSession()->find<MediaLibrary>().where("id = ?").bind(id));
|
||||
}
|
||||
|
||||
MediaLibrary::pointer MediaLibrary::find(Session& session, std::string_view name)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
return session.getDboSession().find<MediaLibrary>().where("name = ?").bind(name).resultValue();
|
||||
return utils::execSingleResultQuery(session.getDboSession()->find<MediaLibrary>().where("name = ?").bind(name));
|
||||
}
|
||||
|
||||
MediaLibrary::pointer MediaLibrary::find(Session& session, const std::filesystem::path& p)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
return session.getDboSession().find<MediaLibrary>().where("path = ?").bind(p).resultValue();
|
||||
return utils::execSingleResultQuery(session.getDboSession()->find<MediaLibrary>().where("path = ?").bind(p));
|
||||
}
|
||||
|
||||
void MediaLibrary::find(Session& session, std::function<void(const MediaLibrary::pointer&)> func)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
auto results{ session.getDboSession().find<MediaLibrary>().resultList() };
|
||||
auto results{ utils::execMultiResultQuery(session.getDboSession()->find<MediaLibrary>()) };
|
||||
for (const auto& result : results)
|
||||
func(result);
|
||||
}
|
||||
|
||||
@@ -43,9 +43,9 @@ namespace lms::db
|
||||
{
|
||||
session.checkWriteTransaction();
|
||||
|
||||
pointer versionInfo{ session.getDboSession().find<VersionInfo>() };
|
||||
pointer versionInfo{ session.getDboSession()->find<VersionInfo>() };
|
||||
if (!versionInfo)
|
||||
return session.getDboSession().add(std::make_unique<VersionInfo>());
|
||||
return session.getDboSession()->add(std::make_unique<VersionInfo>());
|
||||
|
||||
return versionInfo;
|
||||
}
|
||||
@@ -54,7 +54,7 @@ namespace lms::db
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
return session.getDboSession().find<VersionInfo>();
|
||||
return session.getDboSession()->find<VersionInfo>();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -85,7 +85,7 @@ namespace lms::db::Migration
|
||||
{
|
||||
// remove name from track_artist_link
|
||||
// Drop Auth mode
|
||||
session.getDboSession().execute(R"(
|
||||
session.getDboSession()->execute(R"(
|
||||
CREATE TABLE IF NOT EXISTS "track_artist_link_backup" (
|
||||
"id" integer primary key autoincrement,
|
||||
"version" integer not null,
|
||||
@@ -96,49 +96,49 @@ CREATE TABLE IF NOT EXISTS "track_artist_link_backup" (
|
||||
constraint "fk_track_artist_link_artist" foreign key ("artist_id") references "artist" ("id") on delete cascade deferrable initially deferred
|
||||
);
|
||||
))");
|
||||
session.getDboSession().execute("INSERT INTO track_artist_link_backup SELECT id, version, type, track_id, artist_id FROM track_artist_link");
|
||||
session.getDboSession().execute("DROP TABLE track_artist_link");
|
||||
session.getDboSession().execute("ALTER TABLE track_artist_link_backup RENAME TO track_artist_link");
|
||||
session.getDboSession()->execute("INSERT INTO track_artist_link_backup SELECT id, version, type, track_id, artist_id FROM track_artist_link");
|
||||
session.getDboSession()->execute("DROP TABLE track_artist_link");
|
||||
session.getDboSession()->execute("ALTER TABLE track_artist_link_backup RENAME TO track_artist_link");
|
||||
}
|
||||
|
||||
static void migrateFromV34(Session& session)
|
||||
{
|
||||
// Add scrobbling state
|
||||
// By default, everything needs to be sent
|
||||
session.getDboSession().execute("ALTER TABLE starred_artist ADD scrobbling_state INTEGER NOT NULL DEFAULT(" + std::to_string(static_cast<int>(/*ScrobblingState::PendingAdd*/0)) + ")");
|
||||
session.getDboSession().execute("ALTER TABLE starred_release ADD scrobbling_state INTEGER NOT NULL DEFAULT(" + std::to_string(static_cast<int>(/*ScrobblingState::PendingAdd*/0)) + ")");
|
||||
session.getDboSession().execute("ALTER TABLE starred_track ADD scrobbling_state INTEGER NOT NULL DEFAULT(" + std::to_string(static_cast<int>(/*ScrobblingState::PendingAdd*/0)) + ")");
|
||||
session.getDboSession()->execute("ALTER TABLE starred_artist ADD scrobbling_state INTEGER NOT NULL DEFAULT(" + std::to_string(static_cast<int>(/*ScrobblingState::PendingAdd*/0)) + ")");
|
||||
session.getDboSession()->execute("ALTER TABLE starred_release ADD scrobbling_state INTEGER NOT NULL DEFAULT(" + std::to_string(static_cast<int>(/*ScrobblingState::PendingAdd*/0)) + ")");
|
||||
session.getDboSession()->execute("ALTER TABLE starred_track ADD scrobbling_state INTEGER NOT NULL DEFAULT(" + std::to_string(static_cast<int>(/*ScrobblingState::PendingAdd*/0)) + ")");
|
||||
}
|
||||
|
||||
static void migrateFromV35(Session& session)
|
||||
{
|
||||
// Add creattion/last modif date time for tracklists
|
||||
session.getDboSession().execute("ALTER TABLE tracklist ADD creation_date_time TEXT");
|
||||
session.getDboSession().execute("ALTER TABLE tracklist ADD last_modified_date_time TEXT");
|
||||
session.getDboSession()->execute("ALTER TABLE tracklist ADD creation_date_time TEXT");
|
||||
session.getDboSession()->execute("ALTER TABLE tracklist ADD last_modified_date_time TEXT");
|
||||
}
|
||||
|
||||
static void migrateFromV36(Session& session)
|
||||
{
|
||||
// Increased precision for track durations (now in milliseconds instead of secodns)
|
||||
// Just increment the scan version of the settings to make the next scheduled scan rescan everything
|
||||
session.getDboSession().execute("UPDATE scan_settings SET scan_version = scan_version + 1");
|
||||
session.getDboSession()->execute("UPDATE scan_settings SET scan_version = scan_version + 1");
|
||||
}
|
||||
|
||||
static void migrateFromV37(Session& session)
|
||||
{
|
||||
// Support Performer tags (via subtypes)
|
||||
session.getDboSession().execute("ALTER TABLE track_artist_link ADD subtype TEXT");
|
||||
session.getDboSession()->execute("ALTER TABLE track_artist_link ADD subtype TEXT");
|
||||
|
||||
// Just increment the scan version of the settings to make the next scheduled scan rescan everything
|
||||
session.getDboSession().execute("UPDATE scan_settings SET scan_version = scan_version + 1");
|
||||
session.getDboSession()->execute("UPDATE scan_settings SET scan_version = scan_version + 1");
|
||||
}
|
||||
|
||||
static void migrateFromV38(Session& session)
|
||||
{
|
||||
// migrate release-specific tags from Track to Release
|
||||
session.getDboSession().execute("ALTER TABLE release ADD total_disc INTEGER");
|
||||
session.getDboSession()->execute("ALTER TABLE release ADD total_disc INTEGER");
|
||||
|
||||
session.getDboSession().execute(R"(
|
||||
session.getDboSession()->execute(R"(
|
||||
CREATE TABLE IF NOT EXISTS "track_backup" (
|
||||
"id" integer primary key autoincrement,
|
||||
"version" integer not null,
|
||||
@@ -165,177 +165,177 @@ CREATE TABLE IF NOT EXISTS "track_backup" (
|
||||
constraint "fk_track_release" foreign key ("release_id") references "release" ("id") on delete cascade deferrable initially deferred
|
||||
);
|
||||
))");
|
||||
session.getDboSession().execute("INSERT INTO track_backup SELECT id, version, scan_version, track_number, disc_number, total_track, disc_subtitle, name, duration, date, original_date, file_path, file_last_write, file_added, has_cover, mbid, recording_mbid, copyright, copyright_url, track_replay_gain, release_replay_gain, release_id FROM track");
|
||||
session.getDboSession().execute("DROP TABLE track");
|
||||
session.getDboSession().execute("ALTER TABLE track_backup RENAME TO track");
|
||||
session.getDboSession()->execute("INSERT INTO track_backup SELECT id, version, scan_version, track_number, disc_number, total_track, disc_subtitle, name, duration, date, original_date, file_path, file_last_write, file_added, has_cover, mbid, recording_mbid, copyright, copyright_url, track_replay_gain, release_replay_gain, release_id FROM track");
|
||||
session.getDboSession()->execute("DROP TABLE track");
|
||||
session.getDboSession()->execute("ALTER TABLE track_backup RENAME TO track");
|
||||
|
||||
// Just increment the scan version of the settings to make the next scheduled scan rescan everything
|
||||
session.getDboSession().execute("UPDATE scan_settings SET scan_version = scan_version + 1");
|
||||
session.getDboSession()->execute("UPDATE scan_settings SET scan_version = scan_version + 1");
|
||||
}
|
||||
|
||||
static void migrateFromV39(Session& session)
|
||||
{
|
||||
// add release type
|
||||
session.getDboSession().execute("ALTER TABLE release ADD primary_type INTEGER");
|
||||
session.getDboSession().execute("ALTER TABLE release ADD secondary_types INTEGER");
|
||||
session.getDboSession()->execute("ALTER TABLE release ADD primary_type INTEGER");
|
||||
session.getDboSession()->execute("ALTER TABLE release ADD secondary_types INTEGER");
|
||||
|
||||
// Just increment the scan version of the settings to make the next scheduled scan rescan everything
|
||||
session.getDboSession().execute("UPDATE scan_settings SET scan_version = scan_version + 1");
|
||||
session.getDboSession()->execute("UPDATE scan_settings SET scan_version = scan_version + 1");
|
||||
}
|
||||
|
||||
static void migrateFromV40(Session& session)
|
||||
{
|
||||
// add artist_display_name in Release and Track
|
||||
session.getDboSession().execute("ALTER TABLE release ADD artist_display_name TEXT NOT NULL DEFAULT ''");
|
||||
session.getDboSession().execute("ALTER TABLE track ADD artist_display_name TEXT NOT NULL DEFAULT ''");
|
||||
session.getDboSession()->execute("ALTER TABLE release ADD artist_display_name TEXT NOT NULL DEFAULT ''");
|
||||
session.getDboSession()->execute("ALTER TABLE track ADD artist_display_name TEXT NOT NULL DEFAULT ''");
|
||||
|
||||
// Just increment the scan version of the settings to make the next scheduled scan rescan everything
|
||||
session.getDboSession().execute("UPDATE scan_settings SET scan_version = scan_version + 1");
|
||||
session.getDboSession()->execute("UPDATE scan_settings SET scan_version = scan_version + 1");
|
||||
}
|
||||
|
||||
static void migrateFromV41(Session& session)
|
||||
{
|
||||
// add artist_display_name in Release and Track
|
||||
session.getDboSession().execute("ALTER TABLE user RENAME COLUMN subsonic_transcode_format TO subsonic_default_transcode_format");
|
||||
session.getDboSession().execute("ALTER TABLE user RENAME COLUMN subsonic_transcode_bitrate TO subsonic_default_transcode_bitrate");
|
||||
session.getDboSession().execute("ALTER TABLE user DROP COLUMN subsonic_transcode_enable");
|
||||
session.getDboSession()->execute("ALTER TABLE user RENAME COLUMN subsonic_transcode_format TO subsonic_default_transcode_format");
|
||||
session.getDboSession()->execute("ALTER TABLE user RENAME COLUMN subsonic_transcode_bitrate TO subsonic_default_transcode_bitrate");
|
||||
session.getDboSession()->execute("ALTER TABLE user DROP COLUMN subsonic_transcode_enable");
|
||||
}
|
||||
|
||||
static void migrateFromV42(Session& session)
|
||||
{
|
||||
session.getDboSession().execute("DROP INDEX IF EXISTS listen_scrobbler_idx");
|
||||
session.getDboSession().execute("DROP INDEX IF EXISTS listen_user_scrobbler_idx");
|
||||
session.getDboSession().execute("DROP INDEX IF EXISTS listen_user_track_scrobbler_date_time_idx");
|
||||
session.getDboSession().execute("DROP INDEX IF EXISTS starred_artist_user_scrobbler_idx");
|
||||
session.getDboSession().execute("DROP INDEX IF EXISTS starred_artist_artist_user_scrobbler_idx");
|
||||
session.getDboSession().execute("DROP INDEX IF EXISTS starred_release_user_scrobbler_idx");
|
||||
session.getDboSession().execute("DROP INDEX IF EXISTS starred_release_release_user_scrobbler_idx");
|
||||
session.getDboSession().execute("DROP INDEX IF EXISTS starred_track_user_scrobbler_idx");
|
||||
session.getDboSession().execute("DROP INDEX IF EXISTS starred_track_track_user_scrobbler_idx");
|
||||
session.getDboSession()->execute("DROP INDEX IF EXISTS listen_scrobbler_idx");
|
||||
session.getDboSession()->execute("DROP INDEX IF EXISTS listen_user_scrobbler_idx");
|
||||
session.getDboSession()->execute("DROP INDEX IF EXISTS listen_user_track_scrobbler_date_time_idx");
|
||||
session.getDboSession()->execute("DROP INDEX IF EXISTS starred_artist_user_scrobbler_idx");
|
||||
session.getDboSession()->execute("DROP INDEX IF EXISTS starred_artist_artist_user_scrobbler_idx");
|
||||
session.getDboSession()->execute("DROP INDEX IF EXISTS starred_release_user_scrobbler_idx");
|
||||
session.getDboSession()->execute("DROP INDEX IF EXISTS starred_release_release_user_scrobbler_idx");
|
||||
session.getDboSession()->execute("DROP INDEX IF EXISTS starred_track_user_scrobbler_idx");
|
||||
session.getDboSession()->execute("DROP INDEX IF EXISTS starred_track_track_user_scrobbler_idx");
|
||||
|
||||
// New feedback service that now handles the star/unstar stuff (that was previously handled by the scrobbling service)
|
||||
session.getDboSession().execute("ALTER TABLE user RENAME COLUMN scrobbler TO scrobbling_backend");
|
||||
session.getDboSession().execute("ALTER TABLE user ADD feedback_backend INTEGER");
|
||||
session.getDboSession().execute("ALTER TABLE listen RENAME COLUMN scrobbler TO backend");
|
||||
session.getDboSession().execute("ALTER TABLE listen RENAME COLUMN scrobbling_state TO sync_state");
|
||||
session.getDboSession().execute("ALTER TABLE starred_artist RENAME COLUMN scrobbler TO backend");
|
||||
session.getDboSession().execute("ALTER TABLE starred_artist RENAME COLUMN scrobbling_state TO sync_state");
|
||||
session.getDboSession().execute("ALTER TABLE starred_release RENAME COLUMN scrobbler TO backend");
|
||||
session.getDboSession().execute("ALTER TABLE starred_release RENAME COLUMN scrobbling_state TO sync_state");
|
||||
session.getDboSession().execute("ALTER TABLE starred_track RENAME COLUMN scrobbler TO backend");
|
||||
session.getDboSession().execute("ALTER TABLE starred_track RENAME COLUMN scrobbling_state TO sync_state");
|
||||
session.getDboSession()->execute("ALTER TABLE user RENAME COLUMN scrobbler TO scrobbling_backend");
|
||||
session.getDboSession()->execute("ALTER TABLE user ADD feedback_backend INTEGER");
|
||||
session.getDboSession()->execute("ALTER TABLE listen RENAME COLUMN scrobbler TO backend");
|
||||
session.getDboSession()->execute("ALTER TABLE listen RENAME COLUMN scrobbling_state TO sync_state");
|
||||
session.getDboSession()->execute("ALTER TABLE starred_artist RENAME COLUMN scrobbler TO backend");
|
||||
session.getDboSession()->execute("ALTER TABLE starred_artist RENAME COLUMN scrobbling_state TO sync_state");
|
||||
session.getDboSession()->execute("ALTER TABLE starred_release RENAME COLUMN scrobbler TO backend");
|
||||
session.getDboSession()->execute("ALTER TABLE starred_release RENAME COLUMN scrobbling_state TO sync_state");
|
||||
session.getDboSession()->execute("ALTER TABLE starred_track RENAME COLUMN scrobbler TO backend");
|
||||
session.getDboSession()->execute("ALTER TABLE starred_track RENAME COLUMN scrobbling_state TO sync_state");
|
||||
|
||||
session.getDboSession().execute("UPDATE user SET feedback_backend = scrobbling_backend");
|
||||
session.getDboSession()->execute("UPDATE user SET feedback_backend = scrobbling_backend");
|
||||
}
|
||||
|
||||
static void migrateFromV43(Session& session)
|
||||
{
|
||||
// add counts in genre table
|
||||
session.getDboSession().execute("ALTER TABLE cluster ADD track_count INTEGER");
|
||||
session.getDboSession().execute("ALTER TABLE cluster ADD release_count INTEGER");
|
||||
session.getDboSession()->execute("ALTER TABLE cluster ADD track_count INTEGER");
|
||||
session.getDboSession()->execute("ALTER TABLE cluster ADD release_count INTEGER");
|
||||
|
||||
// Just increment the scan version of the settings to make the next scheduled scan rescan everything
|
||||
session.getDboSession().execute("UPDATE scan_settings SET scan_version = scan_version + 1");
|
||||
session.getDboSession()->execute("UPDATE scan_settings SET scan_version = scan_version + 1");
|
||||
}
|
||||
|
||||
static void migrateFromV44(Session& session)
|
||||
{
|
||||
// add bitrate
|
||||
session.getDboSession().execute("ALTER TABLE track ADD bitrate INTEGER NOT NULL DEFAULT 0");
|
||||
session.getDboSession()->execute("ALTER TABLE track ADD bitrate INTEGER NOT NULL DEFAULT 0");
|
||||
|
||||
// Just increment the scan version of the settings to make the next scheduled scan rescan everything
|
||||
session.getDboSession().execute("UPDATE scan_settings SET scan_version = scan_version + 1");
|
||||
session.getDboSession()->execute("UPDATE scan_settings SET scan_version = scan_version + 1");
|
||||
}
|
||||
|
||||
void migrateFromV45(Session& session)
|
||||
{
|
||||
// add subsonic_enable_transcoding_by_default, default is disabled
|
||||
session.getDboSession().execute("ALTER TABLE user ADD subsonic_enable_transcoding_by_default INTEGER NOT NULL DEFAULT(" + std::to_string(static_cast<int>(/*User::defaultSubsonicEnableTranscodingByDefault*/0)) + ")");
|
||||
session.getDboSession()->execute("ALTER TABLE user ADD subsonic_enable_transcoding_by_default INTEGER NOT NULL DEFAULT(" + std::to_string(static_cast<int>(/*User::defaultSubsonicEnableTranscodingByDefault*/0)) + ")");
|
||||
}
|
||||
|
||||
void migrateFromV46(Session& session)
|
||||
{
|
||||
// add extra tags to parse
|
||||
session.getDboSession().execute(R"(CREATE TABLE IF NOT EXISTS "cluster_type_backup" (
|
||||
session.getDboSession()->execute(R"(CREATE TABLE IF NOT EXISTS "cluster_type_backup" (
|
||||
"id" integer primary key autoincrement,
|
||||
"version" integer not null,
|
||||
"name" text not null
|
||||
);)");
|
||||
session.getDboSession().execute("INSERT INTO cluster_type_backup SELECT id, version, name FROM cluster_type");
|
||||
session.getDboSession().execute("DROP TABLE cluster_type");
|
||||
session.getDboSession().execute("ALTER TABLE cluster_type_backup RENAME TO cluster_type");
|
||||
session.getDboSession()->execute("INSERT INTO cluster_type_backup SELECT id, version, name FROM cluster_type");
|
||||
session.getDboSession()->execute("DROP TABLE cluster_type");
|
||||
session.getDboSession()->execute("ALTER TABLE cluster_type_backup RENAME TO cluster_type");
|
||||
|
||||
session.getDboSession().execute("ALTER TABLE scan_settings ADD COLUMN extra_tags_to_scan TEXT");
|
||||
session.getDboSession()->execute("ALTER TABLE scan_settings ADD COLUMN extra_tags_to_scan TEXT");
|
||||
|
||||
// Just increment the scan version of the settings to make the next scheduled scan rescan everything
|
||||
session.getDboSession().execute("UPDATE scan_settings SET scan_version = scan_version + 1");
|
||||
session.getDboSession()->execute("UPDATE scan_settings SET scan_version = scan_version + 1");
|
||||
}
|
||||
|
||||
void migrateFromV47(Session& session)
|
||||
{
|
||||
// release type, new way
|
||||
session.getDboSession().execute("ALTER TABLE release DROP primary_type");
|
||||
session.getDboSession().execute("ALTER TABLE release DROP secondary_types");
|
||||
session.getDboSession()->execute("ALTER TABLE release DROP primary_type");
|
||||
session.getDboSession()->execute("ALTER TABLE release DROP secondary_types");
|
||||
|
||||
session.getDboSession().execute(R"(CREATE TABLE IF NOT EXISTS "release_type" (
|
||||
session.getDboSession()->execute(R"(CREATE TABLE IF NOT EXISTS "release_type" (
|
||||
"id" integer primary key autoincrement,
|
||||
"version" integer not null,
|
||||
"name" text not null))");
|
||||
|
||||
session.getDboSession().execute(R"(CREATE TABLE IF NOT EXISTS "release_release_type" (
|
||||
session.getDboSession()->execute(R"(CREATE TABLE IF NOT EXISTS "release_release_type" (
|
||||
"release_type_id" bigint,
|
||||
"release_id" bigint,
|
||||
primary key ("release_type_id", "release_id"),
|
||||
constraint "fk_release_release_type_key1" foreign key ("release_type_id") references "release_type" ("id") on delete cascade deferrable initially deferred,
|
||||
constraint "fk_release_release_type_key2" foreign key ("release_id") references "release" ("id") on delete cascade deferrable initially deferred
|
||||
))");
|
||||
session.getDboSession().execute(R"(CREATE INDEX "release_release_type_release_type" on "release_release_type" ("release_type_id"))");
|
||||
session.getDboSession().execute(R"(CREATE INDEX "release_release_type_release" on "release_release_type" ("release_id"))");
|
||||
session.getDboSession()->execute(R"(CREATE INDEX "release_release_type_release_type" on "release_release_type" ("release_type_id"))");
|
||||
session.getDboSession()->execute(R"(CREATE INDEX "release_release_type_release" on "release_release_type" ("release_id"))");
|
||||
|
||||
// Just increment the scan version of the settings to make the next scheduled scan rescan everything
|
||||
session.getDboSession().execute("UPDATE scan_settings SET scan_version = scan_version + 1");
|
||||
session.getDboSession()->execute("UPDATE scan_settings SET scan_version = scan_version + 1");
|
||||
}
|
||||
|
||||
void migrateFromV48(Session& session)
|
||||
{
|
||||
// Regression for the extra tags not being parsed
|
||||
// Just increment the scan version of the settings to make the next scheduled scan rescan everything
|
||||
session.getDboSession().execute("UPDATE scan_settings SET scan_version = scan_version + 1");
|
||||
session.getDboSession()->execute("UPDATE scan_settings SET scan_version = scan_version + 1");
|
||||
}
|
||||
|
||||
void migrateFromV49(Session& session)
|
||||
{
|
||||
// Add year / originalYear fields, as date / originalDate are not enough (we don't want a wrong date but year or nothing)
|
||||
session.getDboSession().execute("ALTER TABLE track ADD year INTEGER");
|
||||
session.getDboSession().execute("ALTER TABLE track ADD original_year INTEGER");
|
||||
session.getDboSession()->execute("ALTER TABLE track ADD year INTEGER");
|
||||
session.getDboSession()->execute("ALTER TABLE track ADD original_year INTEGER");
|
||||
|
||||
// Just increment the scan version of the settings to make the next scheduled scan rescan everything
|
||||
session.getDboSession().execute("UPDATE scan_settings SET scan_version = scan_version + 1");
|
||||
session.getDboSession()->execute("UPDATE scan_settings SET scan_version = scan_version + 1");
|
||||
}
|
||||
|
||||
void migrateFromV50(Session& session)
|
||||
{
|
||||
// MediaLibrary support
|
||||
session.getDboSession().execute(R"(CREATE TABLE IF NOT EXISTS "media_library" (
|
||||
session.getDboSession()->execute(R"(CREATE TABLE IF NOT EXISTS "media_library" (
|
||||
"id" integer primary key autoincrement,
|
||||
"version" integer not null,
|
||||
"path" text not null,
|
||||
"name" text not null
|
||||
))");
|
||||
|
||||
const int scanSettingsId{ session.getDboSession().query<int>("SELECT id FROM scan_settings") };
|
||||
const int scanSettingsId{ session.getDboSession()->query<int>("SELECT id FROM scan_settings") };
|
||||
|
||||
// Convert the existing media_directory in the scan_settings table to a media_library with id '1'
|
||||
session.getDboSession().execute(R"(INSERT INTO "media_library" ("id", "version", "path", "name")
|
||||
session.getDboSession()->execute(R"(INSERT INTO "media_library" ("id", "version", "path", "name")
|
||||
SELECT 1, 0, s_s.media_directory, "Main"
|
||||
FROM scan_settings s_s
|
||||
WHERE id = ?)").bind(scanSettingsId);
|
||||
|
||||
// Remove the outdated column in scan_settings
|
||||
session.getDboSession().execute("ALTER TABLE scan_settings DROP media_directory");
|
||||
session.getDboSession()->execute("ALTER TABLE scan_settings DROP media_directory");
|
||||
|
||||
// Add the media_library column in tracks, with id '1'
|
||||
session.getDboSession().execute(R"(
|
||||
session.getDboSession()->execute(R"(
|
||||
CREATE TABLE IF NOT EXISTS "track_backup" (
|
||||
"id" integer primary key autoincrement,
|
||||
"version" integer not null,
|
||||
@@ -369,7 +369,7 @@ CREATE TABLE IF NOT EXISTS "track_backup" (
|
||||
))");
|
||||
|
||||
// Migrate data, with the new media_library_id field set to 1
|
||||
session.getDboSession().execute(R"(INSERT INTO track_backup
|
||||
session.getDboSession()->execute(R"(INSERT INTO track_backup
|
||||
SELECT
|
||||
id,
|
||||
version,
|
||||
@@ -399,33 +399,33 @@ SELECT
|
||||
release_id,
|
||||
1
|
||||
FROM track)");
|
||||
session.getDboSession().execute("DROP TABLE track");
|
||||
session.getDboSession().execute("ALTER TABLE track_backup RENAME TO track");
|
||||
session.getDboSession()->execute("DROP TABLE track");
|
||||
session.getDboSession()->execute("ALTER TABLE track_backup RENAME TO track");
|
||||
}
|
||||
|
||||
void migrateFromV51(Session& session)
|
||||
{
|
||||
// Add custom artist tag delimiters, no need to rescan since it has no effect when empty
|
||||
session.getDboSession().execute("ALTER TABLE scan_settings ADD artist_tag_delimiters TEXT NOT NULL DEFAULT ''");
|
||||
session.getDboSession().execute("ALTER TABLE scan_settings ADD default_tag_delimiters TEXT NOT NULL DEFAULT ''");
|
||||
session.getDboSession()->execute("ALTER TABLE scan_settings ADD artist_tag_delimiters TEXT NOT NULL DEFAULT ''");
|
||||
session.getDboSession()->execute("ALTER TABLE scan_settings ADD default_tag_delimiters TEXT NOT NULL DEFAULT ''");
|
||||
}
|
||||
|
||||
void migrateFromV52(Session& session)
|
||||
{
|
||||
// Add sort name for releases
|
||||
session.getDboSession().execute("ALTER TABLE release ADD sort_name TEXT NOT NULL DEFAULT ''");
|
||||
session.getDboSession()->execute("ALTER TABLE release ADD sort_name TEXT NOT NULL DEFAULT ''");
|
||||
|
||||
// Just increment the scan version of the settings to make the next scheduled scan rescan everything
|
||||
session.getDboSession().execute("UPDATE scan_settings SET scan_version = scan_version + 1");
|
||||
session.getDboSession()->execute("UPDATE scan_settings SET scan_version = scan_version + 1");
|
||||
}
|
||||
|
||||
void migrateFromV53(Session& session)
|
||||
{
|
||||
// Add release group mbid
|
||||
session.getDboSession().execute("ALTER TABLE release ADD group_mbid TEXT NOT NULL DEFAULT ''");
|
||||
session.getDboSession()->execute("ALTER TABLE release ADD group_mbid TEXT NOT NULL DEFAULT ''");
|
||||
|
||||
// Just increment the scan version of the settings to make the next scheduled scan rescan everything
|
||||
session.getDboSession().execute("UPDATE scan_settings SET scan_version = scan_version + 1");
|
||||
session.getDboSession()->execute("UPDATE scan_settings SET scan_version = scan_version + 1");
|
||||
}
|
||||
|
||||
void doDbMigration(Session& session)
|
||||
|
||||
@@ -40,7 +40,7 @@ namespace lms::db
|
||||
template <typename ResultType>
|
||||
Wt::Dbo::Query<ResultType> createQuery(Session& session, std::string_view itemToSelect, const Release::FindParameters& params)
|
||||
{
|
||||
auto query{ session.getDboSession().query<ResultType>("SELECT " + std::string{ itemToSelect } + " from release r") };
|
||||
auto query{ session.getDboSession()->query<ResultType>("SELECT " + std::string{ itemToSelect } + " from release r") };
|
||||
|
||||
if (params.sortMethod == ReleaseSortMethod::ArtistNameThenName
|
||||
|| params.sortMethod == ReleaseSortMethod::LastWritten
|
||||
@@ -206,27 +206,23 @@ namespace lms::db
|
||||
|
||||
ReleaseType::pointer ReleaseType::create(Session& session, std::string_view name)
|
||||
{
|
||||
return session.getDboSession().add(std::unique_ptr<ReleaseType> {new ReleaseType{ name }});
|
||||
return session.getDboSession()->add(std::unique_ptr<ReleaseType> {new ReleaseType{ name }});
|
||||
}
|
||||
|
||||
ReleaseType::pointer ReleaseType::find(Session& session, ReleaseTypeId id)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
return session.getDboSession()
|
||||
.find<ReleaseType>()
|
||||
.where("id = ?").bind(id)
|
||||
.resultValue();
|
||||
return utils::execSingleResultQuery(session.getDboSession()->find<ReleaseType>()
|
||||
.where("id = ?").bind(id));
|
||||
}
|
||||
|
||||
ReleaseType::pointer ReleaseType::find(Session& session, std::string_view name)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
return session.getDboSession()
|
||||
.find<ReleaseType>()
|
||||
.where("name = ?").bind(name)
|
||||
.resultValue();
|
||||
return utils::execSingleResultQuery(session.getDboSession()->find<ReleaseType>()
|
||||
.where("name = ?").bind(name));
|
||||
}
|
||||
|
||||
Release::Release(const std::string& name, const std::optional<core::UUID>& MBID)
|
||||
@@ -237,19 +233,17 @@ namespace lms::db
|
||||
|
||||
Release::pointer Release::create(Session& session, const std::string& name, const std::optional<core::UUID>& MBID)
|
||||
{
|
||||
return session.getDboSession().add(std::unique_ptr<Release> {new Release{ name, MBID }});
|
||||
return session.getDboSession()->add(std::unique_ptr<Release> {new Release{ name, MBID }});
|
||||
}
|
||||
|
||||
std::vector<Release::pointer> Release::find(Session& session, const std::string& name, const std::filesystem::path& releaseDirectory)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
auto res{ session.getDboSession()
|
||||
.query<Wt::Dbo::ptr<Release>>("SELECT DISTINCT r from release r")
|
||||
auto res{ utils::execMultiResultQuery(session.getDboSession()->query<Wt::Dbo::ptr<Release>>("SELECT DISTINCT r from release r")
|
||||
.join("track t ON t.release_id = r.id")
|
||||
.where("r.name = ?").bind(std::string(name, 0, _maxNameLength))
|
||||
.where("t.file_path LIKE ? ESCAPE '" ESCAPE_CHAR_STR "'").bind(utils::escapeLikeKeyword(releaseDirectory.string()) + "%")
|
||||
.resultList() };
|
||||
.where("t.file_path LIKE ? ESCAPE '" ESCAPE_CHAR_STR "'").bind(utils::escapeLikeKeyword(releaseDirectory.string()) + "%"))};
|
||||
|
||||
return std::vector<Release::pointer>(res.begin(), res.end());
|
||||
}
|
||||
@@ -258,48 +252,44 @@ namespace lms::db
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
return session.getDboSession()
|
||||
.find<Release>()
|
||||
.where("mbid = ?").bind(std::string{ mbid.getAsString() })
|
||||
.resultValue();;
|
||||
return utils::execSingleResultQuery(session.getDboSession()->find<Release>()
|
||||
.where("mbid = ?").bind(mbid.getAsString()));
|
||||
}
|
||||
|
||||
Release::pointer Release::find(Session& session, ReleaseId id)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
return session.getDboSession()
|
||||
.find<Release>()
|
||||
.where("id = ?").bind(id)
|
||||
.resultValue();
|
||||
return utils::execSingleResultQuery(session.getDboSession()->find<Release>()
|
||||
.where("id = ?").bind(id));
|
||||
}
|
||||
|
||||
bool Release::exists(Session& session, ReleaseId id)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
return session.getDboSession().query<int>("SELECT 1 FROM release").where("id = ?").bind(id).resultValue() == 1;
|
||||
return utils::execSingleResultQuery(session.getDboSession()->query<int>("SELECT 1 FROM release").where("id = ?").bind(id)) == 1;
|
||||
}
|
||||
|
||||
std::size_t Release::getCount(Session& session)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
return session.getDboSession().query<int>("SELECT COUNT(*) FROM release");
|
||||
return utils::execSingleResultQuery(session.getDboSession()->query<int>("SELECT COUNT(*) FROM release"));
|
||||
}
|
||||
|
||||
RangeResults<ReleaseId> Release::findOrphanIds(Session& session, std::optional<Range> range)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
auto query{ session.getDboSession().query<ReleaseId>("select r.id from release r LEFT OUTER JOIN Track t ON r.id = t.release_id WHERE t.id IS NULL") };
|
||||
return utils::execQuery<ReleaseId>(query, range);
|
||||
auto query{ session.getDboSession()->query<ReleaseId>("select r.id from release r LEFT OUTER JOIN Track t ON r.id = t.release_id WHERE t.id IS NULL") };
|
||||
return utils::execRangeQuery<ReleaseId>(query, range);
|
||||
}
|
||||
|
||||
void Release::find(Session& session, ReleaseId& lastRetrievedRelease, std::size_t count, const std::function<void(const Release::pointer&)>& func, MediaLibraryId library)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
auto query{ session.getDboSession().query<Wt::Dbo::ptr<Release>>("SELECT r FROM release r")
|
||||
auto query{ session.getDboSession()->query<Wt::Dbo::ptr<Release>>("SELECT r FROM release r")
|
||||
.orderBy("r.id")
|
||||
.where("r.id > ?").bind(lastRetrievedRelease)
|
||||
.limit(static_cast<int>(count)) };
|
||||
@@ -310,7 +300,7 @@ namespace lms::db
|
||||
query.where("t.media_library_id = ?").bind(library);
|
||||
}
|
||||
|
||||
auto collection{ query.resultList() };
|
||||
auto collection{ utils::execMultiResultQuery(query) };
|
||||
|
||||
for (auto itResult{ collection.begin() }; itResult != collection.end(); ++itResult)
|
||||
{
|
||||
@@ -324,7 +314,7 @@ namespace lms::db
|
||||
session.checkReadTransaction();
|
||||
|
||||
auto query{ createQuery<Wt::Dbo::ptr<Release>>(session, "DISTINCT r", params) };
|
||||
return utils::execQuery<pointer>(query, params.range);
|
||||
return utils::execRangeQuery<pointer>(query, params.range);
|
||||
}
|
||||
|
||||
void Release::find(Session& session, const FindParameters& params, std::function<void(const pointer&)> func)
|
||||
@@ -332,7 +322,7 @@ namespace lms::db
|
||||
session.checkReadTransaction();
|
||||
|
||||
auto query{ createQuery<Wt::Dbo::ptr<Release>>(session, "DISTINCT r", params) };
|
||||
utils::execQuery<pointer>(query, params.range, func);
|
||||
utils::execRangeQuery<pointer>(query, params.range, func);
|
||||
}
|
||||
|
||||
RangeResults<ReleaseId> Release::findIds(Session& session, const FindParameters& params)
|
||||
@@ -340,23 +330,23 @@ namespace lms::db
|
||||
session.checkReadTransaction();
|
||||
|
||||
auto query{ createQuery<ReleaseId>(session, "DISTINCT r.id", params) };
|
||||
return utils::execQuery<ReleaseId>(query, params.range);
|
||||
return utils::execRangeQuery<ReleaseId>(query, params.range);
|
||||
}
|
||||
|
||||
std::size_t Release::getCount(Session& session, const FindParameters& params)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
return createQuery<int>(session, "COUNT(DISTINCT r.id)", params).resultValue();
|
||||
return utils::execSingleResultQuery(createQuery<int>(session, "COUNT(DISTINCT r.id)", params));
|
||||
}
|
||||
|
||||
std::size_t Release::getDiscCount() const
|
||||
{
|
||||
assert(session());
|
||||
int res{ session()->query<int>("SELECT COUNT(DISTINCT disc_number) FROM track t")
|
||||
int res{ utils::execSingleResultQuery(session()->query<int>("SELECT COUNT(DISTINCT disc_number) FROM track t")
|
||||
.join("release r ON r.id = t.release_id")
|
||||
.where("r.id = ?")
|
||||
.bind(getId()) };
|
||||
.bind(getId())) };
|
||||
|
||||
return res;
|
||||
}
|
||||
@@ -365,12 +355,11 @@ namespace lms::db
|
||||
{
|
||||
assert(session());
|
||||
using ResultType = std::tuple<int, std::string>;
|
||||
auto results{ session()->query<ResultType>("SELECT DISTINCT disc_number, disc_subtitle FROM track t")
|
||||
auto results{ utils::execMultiResultQuery(session()->query<ResultType>("SELECT DISTINCT disc_number, disc_subtitle FROM track t")
|
||||
.join("release r ON r.id = t.release_id")
|
||||
.where("r.id = ?")
|
||||
.orderBy("disc_number")
|
||||
.bind(getId())
|
||||
.resultList() };
|
||||
.bind(getId()))};
|
||||
|
||||
std::vector<DiscInfo> discs;
|
||||
for (const auto& res : results)
|
||||
@@ -395,12 +384,11 @@ namespace lms::db
|
||||
|
||||
const char* field{ original ? "original_date" : "date" };
|
||||
|
||||
auto dates{ session()->query<Wt::WDate>(
|
||||
auto dates{ utils::execMultiResultQuery(session()->query<Wt::WDate>(
|
||||
std::string {"SELECT "} + "t." + field + " FROM track t INNER JOIN release r ON r.id = t.release_id")
|
||||
.where("r.id = ?")
|
||||
.groupBy(field)
|
||||
.bind(getId())
|
||||
.resultList() };
|
||||
.bind(getId())) };
|
||||
|
||||
// various dates => invalid date
|
||||
if (dates.empty() || dates.size() > 1)
|
||||
@@ -425,14 +413,14 @@ namespace lms::db
|
||||
|
||||
const char* field{ original ? "original_year" : "year" };
|
||||
|
||||
auto years{ session()->query<std::optional<int>>(
|
||||
auto years{ utils::execMultiResultQuery(session()->query<std::optional<int>>(
|
||||
std::string {"SELECT "} + "t." + field + " FROM track t INNER JOIN release r ON r.id = t.release_id")
|
||||
.where("r.id = ?").bind(getId())
|
||||
.groupBy(field)
|
||||
.resultList() };
|
||||
.groupBy(field)) };
|
||||
|
||||
// various years => invalid years
|
||||
if (years.empty() || years.size() > 1)
|
||||
const std::size_t count{ years.size() };
|
||||
if (count == 0 || count > 1)
|
||||
return std::nullopt;
|
||||
|
||||
return years.front();
|
||||
@@ -442,11 +430,11 @@ namespace lms::db
|
||||
{
|
||||
assert(session());
|
||||
|
||||
Wt::Dbo::collection<std::string> copyrights = session()->query<std::string>
|
||||
Wt::Dbo::collection<std::string> copyrights{ utils::execMultiResultQuery(session()->query<std::string>
|
||||
("SELECT copyright FROM track t INNER JOIN release r ON r.id = t.release_id")
|
||||
.where("r.id = ?")
|
||||
.groupBy("copyright")
|
||||
.bind(getId());
|
||||
.bind(getId())) };
|
||||
|
||||
std::vector<std::string> values(copyrights.begin(), copyrights.end());
|
||||
|
||||
@@ -454,17 +442,17 @@ namespace lms::db
|
||||
if (values.empty() || values.size() > 1 || values.front().empty())
|
||||
return std::nullopt;
|
||||
|
||||
return values.front();
|
||||
return std::move(values.front());
|
||||
}
|
||||
|
||||
std::optional<std::string> Release::getCopyrightURL() const
|
||||
{
|
||||
assert(session());
|
||||
|
||||
Wt::Dbo::collection<std::string> copyrights = session()->query<std::string>
|
||||
Wt::Dbo::collection<std::string> copyrights {utils::execMultiResultQuery(session()->query<std::string>
|
||||
("SELECT copyright_url FROM track t INNER JOIN release r ON r.id = t.release_id")
|
||||
.where("r.id = ?").bind(getId())
|
||||
.groupBy("copyright_url");
|
||||
.groupBy("copyright_url")) };
|
||||
|
||||
std::vector<std::string> values(copyrights.begin(), copyrights.end());
|
||||
|
||||
@@ -472,31 +460,29 @@ namespace lms::db
|
||||
if (values.empty() || values.size() > 1 || values.front().empty())
|
||||
return std::nullopt;
|
||||
|
||||
return values.front();
|
||||
return std::move(values.front());
|
||||
}
|
||||
|
||||
std::size_t Release::getMeanBitrate() const
|
||||
{
|
||||
assert(session());
|
||||
|
||||
return session()->query<int>("SELECT COALESCE(AVG(t.bitrate), 0) FROM track t")
|
||||
return utils::execSingleResultQuery(session()->query<int>("SELECT COALESCE(AVG(t.bitrate), 0) FROM track t")
|
||||
.where("release_id = ?").bind(getId())
|
||||
.where("bitrate > 0")
|
||||
.resultValue();
|
||||
.where("bitrate > 0"));
|
||||
}
|
||||
|
||||
std::vector<Artist::pointer> Release::getArtists(TrackArtistLinkType linkType) const
|
||||
{
|
||||
assert(session());
|
||||
|
||||
auto res{ session()->query<Wt::Dbo::ptr<Artist>>(
|
||||
auto res{ utils::execMultiResultQuery(session()->query<Wt::Dbo::ptr<Artist>>(
|
||||
"SELECT DISTINCT a FROM artist a"
|
||||
" INNER JOIN track_artist_link t_a_l ON t_a_l.artist_id = a.id"
|
||||
" INNER JOIN track t ON t.id = t_a_l.track_id"
|
||||
" INNER JOIN release r ON r.id = t.release_id")
|
||||
.where("r.id = ?").bind(getId())
|
||||
.where("t_a_l.type = ?").bind(linkType)
|
||||
.resultList() };
|
||||
.where("t_a_l.type = ?").bind(linkType))};
|
||||
|
||||
return std::vector<Artist::pointer>(res.begin(), res.end());
|
||||
}
|
||||
@@ -506,7 +492,7 @@ namespace lms::db
|
||||
assert(session());
|
||||
|
||||
// Select the similar releases using the 5 most used clusters of the release
|
||||
auto res{ session()->query<Wt::Dbo::ptr<Release>>(
|
||||
auto res{ utils::execMultiResultQuery(session()->query<Wt::Dbo::ptr<Release>>(
|
||||
"SELECT r 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"
|
||||
@@ -524,8 +510,7 @@ namespace lms::db
|
||||
.groupBy("r.id")
|
||||
.orderBy("COUNT(*) DESC, RANDOM()")
|
||||
.limit(count ? static_cast<int>(*count) : -1)
|
||||
.offset(offset ? static_cast<int>(*offset) : -1)
|
||||
.resultList() };
|
||||
.offset(offset ? static_cast<int>(*offset) : -1))};
|
||||
|
||||
return std::vector<pointer>(res.begin(), res.end());
|
||||
}
|
||||
@@ -572,20 +557,16 @@ namespace lms::db
|
||||
|
||||
using milli = std::chrono::duration<int, std::milli>;
|
||||
|
||||
Wt::Dbo::Query<milli> query{ session()->query<milli>("SELECT COALESCE(SUM(duration), 0) FROM track t INNER JOIN release r ON t.release_id = r.id")
|
||||
.where("r.id = ?").bind(getId()) };
|
||||
|
||||
return query.resultValue();
|
||||
return utils::execSingleResultQuery(session()->query<milli>("SELECT COALESCE(SUM(duration), 0) FROM track t INNER JOIN release r ON t.release_id = r.id")
|
||||
.where("r.id = ?").bind(getId()));
|
||||
}
|
||||
|
||||
Wt::WDateTime Release::getLastWritten() const
|
||||
{
|
||||
assert(session());
|
||||
|
||||
Wt::Dbo::Query<Wt::WDateTime> query{ session()->query<Wt::WDateTime>("SELECT COALESCE(MAX(file_last_write), '1970-01-01T00:00:00') FROM track t INNER JOIN release r ON t.release_id = r.id")
|
||||
.where("r.id = ?").bind(getId()) };
|
||||
|
||||
return query.resultValue();
|
||||
return utils::execSingleResultQuery(session()->query<Wt::WDateTime>("SELECT COALESCE(MAX(file_last_write), '1970-01-01T00:00:00') FROM track t INNER JOIN release r ON t.release_id = r.id")
|
||||
.where("r.id = ?").bind(getId()));
|
||||
}
|
||||
|
||||
std::vector<std::vector<Cluster::pointer>> Release::getClusterGroups(const std::vector<ClusterTypeId>& clusterTypeIds, std::size_t size) const
|
||||
@@ -612,7 +593,7 @@ namespace lms::db
|
||||
for (const std::string& bindArg : where.getBindArgs())
|
||||
query.bind(bindArg);
|
||||
|
||||
auto queryRes{ query.resultList() };
|
||||
auto queryRes{ utils::execMultiResultQuery(query) };
|
||||
|
||||
std::map<ClusterTypeId, std::vector<Cluster::pointer>> clustersByType;
|
||||
for (const Wt::Dbo::ptr<Cluster>& cluster : queryRes)
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "database/MediaLibrary.hpp"
|
||||
#include "database/Session.hpp"
|
||||
#include "core/String.hpp"
|
||||
#include "Utils.hpp"
|
||||
|
||||
namespace lms::db
|
||||
{
|
||||
@@ -34,14 +35,14 @@ namespace lms::db
|
||||
if (pointer settings{ get(session) })
|
||||
return;
|
||||
|
||||
session.getDboSession().add(std::make_unique<ScanSettings>());
|
||||
session.getDboSession()->add(std::make_unique<ScanSettings>());
|
||||
}
|
||||
|
||||
ScanSettings::pointer ScanSettings::get(Session& session)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
return session.getDboSession().find<ScanSettings>().resultValue();
|
||||
return utils::execSingleResultQuery(session.getDboSession()->find<ScanSettings>());
|
||||
}
|
||||
|
||||
std::vector<std::filesystem::path> ScanSettings::getAudioFileExtensions() const
|
||||
|
||||
@@ -38,40 +38,38 @@ namespace lms::db
|
||||
|
||||
StarredArtist::pointer StarredArtist::create(Session& session, ObjectPtr<Artist> artist, ObjectPtr<User> user, FeedbackBackend backend)
|
||||
{
|
||||
return session.getDboSession().add(std::unique_ptr<StarredArtist> {new StarredArtist{ artist, user, backend }});
|
||||
return session.getDboSession()->add(std::unique_ptr<StarredArtist> {new StarredArtist{ artist, user, backend }});
|
||||
}
|
||||
|
||||
std::size_t StarredArtist::getCount(Session& session)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
return session.getDboSession().query<int>("SELECT COUNT(*) FROM starred_artist");
|
||||
return utils::execSingleResultQuery(session.getDboSession()->query<int>("SELECT COUNT(*) FROM starred_artist"));
|
||||
}
|
||||
|
||||
StarredArtist::pointer StarredArtist::find(Session& session, StarredArtistId id)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
return session.getDboSession().find<StarredArtist>().where("id = ?").bind(id).resultValue();
|
||||
return utils::execSingleResultQuery(session.getDboSession()->find<StarredArtist>().where("id = ?").bind(id));
|
||||
}
|
||||
|
||||
StarredArtist::pointer StarredArtist::find(Session& session, ArtistId artistId, UserId userId)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
return session.getDboSession().query<Wt::Dbo::ptr<StarredArtist>>("SELECT s_a from starred_artist s_a")
|
||||
return utils::execSingleResultQuery(session.getDboSession()->query<Wt::Dbo::ptr<StarredArtist>>("SELECT s_a from starred_artist s_a")
|
||||
.join("user u ON u.id = s_a.user_id")
|
||||
.where("s_a.artist_id = ?").bind(artistId)
|
||||
.where("s_a.user_id = ?").bind(userId)
|
||||
.where("s_a.backend = u.feedback_backend")
|
||||
.resultValue();
|
||||
.where("s_a.backend = u.feedback_backend"));
|
||||
}
|
||||
|
||||
StarredArtist::pointer StarredArtist::find(Session& session, ArtistId artistId, UserId userId, FeedbackBackend backend)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
return session.getDboSession().find<StarredArtist>()
|
||||
return utils::execSingleResultQuery(session.getDboSession()->find<StarredArtist>()
|
||||
.where("artist_id = ?").bind(artistId)
|
||||
.where("user_id = ?").bind(userId)
|
||||
.where("backend = ?").bind(backend)
|
||||
.resultValue();
|
||||
.where("backend = ?").bind(backend));
|
||||
}
|
||||
|
||||
void StarredArtist::setDateTime(const Wt::WDateTime& dateTime)
|
||||
|
||||
@@ -38,40 +38,38 @@ namespace lms::db
|
||||
|
||||
StarredRelease::pointer StarredRelease::create(Session& session, ObjectPtr<Release> release, ObjectPtr<User> user, FeedbackBackend backend)
|
||||
{
|
||||
return session.getDboSession().add(std::unique_ptr<StarredRelease>{new StarredRelease{ release, user, backend }});
|
||||
return session.getDboSession()->add(std::unique_ptr<StarredRelease>{new StarredRelease{ release, user, backend }});
|
||||
}
|
||||
|
||||
std::size_t StarredRelease::getCount(Session& session)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
return session.getDboSession().query<int>("SELECT COUNT(*) FROM starred_release");
|
||||
return session.getDboSession()->query<int>("SELECT COUNT(*) FROM starred_release");
|
||||
}
|
||||
|
||||
StarredRelease::pointer StarredRelease::find(Session& session, StarredReleaseId id)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
return session.getDboSession().find<StarredRelease>().where("id = ?").bind(id).resultValue();
|
||||
return utils::execSingleResultQuery(session.getDboSession()->find<StarredRelease>().where("id = ?").bind(id));
|
||||
}
|
||||
|
||||
StarredRelease::pointer StarredRelease::find(Session& session, ReleaseId releaseId, UserId userId)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
return session.getDboSession().query<Wt::Dbo::ptr<StarredRelease>>("SELECT s_r from starred_release s_r")
|
||||
return utils::execSingleResultQuery(session.getDboSession()->query<Wt::Dbo::ptr<StarredRelease>>("SELECT s_r from starred_release s_r")
|
||||
.join("user u ON u.id = s_r.user_id")
|
||||
.where("s_r.release_id = ?").bind(releaseId)
|
||||
.where("s_r.user_id = ?").bind(userId)
|
||||
.where("s_r.backend = u.feedback_backend")
|
||||
.resultValue();
|
||||
.where("s_r.backend = u.feedback_backend"));
|
||||
}
|
||||
|
||||
StarredRelease::pointer StarredRelease::find(Session& session, ReleaseId releaseId, UserId userId, FeedbackBackend backend)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
return session.getDboSession().find<StarredRelease>()
|
||||
return utils::execSingleResultQuery(session.getDboSession()->find<StarredRelease>()
|
||||
.where("release_id = ?").bind(releaseId)
|
||||
.where("user_id = ?").bind(userId)
|
||||
.where("backend = ?").bind(backend)
|
||||
.resultValue();
|
||||
.where("backend = ?").bind(backend));
|
||||
}
|
||||
|
||||
void StarredRelease::setDateTime(const Wt::WDateTime& dateTime)
|
||||
|
||||
@@ -38,56 +38,53 @@ namespace lms::db
|
||||
|
||||
StarredTrack::pointer StarredTrack::create(Session& session, ObjectPtr<Track> track, ObjectPtr<User> user, FeedbackBackend backend)
|
||||
{
|
||||
return session.getDboSession().add(std::unique_ptr<StarredTrack> {new StarredTrack{ track, user, backend }});
|
||||
return session.getDboSession()->add(std::unique_ptr<StarredTrack> {new StarredTrack{ track, user, backend }});
|
||||
}
|
||||
|
||||
std::size_t StarredTrack::getCount(Session& session)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
return session.getDboSession().query<int>("SELECT COUNT(*) FROM starred_track");
|
||||
return utils::execSingleResultQuery(session.getDboSession()->query<int>("SELECT COUNT(*) FROM starred_track"));
|
||||
}
|
||||
|
||||
StarredTrack::pointer StarredTrack::find(Session& session, StarredTrackId id)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
return session.getDboSession().find<StarredTrack>().where("id = ?").bind(id).resultValue();
|
||||
return utils::execSingleResultQuery(session.getDboSession()->find<StarredTrack>().where("id = ?").bind(id));
|
||||
}
|
||||
|
||||
StarredTrack::pointer StarredTrack::find(Session& session, TrackId trackId, UserId userId)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
return session.getDboSession().query<Wt::Dbo::ptr<StarredTrack>>("SELECT s_t from starred_track s_t")
|
||||
return utils::execSingleResultQuery(session.getDboSession()->query<Wt::Dbo::ptr<StarredTrack>>("SELECT s_t from starred_track s_t")
|
||||
.join("user u ON u.id = s_t.user_id")
|
||||
.where("s_t.track_id = ?").bind(trackId)
|
||||
.where("s_t.user_id = ?").bind(userId)
|
||||
.where("s_t.backend = u.feedback_backend")
|
||||
.resultValue();
|
||||
.where("s_t.backend = u.feedback_backend"));
|
||||
}
|
||||
|
||||
StarredTrack::pointer StarredTrack::find(Session& session, TrackId trackId, UserId userId, FeedbackBackend backend)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
return session.getDboSession().find<StarredTrack>()
|
||||
return utils::execSingleResultQuery(session.getDboSession()->find<StarredTrack>()
|
||||
.where("track_id = ?").bind(trackId)
|
||||
.where("user_id = ?").bind(userId)
|
||||
.where("backend = ?").bind(backend)
|
||||
.resultValue();
|
||||
.where("backend = ?").bind(backend));
|
||||
}
|
||||
|
||||
bool StarredTrack::exists(Session& session, TrackId trackId, UserId userId, FeedbackBackend backend)
|
||||
{
|
||||
return session.getDboSession().query<int>("SELECT 1 from starred_track")
|
||||
return utils::execSingleResultQuery(session.getDboSession()->query<int>("SELECT 1 from starred_track")
|
||||
.where("track_id = ?").bind(trackId)
|
||||
.where("user_id = ?").bind(userId)
|
||||
.where("backend = ?").bind(backend)
|
||||
.resultValue() == 1;
|
||||
.where("backend = ?").bind(backend));
|
||||
}
|
||||
|
||||
RangeResults<StarredTrackId> StarredTrack::find(Session& session, const FindParameters& params)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
auto query{ session.getDboSession().query<StarredTrackId>("SELECT DISTINCT s_t.id FROM starred_track s_t") };
|
||||
auto query{ session.getDboSession()->query<StarredTrackId>("SELECT DISTINCT s_t.id FROM starred_track s_t") };
|
||||
|
||||
if (params.backend)
|
||||
query.where("s_t.backend = ?").bind(*params.backend);
|
||||
@@ -96,7 +93,7 @@ namespace lms::db
|
||||
if (params.user.isValid())
|
||||
query.where("s_t.user_id = ?").bind(params.user);
|
||||
|
||||
return utils::execQuery<StarredTrackId>(query, params.range);
|
||||
return utils::execRangeQuery<StarredTrackId>(query, params.range);
|
||||
}
|
||||
|
||||
void StarredTrack::setDateTime(const Wt::WDateTime& dateTime)
|
||||
|
||||
@@ -45,7 +45,7 @@ namespace lms::db
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
auto query{ session.getDboSession().query<ResultType>("SELECT " + std::string{ itemToSelect } + " FROM track t") };
|
||||
auto query{ session.getDboSession()->query<ResultType>("SELECT " + std::string{ itemToSelect } + " FROM track t") };
|
||||
|
||||
assert(params.keywords.empty() || params.name.empty());
|
||||
for (std::string_view keyword : params.keywords)
|
||||
@@ -202,37 +202,36 @@ namespace lms::db
|
||||
|
||||
Track::pointer Track::create(Session& session, const std::filesystem::path& p)
|
||||
{
|
||||
return session.getDboSession().add(std::unique_ptr<Track> {new Track{ p }});
|
||||
return session.getDboSession()->add(std::unique_ptr<Track> {new Track{ p }});
|
||||
}
|
||||
|
||||
std::size_t Track::getCount(Session& session)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
return session.getDboSession().query<int>("SELECT COUNT(*) FROM track");
|
||||
return utils::execSingleResultQuery(session.getDboSession()->query<int>("SELECT COUNT(*) FROM track"));
|
||||
}
|
||||
|
||||
Track::pointer Track::findByPath(Session& session, const std::filesystem::path& p)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
return session.getDboSession().find<Track>().where("file_path = ?").bind(p.string()).resultValue();
|
||||
return utils::execSingleResultQuery(session.getDboSession()->find<Track>().where("file_path = ?").bind(p.string()));
|
||||
}
|
||||
|
||||
Track::pointer Track::find(Session& session, TrackId id)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
return session.getDboSession().find<Track>()
|
||||
.where("id = ?").bind(id)
|
||||
.resultValue();
|
||||
return utils::execSingleResultQuery(session.getDboSession()->find<Track>()
|
||||
.where("id = ?").bind(id));
|
||||
}
|
||||
|
||||
void Track::find(Session& session, TrackId& lastRetrievedTrack, std::size_t count, const std::function<void(const Track::pointer&)>& func, MediaLibraryId library)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
auto query{ session.getDboSession().find<Track>()
|
||||
auto query{ session.getDboSession()->find<Track>()
|
||||
.orderBy("id")
|
||||
.where("id > ?").bind(lastRetrievedTrack)
|
||||
.limit(static_cast<int>(count)) };
|
||||
@@ -240,7 +239,7 @@ namespace lms::db
|
||||
if (library.isValid())
|
||||
query.where("media_library_id = ?").bind(library);
|
||||
|
||||
auto collection{query.resultList()};
|
||||
auto collection{ utils::execMultiResultQuery(query) };
|
||||
|
||||
for (auto itResult{ collection.begin() }; itResult != collection.end(); ++itResult)
|
||||
{
|
||||
@@ -253,16 +252,15 @@ namespace lms::db
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
return session.getDboSession().query<int>("SELECT 1 from track").where("id = ?").bind(id).resultValue() == 1;
|
||||
return utils::execSingleResultQuery(session.getDboSession()->query<int>("SELECT 1 from track").where("id = ?").bind(id)) == 1;
|
||||
}
|
||||
|
||||
std::vector<Track::pointer> Track::findByMBID(Session& session, const core::UUID& mbid)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
auto res{ session.getDboSession().find<Track>()
|
||||
.where("mbid = ?").bind(std::string {mbid.getAsString()})
|
||||
.resultList() };
|
||||
auto res{ utils::execMultiResultQuery(session.getDboSession()->find<Track>()
|
||||
.where("mbid = ?").bind(std::string {mbid.getAsString()})) };
|
||||
|
||||
return std::vector<Track::pointer>(res.begin(), res.end());
|
||||
}
|
||||
@@ -271,9 +269,8 @@ namespace lms::db
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
auto res{ session.getDboSession().find<Track>()
|
||||
.where("recording_mbid = ?").bind(std::string {mbid.getAsString()})
|
||||
.resultList() };
|
||||
auto res{ utils::execMultiResultQuery(session.getDboSession()->find<Track>()
|
||||
.where("recording_mbid = ?").bind(std::string {mbid.getAsString()})) };
|
||||
|
||||
return std::vector<Track::pointer>(res.begin(), res.end());
|
||||
}
|
||||
@@ -284,9 +281,9 @@ namespace lms::db
|
||||
session.checkReadTransaction();
|
||||
|
||||
// TODO Dbo traits on filesystem
|
||||
auto query{ session.getDboSession().query<QueryResultType>("SELECT id, file_path FROM track") };
|
||||
auto query{ session.getDboSession()->query<QueryResultType>("SELECT id, file_path FROM track") };
|
||||
|
||||
RangeResults<QueryResultType> queryResults{ utils::execQuery<QueryResultType>(query, range) };
|
||||
RangeResults<QueryResultType> queryResults{ utils::execRangeQuery<QueryResultType>(query, range) };
|
||||
|
||||
RangeResults<PathResult> res;
|
||||
res.range = queryResults.range;
|
||||
@@ -306,21 +303,21 @@ namespace lms::db
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
auto query{ session.getDboSession().query<TrackId>("SELECT track.id FROM track WHERE mbid in (SELECT mbid FROM track WHERE mbid <> '' GROUP BY mbid HAVING COUNT (*) > 1)")
|
||||
auto query{ session.getDboSession()->query<TrackId>("SELECT track.id FROM track WHERE mbid in (SELECT mbid FROM track WHERE mbid <> '' GROUP BY mbid HAVING COUNT (*) > 1)")
|
||||
.orderBy("track.release_id,track.disc_number,track.track_number,track.mbid") };
|
||||
|
||||
return utils::execQuery<TrackId>(query, range);
|
||||
return utils::execRangeQuery<TrackId>(query, range);
|
||||
}
|
||||
|
||||
RangeResults<TrackId> Track::findIdsWithRecordingMBIDAndMissingFeatures(Session& session, std::optional<Range> range)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
auto query{ session.getDboSession().query<TrackId>("SELECT t.id FROM track t")
|
||||
auto query{ session.getDboSession()->query<TrackId>("SELECT t.id FROM track t")
|
||||
.where("LENGTH(t.recording_mbid) > 0")
|
||||
.where("NOT EXISTS (SELECT * FROM track_features t_f WHERE t_f.track_id = t.id)") };
|
||||
|
||||
return utils::execQuery<TrackId>(query, range);
|
||||
return utils::execRangeQuery<TrackId>(query, range);
|
||||
}
|
||||
|
||||
std::vector<Cluster::pointer> Track::getClusters() const
|
||||
@@ -332,10 +329,9 @@ namespace lms::db
|
||||
{
|
||||
assert(session());
|
||||
|
||||
auto res{ session()->query<ClusterId>
|
||||
auto res{ utils::execMultiResultQuery(session()->query<ClusterId>
|
||||
("SELECT DISTINCT c.id FROM cluster c INNER JOIN track_cluster t_c ON t_c.cluster_id = c.id INNER JOIN track t ON t.id = t_c.track_id")
|
||||
.where("t.id = ?").bind(getId())
|
||||
.resultList() };
|
||||
.where("t.id = ?").bind(getId())) };
|
||||
|
||||
return std::vector<ClusterId>(res.begin(), res.end());
|
||||
}
|
||||
@@ -345,7 +341,7 @@ namespace lms::db
|
||||
session.checkReadTransaction();
|
||||
|
||||
auto query{ createQuery<TrackId>(session, parameters) };
|
||||
return utils::execQuery<TrackId>(query, parameters.range);
|
||||
return utils::execRangeQuery<TrackId>(query, parameters.range);
|
||||
}
|
||||
|
||||
RangeResults<Track::pointer> Track::find(Session& session, const FindParameters& parameters)
|
||||
@@ -353,7 +349,7 @@ namespace lms::db
|
||||
session.checkReadTransaction();
|
||||
|
||||
auto query{ createQuery<Wt::Dbo::ptr<Track>>(session, parameters) };
|
||||
return utils::execQuery<Track::pointer>(query, parameters.range);
|
||||
return utils::execRangeQuery<Track::pointer>(query, parameters.range);
|
||||
}
|
||||
|
||||
void Track::find(Session& session, const FindParameters& params, std::function<void(const Track::pointer&)> func)
|
||||
@@ -361,7 +357,7 @@ namespace lms::db
|
||||
session.checkReadTransaction();
|
||||
|
||||
auto query{ createQuery<Wt::Dbo::ptr<Track>>(session, params)};
|
||||
utils::execQuery(query, params.range, func);
|
||||
utils::execRangeQuery(query, params.range, func);
|
||||
}
|
||||
|
||||
void Track::find(Session& session, const FindParameters& params, bool& moreResults, std::function<void(const Track::pointer&)> func)
|
||||
@@ -369,7 +365,7 @@ namespace lms::db
|
||||
session.checkReadTransaction();
|
||||
|
||||
auto query{ createQuery<Wt::Dbo::ptr<Track>>(session, params)};
|
||||
utils::execQuery(query, params.range, moreResults, func);
|
||||
utils::execRangeQuery(query, params.range, moreResults, func);
|
||||
}
|
||||
|
||||
RangeResults<TrackId> Track::findSimilarTrackIds(Session& session, const std::vector<TrackId>& tracks, std::optional<Range> range)
|
||||
@@ -385,7 +381,7 @@ namespace lms::db
|
||||
oss << "?";
|
||||
}
|
||||
|
||||
auto query{ session.getDboSession().query<TrackId>(
|
||||
auto query{ session.getDboSession()->query<TrackId>(
|
||||
"SELECT t.id FROM track t"
|
||||
" INNER JOIN track_cluster t_c ON t_c.track_id = t.id"
|
||||
" AND t_c.cluster_id IN (SELECT DISTINCT c.id FROM cluster c INNER JOIN track_cluster t_c ON t_c.cluster_id = c.id WHERE t_c.track_id IN (" + oss.str() + "))"
|
||||
@@ -399,7 +395,7 @@ namespace lms::db
|
||||
for (TrackId trackId : tracks)
|
||||
query.bind(trackId);
|
||||
|
||||
return utils::execQuery<TrackId>(query, range);
|
||||
return utils::execRangeQuery<TrackId>(query, range);
|
||||
}
|
||||
|
||||
void Track::clearArtistLinks()
|
||||
@@ -460,7 +456,7 @@ namespace lms::db
|
||||
|
||||
query.where("t.id = ?").bind(getId());
|
||||
|
||||
auto res{ query.resultList() };
|
||||
auto res{ utils::execMultiResultQuery(query) };
|
||||
return std::vector<Artist::pointer>(std::begin(res), std::end(res));
|
||||
}
|
||||
|
||||
@@ -496,7 +492,7 @@ namespace lms::db
|
||||
|
||||
query.where("t.id = ?").bind(getId());
|
||||
|
||||
auto res{ query.resultList() };
|
||||
auto res{ utils::execMultiResultQuery(query) };
|
||||
return std::vector<ArtistId>(std::cbegin(res), std::cend(res));
|
||||
}
|
||||
|
||||
@@ -530,7 +526,7 @@ namespace lms::db
|
||||
for (const std::string& bindArg : where.getBindArgs())
|
||||
query.bind(bindArg);
|
||||
|
||||
auto queryRes{ query.resultList() };
|
||||
auto queryRes{ utils::execMultiResultQuery(query) };
|
||||
|
||||
std::map<ClusterTypeId, std::vector<Cluster::pointer>> clusters;
|
||||
for (const Wt::Dbo::ptr<Cluster>& cluster : queryRes)
|
||||
|
||||
@@ -34,7 +34,7 @@ namespace lms::db
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
auto query{ session.getDboSession().query<TrackArtistLinkId>("SELECT DISTINCT t_a_l.id FROM track_artist_link t_a_l") };
|
||||
auto query{ session.getDboSession()->query<TrackArtistLinkId>("SELECT DISTINCT t_a_l.id FROM track_artist_link t_a_l") };
|
||||
|
||||
if (params.linkType)
|
||||
query.where("t_a_l.type = ?").bind(*params.linkType);
|
||||
@@ -67,8 +67,8 @@ namespace lms::db
|
||||
{
|
||||
session.checkWriteTransaction();
|
||||
|
||||
TrackArtistLink::pointer res{ session.getDboSession().add(std::make_unique<TrackArtistLink>(track, artist, type, subType)) };
|
||||
session.getDboSession().flush();
|
||||
TrackArtistLink::pointer res{ session.getDboSession()->add(std::make_unique<TrackArtistLink>(track, artist, type, subType)) };
|
||||
session.getDboSession()->flush();
|
||||
|
||||
return res;
|
||||
}
|
||||
@@ -76,7 +76,7 @@ namespace lms::db
|
||||
TrackArtistLink::pointer TrackArtistLink::find(Session& session, TrackArtistLinkId id)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
return session.getDboSession().find<TrackArtistLink>().where("id = ?").bind(id).resultValue();
|
||||
return utils::execSingleResultQuery(session.getDboSession()->find<TrackArtistLink>().where("id = ?").bind(id));
|
||||
}
|
||||
|
||||
RangeResults<TrackArtistLinkId> TrackArtistLink::find(Session& session, const FindParameters& params)
|
||||
@@ -84,14 +84,14 @@ namespace lms::db
|
||||
session.checkReadTransaction();
|
||||
|
||||
auto query{ createQuery(session, params) };
|
||||
return utils::execQuery<TrackArtistLinkId>(query, params.range);
|
||||
return utils::execRangeQuery<TrackArtistLinkId>(query, params.range);
|
||||
}
|
||||
|
||||
core::EnumSet<TrackArtistLinkType> TrackArtistLink::findUsedTypes(Session& session)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
auto res{ session.getDboSession().query<TrackArtistLinkType>("SELECT DISTINCT type from track_artist_link").resultList() };
|
||||
auto res{ utils::execMultiResultQuery(session.getDboSession()->query<TrackArtistLinkType>("SELECT DISTINCT type from track_artist_link")) };
|
||||
|
||||
return core::EnumSet<TrackArtistLinkType>(std::begin(res), std::end(res));
|
||||
}
|
||||
@@ -100,10 +100,8 @@ namespace lms::db
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
auto res{ session.getDboSession()
|
||||
.query<TrackArtistLinkType>("SELECT DISTINCT type from track_artist_link")
|
||||
.where("artist_id = ?").bind(artistId)
|
||||
.resultList() };
|
||||
auto res{ utils::execMultiResultQuery(session.getDboSession()->query<TrackArtistLinkType>("SELECT DISTINCT type from track_artist_link")
|
||||
.where("artist_id = ?").bind(artistId)) };
|
||||
|
||||
return core::EnumSet<TrackArtistLinkType>(std::begin(res), std::end(res));
|
||||
}
|
||||
|
||||
@@ -35,43 +35,41 @@ namespace lms::db
|
||||
|
||||
TrackBookmark::pointer TrackBookmark::create(Session& session, ObjectPtr<User> user, ObjectPtr<Track> track)
|
||||
{
|
||||
return session.getDboSession().add(std::unique_ptr<TrackBookmark> {new TrackBookmark{ user, track }});
|
||||
return session.getDboSession()->add(std::unique_ptr<TrackBookmark> {new TrackBookmark{ user, track }});
|
||||
}
|
||||
|
||||
std::size_t TrackBookmark::getCount(Session& session)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
return session.getDboSession().query<int>("SELECT COUNT(*) FROM track_bookmark");
|
||||
return utils::execSingleResultQuery(session.getDboSession()->query<int>("SELECT COUNT(*) FROM track_bookmark"));
|
||||
}
|
||||
|
||||
RangeResults<TrackBookmarkId> TrackBookmark::find(Session& session, UserId userId, std::optional<Range> range)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
auto query{ session.getDboSession().query<TrackBookmarkId>("SELECT id from track_bookmark")
|
||||
auto query{ session.getDboSession()->query<TrackBookmarkId>("SELECT id from track_bookmark")
|
||||
.where("user_id = ?").bind(userId) };
|
||||
|
||||
return utils::execQuery<TrackBookmarkId>(query, range);
|
||||
return utils::execRangeQuery<TrackBookmarkId>(query, range);
|
||||
}
|
||||
|
||||
TrackBookmark::pointer TrackBookmark::find(Session& session, UserId userId, TrackId trackId)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
return session.getDboSession().find<TrackBookmark>()
|
||||
return utils::execSingleResultQuery(session.getDboSession()->find<TrackBookmark>()
|
||||
.where("user_id = ?").bind(userId)
|
||||
.where("track_id = ?").bind(trackId)
|
||||
.resultValue();
|
||||
.where("track_id = ?").bind(trackId));
|
||||
}
|
||||
|
||||
TrackBookmark::pointer TrackBookmark::find(Session& session, TrackBookmarkId id)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
return session.getDboSession().find<TrackBookmark>()
|
||||
.where("id = ?").bind(id)
|
||||
.resultValue();
|
||||
return utils::execSingleResultQuery(session.getDboSession()->find<TrackBookmark>()
|
||||
.where("id = ?").bind(id));
|
||||
}
|
||||
|
||||
} // namespace lms::db
|
||||
|
||||
@@ -38,41 +38,39 @@ namespace lms::db {
|
||||
|
||||
TrackFeatures::pointer TrackFeatures::create(Session& session, ObjectPtr<Track> track, const std::string& jsonEncodedFeatures)
|
||||
{
|
||||
return session.getDboSession().add(std::unique_ptr<TrackFeatures> {new TrackFeatures{ track, jsonEncodedFeatures }});
|
||||
return session.getDboSession()->add(std::unique_ptr<TrackFeatures> {new TrackFeatures{ track, jsonEncodedFeatures }});
|
||||
}
|
||||
|
||||
std::size_t TrackFeatures::getCount(Session& session)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
return session.getDboSession().query<int>("SELECT COUNT(*) FROM track_features");
|
||||
return utils::execSingleResultQuery(session.getDboSession()->query<int>("SELECT COUNT(*) FROM track_features"));
|
||||
}
|
||||
|
||||
TrackFeatures::pointer TrackFeatures::find(Session& session, TrackFeaturesId id)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
return session.getDboSession().find<TrackFeatures>()
|
||||
.where("id = ?").bind(id)
|
||||
.resultValue();
|
||||
return utils::execSingleResultQuery(session.getDboSession()->find<TrackFeatures>()
|
||||
.where("id = ?").bind(id));
|
||||
}
|
||||
|
||||
TrackFeatures::pointer TrackFeatures::find(Session& session, TrackId trackId)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
return session.getDboSession().find<TrackFeatures>()
|
||||
.where("track_id = ?").bind(trackId)
|
||||
.resultValue();
|
||||
return utils::execSingleResultQuery(session.getDboSession()->find<TrackFeatures>()
|
||||
.where("track_id = ?").bind(trackId));
|
||||
}
|
||||
|
||||
RangeResults<TrackFeaturesId> TrackFeatures::find(Session& session, std::optional<Range> range)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
auto query{ session.getDboSession().query<TrackFeaturesId>("SELECT id from track_features") };
|
||||
auto query{ session.getDboSession()->query<TrackFeaturesId>("SELECT id from track_features") };
|
||||
|
||||
return utils::execQuery<TrackFeaturesId>(query, range);
|
||||
return utils::execRangeQuery<TrackFeaturesId>(query, range);
|
||||
}
|
||||
|
||||
FeatureValues TrackFeatures::getFeatureValues(const FeatureName& featureNode) const
|
||||
|
||||
@@ -48,14 +48,14 @@ namespace lms::db
|
||||
|
||||
TrackList::pointer TrackList::create(Session& session, std::string_view name, TrackListType type, bool isPublic, ObjectPtr<User> user)
|
||||
{
|
||||
return session.getDboSession().add(std::unique_ptr<TrackList> {new TrackList{ name, type, isPublic, user }});
|
||||
return session.getDboSession()->add(std::unique_ptr<TrackList> {new TrackList{ name, type, isPublic, user }});
|
||||
}
|
||||
|
||||
std::size_t TrackList::getCount(Session& session)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
return session.getDboSession().query<int>("SELECT COUNT(*) FROM tracklist");
|
||||
return utils::execSingleResultQuery(session.getDboSession()->query<int>("SELECT COUNT(*) FROM tracklist"));
|
||||
}
|
||||
|
||||
|
||||
@@ -64,17 +64,17 @@ namespace lms::db
|
||||
session.checkReadTransaction();
|
||||
assert(userId.isValid());
|
||||
|
||||
return session.getDboSession().find<TrackList>()
|
||||
return utils::execSingleResultQuery(session.getDboSession()->find<TrackList>()
|
||||
.where("name = ?").bind(name)
|
||||
.where("type = ?").bind(type)
|
||||
.where("user_id = ?").bind(userId).resultValue();
|
||||
.where("user_id = ?").bind(userId));
|
||||
}
|
||||
|
||||
RangeResults<TrackListId> TrackList::find(Session& session, const FindParameters& params)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
auto query{ session.getDboSession().query<TrackListId>("SELECT DISTINCT t_l.id FROM tracklist t_l") };
|
||||
auto query{ session.getDboSession()->query<TrackListId>("SELECT DISTINCT t_l.id FROM tracklist t_l") };
|
||||
|
||||
if (params.user.isValid())
|
||||
query.where("t_l.user_id = ?").bind(params.user);
|
||||
@@ -117,14 +117,14 @@ namespace lms::db
|
||||
break;
|
||||
}
|
||||
|
||||
return utils::execQuery<TrackListId>(query, params.range);
|
||||
return utils::execRangeQuery<TrackListId>(query, params.range);
|
||||
}
|
||||
|
||||
TrackList::pointer TrackList::find(Session& session, TrackListId id)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
return session.getDboSession().find<TrackList>().where("id = ?").bind(id).resultValue();
|
||||
return utils::execSingleResultQuery(session.getDboSession()->find<TrackList>().where("id = ?").bind(id));
|
||||
}
|
||||
|
||||
bool TrackList::isEmpty() const
|
||||
@@ -156,29 +156,27 @@ namespace lms::db
|
||||
.where("tracklist_id = ?").bind(getId())
|
||||
.orderBy("id") };
|
||||
|
||||
return utils::execQuery<TrackListEntry::pointer>(query, range);
|
||||
return utils::execRangeQuery<TrackListEntry::pointer>(query, range);
|
||||
}
|
||||
|
||||
TrackListEntry::pointer TrackList::getEntryByTrackAndDateTime(ObjectPtr<Track> track, const Wt::WDateTime& dateTime) const
|
||||
{
|
||||
assert(session());
|
||||
|
||||
return session()->find<TrackListEntry>()
|
||||
return utils::execSingleResultQuery(session()->find<TrackListEntry>()
|
||||
.where("tracklist_id = ?").bind(getId())
|
||||
.where("track_id = ?").bind(track->getId())
|
||||
.where("date_time = ?").bind(utils::normalizeDateTime(dateTime))
|
||||
.resultValue();
|
||||
.where("date_time = ?").bind(utils::normalizeDateTime(dateTime)));
|
||||
}
|
||||
|
||||
std::vector<Cluster::pointer> TrackList::getClusters() const
|
||||
{
|
||||
assert(session());
|
||||
|
||||
auto res{ session()->query<Wt::Dbo::ptr<Cluster>>("SELECT c from cluster c INNER JOIN track t ON c.id = t_c.cluster_id INNER JOIN track_cluster t_c ON t_c.track_id = t.id INNER JOIN tracklist_entry p_e ON p_e.track_id = t.id INNER JOIN tracklist p ON p.id = p_e.tracklist_id")
|
||||
auto res{ utils::execMultiResultQuery(session()->query<Wt::Dbo::ptr<Cluster>>("SELECT c from cluster c INNER JOIN track t ON c.id = t_c.cluster_id INNER JOIN track_cluster t_c ON t_c.track_id = t.id INNER JOIN tracklist_entry p_e ON p_e.track_id = t.id INNER JOIN tracklist p ON p.id = p_e.tracklist_id")
|
||||
.where("p.id = ?").bind(getId())
|
||||
.groupBy("c.id")
|
||||
.orderBy("COUNT(c.id) DESC")
|
||||
.resultList() };
|
||||
.orderBy("COUNT(c.id) DESC")) };
|
||||
|
||||
return std::vector<Cluster::pointer>(res.begin(), res.end());
|
||||
}
|
||||
@@ -218,7 +216,7 @@ namespace lms::db
|
||||
query.groupBy("c.id");
|
||||
query.orderBy("COUNT(c.id) DESC");
|
||||
|
||||
auto queryRes{ query.resultList() };
|
||||
auto queryRes{ utils::execMultiResultQuery(query) };
|
||||
|
||||
std::map<ClusterTypeId, std::vector<Cluster::pointer>> clustersByType;
|
||||
for (const Wt::Dbo::ptr<Cluster>& cluster : queryRes)
|
||||
@@ -237,7 +235,7 @@ namespace lms::db
|
||||
{
|
||||
assert(session());
|
||||
|
||||
auto res{ session()->query<Wt::Dbo::ptr<Track>>(
|
||||
auto res{ utils::execMultiResultQuery(session()->query<Wt::Dbo::ptr<Track>>(
|
||||
"SELECT t FROM track t"
|
||||
" INNER JOIN track_cluster t_c ON t_c.track_id = t.id"
|
||||
" WHERE "
|
||||
@@ -249,8 +247,7 @@ namespace lms::db
|
||||
.groupBy("t.id")
|
||||
.orderBy("COUNT(*) DESC, RANDOM()")
|
||||
.limit(size ? static_cast<int>(*size) : -1)
|
||||
.offset(offset ? static_cast<int>(*offset) : -1)
|
||||
.resultList() };
|
||||
.offset(offset ? static_cast<int>(*offset) : -1))};
|
||||
|
||||
return std::vector<Track::pointer>(res.begin(), res.end());
|
||||
}
|
||||
@@ -259,8 +256,8 @@ namespace lms::db
|
||||
{
|
||||
assert(session());
|
||||
|
||||
Wt::Dbo::collection<TrackId> res = session()->query<TrackId>("SELECT p_e.track_id from tracklist_entry p_e INNER JOIN tracklist p ON p_e.tracklist_id = p.id")
|
||||
.where("p.id = ?").bind(getId());
|
||||
auto res {utils::execMultiResultQuery(session()->query<TrackId>("SELECT p_e.track_id from tracklist_entry p_e INNER JOIN tracklist p ON p_e.tracklist_id = p.id")
|
||||
.where("p.id = ?").bind(getId())) };
|
||||
|
||||
return std::vector<TrackId>(res.begin(), res.end());
|
||||
}
|
||||
@@ -271,10 +268,8 @@ namespace lms::db
|
||||
|
||||
using milli = std::chrono::duration<int, std::milli>;
|
||||
|
||||
Wt::Dbo::Query<milli> query{ session()->query<milli>("SELECT COALESCE(SUM(duration), 0) FROM track t INNER JOIN tracklist_entry p_e ON t.id = p_e.track_id")
|
||||
.where("p_e.tracklist_id = ?").bind(getId()) };
|
||||
|
||||
return query.resultValue();
|
||||
return utils::execSingleResultQuery(session()->query<milli>("SELECT COALESCE(SUM(duration), 0) FROM track t INNER JOIN tracklist_entry p_e ON t.id = p_e.track_id")
|
||||
.where("p_e.tracklist_id = ?").bind(getId()));
|
||||
}
|
||||
|
||||
void TrackList::setLastModifiedDateTime(const Wt::WDateTime& dateTime)
|
||||
@@ -293,7 +288,7 @@ namespace lms::db
|
||||
|
||||
TrackListEntry::pointer TrackListEntry::create(Session& session, ObjectPtr<Track> track, ObjectPtr<TrackList> tracklist, const Wt::WDateTime& dateTime)
|
||||
{
|
||||
return session.getDboSession().add(std::unique_ptr<TrackListEntry> {new TrackListEntry{ track, tracklist, dateTime }});
|
||||
return session.getDboSession()->add(std::unique_ptr<TrackListEntry> {new TrackListEntry{ track, tracklist, dateTime }});
|
||||
}
|
||||
|
||||
void TrackListEntry::onPostCreated()
|
||||
@@ -310,6 +305,6 @@ namespace lms::db
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
return session.getDboSession().find<TrackListEntry>().where("id = ?").bind(id).resultValue();
|
||||
return utils::execSingleResultQuery(session.getDboSession()->find<TrackListEntry>().where("id = ?").bind(id));
|
||||
}
|
||||
} // namespace lms::db
|
||||
|
||||
@@ -28,8 +28,8 @@
|
||||
#include "StringViewTraits.hpp"
|
||||
#include "Utils.hpp"
|
||||
|
||||
namespace lms::db {
|
||||
|
||||
namespace lms::db
|
||||
{
|
||||
User::User(std::string_view loginName)
|
||||
: _loginName{ loginName }
|
||||
{
|
||||
@@ -37,47 +37,46 @@ namespace lms::db {
|
||||
|
||||
User::pointer User::create(Session& session, std::string_view loginName)
|
||||
{
|
||||
return session.getDboSession().add(std::unique_ptr<User> {new User{ loginName }});
|
||||
return session.getDboSession()->add(std::unique_ptr<User> {new User{ loginName }});
|
||||
}
|
||||
|
||||
std::size_t User::getCount(Session& session)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
return session.getDboSession().query<int>("SELECT COUNT(*) FROM user");
|
||||
return utils::execSingleResultQuery(session.getDboSession()->query<int>("SELECT COUNT(*) FROM user"));
|
||||
}
|
||||
|
||||
RangeResults<UserId> User::find(Session& session, const FindParameters& params)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
auto query{ session.getDboSession().query<UserId>("SELECT id FROM user") };
|
||||
auto query{ session.getDboSession()->query<UserId>("SELECT id FROM user") };
|
||||
|
||||
if (params.scrobblingBackend)
|
||||
query.where("scrobbling_backend = ?").bind(*params.scrobblingBackend);
|
||||
if (params.feedbackBackend)
|
||||
query.where("feedback_backend = ?").bind(*params.feedbackBackend);
|
||||
|
||||
return utils::execQuery<UserId>(query, params.range);
|
||||
return utils::execRangeQuery<UserId>(query, params.range);
|
||||
}
|
||||
|
||||
User::pointer User::findDemoUser(Session& session)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
return session.getDboSession().find<User>().where("type = ?").bind(UserType::DEMO).resultValue();
|
||||
return utils::execSingleResultQuery(session.getDboSession()->find<User>().where("type = ?").bind(UserType::DEMO));
|
||||
}
|
||||
|
||||
User::pointer User::find(Session& session, UserId id)
|
||||
{
|
||||
return session.getDboSession().find<User>().where("id = ?").bind(id).resultValue();
|
||||
return utils::execSingleResultQuery(session.getDboSession()->find<User>().where("id = ?").bind(id));
|
||||
}
|
||||
|
||||
User::pointer User::find(Session& session, std::string_view name)
|
||||
{
|
||||
return session.getDboSession().find<User>()
|
||||
.where("login_name = ?").bind(name)
|
||||
.resultValue();
|
||||
return utils::execSingleResultQuery(session.getDboSession()->find<User>()
|
||||
.where("login_name = ?").bind(name));
|
||||
}
|
||||
|
||||
void User::setSubsonicDefaultTranscodingOutputBitrate(Bitrate bitrate)
|
||||
|
||||
@@ -45,11 +45,23 @@ namespace lms::db::utils
|
||||
}
|
||||
}
|
||||
|
||||
template <typename ResultType, typename Query>
|
||||
RangeResults<ResultType> execQuery(Query& query, std::optional<Range> range)
|
||||
template <typename Query>
|
||||
auto execSingleResultQuery(const Query& query)
|
||||
{
|
||||
LMS_SCOPED_TRACE_DETAILED("Database", "ExecQueryRange");
|
||||
LMS_SCOPED_TRACE_DETAILED("Database", "ExecSingleResultQuery");
|
||||
return query.resultValue();
|
||||
}
|
||||
|
||||
template <typename Query>
|
||||
auto execMultiResultQuery(const Query& query)
|
||||
{
|
||||
LMS_SCOPED_TRACE_DETAILED("Database", "ExecMultiResultQuery");
|
||||
return query.resultList();
|
||||
}
|
||||
|
||||
template <typename ResultType, typename Query>
|
||||
RangeResults<ResultType> execRangeQuery(Query& query, std::optional<Range> range)
|
||||
{
|
||||
RangeResults<ResultType> res;
|
||||
|
||||
if (range)
|
||||
@@ -60,7 +72,7 @@ namespace lms::db::utils
|
||||
res.results.reserve(range->size);
|
||||
}
|
||||
|
||||
auto collection{ query.resultList() };
|
||||
auto collection{ execMultiResultQuery(query) };
|
||||
for (auto itResult{ collection.begin() }; itResult != collection.end(); ++itResult)
|
||||
{
|
||||
if (range && res.results.size() == range->size)
|
||||
@@ -78,20 +90,21 @@ namespace lms::db::utils
|
||||
}
|
||||
|
||||
template <typename ResultType, typename Query>
|
||||
void execQuery(Query& query, std::optional<Range> range, std::function<void(const ResultType&)> func)
|
||||
void execRangeQuery(Query& query, std::optional<Range> range, const std::function<void(const ResultType&)>& func)
|
||||
{
|
||||
if (range)
|
||||
applyRange(query, range);
|
||||
|
||||
for (const auto& res : query.resultList())
|
||||
auto collection{ execMultiResultQuery(query) };
|
||||
for (const auto& res : collection)
|
||||
{
|
||||
LMS_SCOPED_TRACE_DETAILED("Database", "ExecQueryResult");
|
||||
LMS_SCOPED_TRACE_DETAILED("Database", "ExecQueryRangeForEach");
|
||||
func(res);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename ResultType, typename Query>
|
||||
void execQuery(Query& query, std::optional<Range> range, bool& moreResults, std::function<void(const ResultType&)> func)
|
||||
void execRangeQuery(Query& query, std::optional<Range> range, bool& moreResults, const std::function<void(const ResultType&)>& func)
|
||||
{
|
||||
if (range)
|
||||
applyRange(query, Range{ range->offset, range->size + 1 });
|
||||
@@ -99,7 +112,8 @@ namespace lms::db::utils
|
||||
moreResults = false;
|
||||
|
||||
std::size_t count{};
|
||||
for (const auto& res : query.resultList())
|
||||
auto collection{ execMultiResultQuery(query) };
|
||||
for (const auto& res : collection)
|
||||
{
|
||||
if (range && (count++ == static_cast<std::size_t>(range->size)))
|
||||
{
|
||||
@@ -107,7 +121,7 @@ namespace lms::db::utils
|
||||
break;
|
||||
}
|
||||
|
||||
LMS_SCOPED_TRACE_DETAILED("Database", "ExecQueryResult");
|
||||
LMS_SCOPED_TRACE_DETAILED("Database", "ExecQueryRangeForEach");
|
||||
func(res);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user