Do not attempt extra data fetch when hitting the end of a query

This commit is contained in:
emeric
2024-03-14 13:51:28 +01:00
parent a769909ebc
commit e4ad0a5406
19 changed files with 177 additions and 148 deletions
+8
View File
@@ -343,6 +343,14 @@ namespace lms::db
utils::execQuery(query, params.range, func);
}
void Track::find(Session& session, const FindParameters& params, bool& moreResults, std::function<void(const Track::pointer&)> func)
{
session.checkReadTransaction();
auto query{ createQuery<Wt::Dbo::ptr<Track>>(session, params)};
utils::execQuery(query, params.range, moreResults, func);
}
RangeResults<TrackId> Track::findSimilarTrackIds(Session& session, const std::vector<TrackId>& tracks, std::optional<Range> range)
{
assert(!tracks.empty());
+6 -21
View File
@@ -142,25 +142,21 @@ namespace lms::db
TrackListEntry::pointer res;
auto entries = getEntries(Range{ pos, 1 });
if (!entries.empty())
res = entries.front();
if (!entries.results.empty())
res = entries.results.front();
return res;
}
std::vector<TrackListEntry::pointer> TrackList::getEntries(std::optional<Range> range) const
RangeResults<ObjectPtr<TrackListEntry>> TrackList::getEntries(std::optional<Range> range) const
{
assert(session());
auto entries{
session()->find<TrackListEntry>()
auto query{session()->find<TrackListEntry>()
.where("tracklist_id = ?").bind(getId())
.orderBy("id")
.limit(range ? static_cast<int>(range->size) + 1 : -1)
.offset(range ? static_cast<int>(range->offset) : -1)
.resultList() };
.orderBy("id") };
return std::vector<TrackListEntry::pointer>(entries.begin(), entries.end());
return utils::execQuery<TrackListEntry::pointer>(query, range);
}
TrackListEntry::pointer TrackList::getEntryByTrackAndDateTime(ObjectPtr<Track> track, const Wt::WDateTime& dateTime) const
@@ -237,17 +233,6 @@ namespace lms::db
return res;
}
bool TrackList::hasTrack(TrackId trackId) const
{
assert(session());
Wt::Dbo::collection<TrackListEntry::pointer> res = session()->query<TrackListEntry::pointer>("SELECT p_e from tracklist_entry p_e INNER JOIN tracklist p ON p_e.tracklist_id = p.id")
.where("p_e.track_id = ?").bind(trackId)
.where("p.id = ?").bind(getId());
return res.size() > 0;
}
std::vector<Track::pointer> TrackList::getSimilarTracks(std::optional<std::size_t> offset, std::optional<std::size_t> size) const
{
assert(session());
+32 -5
View File
@@ -56,15 +56,20 @@ namespace lms::db::utils
{
res.range.offset = range->offset;
applyRange(query, Range{ range->offset, range->size + 1 });
res.results.reserve(range->size);
}
auto collection{ query.resultList() };
res.results.assign(collection.begin(), collection.end());
if (range && res.results.size() == static_cast<std::size_t>(range->size) + 1)
for (auto itResult{ collection.begin() }; itResult != collection.end(); ++itResult)
{
// TODO may optim by not actually requesting the last one
res.moreResults = true;
res.results.pop_back();
if (range && res.results.size() == range->size)
{
res.moreResults = true;
break;
}
res.results.push_back(std::move(*itResult));
}
res.range.size = res.results.size();
@@ -85,6 +90,28 @@ namespace lms::db::utils
}
}
template <typename ResultType, typename Query>
void execQuery(Query& query, std::optional<Range> range, bool& moreResults, std::function<void(const ResultType&)> func)
{
if (range)
applyRange(query, Range{ range->offset, range->size + 1 });
moreResults = false;
std::size_t count{};
for (const auto& res : query.resultList())
{
if (range && (count++ == static_cast<std::size_t>(range->size)))
{
moreResults = true;
break;
}
LMS_SCOPED_TRACE_DETAILED("Database", "ExecQueryResult");
func(res);
}
}
Wt::WDateTime normalizeDateTime(const Wt::WDateTime& dateTime);
}
@@ -118,6 +118,7 @@ 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 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);
@@ -85,7 +85,7 @@ namespace lms::db
bool isEmpty() const;
std::size_t getCount() const;
ObjectPtr<TrackListEntry> getEntry(std::size_t pos) const;
std::vector<ObjectPtr<TrackListEntry>> getEntries(std::optional<Range> range = {}) const;
RangeResults<ObjectPtr<TrackListEntry>> getEntries(std::optional<Range> range = {}) const;
ObjectPtr<TrackListEntry> getEntryByTrackAndDateTime(ObjectPtr<Track> track, const Wt::WDateTime& dateTime) const;
std::vector<TrackId> getTrackIds() const;
@@ -97,8 +97,6 @@ namespace lms::db
std::vector<ObjectPtr<Cluster>> getClusters() const;
std::vector<std::vector<ObjectPtr<Cluster>>> getClusterGroups(const std::vector<ClusterTypeId>& clusterTypeIds, std::size_t size) const;
bool hasTrack(TrackId trackId) const;
// Ordered from most clusters in common
std::vector<ObjectPtr<Track>> getSimilarTracks(std::optional<std::size_t> offset = {}, std::optional<std::size_t> size = {}) const;
+7 -7
View File
@@ -198,8 +198,8 @@ namespace lms::db::tests
{
auto transaction{ session.createReadTransaction() };
auto entries{ trackList.get()->getEntries() };
ASSERT_EQ(entries.size(), 1);
EXPECT_EQ(entries.front()->getTrack()->getId(), track1.getId());
ASSERT_EQ(entries.results.size(), 1);
EXPECT_EQ(entries.results.front()->getTrack()->getId(), track1.getId());
}
{
@@ -210,16 +210,16 @@ namespace lms::db::tests
{
auto transaction{ session.createReadTransaction() };
auto entries{ trackList.get()->getEntries() };
ASSERT_EQ(entries.size(), 2);
EXPECT_EQ(entries[0]->getTrack()->getId(), track1.getId());
EXPECT_EQ(entries[1]->getTrack()->getId(), track2.getId());
ASSERT_EQ(entries.results.size(), 2);
EXPECT_EQ(entries.results[0]->getTrack()->getId(), track1.getId());
EXPECT_EQ(entries.results[1]->getTrack()->getId(), track2.getId());
}
{
auto transaction{ session.createReadTransaction() };
auto entries{ trackList.get()->getEntries(Range {1, 1}) };
ASSERT_EQ(entries.size(), 1);
EXPECT_EQ(entries[0]->getTrack()->getId(), track2.getId());
ASSERT_EQ(entries.results.size(), 1);
EXPECT_EQ(entries.results[0]->getTrack()->getId(), track2.getId());
}
}
}