Commit b8888bb2 authored by Duncan McNAMARA's avatar Duncan McNAMARA

Albums: Add sort by album + artist

parent eae2551b
Pipeline #8778 passed with stage
in 19 minutes and 25 seconds
......@@ -215,6 +215,53 @@ bool Album::setThumbnail( std::shared_ptr<Thumbnail> newThumbnail )
return res;
}
std::string Album::addRequestJoin( const QueryParameters* params,
bool albumTrack )
{
auto sort = params != nullptr ? params->sort : SortingCriteria::Alpha;
bool artist = false;
bool media = false;
switch( sort )
{
case SortingCriteria::Duration:
case SortingCriteria::InsertionDate:
case SortingCriteria::ReleaseDate:
case SortingCriteria::Filename:
case SortingCriteria::Album:
case SortingCriteria::LastModificationDate:
case SortingCriteria::FileSize:
case SortingCriteria::TrackNumber:
case SortingCriteria::NbAudio:
case SortingCriteria::NbVideo:
case SortingCriteria::NbMedia:
// Unused for album sorting
break;
case SortingCriteria::Artist:
case SortingCriteria::Alpha:
case SortingCriteria::Default:
// In case of identical album name
// sort should continue with artist name
artist = true;
break;
case SortingCriteria::PlayCount:
albumTrack = true;
media = true;
break;
}
std::string req;
if ( artist == true )
req += "LEFT JOIN " + Artist::Table::Name + " art ON alb.artist_id = art.id_artist ";
if ( albumTrack == true )
req += "INNER JOIN " + AlbumTrack::Table::Name + " att ON alb.id_album = att.album_id ";
if ( media == true )
{
assert( albumTrack == true );
req += "INNER JOIN " + Media::Table::Name + " m ON att.media_id = m.id_media ";
}
return req;
}
std::string Album::orderTracksBy( const QueryParameters* params = nullptr )
{
std::string req = " ORDER BY ";
......@@ -254,6 +301,12 @@ std::string Album::orderBy( const QueryParameters* params )
auto desc = params != nullptr ? params->desc : false;
switch ( sort )
{
case SortingCriteria::Artist:
req += "art.name";
if ( desc == true )
req += " DESC";
req += ", alb.title ";
break;
case SortingCriteria::ReleaseDate:
if ( desc == true )
req += "release_year DESC, title";
......@@ -276,6 +329,9 @@ std::string Album::orderBy( const QueryParameters* params )
case SortingCriteria::Default:
case SortingCriteria::Alpha:
req += "title";
if ( desc == true )
req += " DESC";
req += ", art.name";
if ( desc == true )
req += " DESC";
break;
......@@ -531,12 +587,13 @@ std::shared_ptr<Album> Album::createUnknownAlbum( MediaLibraryPtr ml, const Arti
Query<IAlbum> Album::search( MediaLibraryPtr ml, const std::string& pattern,
const QueryParameters* params )
{
std::string req = "FROM " + Table::Name + " alb "
"WHERE id_album IN "
std::string req = "FROM " + Table::Name + " alb ";
req += addRequestJoin( params, false );
req += "WHERE id_album IN "
"(SELECT rowid FROM " + Table::Name + "Fts WHERE " +
Table::Name + "Fts MATCH ?)"
"AND is_present != 0";
return make_query<Album, IAlbum>( ml, "*", std::move( req ),
"AND alb.is_present != 0";
return make_query<Album, IAlbum>( ml, "alb.*", std::move( req ),
orderBy( params ),
sqlite::Tools::sanitizePattern( pattern ) );
}
......@@ -544,13 +601,14 @@ Query<IAlbum> Album::search( MediaLibraryPtr ml, const std::string& pattern,
Query<IAlbum> Album::searchFromArtist( MediaLibraryPtr ml, const std::string& pattern,
int64_t artistId, const QueryParameters* params )
{
std::string req = "FROM " + Table::Name + " alb "
"WHERE id_album IN "
std::string req = "FROM " + Table::Name + " alb ";
req += addRequestJoin( params, false );
req += "WHERE id_album IN "
"(SELECT rowid FROM " + Table::Name + "Fts WHERE " +
Table::Name + "Fts MATCH ?)"
"AND is_present != 0 "
"AND alb.is_present != 0 "
"AND artist_id = ?";
return make_query<Album, IAlbum>( ml, "*", std::move( req ),
return make_query<Album, IAlbum>( ml, "alb.*", std::move( req ),
orderBy( params ),
sqlite::Tools::sanitizePattern( pattern ),
artistId );
......@@ -598,9 +656,9 @@ Query<IAlbum> Album::fromArtist( MediaLibraryPtr ml, int64_t artistId, const Que
Query<IAlbum> Album::fromGenre( MediaLibraryPtr ml, int64_t genreId, const QueryParameters* params )
{
std::string req = "FROM " + Table::Name + " alb "
"INNER JOIN " + AlbumTrack::Table::Name + " att ON att.album_id = alb.id_album "
"WHERE att.genre_id = ?";
std::string req = "FROM " + Table::Name + " alb ";
req += addRequestJoin( params, true );
req += "WHERE att.genre_id = ?";
std::string groupAndOrderBy = "GROUP BY att.album_id" + orderBy( params );
return make_query<Album, IAlbum>( ml, "alb.*", std::move( req ),
std::move( groupAndOrderBy ), genreId );
......@@ -609,9 +667,9 @@ Query<IAlbum> Album::fromGenre( MediaLibraryPtr ml, int64_t genreId, const Query
Query<IAlbum> Album::searchFromGenre( MediaLibraryPtr ml, const std::string& pattern,
int64_t genreId, const QueryParameters* params )
{
std::string req = "FROM " + Table::Name + " alb "
"INNER JOIN " + AlbumTrack::Table::Name + " att ON att.album_id = alb.id_album "
"WHERE id_album IN "
std::string req = "FROM " + Table::Name + " alb ";
req += addRequestJoin( params, true );
req += "WHERE id_album IN "
"(SELECT rowid FROM " + Table::Name + "Fts WHERE " +
Table::Name + "Fts MATCH ?)"
"AND att.genre_id = ?";
......@@ -629,20 +687,10 @@ Query<IAlbum> Album::listAll( MediaLibraryPtr ml, const QueryParameters* params
std::string countReq = "SELECT COUNT(*) FROM " + Table::Name + " WHERE "
"is_present != 0";
std::string req = "SELECT alb.* FROM " + Table::Name + " alb ";
if ( sort == SortingCriteria::Artist )
{
req += "INNER JOIN " + Artist::Table::Name + " art ON alb.artist_id = art.id_artist "
"WHERE alb.is_present != 0 ";
req += "ORDER BY art.name ";
if ( desc == true )
req += "DESC ";
req += ", alb.title";
}
else if ( sort == SortingCriteria::PlayCount )
req += addRequestJoin( params, false );
req += "WHERE alb.is_present != 0 ";
if ( sort == SortingCriteria::PlayCount )
{
req += "INNER JOIN " + AlbumTrack::Table::Name + " t ON alb.id_album = t.album_id "
"INNER JOIN " + Media::Table::Name + " m ON t.media_id = m.id_media "
"WHERE alb.is_present != 0 ";
req += "GROUP BY id_album "
"ORDER BY SUM(m.play_count) ";
if ( desc == false )
......@@ -651,7 +699,6 @@ Query<IAlbum> Album::listAll( MediaLibraryPtr ml, const QueryParameters* params
}
else
{
req += " WHERE is_present != 0";
req += orderBy( params );
}
return make_query_with_count<Album, IAlbum>( ml, std::move( countReq ),
......
......@@ -132,6 +132,8 @@ class Album : public IAlbum, public DatabaseHelpers<Album>
static bool checkDBConsistency( MediaLibraryPtr ml );
private:
static std::string addRequestJoin( const QueryParameters* params,
bool albumTrack);
static std::string orderTracksBy( const QueryParameters* params );
static std::string orderBy( const QueryParameters* params );
bool shouldUpdateThumbnail(Thumbnail& currentThumbnail,
......
......@@ -260,6 +260,58 @@ TEST_F( Albums, AlbumArtist )
ASSERT_EQ( albumArtist->name(), artist->name() );
}
TEST_F( Albums, SortAlbumThenArtist )
{
// First
auto albumOttersO = ml->createAlbum( "otters" );
// Second
auto albumPangolinsP = ml->createAlbum( "pangolins of fire" );
// Fourth
auto albumPangolinsS = ml->createAlbum( "see otters" );
// Third
auto albumOttersS = ml->createAlbum( "sea otters" );
// Originally the medialibrary handled ordering in case of identical
// album name by using the insertion order.
// Here the insertion order is different than the expected sort order.
auto artistP = ml->createArtist( "pangolins" );
auto artistO = ml->createArtist( "otters" );
albumOttersO->setAlbumArtist( artistO );
albumPangolinsP->setAlbumArtist( artistP );
albumOttersS->setAlbumArtist( artistO );
albumPangolinsS->setAlbumArtist( artistP);
auto m = std::static_pointer_cast<Media>( ml->addMedia( "media.mp3" ) );
albumOttersO->addTrack( m, 1, 0, 0, nullptr );
m->save();
auto m2 = std::static_pointer_cast<Media>( ml->addMedia( "media2.mp3" ) );
albumPangolinsP->addTrack( m2, 1, 0, 0, nullptr );
m2->save();
auto m3 = std::static_pointer_cast<Media>( ml->addMedia( "media3.mp3" ) );
albumOttersS->addTrack( m3, 1, 0, 0, nullptr );
m3->save();
auto m4 = std::static_pointer_cast<Media>( ml->addMedia( "media4.mp3" ) );
albumPangolinsS->addTrack( m4, 1, 0, 0, nullptr );
m3->save();
QueryParameters params { SortingCriteria::Alpha, false };
auto albums = ml->albums( &params )->all();
ASSERT_EQ( 4u, albums.size() );
ASSERT_EQ( albumOttersO->id(), albums[0]->id() );
ASSERT_EQ( albumPangolinsP->id(), albums[1]->id() );
ASSERT_EQ( albumOttersS->id(), albums[2]->id() );
ASSERT_EQ( albumPangolinsS->id(), albums[3]->id() );
params.desc = true;
albums = ml->albums( &params )->all();
ASSERT_EQ( 4u, albums.size() );
ASSERT_EQ( albumPangolinsS->id(), albums[0]->id() );
ASSERT_EQ( albumOttersS->id(), albums[1]->id() );
ASSERT_EQ( albumPangolinsP->id(), albums[2]->id() );
ASSERT_EQ( albumOttersO->id(), albums[3]->id() );
}
TEST_F( Albums, SearchByTitle )
{
auto a1 = ml->createAlbum( "sea otters" );
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment