Chaned the way the inner dbo session is accessed + added exec wrappers for queries

This commit is contained in:
emeric
2024-03-31 13:13:01 +02:00
parent 4ba8330194
commit 418286a1f2
19 changed files with 386 additions and 423 deletions
+18 -19
View File
@@ -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)
+21 -25
View File
@@ -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));
}
}
+27 -29
View File
@@ -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());
}
+33 -38
View File
@@ -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
+7 -6
View File
@@ -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);
}
+87 -87
View File
@@ -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)
+50 -69
View File
@@ -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)
+3 -2
View File
@@ -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
+7 -9
View File
@@ -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)
+7 -9
View File
@@ -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)
+11 -14
View File
@@ -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)
+30 -34
View File
@@ -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)
+8 -10
View File
@@ -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));
}
+8 -10
View File
@@ -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
+8 -10
View File
@@ -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
+21 -26
View File
@@ -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
+10 -11
View File
@@ -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)
+24 -10
View File
@@ -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);
}
}