Listenbrainz: fixed listens parsing. fixes #262

This commit is contained in:
emeric
2022-09-26 20:41:31 +02:00
parent f8d61b67ac
commit ff63ad6448
14 changed files with 453 additions and 144 deletions
+19 -16
View File
@@ -45,9 +45,13 @@ createQuery(Session& session, const Track::FindParameters& params)
auto query {session.getDboSession().query<TrackId>(params.distinct ? "SELECT DISTINCT t.id FROM track t" : "SELECT t.id FROM track t")};
assert(params.keywords.empty() || params.name.empty());
for (std::string_view keyword : params.keywords)
query.where("t.name LIKE ? ESCAPE '" ESCAPE_CHAR_STR "'").bind("%" + Utils::escapeLikeKeyword(keyword) + "%");
if (!params.name.empty())
query.where("t.name = ?").bind(params.name);
if (params.writtenAfter.isValid())
query.where("t.file_last_write > ?").bind(params.writtenAfter);
@@ -80,11 +84,15 @@ createQuery(Session& session, const Track::FindParameters& params)
query.where(oss.str());
}
if (params.artist.isValid())
if (params.artist.isValid() || !params.artistName.empty())
{
query.join("artist a ON a.id = t_a_l.artist_id")
.join("track_artist_link t_a_l ON t_a_l.track_id = t.id")
.where("a.id = ?").bind(params.artist);
.join("track_artist_link t_a_l ON t_a_l.track_id = t.id");
if (params.artist.isValid())
query.where("a.id = ?").bind(params.artist);
if (!params.artistName.empty())
query.where("a.name = ?").bind(params.artistName);
if (!params.trackArtistLinkTypes.empty())
{
@@ -109,6 +117,11 @@ createQuery(Session& session, const Track::FindParameters& params)
query.where("t.release_id IS NULL");
else if (params.release.isValid())
query.where("t.release_id = ?").bind(params.release);
else if (!params.releaseName.empty())
{
query.join("release r ON t.release_id = r.id");
query.where("r.name = ?").bind(params.releaseName);
}
if (params.trackList.isValid())
{
@@ -117,6 +130,9 @@ createQuery(Session& session, const Track::FindParameters& params)
query.where("t_l.id = ?").bind(params.trackList);
}
if (params.trackNumber)
query.where("t.track_number = ?").bind(*params.trackNumber);
switch (params.sortMethod)
{
case TrackSortMethod::None:
@@ -282,19 +298,6 @@ Track::find(Session& session, const FindParameters& parameters)
return Utils::execQuery(query, parameters.range);
}
RangeResults<TrackId>
Track::findByNameAndReleaseName(Session& session, std::string_view trackName, std::string_view releaseName)
{
session.checkSharedLocked();
auto query {session.getDboSession().query<TrackId>("SELECT t.id from track t")
.join("release r ON t.release_id = r.id")
.where("t.name = ?").bind(trackName)
.where("r.name = ?").bind(releaseName)};
return Utils::execQuery(query, Range {});
}
RangeResults<TrackId>
Track::findSimilarTracks(Session& session, const std::vector<TrackId>& tracks, Range range)
{
@@ -59,30 +59,38 @@ class Track : public Object<Track, TrackId>
public:
struct FindParameters
{
std::vector<ClusterId> clusters; // if non empty, tracks that belong to these clusters
std::vector<std::string_view> keywords; // if non empty, name must match all of these keywords
std::vector<ClusterId> clusters; // if non empty, tracks that belong to these clusters
std::vector<std::string_view> keywords; // if non empty, name must match all of these keywords
std::string name; // if non empty, must match this name
TrackSortMethod sortMethod {TrackSortMethod::None};
Range range;
Wt::WDateTime writtenAfter;
UserId starringUser; // only tracks starred by this user
std::optional<Scrobbler> scrobbler; // and for this scrobbler
ArtistId artist; // only tracks that involve this user
ArtistId artist; // only tracks that involve this artist
std::string artistName; // only tracks that involve this artist name
EnumSet<TrackArtistLinkType> trackArtistLinkTypes; // and for these link types
bool nonRelease {}; // only tracks that do not belong to a release
ReleaseId release; // matching this release
std::string releaseName; // matching this release name
TrackListId trackList; // matching this trackList
std::optional<int> trackNumber; // matching this track number
bool distinct {true};
FindParameters& setClusters(const std::vector<ClusterId>& _clusters) { clusters = _clusters; return *this; }
FindParameters& setKeywords(const std::vector<std::string_view>& _keywords) { keywords = _keywords; return *this; }
FindParameters& setName(std::string_view _name) { name = _name; return *this; }
FindParameters& setSortMethod(TrackSortMethod _method) { sortMethod = _method; return *this; }
FindParameters& setRange(Range _range) { range = _range; return *this; }
FindParameters& setWrittenAfter(const Wt::WDateTime& _after) { writtenAfter = _after; return *this; }
FindParameters& setStarringUser(UserId _user, Scrobbler _scrobbler) { starringUser = _user; scrobbler = _scrobbler; return *this; }
FindParameters& setArtist(ArtistId _artist, EnumSet<TrackArtistLinkType> _trackArtistLinkTypes = {}) { artist = _artist; trackArtistLinkTypes = _trackArtistLinkTypes; return *this; }
FindParameters& setArtistName(std::string_view _artistName, EnumSet<TrackArtistLinkType> _trackArtistLinkTypes = {}) { artistName = _artistName; trackArtistLinkTypes = _trackArtistLinkTypes; return *this; }
FindParameters& setNonRelease(bool _nonRelease) { nonRelease = _nonRelease; return *this; }
FindParameters& setRelease(ReleaseId _release) { release = _release; return *this; }
FindParameters& setReleaseName(std::string_view _releaseName) { releaseName = _releaseName; return *this; }
FindParameters& setTrackList(TrackListId _trackList) { trackList = _trackList; return *this; }
FindParameters& setTrackNumber(int _trackNumber) { trackNumber = _trackNumber; return *this; }
FindParameters& setDistinct(bool _distinct) { distinct = _distinct; return *this; }
};
@@ -103,7 +111,6 @@ class Track : public Object<Track, TrackId>
static RangeResults<TrackId> findSimilarTracks(Session& session, const std::vector<TrackId>& trackIds, Range range);
static RangeResults<TrackId> find(Session& session, const FindParameters& parameters);
static RangeResults<TrackId> findByNameAndReleaseName(Session& session, std::string_view trackName, std::string_view releaseName);
static RangeResults<PathResult> findPaths(Session& session, Range range);
static RangeResults<TrackId> findRecordingMBIDDuplicates(Session& session, Range range);
static RangeResults<TrackId> findWithRecordingMBIDAndMissingFeatures(Session& session, Range range);
@@ -65,6 +65,7 @@ TEST_F(DatabaseFixture, Artist_singleTrack)
{
auto transaction {session.createUniqueTransaction()};
track.get().modify()->setName("MyTrackName");
TrackArtistLink::create(session, track.get(), artist.get(), TrackArtistLinkType::Artist);
}
@@ -89,6 +90,23 @@ TEST_F(DatabaseFixture, Artist_singleTrack)
EXPECT_TRUE(track->getArtists({TrackArtistLinkType::ReleaseArtist}).empty());
EXPECT_EQ(track->getArtists({}).size(), 1);
}
{
auto transaction {session.createUniqueTransaction()};
auto tracks {Track::find(session, Track::FindParameters{}.setName("MyTrackName").setArtistName("MyArtist"))};
ASSERT_EQ(tracks.results.size(), 1);
EXPECT_EQ(tracks.results.front(), track.getId());
}
{
auto transaction {session.createUniqueTransaction()};
auto tracks {Track::find(session, Track::FindParameters{}.setName("MyTrackName").setArtistName("MyArtistFoo"))};
EXPECT_EQ(tracks.results.size(), 0);
}
{
auto transaction {session.createUniqueTransaction()};
auto tracks {Track::find(session, Track::FindParameters{}.setName("MyTrackNameFoo").setArtistName("MyArtist"))};
EXPECT_EQ(tracks.results.size(), 0);
}
}
TEST_F(DatabaseFixture, Artist_singleTracktMultiRoles)
+3 -3
View File
@@ -84,18 +84,18 @@ TEST_F(DatabaseFixture, Release_singleTrack)
{
auto transaction {session.createUniqueTransaction()};
auto tracks {Track::findByNameAndReleaseName(session, "MyTrackName", "MyReleaseName")};
auto tracks {Track::find(session, Track::FindParameters{}.setName("MyTrackName").setReleaseName("MyReleaseName"))};
ASSERT_EQ(tracks.results.size(), 1);
EXPECT_EQ(tracks.results.front(), track.getId());
}
{
auto transaction {session.createUniqueTransaction()};
auto tracks {Track::findByNameAndReleaseName(session, "MyTrackName", "MyReleaseFoo")};
auto tracks {Track::find(session, Track::FindParameters{}.setName("MyTrackName").setReleaseName("MyReleaseFoo"))};
EXPECT_EQ(tracks.results.size(), 0);
}
{
auto transaction {session.createUniqueTransaction()};
auto tracks {Track::findByNameAndReleaseName(session, "MyTrackFoo", "MyReleaseName")};
auto tracks {Track::find(session, Track::FindParameters{}.setName("MyTrackFoo").setReleaseName("MyReleaseName"))};
EXPECT_EQ(tracks.results.size(), 0);
}
}