Tracing: added some more details for db operations
This commit is contained in:
@@ -182,7 +182,7 @@ namespace lms::db
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
return utils::execSingleResultQuery(session.getDboSession()->query<int>("SELECT COUNT(*) FROM artist"));
|
||||
return utils::fetchQuerySingleResult(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)
|
||||
@@ -201,43 +201,38 @@ namespace lms::db
|
||||
query.where("t.media_library_id = ?").bind(library);
|
||||
}
|
||||
|
||||
auto collection{ utils::execMultiResultQuery(query) };
|
||||
|
||||
for (auto itResult{ collection.begin() }; itResult != collection.end(); ++itResult)
|
||||
{
|
||||
LMS_SCOPED_TRACE_DETAILED("Database", "ExecQueryRangeForEach");
|
||||
func(*itResult);
|
||||
lastRetrievedArtist = (*itResult)->getId();
|
||||
}
|
||||
utils::forEachQueryResult(query, [&](const Artist::pointer& artist)
|
||||
{
|
||||
func(artist);
|
||||
lastRetrievedArtist = artist->getId();
|
||||
});
|
||||
}
|
||||
|
||||
std::vector<Artist::pointer> Artist::find(Session& session, std::string_view name)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
Wt::Dbo::collection<Wt::Dbo::ptr<Artist>> res{ utils::execMultiResultQuery(session.getDboSession()->find<Artist>()
|
||||
return utils::fetchQueryResults<Artist::pointer>(session.getDboSession()->find<Artist>()
|
||||
.where("name = ?").bind(std::string{ name, 0, _maxNameLength })
|
||||
.orderBy("LENGTH(mbid) DESC")) }; // put mbid entries first
|
||||
|
||||
return std::vector<Artist::pointer>(res.begin(), res.end());
|
||||
.orderBy("LENGTH(mbid) DESC")); // put mbid entries first
|
||||
}
|
||||
|
||||
Artist::pointer Artist::find(Session& session, const core::UUID& mbid)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
return utils::execSingleResultQuery(session.getDboSession()->find<Artist>().where("mbid = ?").bind(std::string{ mbid.getAsString() }));
|
||||
return utils::fetchQuerySingleResult(session.getDboSession()->find<Artist>().where("mbid = ?").bind(std::string{ mbid.getAsString() }));
|
||||
}
|
||||
|
||||
Artist::pointer Artist::find(Session& session, ArtistId id)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
return utils::execSingleResultQuery(session.getDboSession()->find<Artist>().where("id = ?").bind(id));
|
||||
return utils::fetchQuerySingleResult(session.getDboSession()->find<Artist>().where("id = ?").bind(id));
|
||||
}
|
||||
|
||||
bool Artist::exists(Session& session, ArtistId id)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
return utils::execSingleResultQuery(session.getDboSession()->query<int>("SELECT 1 FROM artist").where("id = ?").bind(id)) == 1;
|
||||
return utils::fetchQuerySingleResult(session.getDboSession()->query<int>("SELECT 1 FROM artist").where("id = ?").bind(id)) == 1;
|
||||
}
|
||||
|
||||
RangeResults<ArtistId> Artist::findOrphanIds(Session& session, std::optional<Range> range)
|
||||
@@ -268,7 +263,7 @@ namespace lms::db
|
||||
session.checkReadTransaction();
|
||||
|
||||
auto query{ createQuery<Wt::Dbo::ptr<Artist>>(session, params) };
|
||||
utils::execRangeQuery(query, params.range, func);
|
||||
utils::forEachQueryRangeResult(query, params.range, func);
|
||||
}
|
||||
|
||||
RangeResults<ArtistId> Artist::findSimilarArtistIds(core::EnumSet<TrackArtistLinkType> artistLinkTypes, std::optional<Range> range) const
|
||||
@@ -343,14 +338,12 @@ namespace lms::db
|
||||
for (const std::string& bindArg : where.getBindArgs())
|
||||
query.bind(bindArg);
|
||||
|
||||
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)
|
||||
{
|
||||
if (clustersByType[cluster->getType()->getId()].size() < size)
|
||||
clustersByType[cluster->getType()->getId()].push_back(cluster);
|
||||
}
|
||||
utils::forEachQueryResult(query, [&](const Cluster::pointer& cluster)
|
||||
{
|
||||
if (clustersByType[cluster->getType()->getId()].size() < size)
|
||||
clustersByType[cluster->getType()->getId()].push_back(cluster);
|
||||
});
|
||||
|
||||
std::vector<std::vector<Cluster::pointer>> res;
|
||||
for (const auto& [clusterTypeId, clusters] : clustersByType)
|
||||
|
||||
@@ -28,7 +28,6 @@
|
||||
|
||||
namespace lms::db
|
||||
{
|
||||
|
||||
AuthToken::AuthToken(std::string_view value, const Wt::WDateTime& expiry, ObjectPtr<User> user)
|
||||
: _value{ value }
|
||||
, _expiry{ expiry }
|
||||
@@ -52,6 +51,6 @@ namespace lms::db
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
return utils::execSingleResultQuery(session.getDboSession()->find<AuthToken>().where("value = ?").bind(value));
|
||||
return utils::fetchQuerySingleResult(session.getDboSession()->find<AuthToken>().where("value = ?").bind(value));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -93,7 +93,7 @@ namespace lms::db
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
return utils::execSingleResultQuery(session.getDboSession()->query<int>("SELECT COUNT(*) FROM cluster"));
|
||||
return utils::fetchQuerySingleResult(session.getDboSession()->query<int>("SELECT COUNT(*) FROM cluster"));
|
||||
}
|
||||
|
||||
RangeResults<ClusterId> Cluster::findIds(Session& session, const FindParameters& params)
|
||||
@@ -124,14 +124,14 @@ namespace lms::db
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
return utils::execSingleResultQuery(session.getDboSession()->find<Cluster>().where("id = ?").bind(id));
|
||||
return utils::fetchQuerySingleResult(session.getDboSession()->find<Cluster>().where("id = ?").bind(id));
|
||||
}
|
||||
|
||||
std::size_t Cluster::computeTrackCount(Session& session, ClusterId id)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
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")
|
||||
return utils::fetchQuerySingleResult(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));
|
||||
}
|
||||
|
||||
@@ -139,7 +139,7 @@ namespace lms::db
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
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")
|
||||
return utils::fetchQuerySingleResult(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));
|
||||
}
|
||||
|
||||
@@ -172,7 +172,7 @@ namespace lms::db
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
return utils::execSingleResultQuery(session.getDboSession()->query<int>("SELECT COUNT(*) FROM cluster_type"));
|
||||
return utils::fetchQuerySingleResult(session.getDboSession()->query<int>("SELECT COUNT(*) FROM cluster_type"));
|
||||
}
|
||||
|
||||
RangeResults<ClusterTypeId> ClusterType::findOrphanIds(Session& session, std::optional<Range> range)
|
||||
@@ -202,14 +202,14 @@ namespace lms::db
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
return utils::execSingleResultQuery(session.getDboSession()->find<ClusterType>().where("name = ?").bind(std::string{ name }));
|
||||
return utils::fetchQuerySingleResult(session.getDboSession()->find<ClusterType>().where("name = ?").bind(std::string{ name }));
|
||||
}
|
||||
|
||||
ClusterType::pointer ClusterType::find(Session& session, ClusterTypeId id)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
return utils::execSingleResultQuery(session.getDboSession()->find<ClusterType>().where("id = ?").bind(id));
|
||||
return utils::fetchQuerySingleResult(session.getDboSession()->find<ClusterType>().where("id = ?").bind(id));
|
||||
}
|
||||
|
||||
RangeResults<ClusterTypeId> ClusterType::findIds(Session& session, std::optional<Range> range)
|
||||
@@ -226,7 +226,7 @@ namespace lms::db
|
||||
assert(self());
|
||||
assert(session());
|
||||
|
||||
return utils::execSingleResultQuery(session()->find<Cluster>()
|
||||
return utils::fetchQuerySingleResult(session()->find<Cluster>()
|
||||
.where("name = ?").bind(name)
|
||||
.where("cluster_type_id = ?").bind(getId()));
|
||||
}
|
||||
@@ -236,10 +236,8 @@ namespace lms::db
|
||||
assert(self());
|
||||
assert(session());
|
||||
|
||||
auto res{ utils::execMultiResultQuery(session()->find<Cluster>()
|
||||
return utils::fetchQueryResults<Cluster::pointer>(session()->find<Cluster>()
|
||||
.where("cluster_type_id = ?").bind(getId())
|
||||
.orderBy("name")) };
|
||||
|
||||
return std::vector<Cluster::pointer>(res.begin(), res.end());
|
||||
.orderBy("name"));
|
||||
}
|
||||
} // namespace lms::db
|
||||
|
||||
@@ -180,13 +180,13 @@ namespace lms::db
|
||||
std::size_t Listen::getCount(Session& session)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
return utils::execSingleResultQuery(session.getDboSession()->query<int>("SELECT COUNT(*) FROM listen"));
|
||||
return utils::fetchQuerySingleResult(session.getDboSession()->query<int>("SELECT COUNT(*) FROM listen"));
|
||||
}
|
||||
|
||||
Listen::pointer Listen::find(Session& session, ListenId id)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
return utils::execSingleResultQuery(session.getDboSession()->find<Listen>().where("id = ?").bind(id));
|
||||
return utils::fetchQuerySingleResult(session.getDboSession()->find<Listen>().where("id = ?").bind(id));
|
||||
}
|
||||
|
||||
RangeResults<ListenId> Listen::find(Session& session, const FindParameters& parameters)
|
||||
@@ -212,7 +212,7 @@ namespace lms::db
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
return utils::execSingleResultQuery(session.getDboSession()->find<Listen>()
|
||||
return utils::fetchQuerySingleResult(session.getDboSession()->find<Listen>()
|
||||
.where("user_id = ?").bind(userId)
|
||||
.where("track_id = ?").bind(trackId)
|
||||
.where("backend = ?").bind(backend)
|
||||
@@ -285,7 +285,7 @@ namespace lms::db
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
return utils::execSingleResultQuery(session.getDboSession()->query<int>("SELECT COUNT(*) from listen l")
|
||||
return utils::fetchQuerySingleResult(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)
|
||||
@@ -296,7 +296,7 @@ namespace lms::db
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
return utils::execSingleResultQuery(session.getDboSession()->query<int>(
|
||||
return utils::fetchQuerySingleResult(session.getDboSession()->query<int>(
|
||||
"SELECT IFNULL(MIN(count_result), 0)"
|
||||
" FROM ("
|
||||
" SELECT COUNT(l.track_id) AS count_result"
|
||||
@@ -314,7 +314,7 @@ namespace lms::db
|
||||
session.checkReadTransaction();
|
||||
|
||||
// TODO not pending remove?
|
||||
return utils::execSingleResultQuery(session.getDboSession()->query<Wt::Dbo::ptr<Listen>>("SELECT l from listen l")
|
||||
return utils::fetchQuerySingleResult(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)
|
||||
@@ -327,7 +327,7 @@ namespace lms::db
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
// TODO not pending remove?
|
||||
return utils::execSingleResultQuery(session.getDboSession()->query<Wt::Dbo::ptr<Listen>>("SELECT l from listen l")
|
||||
return utils::fetchQuerySingleResult(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)
|
||||
|
||||
@@ -44,36 +44,37 @@ namespace lms::db
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
return utils::execSingleResultQuery(session.getDboSession()->query<int>("SELECT COUNT(*) FROM media_library"));
|
||||
return utils::fetchQuerySingleResult(session.getDboSession()->query<int>("SELECT COUNT(*) FROM media_library"));
|
||||
}
|
||||
|
||||
MediaLibrary::pointer MediaLibrary::find(Session& session, MediaLibraryId id)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
return utils::execSingleResultQuery(session.getDboSession()->find<MediaLibrary>().where("id = ?").bind(id));
|
||||
return utils::fetchQuerySingleResult(session.getDboSession()->find<MediaLibrary>().where("id = ?").bind(id));
|
||||
}
|
||||
|
||||
MediaLibrary::pointer MediaLibrary::find(Session& session, std::string_view name)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
return utils::execSingleResultQuery(session.getDboSession()->find<MediaLibrary>().where("name = ?").bind(name));
|
||||
return utils::fetchQuerySingleResult(session.getDboSession()->find<MediaLibrary>().where("name = ?").bind(name));
|
||||
}
|
||||
|
||||
MediaLibrary::pointer MediaLibrary::find(Session& session, const std::filesystem::path& p)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
return utils::execSingleResultQuery(session.getDboSession()->find<MediaLibrary>().where("path = ?").bind(p));
|
||||
return utils::fetchQuerySingleResult(session.getDboSession()->find<MediaLibrary>().where("path = ?").bind(p));
|
||||
}
|
||||
|
||||
void MediaLibrary::find(Session& session, std::function<void(const MediaLibrary::pointer&)> func)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
auto results{ utils::execMultiResultQuery(session.getDboSession()->find<MediaLibrary>()) };
|
||||
for (const auto& result : results)
|
||||
func(result);
|
||||
utils::forEachQueryResult(session.getDboSession()->find<MediaLibrary>(), [&](const MediaLibrary::pointer& mediaLibrary)
|
||||
{
|
||||
func(mediaLibrary);
|
||||
});
|
||||
}
|
||||
} // namespace lms::db
|
||||
|
||||
@@ -213,7 +213,7 @@ namespace lms::db
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
return utils::execSingleResultQuery(session.getDboSession()->find<ReleaseType>()
|
||||
return utils::fetchQuerySingleResult(session.getDboSession()->find<ReleaseType>()
|
||||
.where("id = ?").bind(id));
|
||||
}
|
||||
|
||||
@@ -221,7 +221,7 @@ namespace lms::db
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
return utils::execSingleResultQuery(session.getDboSession()->find<ReleaseType>()
|
||||
return utils::fetchQuerySingleResult(session.getDboSession()->find<ReleaseType>()
|
||||
.where("name = ?").bind(name));
|
||||
}
|
||||
|
||||
@@ -240,19 +240,17 @@ namespace lms::db
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
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()) + "%"))};
|
||||
|
||||
return std::vector<Release::pointer>(res.begin(), res.end());
|
||||
return utils::fetchQueryResults<Release::pointer>(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()) + "%"));
|
||||
}
|
||||
|
||||
Release::pointer Release::find(Session& session, const core::UUID& mbid)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
return utils::execSingleResultQuery(session.getDboSession()->find<Release>()
|
||||
return utils::fetchQuerySingleResult(session.getDboSession()->find<Release>()
|
||||
.where("mbid = ?").bind(mbid.getAsString()));
|
||||
}
|
||||
|
||||
@@ -260,21 +258,21 @@ namespace lms::db
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
return utils::execSingleResultQuery(session.getDboSession()->find<Release>()
|
||||
return utils::fetchQuerySingleResult(session.getDboSession()->find<Release>()
|
||||
.where("id = ?").bind(id));
|
||||
}
|
||||
|
||||
bool Release::exists(Session& session, ReleaseId id)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
return utils::execSingleResultQuery(session.getDboSession()->query<int>("SELECT 1 FROM release").where("id = ?").bind(id)) == 1;
|
||||
return utils::fetchQuerySingleResult(session.getDboSession()->query<int>("SELECT 1 FROM release").where("id = ?").bind(id)) == 1;
|
||||
}
|
||||
|
||||
std::size_t Release::getCount(Session& session)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
return utils::execSingleResultQuery(session.getDboSession()->query<int>("SELECT COUNT(*) FROM release"));
|
||||
return utils::fetchQuerySingleResult(session.getDboSession()->query<int>("SELECT COUNT(*) FROM release"));
|
||||
}
|
||||
|
||||
RangeResults<ReleaseId> Release::findOrphanIds(Session& session, std::optional<Range> range)
|
||||
@@ -300,13 +298,11 @@ namespace lms::db
|
||||
query.where("t.media_library_id = ?").bind(library);
|
||||
}
|
||||
|
||||
auto collection{ utils::execMultiResultQuery(query) };
|
||||
for (auto itResult{ collection.begin() }; itResult != collection.end(); ++itResult)
|
||||
{
|
||||
LMS_SCOPED_TRACE_DETAILED("Database", "ExecQueryRangeForEach");
|
||||
func(*itResult);
|
||||
lastRetrievedRelease = (*itResult)->getId();
|
||||
}
|
||||
utils::forEachQueryResult(query, [&](const Release::pointer& release)
|
||||
{
|
||||
func(release);
|
||||
lastRetrievedRelease = release->getId();
|
||||
});
|
||||
}
|
||||
|
||||
RangeResults<Release::pointer> Release::find(Session& session, const FindParameters& params)
|
||||
@@ -317,12 +313,12 @@ namespace lms::db
|
||||
return utils::execRangeQuery<pointer>(query, params.range);
|
||||
}
|
||||
|
||||
void Release::find(Session& session, const FindParameters& params, std::function<void(const pointer&)> func)
|
||||
void Release::find(Session& session, const FindParameters& params, const std::function<void(const pointer&)>& func)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
auto query{ createQuery<Wt::Dbo::ptr<Release>>(session, "DISTINCT r", params) };
|
||||
utils::execRangeQuery<pointer>(query, params.range, func);
|
||||
utils::forEachQueryRangeResult(query, params.range, func);
|
||||
}
|
||||
|
||||
RangeResults<ReleaseId> Release::findIds(Session& session, const FindParameters& params)
|
||||
@@ -337,13 +333,13 @@ namespace lms::db
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
return utils::execSingleResultQuery(createQuery<int>(session, "COUNT(DISTINCT r.id)", params));
|
||||
return utils::fetchQuerySingleResult(createQuery<int>(session, "COUNT(DISTINCT r.id)", params));
|
||||
}
|
||||
|
||||
std::size_t Release::getDiscCount() const
|
||||
{
|
||||
assert(session());
|
||||
int res{ utils::execSingleResultQuery(session()->query<int>("SELECT COUNT(DISTINCT disc_number) FROM track t")
|
||||
int res{ utils::fetchQuerySingleResult(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())) };
|
||||
@@ -354,16 +350,20 @@ namespace lms::db
|
||||
std::vector<DiscInfo> Release::getDiscs() const
|
||||
{
|
||||
assert(session());
|
||||
|
||||
|
||||
using ResultType = std::tuple<int, std::string>;
|
||||
auto results{ utils::execMultiResultQuery(session()->query<ResultType>("SELECT DISTINCT disc_number, disc_subtitle FROM track t")
|
||||
const auto query{ 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()))};
|
||||
.bind(getId()) };
|
||||
|
||||
std::vector<DiscInfo> discs;
|
||||
for (const auto& res : results)
|
||||
discs.emplace_back(DiscInfo{ static_cast<std::size_t>(std::get<int>(res)), std::get<std::string>(res) });
|
||||
utils::forEachQueryResult(query, [&](ResultType&& res)
|
||||
{
|
||||
discs.emplace_back(DiscInfo{ static_cast<std::size_t>(std::get<int>(res)), std::move(std::get<std::string>(res)) });
|
||||
});
|
||||
|
||||
return discs;
|
||||
}
|
||||
@@ -383,13 +383,13 @@ namespace lms::db
|
||||
assert(session());
|
||||
|
||||
const char* field{ original ? "original_date" : "date" };
|
||||
|
||||
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")
|
||||
auto query{ (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())) };
|
||||
|
||||
const auto dates{ utils::fetchQueryResults(query) };
|
||||
|
||||
// various dates => invalid date
|
||||
if (dates.empty() || dates.size() > 1)
|
||||
return {};
|
||||
@@ -412,11 +412,11 @@ namespace lms::db
|
||||
assert(session());
|
||||
|
||||
const char* field{ original ? "original_year" : "year" };
|
||||
|
||||
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")
|
||||
auto query{ 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)) };
|
||||
.groupBy(field) };
|
||||
|
||||
const auto years{ utils::fetchQueryResults(query) };
|
||||
|
||||
// various years => invalid years
|
||||
const std::size_t count{ years.size() };
|
||||
@@ -430,44 +430,43 @@ namespace lms::db
|
||||
{
|
||||
assert(session());
|
||||
|
||||
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")
|
||||
auto query{ 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());
|
||||
const auto copyrights{ utils::fetchQueryResults(query) };
|
||||
|
||||
// various copyrights => no copyright
|
||||
if (values.empty() || values.size() > 1 || values.front().empty())
|
||||
if (copyrights.empty() || copyrights.size() > 1 || copyrights.front().empty())
|
||||
return std::nullopt;
|
||||
|
||||
return std::move(values.front());
|
||||
return std::move(copyrights.front());
|
||||
}
|
||||
|
||||
std::optional<std::string> Release::getCopyrightURL() const
|
||||
{
|
||||
assert(session());
|
||||
|
||||
Wt::Dbo::collection<std::string> copyrights {utils::execMultiResultQuery(session()->query<std::string>
|
||||
const auto query{ 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());
|
||||
const auto copyrights{ utils::fetchQueryResults(query) };
|
||||
|
||||
// various copyright URLs => no copyright URL
|
||||
if (values.empty() || values.size() > 1 || values.front().empty())
|
||||
if (copyrights.empty() || copyrights.size() > 1 || copyrights.front().empty())
|
||||
return std::nullopt;
|
||||
|
||||
return std::move(values.front());
|
||||
return std::move(copyrights.front());
|
||||
}
|
||||
|
||||
std::size_t Release::getMeanBitrate() const
|
||||
{
|
||||
assert(session());
|
||||
|
||||
return utils::execSingleResultQuery(session()->query<int>("SELECT COALESCE(AVG(t.bitrate), 0) FROM track t")
|
||||
return utils::fetchQuerySingleResult(session()->query<int>("SELECT COALESCE(AVG(t.bitrate), 0) FROM track t")
|
||||
.where("release_id = ?").bind(getId())
|
||||
.where("bitrate > 0"));
|
||||
}
|
||||
@@ -476,15 +475,15 @@ namespace lms::db
|
||||
{
|
||||
assert(session());
|
||||
|
||||
auto res{ utils::execMultiResultQuery(session()->query<Wt::Dbo::ptr<Artist>>(
|
||||
const auto query{ 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))};
|
||||
.where("t_a_l.type = ?").bind(linkType) };
|
||||
|
||||
return std::vector<Artist::pointer>(res.begin(), res.end());
|
||||
return utils::fetchQueryResults<Artist::pointer>(query);
|
||||
}
|
||||
|
||||
std::vector<Release::pointer> Release::getSimilarReleases(std::optional<std::size_t> offset, std::optional<std::size_t> count) const
|
||||
@@ -492,7 +491,7 @@ namespace lms::db
|
||||
assert(session());
|
||||
|
||||
// Select the similar releases using the 5 most used clusters of the release
|
||||
auto res{ utils::execMultiResultQuery(session()->query<Wt::Dbo::ptr<Release>>(
|
||||
auto query{ 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"
|
||||
@@ -510,9 +509,9 @@ namespace lms::db
|
||||
.groupBy("r.id")
|
||||
.orderBy("COUNT(*) DESC, RANDOM()")
|
||||
.limit(count ? static_cast<int>(*count) : -1)
|
||||
.offset(offset ? static_cast<int>(*offset) : -1))};
|
||||
.offset(offset ? static_cast<int>(*offset) : -1) };
|
||||
|
||||
return std::vector<pointer>(res.begin(), res.end());
|
||||
return utils::fetchQueryResults<Release::pointer>(query);
|
||||
}
|
||||
|
||||
void Release::clearReleaseTypes()
|
||||
@@ -538,6 +537,7 @@ namespace lms::db
|
||||
|
||||
std::vector<ObjectPtr<ReleaseType>> Release::getReleaseTypes() const
|
||||
{
|
||||
// TODO remove?
|
||||
return std::vector<ObjectPtr<ReleaseType>>(_releaseTypes.begin(), _releaseTypes.end());
|
||||
}
|
||||
|
||||
@@ -557,7 +557,7 @@ namespace lms::db
|
||||
|
||||
using milli = std::chrono::duration<int, std::milli>;
|
||||
|
||||
return utils::execSingleResultQuery(session()->query<milli>("SELECT COALESCE(SUM(duration), 0) FROM track t INNER JOIN release r ON t.release_id = r.id")
|
||||
return utils::fetchQuerySingleResult(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()));
|
||||
}
|
||||
|
||||
@@ -565,7 +565,7 @@ namespace lms::db
|
||||
{
|
||||
assert(session());
|
||||
|
||||
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")
|
||||
return utils::fetchQuerySingleResult(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()));
|
||||
}
|
||||
|
||||
@@ -593,14 +593,12 @@ namespace lms::db
|
||||
for (const std::string& bindArg : where.getBindArgs())
|
||||
query.bind(bindArg);
|
||||
|
||||
auto queryRes{ utils::execMultiResultQuery(query) };
|
||||
|
||||
std::map<ClusterTypeId, std::vector<Cluster::pointer>> clustersByType;
|
||||
for (const Wt::Dbo::ptr<Cluster>& cluster : queryRes)
|
||||
{
|
||||
if (clustersByType[cluster->getType()->getId()].size() < size)
|
||||
clustersByType[cluster->getType()->getId()].push_back(cluster);
|
||||
}
|
||||
utils::forEachQueryResult(query, [&](const Cluster::pointer& cluster)
|
||||
{
|
||||
if (clustersByType[cluster->getType()->getId()].size() < size)
|
||||
clustersByType[cluster->getType()->getId()].push_back(cluster);
|
||||
});
|
||||
|
||||
std::vector<std::vector<Cluster::pointer>> res;
|
||||
for (const auto& [clusterTypeId, clusters] : clustersByType)
|
||||
|
||||
@@ -42,7 +42,7 @@ namespace lms::db
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
return utils::execSingleResultQuery(session.getDboSession()->find<ScanSettings>());
|
||||
return utils::fetchQuerySingleResult(session.getDboSession()->find<ScanSettings>());
|
||||
}
|
||||
|
||||
std::vector<std::filesystem::path> ScanSettings::getAudioFileExtensions() const
|
||||
|
||||
@@ -44,19 +44,19 @@ namespace lms::db
|
||||
std::size_t StarredArtist::getCount(Session& session)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
return utils::execSingleResultQuery(session.getDboSession()->query<int>("SELECT COUNT(*) FROM starred_artist"));
|
||||
return utils::fetchQuerySingleResult(session.getDboSession()->query<int>("SELECT COUNT(*) FROM starred_artist"));
|
||||
}
|
||||
|
||||
StarredArtist::pointer StarredArtist::find(Session& session, StarredArtistId id)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
return utils::execSingleResultQuery(session.getDboSession()->find<StarredArtist>().where("id = ?").bind(id));
|
||||
return utils::fetchQuerySingleResult(session.getDboSession()->find<StarredArtist>().where("id = ?").bind(id));
|
||||
}
|
||||
|
||||
StarredArtist::pointer StarredArtist::find(Session& session, ArtistId artistId, UserId userId)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
return utils::execSingleResultQuery(session.getDboSession()->query<Wt::Dbo::ptr<StarredArtist>>("SELECT s_a from starred_artist s_a")
|
||||
return utils::fetchQuerySingleResult(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)
|
||||
@@ -66,7 +66,7 @@ namespace lms::db
|
||||
StarredArtist::pointer StarredArtist::find(Session& session, ArtistId artistId, UserId userId, FeedbackBackend backend)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
return utils::execSingleResultQuery(session.getDboSession()->find<StarredArtist>()
|
||||
return utils::fetchQuerySingleResult(session.getDboSession()->find<StarredArtist>()
|
||||
.where("artist_id = ?").bind(artistId)
|
||||
.where("user_id = ?").bind(userId)
|
||||
.where("backend = ?").bind(backend));
|
||||
|
||||
@@ -50,13 +50,13 @@ namespace lms::db
|
||||
StarredRelease::pointer StarredRelease::find(Session& session, StarredReleaseId id)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
return utils::execSingleResultQuery(session.getDboSession()->find<StarredRelease>().where("id = ?").bind(id));
|
||||
return utils::fetchQuerySingleResult(session.getDboSession()->find<StarredRelease>().where("id = ?").bind(id));
|
||||
}
|
||||
|
||||
StarredRelease::pointer StarredRelease::find(Session& session, ReleaseId releaseId, UserId userId)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
return utils::execSingleResultQuery(session.getDboSession()->query<Wt::Dbo::ptr<StarredRelease>>("SELECT s_r from starred_release s_r")
|
||||
return utils::fetchQuerySingleResult(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)
|
||||
@@ -66,7 +66,7 @@ namespace lms::db
|
||||
StarredRelease::pointer StarredRelease::find(Session& session, ReleaseId releaseId, UserId userId, FeedbackBackend backend)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
return utils::execSingleResultQuery(session.getDboSession()->find<StarredRelease>()
|
||||
return utils::fetchQuerySingleResult(session.getDboSession()->find<StarredRelease>()
|
||||
.where("release_id = ?").bind(releaseId)
|
||||
.where("user_id = ?").bind(userId)
|
||||
.where("backend = ?").bind(backend));
|
||||
|
||||
@@ -44,19 +44,19 @@ namespace lms::db
|
||||
std::size_t StarredTrack::getCount(Session& session)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
return utils::execSingleResultQuery(session.getDboSession()->query<int>("SELECT COUNT(*) FROM starred_track"));
|
||||
return utils::fetchQuerySingleResult(session.getDboSession()->query<int>("SELECT COUNT(*) FROM starred_track"));
|
||||
}
|
||||
|
||||
StarredTrack::pointer StarredTrack::find(Session& session, StarredTrackId id)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
return utils::execSingleResultQuery(session.getDboSession()->find<StarredTrack>().where("id = ?").bind(id));
|
||||
return utils::fetchQuerySingleResult(session.getDboSession()->find<StarredTrack>().where("id = ?").bind(id));
|
||||
}
|
||||
|
||||
StarredTrack::pointer StarredTrack::find(Session& session, TrackId trackId, UserId userId)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
return utils::execSingleResultQuery(session.getDboSession()->query<Wt::Dbo::ptr<StarredTrack>>("SELECT s_t from starred_track s_t")
|
||||
return utils::fetchQuerySingleResult(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)
|
||||
@@ -66,7 +66,7 @@ namespace lms::db
|
||||
StarredTrack::pointer StarredTrack::find(Session& session, TrackId trackId, UserId userId, FeedbackBackend backend)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
return utils::execSingleResultQuery(session.getDboSession()->find<StarredTrack>()
|
||||
return utils::fetchQuerySingleResult(session.getDboSession()->find<StarredTrack>()
|
||||
.where("track_id = ?").bind(trackId)
|
||||
.where("user_id = ?").bind(userId)
|
||||
.where("backend = ?").bind(backend));
|
||||
@@ -74,7 +74,7 @@ namespace lms::db
|
||||
|
||||
bool StarredTrack::exists(Session& session, TrackId trackId, UserId userId, FeedbackBackend backend)
|
||||
{
|
||||
return utils::execSingleResultQuery(session.getDboSession()->query<int>("SELECT 1 from starred_track")
|
||||
return utils::fetchQuerySingleResult(session.getDboSession()->query<int>("SELECT 1 from starred_track")
|
||||
.where("track_id = ?").bind(trackId)
|
||||
.where("user_id = ?").bind(userId)
|
||||
.where("backend = ?").bind(backend));
|
||||
|
||||
@@ -178,12 +178,12 @@ namespace lms::db
|
||||
|
||||
return query;
|
||||
}
|
||||
|
||||
|
||||
template <typename ResultType>
|
||||
Wt::Dbo::Query<ResultType> createQuery(Session& session, const Track::FindParameters& params)
|
||||
{
|
||||
std::string_view itemToSelect;
|
||||
|
||||
|
||||
if constexpr (std::is_same_v<ResultType, TrackId>)
|
||||
itemToSelect = "t.id";
|
||||
else if constexpr (std::is_same_v<ResultType, Wt::Dbo::ptr<Track>>)
|
||||
@@ -209,21 +209,21 @@ namespace lms::db
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
return utils::execSingleResultQuery(session.getDboSession()->query<int>("SELECT COUNT(*) FROM track"));
|
||||
return utils::fetchQuerySingleResult(session.getDboSession()->query<int>("SELECT COUNT(*) FROM track"));
|
||||
}
|
||||
|
||||
Track::pointer Track::findByPath(Session& session, const std::filesystem::path& p)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
return utils::execSingleResultQuery(session.getDboSession()->find<Track>().where("file_path = ?").bind(p.string()));
|
||||
return utils::fetchQuerySingleResult(session.getDboSession()->find<Track>().where("file_path = ?").bind(p.string()));
|
||||
}
|
||||
|
||||
Track::pointer Track::find(Session& session, TrackId id)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
return utils::execSingleResultQuery(session.getDboSession()->find<Track>()
|
||||
return utils::fetchQuerySingleResult(session.getDboSession()->find<Track>()
|
||||
.where("id = ?").bind(id));
|
||||
}
|
||||
|
||||
@@ -239,41 +239,34 @@ namespace lms::db
|
||||
if (library.isValid())
|
||||
query.where("media_library_id = ?").bind(library);
|
||||
|
||||
auto collection{ utils::execMultiResultQuery(query) };
|
||||
|
||||
for (auto itResult{ collection.begin() }; itResult != collection.end(); ++itResult)
|
||||
{
|
||||
LMS_SCOPED_TRACE_DETAILED("Database", "ExecQueryRangeForEach");
|
||||
func(*itResult);
|
||||
lastRetrievedTrack = (*itResult)->getId();
|
||||
}
|
||||
utils::forEachQueryResult(query, [&](const Track::pointer& track)
|
||||
{
|
||||
func(track);
|
||||
lastRetrievedTrack = track->getId();
|
||||
});
|
||||
}
|
||||
|
||||
bool Track::exists(Session& session, TrackId id)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
return utils::execSingleResultQuery(session.getDboSession()->query<int>("SELECT 1 from track").where("id = ?").bind(id)) == 1;
|
||||
return utils::fetchQuerySingleResult(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{ utils::execMultiResultQuery(session.getDboSession()->find<Track>()
|
||||
.where("mbid = ?").bind(std::string {mbid.getAsString()})) };
|
||||
|
||||
return std::vector<Track::pointer>(res.begin(), res.end());
|
||||
return utils::fetchQueryResults<Track::pointer>(session.getDboSession()->find<Track>()
|
||||
.where("mbid = ?").bind(mbid.getAsString()));
|
||||
}
|
||||
|
||||
std::vector<Track::pointer> Track::findByRecordingMBID(Session& session, const core::UUID& mbid)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
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());
|
||||
return utils::fetchQueryResults<Track::pointer>(session.getDboSession()->find<Track>()
|
||||
.where("recording_mbid = ?").bind(mbid.getAsString()));
|
||||
}
|
||||
|
||||
RangeResults<Track::PathResult> Track::findPaths(Session& session, std::optional<Range> range)
|
||||
@@ -330,11 +323,11 @@ namespace lms::db
|
||||
{
|
||||
assert(session());
|
||||
|
||||
auto res{ utils::execMultiResultQuery(session()->query<ClusterId>
|
||||
const auto query{ 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())) };
|
||||
.where("t.id = ?").bind(getId()) };
|
||||
|
||||
return std::vector<ClusterId>(res.begin(), res.end());
|
||||
return utils::fetchQueryResults(query);
|
||||
}
|
||||
|
||||
RangeResults<TrackId> Track::findIds(Session& session, const FindParameters& parameters)
|
||||
@@ -353,20 +346,20 @@ namespace lms::db
|
||||
return utils::execRangeQuery<Track::pointer>(query, parameters.range);
|
||||
}
|
||||
|
||||
void Track::find(Session& session, const FindParameters& params, std::function<void(const Track::pointer&)> func)
|
||||
void Track::find(Session& session, const FindParameters& params, const std::function<void(const Track::pointer&)>& func)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
auto query{ createQuery<Wt::Dbo::ptr<Track>>(session, params)};
|
||||
utils::execRangeQuery(query, params.range, func);
|
||||
auto query{ createQuery<Wt::Dbo::ptr<Track>>(session, params) };
|
||||
utils::forEachQueryRangeResult(query, params.range, func);
|
||||
}
|
||||
|
||||
void Track::find(Session& session, const FindParameters& params, bool& moreResults, std::function<void(const Track::pointer&)> func)
|
||||
void Track::find(Session& session, const FindParameters& params, bool& moreResults, const std::function<void(const Track::pointer&)>& func)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
auto query{ createQuery<Wt::Dbo::ptr<Track>>(session, params)};
|
||||
utils::execRangeQuery(query, params.range, moreResults, func);
|
||||
auto query{ createQuery<Wt::Dbo::ptr<Track>>(session, params) };
|
||||
utils::forEachQueryRangeResult(query, params.range, moreResults, func);
|
||||
}
|
||||
|
||||
RangeResults<TrackId> Track::findSimilarTrackIds(Session& session, const std::vector<TrackId>& tracks, std::optional<Range> range)
|
||||
@@ -457,8 +450,7 @@ namespace lms::db
|
||||
|
||||
query.where("t.id = ?").bind(getId());
|
||||
|
||||
auto res{ utils::execMultiResultQuery(query) };
|
||||
return std::vector<Artist::pointer>(std::begin(res), std::end(res));
|
||||
return utils::fetchQueryResults<Artist::pointer>(query);
|
||||
}
|
||||
|
||||
std::vector<ArtistId> Track::getArtistIds(core::EnumSet<TrackArtistLinkType> linkTypes) const
|
||||
@@ -493,8 +485,7 @@ namespace lms::db
|
||||
|
||||
query.where("t.id = ?").bind(getId());
|
||||
|
||||
auto res{ utils::execMultiResultQuery(query) };
|
||||
return std::vector<ArtistId>(std::cbegin(res), std::cend(res));
|
||||
return utils::fetchQueryResults(query);
|
||||
}
|
||||
|
||||
std::vector<TrackArtistLink::pointer> Track::getArtistLinks() const
|
||||
@@ -527,14 +518,12 @@ namespace lms::db
|
||||
for (const std::string& bindArg : where.getBindArgs())
|
||||
query.bind(bindArg);
|
||||
|
||||
auto queryRes{ utils::execMultiResultQuery(query) };
|
||||
|
||||
std::map<ClusterTypeId, std::vector<Cluster::pointer>> clusters;
|
||||
for (const Wt::Dbo::ptr<Cluster>& cluster : queryRes)
|
||||
{
|
||||
if (clusters[cluster->getType()->getId()].size() < size)
|
||||
clusters[cluster->getType()->getId()].push_back(cluster);
|
||||
}
|
||||
utils::forEachQueryResult(query, [&](const Cluster::pointer& cluster)
|
||||
{
|
||||
if (clusters[cluster->getType()->getId()].size() < size)
|
||||
clusters[cluster->getType()->getId()].push_back(cluster);
|
||||
});
|
||||
|
||||
std::vector<std::vector<Cluster::pointer>> res;
|
||||
for (const auto& [type, clusters] : clusters)
|
||||
|
||||
@@ -76,7 +76,7 @@ namespace lms::db
|
||||
TrackArtistLink::pointer TrackArtistLink::find(Session& session, TrackArtistLinkId id)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
return utils::execSingleResultQuery(session.getDboSession()->find<TrackArtistLink>().where("id = ?").bind(id));
|
||||
return utils::fetchQuerySingleResult(session.getDboSession()->find<TrackArtistLink>().where("id = ?").bind(id));
|
||||
}
|
||||
|
||||
RangeResults<TrackArtistLinkId> TrackArtistLink::find(Session& session, const FindParameters& params)
|
||||
@@ -91,19 +91,28 @@ namespace lms::db
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
auto res{ utils::execMultiResultQuery(session.getDboSession()->query<TrackArtistLinkType>("SELECT DISTINCT type from track_artist_link")) };
|
||||
const auto query{ session.getDboSession()->query<TrackArtistLinkType>("SELECT DISTINCT type from track_artist_link") };
|
||||
|
||||
return core::EnumSet<TrackArtistLinkType>(std::begin(res), std::end(res));
|
||||
core::EnumSet<TrackArtistLinkType> res;
|
||||
utils::forEachQueryResult(query, [&](TrackArtistLinkType linkType)
|
||||
{
|
||||
res.insert(linkType);
|
||||
});
|
||||
return res;
|
||||
}
|
||||
|
||||
core::EnumSet<TrackArtistLinkType> TrackArtistLink::findUsedTypes(Session& session, ArtistId artistId)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
auto res{ utils::execMultiResultQuery(session.getDboSession()->query<TrackArtistLinkType>("SELECT DISTINCT type from track_artist_link")
|
||||
.where("artist_id = ?").bind(artistId)) };
|
||||
const auto query{ 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));
|
||||
core::EnumSet<TrackArtistLinkType> res;
|
||||
utils::forEachQueryResult(query, [&](TrackArtistLinkType linkType)
|
||||
{
|
||||
res.insert(linkType);
|
||||
});
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@ namespace lms::db
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
return utils::execSingleResultQuery(session.getDboSession()->query<int>("SELECT COUNT(*) FROM track_bookmark"));
|
||||
return utils::fetchQuerySingleResult(session.getDboSession()->query<int>("SELECT COUNT(*) FROM track_bookmark"));
|
||||
}
|
||||
|
||||
RangeResults<TrackBookmarkId> TrackBookmark::find(Session& session, UserId userId, std::optional<Range> range)
|
||||
@@ -59,7 +59,7 @@ namespace lms::db
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
return utils::execSingleResultQuery(session.getDboSession()->find<TrackBookmark>()
|
||||
return utils::fetchQuerySingleResult(session.getDboSession()->find<TrackBookmark>()
|
||||
.where("user_id = ?").bind(userId)
|
||||
.where("track_id = ?").bind(trackId));
|
||||
}
|
||||
@@ -68,7 +68,7 @@ namespace lms::db
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
return utils::execSingleResultQuery(session.getDboSession()->find<TrackBookmark>()
|
||||
return utils::fetchQuerySingleResult(session.getDboSession()->find<TrackBookmark>()
|
||||
.where("id = ?").bind(id));
|
||||
}
|
||||
|
||||
|
||||
@@ -45,14 +45,14 @@ namespace lms::db {
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
return utils::execSingleResultQuery(session.getDboSession()->query<int>("SELECT COUNT(*) FROM track_features"));
|
||||
return utils::fetchQuerySingleResult(session.getDboSession()->query<int>("SELECT COUNT(*) FROM track_features"));
|
||||
}
|
||||
|
||||
TrackFeatures::pointer TrackFeatures::find(Session& session, TrackFeaturesId id)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
return utils::execSingleResultQuery(session.getDboSession()->find<TrackFeatures>()
|
||||
return utils::fetchQuerySingleResult(session.getDboSession()->find<TrackFeatures>()
|
||||
.where("id = ?").bind(id));
|
||||
}
|
||||
|
||||
@@ -60,7 +60,7 @@ namespace lms::db {
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
return utils::execSingleResultQuery(session.getDboSession()->find<TrackFeatures>()
|
||||
return utils::fetchQuerySingleResult(session.getDboSession()->find<TrackFeatures>()
|
||||
.where("track_id = ?").bind(trackId));
|
||||
}
|
||||
|
||||
|
||||
@@ -55,7 +55,7 @@ namespace lms::db
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
return utils::execSingleResultQuery(session.getDboSession()->query<int>("SELECT COUNT(*) FROM tracklist"));
|
||||
return utils::fetchQuerySingleResult(session.getDboSession()->query<int>("SELECT COUNT(*) FROM tracklist"));
|
||||
}
|
||||
|
||||
|
||||
@@ -64,7 +64,7 @@ namespace lms::db
|
||||
session.checkReadTransaction();
|
||||
assert(userId.isValid());
|
||||
|
||||
return utils::execSingleResultQuery(session.getDboSession()->find<TrackList>()
|
||||
return utils::fetchQuerySingleResult(session.getDboSession()->find<TrackList>()
|
||||
.where("name = ?").bind(name)
|
||||
.where("type = ?").bind(type)
|
||||
.where("user_id = ?").bind(userId));
|
||||
@@ -124,7 +124,7 @@ namespace lms::db
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
return utils::execSingleResultQuery(session.getDboSession()->find<TrackList>().where("id = ?").bind(id));
|
||||
return utils::fetchQuerySingleResult(session.getDboSession()->find<TrackList>().where("id = ?").bind(id));
|
||||
}
|
||||
|
||||
bool TrackList::isEmpty() const
|
||||
@@ -163,7 +163,7 @@ namespace lms::db
|
||||
{
|
||||
assert(session());
|
||||
|
||||
return utils::execSingleResultQuery(session()->find<TrackListEntry>()
|
||||
return utils::fetchQuerySingleResult(session()->find<TrackListEntry>()
|
||||
.where("tracklist_id = ?").bind(getId())
|
||||
.where("track_id = ?").bind(track->getId())
|
||||
.where("date_time = ?").bind(utils::normalizeDateTime(dateTime)));
|
||||
@@ -173,12 +173,12 @@ namespace lms::db
|
||||
{
|
||||
assert(session());
|
||||
|
||||
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")
|
||||
const auto query{ 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")) };
|
||||
.orderBy("COUNT(c.id) DESC") };
|
||||
|
||||
return std::vector<Cluster::pointer>(res.begin(), res.end());
|
||||
return utils::fetchQueryResults<Cluster::pointer>(query);
|
||||
}
|
||||
|
||||
std::vector<std::vector<Cluster::pointer>> TrackList::getClusterGroups(const std::vector<ClusterTypeId>& clusterTypeIds, std::size_t size) const
|
||||
@@ -216,14 +216,12 @@ namespace lms::db
|
||||
query.groupBy("c.id");
|
||||
query.orderBy("COUNT(c.id) DESC");
|
||||
|
||||
auto queryRes{ utils::execMultiResultQuery(query) };
|
||||
|
||||
std::map<ClusterTypeId, std::vector<Cluster::pointer>> clustersByType;
|
||||
for (const Wt::Dbo::ptr<Cluster>& cluster : queryRes)
|
||||
{
|
||||
if (clustersByType[cluster->getType()->getId()].size() < size)
|
||||
clustersByType[cluster->getType()->getId()].push_back(cluster);
|
||||
}
|
||||
utils::forEachQueryResult(query, [&](const Cluster::pointer& cluster)
|
||||
{
|
||||
if (clustersByType[cluster->getType()->getId()].size() < size)
|
||||
clustersByType[cluster->getType()->getId()].push_back(cluster);
|
||||
});
|
||||
|
||||
for (const auto& [clusterTypeId, clusters] : clustersByType)
|
||||
res.push_back(clusters);
|
||||
@@ -235,7 +233,7 @@ namespace lms::db
|
||||
{
|
||||
assert(session());
|
||||
|
||||
auto res{ utils::execMultiResultQuery(session()->query<Wt::Dbo::ptr<Track>>(
|
||||
auto query{ 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 "
|
||||
@@ -247,19 +245,19 @@ namespace lms::db
|
||||
.groupBy("t.id")
|
||||
.orderBy("COUNT(*) DESC, RANDOM()")
|
||||
.limit(size ? static_cast<int>(*size) : -1)
|
||||
.offset(offset ? static_cast<int>(*offset) : -1))};
|
||||
.offset(offset ? static_cast<int>(*offset) : -1) };
|
||||
|
||||
return std::vector<Track::pointer>(res.begin(), res.end());
|
||||
return utils::fetchQueryResults<Track::pointer>(query);
|
||||
}
|
||||
|
||||
std::vector<TrackId> TrackList::getTrackIds() const
|
||||
{
|
||||
assert(session());
|
||||
|
||||
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())) };
|
||||
auto query{ 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());
|
||||
return utils::fetchQueryResults(query);
|
||||
}
|
||||
|
||||
std::chrono::milliseconds TrackList::getDuration() const
|
||||
@@ -268,7 +266,7 @@ namespace lms::db
|
||||
|
||||
using milli = std::chrono::duration<int, std::milli>;
|
||||
|
||||
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")
|
||||
return utils::fetchQuerySingleResult(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()));
|
||||
}
|
||||
|
||||
@@ -305,6 +303,6 @@ namespace lms::db
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
return utils::execSingleResultQuery(session.getDboSession()->find<TrackListEntry>().where("id = ?").bind(id));
|
||||
return utils::fetchQuerySingleResult(session.getDboSession()->find<TrackListEntry>().where("id = ?").bind(id));
|
||||
}
|
||||
} // namespace lms::db
|
||||
|
||||
@@ -44,7 +44,7 @@ namespace lms::db
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
return utils::execSingleResultQuery(session.getDboSession()->query<int>("SELECT COUNT(*) FROM user"));
|
||||
return utils::fetchQuerySingleResult(session.getDboSession()->query<int>("SELECT COUNT(*) FROM user"));
|
||||
}
|
||||
|
||||
RangeResults<UserId> User::find(Session& session, const FindParameters& params)
|
||||
@@ -65,17 +65,17 @@ namespace lms::db
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
return utils::execSingleResultQuery(session.getDboSession()->find<User>().where("type = ?").bind(UserType::DEMO));
|
||||
return utils::fetchQuerySingleResult(session.getDboSession()->find<User>().where("type = ?").bind(UserType::DEMO));
|
||||
}
|
||||
|
||||
User::pointer User::find(Session& session, UserId id)
|
||||
{
|
||||
return utils::execSingleResultQuery(session.getDboSession()->find<User>().where("id = ?").bind(id));
|
||||
return utils::fetchQuerySingleResult(session.getDboSession()->find<User>().where("id = ?").bind(id));
|
||||
}
|
||||
|
||||
User::pointer User::find(Session& session, std::string_view name)
|
||||
{
|
||||
return utils::execSingleResultQuery(session.getDboSession()->find<User>()
|
||||
return utils::fetchQuerySingleResult(session.getDboSession()->find<User>()
|
||||
.where("login_name = ?").bind(name));
|
||||
}
|
||||
|
||||
|
||||
@@ -45,22 +45,74 @@ namespace lms::db::utils
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Query>
|
||||
auto execSingleResultQuery(const Query& query)
|
||||
template <typename T>
|
||||
auto fetchFirstResult(const Wt::Dbo::collection<T>& collection)
|
||||
{
|
||||
LMS_SCOPED_TRACE_DETAILED_WITH_ARG("Database", "ExecSingleResultQuery", "Query", query.asString());
|
||||
LMS_SCOPED_TRACE_DETAILED("Database", "FetchFirstResult");
|
||||
return collection.begin();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void fetchNextResult(typename Wt::Dbo::collection<T>::const_iterator& it)
|
||||
{
|
||||
LMS_SCOPED_TRACE_DETAILED("Database", "FetchNextResult");
|
||||
it++;
|
||||
}
|
||||
|
||||
template <typename T, typename Func>
|
||||
void forEachResult(const Wt::Dbo::collection<T>& collection, Func&& func)
|
||||
{
|
||||
typename Wt::Dbo::collection<T>::const_iterator it{ fetchFirstResult(collection) };
|
||||
while (it != collection.end())
|
||||
{
|
||||
func(*it);
|
||||
fetchNextResult<T>(it);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
struct QueryResultType;
|
||||
|
||||
template <class ResultType, typename BindStrategy>
|
||||
struct QueryResultType<Wt::Dbo::Query<ResultType, BindStrategy>>
|
||||
{
|
||||
using type = ResultType;
|
||||
};
|
||||
|
||||
template <typename Query, typename UnaryFunc>
|
||||
void forEachQueryResult(const Query& query, UnaryFunc&& func)
|
||||
{
|
||||
LMS_SCOPED_TRACE_DETAILED_WITH_ARG("Database", "ForEachQueryResult", "Query", query.asString());
|
||||
forEachResult(query.resultList(), std::forward<UnaryFunc>(func));
|
||||
}
|
||||
|
||||
template <typename T, typename Query>
|
||||
std::vector<T> fetchQueryResults(const Query& query)
|
||||
{
|
||||
LMS_SCOPED_TRACE_DETAILED_WITH_ARG("Database", "FetchQueryResults", "Query", query.asString());
|
||||
|
||||
auto collection{ query.resultList() };
|
||||
return std::vector<T>(collection.begin(), collection.end());
|
||||
}
|
||||
|
||||
template <typename Query>
|
||||
std::vector<typename QueryResultType<Query>::type> fetchQueryResults(const Query& query)
|
||||
{
|
||||
LMS_SCOPED_TRACE_DETAILED_WITH_ARG("Database", "FetchQueryResults", "Query", query.asString());
|
||||
|
||||
auto collection{ query.resultList() };
|
||||
return std::vector<typename QueryResultType<Query>::type>(collection.begin(), collection.end());
|
||||
}
|
||||
|
||||
template <typename Query>
|
||||
auto fetchQuerySingleResult(const Query& query)
|
||||
{
|
||||
LMS_SCOPED_TRACE_DETAILED_WITH_ARG("Database", "FetchQuerySingleResult", "Query", query.asString());
|
||||
return query.resultValue();
|
||||
}
|
||||
|
||||
template <typename Query>
|
||||
auto execMultiResultQuery(const Query& query)
|
||||
{
|
||||
LMS_SCOPED_TRACE_DETAILED_WITH_ARG("Database", "ExecMultiResultQuery", "Query", query.asString());
|
||||
return query.resultList();
|
||||
}
|
||||
|
||||
template <typename ResultType, typename Query>
|
||||
RangeResults<ResultType> execRangeQuery(Query& query, std::optional<Range> range)
|
||||
RangeResults<ResultType> execRangeQuery(Query& query, const std::optional<Range> range)
|
||||
{
|
||||
RangeResults<ResultType> res;
|
||||
|
||||
@@ -72,16 +124,12 @@ namespace lms::db::utils
|
||||
res.results.reserve(range->size);
|
||||
}
|
||||
|
||||
auto collection{ execMultiResultQuery(query) };
|
||||
for (auto itResult{ collection.begin() }; itResult != collection.end(); ++itResult)
|
||||
// TODO optim useless last copy
|
||||
res.results = utils::fetchQueryResults<ResultType>(query);
|
||||
if (range && (res.results.size() == range->size + 1))
|
||||
{
|
||||
if (range && res.results.size() == range->size)
|
||||
{
|
||||
res.moreResults = true;
|
||||
break;
|
||||
}
|
||||
|
||||
res.results.push_back(std::move(*itResult));
|
||||
res.moreResults = true;
|
||||
res.results.pop_back();
|
||||
}
|
||||
|
||||
res.range.size = res.results.size();
|
||||
@@ -89,31 +137,29 @@ namespace lms::db::utils
|
||||
return res;
|
||||
}
|
||||
|
||||
template <typename ResultType, typename Query>
|
||||
void execRangeQuery(Query& query, std::optional<Range> range, const std::function<void(const ResultType&)>& func)
|
||||
template <typename Query, typename UnaryFunc>
|
||||
void forEachQueryRangeResult(Query& query, std::optional<Range> range, UnaryFunc&& func)
|
||||
{
|
||||
if (range)
|
||||
applyRange(query, range);
|
||||
|
||||
auto collection{ execMultiResultQuery(query) };
|
||||
for (const auto& res : collection)
|
||||
{
|
||||
LMS_SCOPED_TRACE_DETAILED("Database", "ExecQueryRangeForEach");
|
||||
func(res);
|
||||
}
|
||||
forEachQueryResult(query, std::forward<UnaryFunc>(func));
|
||||
}
|
||||
|
||||
template <typename ResultType, typename Query>
|
||||
void execRangeQuery(Query& query, std::optional<Range> range, bool& moreResults, const std::function<void(const ResultType&)>& func)
|
||||
template <typename Query, typename UnaryFunc>
|
||||
void forEachQueryRangeResult(Query& query, std::optional<Range> range, bool& moreResults, UnaryFunc&& func)
|
||||
{
|
||||
using ResultType = typename QueryResultType<Query>::type;
|
||||
|
||||
if (range)
|
||||
applyRange(query, Range{ range->offset, range->size + 1 });
|
||||
|
||||
moreResults = false;
|
||||
|
||||
std::size_t count{};
|
||||
auto collection{ execMultiResultQuery(query) };
|
||||
for (const auto& res : collection)
|
||||
const auto collection{ query.resultList() };
|
||||
auto it{ fetchFirstResult(collection) };
|
||||
while (it != collection.end())
|
||||
{
|
||||
if (range && (count++ == static_cast<std::size_t>(range->size)))
|
||||
{
|
||||
@@ -121,8 +167,8 @@ namespace lms::db::utils
|
||||
break;
|
||||
}
|
||||
|
||||
LMS_SCOPED_TRACE_DETAILED("Database", "ExecQueryRangeForEach");
|
||||
func(res);
|
||||
func(*it);
|
||||
fetchNextResult<ResultType>(it);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -124,7 +124,7 @@ namespace lms::db
|
||||
static pointer find(Session& session, ReleaseId id);
|
||||
static void find(Session& session, ReleaseId& lastRetrievedRelease, std::size_t count, const std::function<void(const Release::pointer&)>& func, MediaLibraryId library = {});
|
||||
static RangeResults<pointer> find(Session& session, const FindParameters& parameters);
|
||||
static void find(Session& session, const FindParameters& parameters, std::function<void(const pointer&)> func);
|
||||
static void find(Session& session, const FindParameters& parameters, const std::function<void(const pointer&)>& func);
|
||||
static RangeResults<ReleaseId> findIds(Session& session, const FindParameters& parameters);
|
||||
static std::size_t getCount(Session& session, const FindParameters& parameters);
|
||||
static RangeResults<ReleaseId> findOrphanIds(Session& session, std::optional<Range> range = std::nullopt); // not track related
|
||||
|
||||
@@ -118,8 +118,8 @@ namespace lms::db
|
||||
|
||||
static RangeResults<TrackId> findIds(Session& session, const FindParameters& parameters);
|
||||
static RangeResults<pointer> find(Session& session, const FindParameters& parameters);
|
||||
static void find(Session& session, const FindParameters& parameters, std::function<void(const Track::pointer&)> func);
|
||||
static void find(Session& session, const FindParameters& parameters, bool& moreResults, std::function<void(const Track::pointer&)> func);
|
||||
static void find(Session& session, const FindParameters& parameters, const std::function<void(const Track::pointer&)>& func);
|
||||
static void find(Session& session, const FindParameters& parameters, bool& moreResults, const std::function<void(const Track::pointer&)>& func);
|
||||
static RangeResults<PathResult> findPaths(Session& session, std::optional<Range> range = std::nullopt);
|
||||
static RangeResults<TrackId> findIdsTrackMBIDDuplicates(Session& session, std::optional<Range> range = std::nullopt);
|
||||
static RangeResults<TrackId> findIdsWithRecordingMBIDAndMissingFeatures(Session& session, std::optional<Range> range = std::nullopt);
|
||||
|
||||
Reference in New Issue
Block a user