Commit 0fc6b3bb authored by Hugo Beauzée-Luyssen's avatar Hugo Beauzée-Luyssen

Add case insensitive Genre to the 6 to 7 migration

parent ab6a6596
......@@ -900,12 +900,73 @@ bool MediaLibrary::migrateModel5to6()
bool MediaLibrary::migrateModel6to7()
{
auto conn = getConn();
// Delete already parsed files with unknown type from Media.
// It will force a rescan of playlist files.
// This needs to be done from outside of the weak context, as we want
// triggers & foreign key to be enforced.
std::string req = "DELETE FROM " + policy::MediaTable::Name + " WHERE type = 0";
if ( sqlite::Tools::executeRequest( getConn(), req ) == false )
if ( sqlite::Tools::executeRequest( conn, req ) == false )
return false;
auto oldGenres = genres( SortingCriteria::Default, false );
sqlite::Connection::WeakDbContext weakConnCtx{ conn };
auto t = conn->newTransaction();
using namespace policy;
const std::string reqs[] = {
# include "database/migrations/migration6-7.sql"
};
for ( const auto& req : reqs )
{
if ( sqlite::Tools::executeRequest( conn, req ) == false )
return false;
}
// Clear the genres that were inserted in the cache when fetching oldGenres
Genre::clear();
// Since the ID might change, we need to keep track of newly inserted
// entities for book keeping later
std::vector<std::shared_ptr<Genre>> newGenres;
for ( const auto& g : oldGenres )
{
std::shared_ptr<Genre> newGenre;
try
{
// Attempt to insert the old genre. If it fails, it's because an
// existing genre already exists with a different case.
newGenre = Genre::create( this, g->name() );
if ( newGenre != nullptr )
newGenres.push_back( newGenre );
}
catch( sqlite::errors::ConstraintViolation& )
{
}
// If we fail to recreate the genre, fetch the one that already exists
// with a different case
if ( newGenre == nullptr )
newGenre = Genre::fromName( this, g->name() );
// If we can't find a genre with the same name, all bets are off, let's pray.
sqlite::Tools::executeUpdate( conn, "UPDATE " + AlbumTrackTable::Name +
" SET genre_id = ? WHERE genre_id = ?",
sqlite::ForeignKey( newGenre != nullptr ? newGenre->id() : 0 ),
g->id() );
}
// Triggers were disabled, so we need to maintain the consistency of the
// per-genre track count
for ( const auto& g : newGenres )
{
std::string req = "UPDATE " + GenreTable::Name + " SET nb_tracks = "
"("
"SELECT COUNT(id_track) FROM " + AlbumTrackTable::Name + " "
"WHERE genre_id = ?"
")"
"WHERE id_genre = ?";
sqlite::Tools::executeUpdate( conn, req, g->id(), g->id() );
}
// All nbTracks information are now invalid, so let's flush our entity cache (again)
Genre::clear();
t->commit();
return true;
}
......
"DROP TABLE " + GenreTable::Name + ";",
"CREATE TABLE " + GenreTable::Name + "("
"id_genre INTEGER PRIMARY KEY AUTOINCREMENT,"
"name TEXT COLLATE NOCASE UNIQUE ON CONFLICT FAIL,"
"nb_tracks INTEGER NOT NULL DEFAULT 0);",
......@@ -29,6 +29,7 @@
#include "Tests.h"
#include "database/SqliteTools.h"
#include "database/SqliteConnection.h"
#include "medialibrary/IGenre.h"
class Misc : public Tests
{
......@@ -152,4 +153,13 @@ TEST_F ( DbModel, Upgrade6to7 )
// Checking that the initial file is gone, ready to be parsed again
auto media = ml->media( 1 );
ASSERT_EQ( media, nullptr );
// Check that we now have only a single genre with correct values
auto genres = ml->genres( SortingCriteria::Alpha, false );
ASSERT_EQ( 2u, genres.size() );
auto g = genres[0];
ASSERT_EQ( g->nbTracks(), 2u );
g = genres[1];
ASSERT_EQ( "Test", g->name() );
ASSERT_EQ( g->nbTracks(), 1u );
}
......@@ -38,3 +38,13 @@ CREATE TABLE ShowEpisode(id_episode INTEGER PRIMARY KEY AUTOINCREMENT,media_id U
CREATE INDEX show_episode_media_show_idx ON ShowEpisode(media_id, show_id);
CREATE TABLE VideoTrack(id_track INTEGER PRIMARY KEY AUTOINCREMENT,codec TEXT,width UNSIGNED INTEGER,height UNSIGNED INTEGER,fps FLOAT,media_id UNSIGNED INT,language TEXT,description TEXT,FOREIGN KEY ( media_id ) REFERENCES Media(id_media) ON DELETE CASCADE);
CREATE INDEX video_track_media_idx ON VideoTrack(media_id);
INSERT INTO Genre VALUES(1, "Genre", 0);
INSERT INTO Genre VALUES(2, "GENRE", 0);
INSERT INTO Genre VALUES(3, "Test", 0);
INSERT INTO Album(id_album, title) VALUES(1, "Dummy album");
INSERT INTO Media(id_media, type, insertion_date, title) VALUES(2, 2, 1, "dummy media");
INSERT INTO Media(id_media, type, insertion_date, title) VALUES(3, 2, 1, "dummy media");
INSERT INTO Media(id_media, type, insertion_date, title) VALUES(4, 2, 1, "dummy media");
INSERT INTO AlbumTrack(media_id, duration, artist_id, genre_id, album_id) VALUES(2, 1, NULL, 1, 1);
INSERT INTO AlbumTrack(media_id, duration, artist_id, genre_id, album_id) VALUES(3, 1, NULL, 2, 1);
INSERT INTO AlbumTrack(media_id, duration, artist_id, genre_id, album_id) VALUES(4, 1, NULL, 3, 1);
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