diff --git a/src/libs/database/impl/Artist.cpp b/src/libs/database/impl/Artist.cpp index 001ca984..cabdfc88 100644 --- a/src/libs/database/impl/Artist.cpp +++ b/src/libs/database/impl/Artist.cpp @@ -182,7 +182,7 @@ namespace lms::db { session.checkReadTransaction(); - return utils::execSingleResultQuery(session.getDboSession()->query("SELECT COUNT(*) FROM artist")); + return utils::fetchQuerySingleResult(session.getDboSession()->query("SELECT COUNT(*) FROM artist")); } void Artist::find(Session& session, ArtistId& lastRetrievedArtist, std::size_t count, const std::function& 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::find(Session& session, std::string_view name) { session.checkReadTransaction(); - Wt::Dbo::collection> res{ utils::execMultiResultQuery(session.getDboSession()->find() + return utils::fetchQueryResults(session.getDboSession()->find() .where("name = ?").bind(std::string{ name, 0, _maxNameLength }) - .orderBy("LENGTH(mbid) DESC")) }; // put mbid entries first - - return std::vector(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().where("mbid = ?").bind(std::string{ mbid.getAsString() })); + return utils::fetchQuerySingleResult(session.getDboSession()->find().where("mbid = ?").bind(std::string{ mbid.getAsString() })); } Artist::pointer Artist::find(Session& session, ArtistId id) { session.checkReadTransaction(); - return utils::execSingleResultQuery(session.getDboSession()->find().where("id = ?").bind(id)); + return utils::fetchQuerySingleResult(session.getDboSession()->find().where("id = ?").bind(id)); } bool Artist::exists(Session& session, ArtistId id) { session.checkReadTransaction(); - return utils::execSingleResultQuery(session.getDboSession()->query("SELECT 1 FROM artist").where("id = ?").bind(id)) == 1; + return utils::fetchQuerySingleResult(session.getDboSession()->query("SELECT 1 FROM artist").where("id = ?").bind(id)) == 1; } RangeResults Artist::findOrphanIds(Session& session, std::optional range) @@ -268,7 +263,7 @@ namespace lms::db session.checkReadTransaction(); auto query{ createQuery>(session, params) }; - utils::execRangeQuery(query, params.range, func); + utils::forEachQueryRangeResult(query, params.range, func); } RangeResults Artist::findSimilarArtistIds(core::EnumSet artistLinkTypes, std::optional range) const @@ -343,14 +338,12 @@ namespace lms::db for (const std::string& bindArg : where.getBindArgs()) query.bind(bindArg); - Wt::Dbo::collection> queryRes{ utils::execMultiResultQuery(query) }; - std::map> 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> res; for (const auto& [clusterTypeId, clusters] : clustersByType) diff --git a/src/libs/database/impl/AuthToken.cpp b/src/libs/database/impl/AuthToken.cpp index b5e3e6c9..acdf936d 100644 --- a/src/libs/database/impl/AuthToken.cpp +++ b/src/libs/database/impl/AuthToken.cpp @@ -28,7 +28,6 @@ namespace lms::db { - AuthToken::AuthToken(std::string_view value, const Wt::WDateTime& expiry, ObjectPtr user) : _value{ value } , _expiry{ expiry } @@ -52,6 +51,6 @@ namespace lms::db { session.checkReadTransaction(); - return utils::execSingleResultQuery(session.getDboSession()->find().where("value = ?").bind(value)); + return utils::fetchQuerySingleResult(session.getDboSession()->find().where("value = ?").bind(value)); } } diff --git a/src/libs/database/impl/Cluster.cpp b/src/libs/database/impl/Cluster.cpp index ea67b5a2..704a334f 100644 --- a/src/libs/database/impl/Cluster.cpp +++ b/src/libs/database/impl/Cluster.cpp @@ -93,7 +93,7 @@ namespace lms::db { session.checkReadTransaction(); - return utils::execSingleResultQuery(session.getDboSession()->query("SELECT COUNT(*) FROM cluster")); + return utils::fetchQuerySingleResult(session.getDboSession()->query("SELECT COUNT(*) FROM cluster")); } RangeResults Cluster::findIds(Session& session, const FindParameters& params) @@ -124,14 +124,14 @@ namespace lms::db { session.checkReadTransaction(); - return utils::execSingleResultQuery(session.getDboSession()->find().where("id = ?").bind(id)); + return utils::fetchQuerySingleResult(session.getDboSession()->find().where("id = ?").bind(id)); } std::size_t Cluster::computeTrackCount(Session& session, ClusterId id) { session.checkReadTransaction(); - return utils::execSingleResultQuery(session.getDboSession()->query("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("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("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("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("SELECT COUNT(*) FROM cluster_type")); + return utils::fetchQuerySingleResult(session.getDboSession()->query("SELECT COUNT(*) FROM cluster_type")); } RangeResults ClusterType::findOrphanIds(Session& session, std::optional range) @@ -202,14 +202,14 @@ namespace lms::db { session.checkReadTransaction(); - return utils::execSingleResultQuery(session.getDboSession()->find().where("name = ?").bind(std::string{ name })); + return utils::fetchQuerySingleResult(session.getDboSession()->find().where("name = ?").bind(std::string{ name })); } ClusterType::pointer ClusterType::find(Session& session, ClusterTypeId id) { session.checkReadTransaction(); - return utils::execSingleResultQuery(session.getDboSession()->find().where("id = ?").bind(id)); + return utils::fetchQuerySingleResult(session.getDboSession()->find().where("id = ?").bind(id)); } RangeResults ClusterType::findIds(Session& session, std::optional range) @@ -226,7 +226,7 @@ namespace lms::db assert(self()); assert(session()); - return utils::execSingleResultQuery(session()->find() + return utils::fetchQuerySingleResult(session()->find() .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() + return utils::fetchQueryResults(session()->find() .where("cluster_type_id = ?").bind(getId()) - .orderBy("name")) }; - - return std::vector(res.begin(), res.end()); + .orderBy("name")); } } // namespace lms::db diff --git a/src/libs/database/impl/Listen.cpp b/src/libs/database/impl/Listen.cpp index fecdbc5f..bd4b6b47 100644 --- a/src/libs/database/impl/Listen.cpp +++ b/src/libs/database/impl/Listen.cpp @@ -180,13 +180,13 @@ namespace lms::db std::size_t Listen::getCount(Session& session) { session.checkReadTransaction(); - return utils::execSingleResultQuery(session.getDboSession()->query("SELECT COUNT(*) FROM listen")); + return utils::fetchQuerySingleResult(session.getDboSession()->query("SELECT COUNT(*) FROM listen")); } Listen::pointer Listen::find(Session& session, ListenId id) { session.checkReadTransaction(); - return utils::execSingleResultQuery(session.getDboSession()->find().where("id = ?").bind(id)); + return utils::fetchQuerySingleResult(session.getDboSession()->find().where("id = ?").bind(id)); } RangeResults Listen::find(Session& session, const FindParameters& parameters) @@ -212,7 +212,7 @@ namespace lms::db { session.checkReadTransaction(); - return utils::execSingleResultQuery(session.getDboSession()->find() + return utils::fetchQuerySingleResult(session.getDboSession()->find() .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("SELECT COUNT(*) from listen l") + return utils::fetchQuerySingleResult(session.getDboSession()->query("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( + return utils::fetchQuerySingleResult(session.getDboSession()->query( "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>("SELECT l from listen l") + return utils::fetchQuerySingleResult(session.getDboSession()->query>("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>("SELECT l from listen l") + return utils::fetchQuerySingleResult(session.getDboSession()->query>("SELECT l from listen l") .where("l.track_id = ?").bind(trackId) .where("l.user_id = ?").bind(userId) .where("l.backend = ?").bind(backend) diff --git a/src/libs/database/impl/MediaLibrary.cpp b/src/libs/database/impl/MediaLibrary.cpp index bda69a7a..f30105c7 100644 --- a/src/libs/database/impl/MediaLibrary.cpp +++ b/src/libs/database/impl/MediaLibrary.cpp @@ -44,36 +44,37 @@ namespace lms::db { session.checkReadTransaction(); - return utils::execSingleResultQuery(session.getDboSession()->query("SELECT COUNT(*) FROM media_library")); + return utils::fetchQuerySingleResult(session.getDboSession()->query("SELECT COUNT(*) FROM media_library")); } MediaLibrary::pointer MediaLibrary::find(Session& session, MediaLibraryId id) { session.checkReadTransaction(); - return utils::execSingleResultQuery(session.getDboSession()->find().where("id = ?").bind(id)); + return utils::fetchQuerySingleResult(session.getDboSession()->find().where("id = ?").bind(id)); } MediaLibrary::pointer MediaLibrary::find(Session& session, std::string_view name) { session.checkReadTransaction(); - return utils::execSingleResultQuery(session.getDboSession()->find().where("name = ?").bind(name)); + return utils::fetchQuerySingleResult(session.getDboSession()->find().where("name = ?").bind(name)); } MediaLibrary::pointer MediaLibrary::find(Session& session, const std::filesystem::path& p) { session.checkReadTransaction(); - return utils::execSingleResultQuery(session.getDboSession()->find().where("path = ?").bind(p)); + return utils::fetchQuerySingleResult(session.getDboSession()->find().where("path = ?").bind(p)); } void MediaLibrary::find(Session& session, std::function func) { session.checkReadTransaction(); - auto results{ utils::execMultiResultQuery(session.getDboSession()->find()) }; - for (const auto& result : results) - func(result); + utils::forEachQueryResult(session.getDboSession()->find(), [&](const MediaLibrary::pointer& mediaLibrary) + { + func(mediaLibrary); + }); } } // namespace lms::db diff --git a/src/libs/database/impl/Release.cpp b/src/libs/database/impl/Release.cpp index 8e3088d8..7c4a844e 100644 --- a/src/libs/database/impl/Release.cpp +++ b/src/libs/database/impl/Release.cpp @@ -213,7 +213,7 @@ namespace lms::db { session.checkReadTransaction(); - return utils::execSingleResultQuery(session.getDboSession()->find() + return utils::fetchQuerySingleResult(session.getDboSession()->find() .where("id = ?").bind(id)); } @@ -221,7 +221,7 @@ namespace lms::db { session.checkReadTransaction(); - return utils::execSingleResultQuery(session.getDboSession()->find() + return utils::fetchQuerySingleResult(session.getDboSession()->find() .where("name = ?").bind(name)); } @@ -240,19 +240,17 @@ namespace lms::db { session.checkReadTransaction(); - auto res{ utils::execMultiResultQuery(session.getDboSession()->query>("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(res.begin(), res.end()); + return utils::fetchQueryResults(session.getDboSession()->query>("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() + return utils::fetchQuerySingleResult(session.getDboSession()->find() .where("mbid = ?").bind(mbid.getAsString())); } @@ -260,21 +258,21 @@ namespace lms::db { session.checkReadTransaction(); - return utils::execSingleResultQuery(session.getDboSession()->find() + return utils::fetchQuerySingleResult(session.getDboSession()->find() .where("id = ?").bind(id)); } bool Release::exists(Session& session, ReleaseId id) { session.checkReadTransaction(); - return utils::execSingleResultQuery(session.getDboSession()->query("SELECT 1 FROM release").where("id = ?").bind(id)) == 1; + return utils::fetchQuerySingleResult(session.getDboSession()->query("SELECT 1 FROM release").where("id = ?").bind(id)) == 1; } std::size_t Release::getCount(Session& session) { session.checkReadTransaction(); - return utils::execSingleResultQuery(session.getDboSession()->query("SELECT COUNT(*) FROM release")); + return utils::fetchQuerySingleResult(session.getDboSession()->query("SELECT COUNT(*) FROM release")); } RangeResults Release::findOrphanIds(Session& session, std::optional 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::find(Session& session, const FindParameters& params) @@ -317,12 +313,12 @@ namespace lms::db return utils::execRangeQuery(query, params.range); } - void Release::find(Session& session, const FindParameters& params, std::function func) + void Release::find(Session& session, const FindParameters& params, const std::function& func) { session.checkReadTransaction(); auto query{ createQuery>(session, "DISTINCT r", params) }; - utils::execRangeQuery(query, params.range, func); + utils::forEachQueryRangeResult(query, params.range, func); } RangeResults Release::findIds(Session& session, const FindParameters& params) @@ -337,13 +333,13 @@ namespace lms::db { session.checkReadTransaction(); - return utils::execSingleResultQuery(createQuery(session, "COUNT(DISTINCT r.id)", params)); + return utils::fetchQuerySingleResult(createQuery(session, "COUNT(DISTINCT r.id)", params)); } std::size_t Release::getDiscCount() const { assert(session()); - int res{ utils::execSingleResultQuery(session()->query("SELECT COUNT(DISTINCT disc_number) FROM track t") + int res{ utils::fetchQuerySingleResult(session()->query("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 Release::getDiscs() const { assert(session()); + + using ResultType = std::tuple; - auto results{ utils::execMultiResultQuery(session()->query("SELECT DISTINCT disc_number, disc_subtitle FROM track t") + const auto query{ session()->query("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 discs; - for (const auto& res : results) - discs.emplace_back(DiscInfo{ static_cast(std::get(res)), std::get(res) }); + utils::forEachQueryResult(query, [&](ResultType&& res) + { + discs.emplace_back(DiscInfo{ static_cast(std::get(res)), std::move(std::get(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( - std::string {"SELECT "} + "t." + field + " FROM track t INNER JOIN release r ON r.id = t.release_id") + auto query{ (session()->query(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::string {"SELECT "} + "t." + field + " FROM track t INNER JOIN release r ON r.id = t.release_id") + auto query{ session()->query>(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 copyrights{ utils::execMultiResultQuery(session()->query - ("SELECT copyright FROM track t INNER JOIN release r ON r.id = t.release_id") + auto query{ session()->query("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 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 Release::getCopyrightURL() const { assert(session()); - Wt::Dbo::collection copyrights {utils::execMultiResultQuery(session()->query + const auto query{ session()->query ("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 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("SELECT COALESCE(AVG(t.bitrate), 0) FROM track t") + return utils::fetchQuerySingleResult(session()->query("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>( + const auto query{ session()->query>( "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(res.begin(), res.end()); + return utils::fetchQueryResults(query); } std::vector Release::getSimilarReleases(std::optional offset, std::optional 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>( + auto query{ session()->query>( "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(*count) : -1) - .offset(offset ? static_cast(*offset) : -1))}; + .offset(offset ? static_cast(*offset) : -1) }; - return std::vector(res.begin(), res.end()); + return utils::fetchQueryResults(query); } void Release::clearReleaseTypes() @@ -538,6 +537,7 @@ namespace lms::db std::vector> Release::getReleaseTypes() const { + // TODO remove? return std::vector>(_releaseTypes.begin(), _releaseTypes.end()); } @@ -557,7 +557,7 @@ namespace lms::db using milli = std::chrono::duration; - return utils::execSingleResultQuery(session()->query("SELECT COALESCE(SUM(duration), 0) FROM track t INNER JOIN release r ON t.release_id = r.id") + return utils::fetchQuerySingleResult(session()->query("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("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("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> clustersByType; - for (const Wt::Dbo::ptr& 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> res; for (const auto& [clusterTypeId, clusters] : clustersByType) diff --git a/src/libs/database/impl/ScanSettings.cpp b/src/libs/database/impl/ScanSettings.cpp index e76c24cb..40c39b81 100644 --- a/src/libs/database/impl/ScanSettings.cpp +++ b/src/libs/database/impl/ScanSettings.cpp @@ -42,7 +42,7 @@ namespace lms::db { session.checkReadTransaction(); - return utils::execSingleResultQuery(session.getDboSession()->find()); + return utils::fetchQuerySingleResult(session.getDboSession()->find()); } std::vector ScanSettings::getAudioFileExtensions() const diff --git a/src/libs/database/impl/StarredArtist.cpp b/src/libs/database/impl/StarredArtist.cpp index f8478be5..69b7e340 100644 --- a/src/libs/database/impl/StarredArtist.cpp +++ b/src/libs/database/impl/StarredArtist.cpp @@ -44,19 +44,19 @@ namespace lms::db std::size_t StarredArtist::getCount(Session& session) { session.checkReadTransaction(); - return utils::execSingleResultQuery(session.getDboSession()->query("SELECT COUNT(*) FROM starred_artist")); + return utils::fetchQuerySingleResult(session.getDboSession()->query("SELECT COUNT(*) FROM starred_artist")); } StarredArtist::pointer StarredArtist::find(Session& session, StarredArtistId id) { session.checkReadTransaction(); - return utils::execSingleResultQuery(session.getDboSession()->find().where("id = ?").bind(id)); + return utils::fetchQuerySingleResult(session.getDboSession()->find().where("id = ?").bind(id)); } StarredArtist::pointer StarredArtist::find(Session& session, ArtistId artistId, UserId userId) { session.checkReadTransaction(); - return utils::execSingleResultQuery(session.getDboSession()->query>("SELECT s_a from starred_artist s_a") + return utils::fetchQuerySingleResult(session.getDboSession()->query>("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() + return utils::fetchQuerySingleResult(session.getDboSession()->find() .where("artist_id = ?").bind(artistId) .where("user_id = ?").bind(userId) .where("backend = ?").bind(backend)); diff --git a/src/libs/database/impl/StarredRelease.cpp b/src/libs/database/impl/StarredRelease.cpp index 944946e2..1b42407a 100644 --- a/src/libs/database/impl/StarredRelease.cpp +++ b/src/libs/database/impl/StarredRelease.cpp @@ -50,13 +50,13 @@ namespace lms::db StarredRelease::pointer StarredRelease::find(Session& session, StarredReleaseId id) { session.checkReadTransaction(); - return utils::execSingleResultQuery(session.getDboSession()->find().where("id = ?").bind(id)); + return utils::fetchQuerySingleResult(session.getDboSession()->find().where("id = ?").bind(id)); } StarredRelease::pointer StarredRelease::find(Session& session, ReleaseId releaseId, UserId userId) { session.checkReadTransaction(); - return utils::execSingleResultQuery(session.getDboSession()->query>("SELECT s_r from starred_release s_r") + return utils::fetchQuerySingleResult(session.getDboSession()->query>("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() + return utils::fetchQuerySingleResult(session.getDboSession()->find() .where("release_id = ?").bind(releaseId) .where("user_id = ?").bind(userId) .where("backend = ?").bind(backend)); diff --git a/src/libs/database/impl/StarredTrack.cpp b/src/libs/database/impl/StarredTrack.cpp index 3a4049de..f2b42ed1 100644 --- a/src/libs/database/impl/StarredTrack.cpp +++ b/src/libs/database/impl/StarredTrack.cpp @@ -44,19 +44,19 @@ namespace lms::db std::size_t StarredTrack::getCount(Session& session) { session.checkReadTransaction(); - return utils::execSingleResultQuery(session.getDboSession()->query("SELECT COUNT(*) FROM starred_track")); + return utils::fetchQuerySingleResult(session.getDboSession()->query("SELECT COUNT(*) FROM starred_track")); } StarredTrack::pointer StarredTrack::find(Session& session, StarredTrackId id) { session.checkReadTransaction(); - return utils::execSingleResultQuery(session.getDboSession()->find().where("id = ?").bind(id)); + return utils::fetchQuerySingleResult(session.getDboSession()->find().where("id = ?").bind(id)); } StarredTrack::pointer StarredTrack::find(Session& session, TrackId trackId, UserId userId) { session.checkReadTransaction(); - return utils::execSingleResultQuery(session.getDboSession()->query>("SELECT s_t from starred_track s_t") + return utils::fetchQuerySingleResult(session.getDboSession()->query>("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() + return utils::fetchQuerySingleResult(session.getDboSession()->find() .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("SELECT 1 from starred_track") + return utils::fetchQuerySingleResult(session.getDboSession()->query("SELECT 1 from starred_track") .where("track_id = ?").bind(trackId) .where("user_id = ?").bind(userId) .where("backend = ?").bind(backend)); diff --git a/src/libs/database/impl/Track.cpp b/src/libs/database/impl/Track.cpp index b1140ea8..068620eb 100644 --- a/src/libs/database/impl/Track.cpp +++ b/src/libs/database/impl/Track.cpp @@ -178,12 +178,12 @@ namespace lms::db return query; } - + template Wt::Dbo::Query createQuery(Session& session, const Track::FindParameters& params) { std::string_view itemToSelect; - + if constexpr (std::is_same_v) itemToSelect = "t.id"; else if constexpr (std::is_same_v>) @@ -209,21 +209,21 @@ namespace lms::db { session.checkReadTransaction(); - return utils::execSingleResultQuery(session.getDboSession()->query("SELECT COUNT(*) FROM track")); + return utils::fetchQuerySingleResult(session.getDboSession()->query("SELECT COUNT(*) FROM track")); } Track::pointer Track::findByPath(Session& session, const std::filesystem::path& p) { session.checkReadTransaction(); - return utils::execSingleResultQuery(session.getDboSession()->find().where("file_path = ?").bind(p.string())); + return utils::fetchQuerySingleResult(session.getDboSession()->find().where("file_path = ?").bind(p.string())); } Track::pointer Track::find(Session& session, TrackId id) { session.checkReadTransaction(); - return utils::execSingleResultQuery(session.getDboSession()->find() + return utils::fetchQuerySingleResult(session.getDboSession()->find() .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("SELECT 1 from track").where("id = ?").bind(id)) == 1; + return utils::fetchQuerySingleResult(session.getDboSession()->query("SELECT 1 from track").where("id = ?").bind(id)) == 1; } std::vector Track::findByMBID(Session& session, const core::UUID& mbid) { session.checkReadTransaction(); - auto res{ utils::execMultiResultQuery(session.getDboSession()->find() - .where("mbid = ?").bind(std::string {mbid.getAsString()})) }; - - return std::vector(res.begin(), res.end()); + return utils::fetchQueryResults(session.getDboSession()->find() + .where("mbid = ?").bind(mbid.getAsString())); } std::vector Track::findByRecordingMBID(Session& session, const core::UUID& mbid) { session.checkReadTransaction(); - auto res{ utils::execMultiResultQuery(session.getDboSession()->find() - .where("recording_mbid = ?").bind(std::string {mbid.getAsString()})) }; - - return std::vector(res.begin(), res.end()); + return utils::fetchQueryResults(session.getDboSession()->find() + .where("recording_mbid = ?").bind(mbid.getAsString())); } RangeResults Track::findPaths(Session& session, std::optional range) @@ -330,11 +323,11 @@ namespace lms::db { assert(session()); - auto res{ utils::execMultiResultQuery(session()->query + const auto query{ session()->query ("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(res.begin(), res.end()); + return utils::fetchQueryResults(query); } RangeResults Track::findIds(Session& session, const FindParameters& parameters) @@ -353,20 +346,20 @@ namespace lms::db return utils::execRangeQuery(query, parameters.range); } - void Track::find(Session& session, const FindParameters& params, std::function func) + void Track::find(Session& session, const FindParameters& params, const std::function& func) { session.checkReadTransaction(); - auto query{ createQuery>(session, params)}; - utils::execRangeQuery(query, params.range, func); + auto query{ createQuery>(session, params) }; + utils::forEachQueryRangeResult(query, params.range, func); } - void Track::find(Session& session, const FindParameters& params, bool& moreResults, std::function func) + void Track::find(Session& session, const FindParameters& params, bool& moreResults, const std::function& func) { session.checkReadTransaction(); - auto query{ createQuery>(session, params)}; - utils::execRangeQuery(query, params.range, moreResults, func); + auto query{ createQuery>(session, params) }; + utils::forEachQueryRangeResult(query, params.range, moreResults, func); } RangeResults Track::findSimilarTrackIds(Session& session, const std::vector& tracks, std::optional range) @@ -457,8 +450,7 @@ namespace lms::db query.where("t.id = ?").bind(getId()); - auto res{ utils::execMultiResultQuery(query) }; - return std::vector(std::begin(res), std::end(res)); + return utils::fetchQueryResults(query); } std::vector Track::getArtistIds(core::EnumSet linkTypes) const @@ -493,8 +485,7 @@ namespace lms::db query.where("t.id = ?").bind(getId()); - auto res{ utils::execMultiResultQuery(query) }; - return std::vector(std::cbegin(res), std::cend(res)); + return utils::fetchQueryResults(query); } std::vector 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> clusters; - for (const Wt::Dbo::ptr& 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> res; for (const auto& [type, clusters] : clusters) diff --git a/src/libs/database/impl/TrackArtistLink.cpp b/src/libs/database/impl/TrackArtistLink.cpp index 38059dda..f3ca0ca9 100644 --- a/src/libs/database/impl/TrackArtistLink.cpp +++ b/src/libs/database/impl/TrackArtistLink.cpp @@ -76,7 +76,7 @@ namespace lms::db TrackArtistLink::pointer TrackArtistLink::find(Session& session, TrackArtistLinkId id) { session.checkReadTransaction(); - return utils::execSingleResultQuery(session.getDboSession()->find().where("id = ?").bind(id)); + return utils::fetchQuerySingleResult(session.getDboSession()->find().where("id = ?").bind(id)); } RangeResults TrackArtistLink::find(Session& session, const FindParameters& params) @@ -91,19 +91,28 @@ namespace lms::db { session.checkReadTransaction(); - auto res{ utils::execMultiResultQuery(session.getDboSession()->query("SELECT DISTINCT type from track_artist_link")) }; + const auto query{ session.getDboSession()->query("SELECT DISTINCT type from track_artist_link") }; - return core::EnumSet(std::begin(res), std::end(res)); + core::EnumSet res; + utils::forEachQueryResult(query, [&](TrackArtistLinkType linkType) + { + res.insert(linkType); + }); + return res; } core::EnumSet TrackArtistLink::findUsedTypes(Session& session, ArtistId artistId) { session.checkReadTransaction(); - auto res{ utils::execMultiResultQuery(session.getDboSession()->query("SELECT DISTINCT type from track_artist_link") - .where("artist_id = ?").bind(artistId)) }; + const auto query{ session.getDboSession()->query("SELECT DISTINCT type from track_artist_link") + .where("artist_id = ?").bind(artistId) }; - return core::EnumSet(std::begin(res), std::end(res)); + core::EnumSet res; + utils::forEachQueryResult(query, [&](TrackArtistLinkType linkType) + { + res.insert(linkType); + }); + return res; } } - diff --git a/src/libs/database/impl/TrackBookmark.cpp b/src/libs/database/impl/TrackBookmark.cpp index d5033ef0..d63c63c4 100644 --- a/src/libs/database/impl/TrackBookmark.cpp +++ b/src/libs/database/impl/TrackBookmark.cpp @@ -42,7 +42,7 @@ namespace lms::db { session.checkReadTransaction(); - return utils::execSingleResultQuery(session.getDboSession()->query("SELECT COUNT(*) FROM track_bookmark")); + return utils::fetchQuerySingleResult(session.getDboSession()->query("SELECT COUNT(*) FROM track_bookmark")); } RangeResults TrackBookmark::find(Session& session, UserId userId, std::optional range) @@ -59,7 +59,7 @@ namespace lms::db { session.checkReadTransaction(); - return utils::execSingleResultQuery(session.getDboSession()->find() + return utils::fetchQuerySingleResult(session.getDboSession()->find() .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() + return utils::fetchQuerySingleResult(session.getDboSession()->find() .where("id = ?").bind(id)); } diff --git a/src/libs/database/impl/TrackFeatures.cpp b/src/libs/database/impl/TrackFeatures.cpp index 5867114a..40a2a6d9 100644 --- a/src/libs/database/impl/TrackFeatures.cpp +++ b/src/libs/database/impl/TrackFeatures.cpp @@ -45,14 +45,14 @@ namespace lms::db { { session.checkReadTransaction(); - return utils::execSingleResultQuery(session.getDboSession()->query("SELECT COUNT(*) FROM track_features")); + return utils::fetchQuerySingleResult(session.getDboSession()->query("SELECT COUNT(*) FROM track_features")); } TrackFeatures::pointer TrackFeatures::find(Session& session, TrackFeaturesId id) { session.checkReadTransaction(); - return utils::execSingleResultQuery(session.getDboSession()->find() + return utils::fetchQuerySingleResult(session.getDboSession()->find() .where("id = ?").bind(id)); } @@ -60,7 +60,7 @@ namespace lms::db { { session.checkReadTransaction(); - return utils::execSingleResultQuery(session.getDboSession()->find() + return utils::fetchQuerySingleResult(session.getDboSession()->find() .where("track_id = ?").bind(trackId)); } diff --git a/src/libs/database/impl/TrackList.cpp b/src/libs/database/impl/TrackList.cpp index d83e0af7..d97e74a8 100644 --- a/src/libs/database/impl/TrackList.cpp +++ b/src/libs/database/impl/TrackList.cpp @@ -55,7 +55,7 @@ namespace lms::db { session.checkReadTransaction(); - return utils::execSingleResultQuery(session.getDboSession()->query("SELECT COUNT(*) FROM tracklist")); + return utils::fetchQuerySingleResult(session.getDboSession()->query("SELECT COUNT(*) FROM tracklist")); } @@ -64,7 +64,7 @@ namespace lms::db session.checkReadTransaction(); assert(userId.isValid()); - return utils::execSingleResultQuery(session.getDboSession()->find() + return utils::fetchQuerySingleResult(session.getDboSession()->find() .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().where("id = ?").bind(id)); + return utils::fetchQuerySingleResult(session.getDboSession()->find().where("id = ?").bind(id)); } bool TrackList::isEmpty() const @@ -163,7 +163,7 @@ namespace lms::db { assert(session()); - return utils::execSingleResultQuery(session()->find() + return utils::fetchQuerySingleResult(session()->find() .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>("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>("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(res.begin(), res.end()); + return utils::fetchQueryResults(query); } std::vector> TrackList::getClusterGroups(const std::vector& 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> clustersByType; - for (const Wt::Dbo::ptr& 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>( + auto query{ session()->query>( "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(*size) : -1) - .offset(offset ? static_cast(*offset) : -1))}; + .offset(offset ? static_cast(*offset) : -1) }; - return std::vector(res.begin(), res.end()); + return utils::fetchQueryResults(query); } std::vector TrackList::getTrackIds() const { assert(session()); - auto res {utils::execMultiResultQuery(session()->query("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("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(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; - return utils::execSingleResultQuery(session()->query("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("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().where("id = ?").bind(id)); + return utils::fetchQuerySingleResult(session.getDboSession()->find().where("id = ?").bind(id)); } } // namespace lms::db diff --git a/src/libs/database/impl/User.cpp b/src/libs/database/impl/User.cpp index e34253b2..cf5b356b 100644 --- a/src/libs/database/impl/User.cpp +++ b/src/libs/database/impl/User.cpp @@ -44,7 +44,7 @@ namespace lms::db { session.checkReadTransaction(); - return utils::execSingleResultQuery(session.getDboSession()->query("SELECT COUNT(*) FROM user")); + return utils::fetchQuerySingleResult(session.getDboSession()->query("SELECT COUNT(*) FROM user")); } RangeResults User::find(Session& session, const FindParameters& params) @@ -65,17 +65,17 @@ namespace lms::db { session.checkReadTransaction(); - return utils::execSingleResultQuery(session.getDboSession()->find().where("type = ?").bind(UserType::DEMO)); + return utils::fetchQuerySingleResult(session.getDboSession()->find().where("type = ?").bind(UserType::DEMO)); } User::pointer User::find(Session& session, UserId id) { - return utils::execSingleResultQuery(session.getDboSession()->find().where("id = ?").bind(id)); + return utils::fetchQuerySingleResult(session.getDboSession()->find().where("id = ?").bind(id)); } User::pointer User::find(Session& session, std::string_view name) { - return utils::execSingleResultQuery(session.getDboSession()->find() + return utils::fetchQuerySingleResult(session.getDboSession()->find() .where("login_name = ?").bind(name)); } diff --git a/src/libs/database/impl/Utils.hpp b/src/libs/database/impl/Utils.hpp index dbd0b6a7..14cca456 100644 --- a/src/libs/database/impl/Utils.hpp +++ b/src/libs/database/impl/Utils.hpp @@ -45,22 +45,74 @@ namespace lms::db::utils } } - template - auto execSingleResultQuery(const Query& query) + template + auto fetchFirstResult(const Wt::Dbo::collection& collection) { - LMS_SCOPED_TRACE_DETAILED_WITH_ARG("Database", "ExecSingleResultQuery", "Query", query.asString()); + LMS_SCOPED_TRACE_DETAILED("Database", "FetchFirstResult"); + return collection.begin(); + } + + template + void fetchNextResult(typename Wt::Dbo::collection::const_iterator& it) + { + LMS_SCOPED_TRACE_DETAILED("Database", "FetchNextResult"); + it++; + } + + template + void forEachResult(const Wt::Dbo::collection& collection, Func&& func) + { + typename Wt::Dbo::collection::const_iterator it{ fetchFirstResult(collection) }; + while (it != collection.end()) + { + func(*it); + fetchNextResult(it); + } + } + + template + struct QueryResultType; + + template + struct QueryResultType> + { + using type = ResultType; + }; + + template + void forEachQueryResult(const Query& query, UnaryFunc&& func) + { + LMS_SCOPED_TRACE_DETAILED_WITH_ARG("Database", "ForEachQueryResult", "Query", query.asString()); + forEachResult(query.resultList(), std::forward(func)); + } + + template + std::vector fetchQueryResults(const Query& query) + { + LMS_SCOPED_TRACE_DETAILED_WITH_ARG("Database", "FetchQueryResults", "Query", query.asString()); + + auto collection{ query.resultList() }; + return std::vector(collection.begin(), collection.end()); + } + + template + std::vector::type> fetchQueryResults(const Query& query) + { + LMS_SCOPED_TRACE_DETAILED_WITH_ARG("Database", "FetchQueryResults", "Query", query.asString()); + + auto collection{ query.resultList() }; + return std::vector::type>(collection.begin(), collection.end()); + } + + template + auto fetchQuerySingleResult(const Query& query) + { + LMS_SCOPED_TRACE_DETAILED_WITH_ARG("Database", "FetchQuerySingleResult", "Query", query.asString()); return query.resultValue(); } - template - auto execMultiResultQuery(const Query& query) - { - LMS_SCOPED_TRACE_DETAILED_WITH_ARG("Database", "ExecMultiResultQuery", "Query", query.asString()); - return query.resultList(); - } - template - RangeResults execRangeQuery(Query& query, std::optional range) + RangeResults execRangeQuery(Query& query, const std::optional range) { RangeResults 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(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 - void execRangeQuery(Query& query, std::optional range, const std::function& func) + template + void forEachQueryRangeResult(Query& query, std::optional 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(func)); } - template - void execRangeQuery(Query& query, std::optional range, bool& moreResults, const std::function& func) + template + void forEachQueryRangeResult(Query& query, std::optional range, bool& moreResults, UnaryFunc&& func) { + using ResultType = typename QueryResultType::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(range->size))) { @@ -121,8 +167,8 @@ namespace lms::db::utils break; } - LMS_SCOPED_TRACE_DETAILED("Database", "ExecQueryRangeForEach"); - func(res); + func(*it); + fetchNextResult(it); } } diff --git a/src/libs/database/include/database/Release.hpp b/src/libs/database/include/database/Release.hpp index f12a7397..c9a79bcf 100644 --- a/src/libs/database/include/database/Release.hpp +++ b/src/libs/database/include/database/Release.hpp @@ -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& func, MediaLibraryId library = {}); static RangeResults find(Session& session, const FindParameters& parameters); - static void find(Session& session, const FindParameters& parameters, std::function func); + static void find(Session& session, const FindParameters& parameters, const std::function& func); static RangeResults findIds(Session& session, const FindParameters& parameters); static std::size_t getCount(Session& session, const FindParameters& parameters); static RangeResults findOrphanIds(Session& session, std::optional range = std::nullopt); // not track related diff --git a/src/libs/database/include/database/Track.hpp b/src/libs/database/include/database/Track.hpp index 6b29414a..0dba7003 100644 --- a/src/libs/database/include/database/Track.hpp +++ b/src/libs/database/include/database/Track.hpp @@ -118,8 +118,8 @@ namespace lms::db static RangeResults findIds(Session& session, const FindParameters& parameters); static RangeResults find(Session& session, const FindParameters& parameters); - static void find(Session& session, const FindParameters& parameters, std::function func); - static void find(Session& session, const FindParameters& parameters, bool& moreResults, std::function func); + static void find(Session& session, const FindParameters& parameters, const std::function& func); + static void find(Session& session, const FindParameters& parameters, bool& moreResults, const std::function& func); static RangeResults findPaths(Session& session, std::optional range = std::nullopt); static RangeResults findIdsTrackMBIDDuplicates(Session& session, std::optional range = std::nullopt); static RangeResults findIdsWithRecordingMBIDAndMissingFeatures(Session& session, std::optional range = std::nullopt);