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

Folder: Add a nb_media field

ref #42
parent 861d977f
......@@ -47,6 +47,7 @@ public:
* from being discovered.
*/
virtual bool isBanned() const = 0;
virtual uint32_t nbMedia() const = 0;
};
}
......@@ -52,6 +52,7 @@ Folder::Folder( MediaLibraryPtr ml, sqlite::Row& row )
, m_isBanned( row.load<decltype(m_isBanned)>( 3 ) )
, m_deviceId( row.load<decltype(m_deviceId)>( 4 ) )
, m_isRemovable( row.load<decltype(m_isRemovable)>( 5 ) )
, m_nbMedia( row.load<decltype(m_nbMedia)>( 6 ) )
{
}
......@@ -75,13 +76,35 @@ void Folder::createTable( sqlite::Connection* connection)
sqlite::Tools::executeRequest( connection, req );
}
void Folder::createTriggers( sqlite::Connection* connection )
void Folder::createTriggers( sqlite::Connection* connection, uint32_t modelVersion )
{
const std::string reqs[] = {
#include "database/tables/Folder_triggers_v14.sql"
};
for ( const auto& req : reqs )
sqlite::Tools::executeRequest( connection, req );
if ( modelVersion >= 14 )
{
const std::string v14Reqs[] = {
"CREATE TRIGGER IF NOT EXISTS update_folder_nb_media_on_insert "
"AFTER INSERT ON " + Media::Table::Name + " "
"WHEN new.folder_id IS NOT NULL "
"BEGIN "
"UPDATE " + Folder::Table::Name + " SET nb_media = nb_media + 1 "
"WHERE id_folder = new.folder_id;"
"END",
"CREATE TRIGGER IF NOT EXISTS update_folder_nb_media_on_delete "
"AFTER DELETE ON " + Media::Table::Name + " "
"WHEN old.folder_id IS NOT NULL "
"BEGIN "
"UPDATE " + Folder::Table::Name + " SET nb_media = nb_media - 1 "
"WHERE id_folder = old.folder_id;"
"END",
};
for ( const auto& req : v14Reqs )
sqlite::Tools::executeRequest( connection, req );
}
}
std::shared_ptr<Folder> Folder::create( MediaLibraryPtr ml, const std::string& mrl,
......@@ -334,6 +357,11 @@ bool Folder::isRootFolder() const
return m_parent == 0;
}
uint32_t Folder::nbMedia() const
{
return m_nbMedia;
}
std::vector<std::shared_ptr<Folder>> Folder::fetchRootFolders( MediaLibraryPtr ml )
{
static const std::string req = "SELECT * FROM " + Folder::Table::Name + " f "
......
......@@ -56,7 +56,7 @@ public:
Folder(MediaLibraryPtr ml, const std::string& path, int64_t parent , int64_t deviceId , bool isRemovable );
static void createTable( sqlite::Connection* connection );
static void createTriggers( sqlite::Connection* connection );
static void createTriggers( sqlite::Connection* connection, uint32_t modelVersion );
static std::shared_ptr<Folder> create( MediaLibraryPtr ml, const std::string& mrl, int64_t parentId, Device& device, fs::IDevice& deviceFs );
static void excludeEntryFolder( MediaLibraryPtr ml, int64_t folderId );
static bool ban( MediaLibraryPtr ml, const std::string& mrl );
......@@ -76,6 +76,7 @@ public:
virtual bool isPresent() const override;
virtual bool isBanned() const override;
bool isRootFolder() const;
virtual uint32_t nbMedia() const override;
enum class BannedType
{
......@@ -97,6 +98,7 @@ private:
const bool m_isBanned;
const int64_t m_deviceId;
const bool m_isRemovable;
uint32_t m_nbMedia;
mutable std::string m_deviceMountpoint;
mutable std::shared_ptr<Device> m_device;
......
......@@ -157,7 +157,7 @@ void MediaLibrary::createAllTables()
void MediaLibrary::createAllTriggers()
{
auto dbModelVersion = m_settings.dbModelVersion();
Folder::createTriggers( m_dbConnection.get() );
Folder::createTriggers( m_dbConnection.get(), dbModelVersion );
Album::createTriggers( m_dbConnection.get() );
AlbumTrack::createTriggers( m_dbConnection.get() );
Artist::createTriggers( m_dbConnection.get(), dbModelVersion );
......@@ -1178,7 +1178,7 @@ void MediaLibrary::migrateModel13to14( uint32_t originalPreviousVersion )
Artist::createTriggers( dbConn, 14 );
Show::createTriggers( dbConn );
Playlist::createTriggers( dbConn );
Folder::createTriggers( dbConn );
Folder::createTriggers( dbConn, 14 );
const std::string req = "SELECT * FROM " + Media::Table::Name +
" WHERE filename LIKE '%#%%' ESCAPE '#'";
auto media = Media::fetchAll<Media>( this, req );
......
......@@ -173,6 +173,9 @@ IMedia::Type::Unknown ) ),
"SELECT id_folder, path, parent_id, is_blacklisted, device_id, is_removable "
"FROM " + Folder::Table::Name + "_backup",
"UPDATE " + Folder::Table::Name + " SET nb_media = "
"(SELECT COUNT() FROM " + Media::Table::Name + " m WHERE m.folder_id = id_folder )",
"DROP TABLE " + Folder::Table::Name + "_backup",
/******************* Migrate File table *************************************/
......
......@@ -2,4 +2,5 @@
Folder::Table::Name + " (device_id)",
"CREATE INDEX IF NOT EXISTS parent_folder_id_idx ON " +
Folder::Table::Name + " (parent_id)"
Folder::Table::Name + " (parent_id)",
......@@ -6,6 +6,7 @@
"is_banned BOOLEAN NOT NULL DEFAULT 0,"
"device_id UNSIGNED INTEGER,"
"is_removable BOOLEAN NOT NULL,"
"nb_media UNSIGNED INTEGER NOT NULL DEFAULT 0,"
"FOREIGN KEY (parent_id) REFERENCES " + Folder::Table::Name +
"(id_folder) ON DELETE CASCADE,"
......
......@@ -54,6 +54,11 @@ FolderPtr MediaLibraryTester::folder( const std::string& mrl ) const
return Folder::fromMrl( this, mrl, Folder::BannedType::No );
}
FolderPtr MediaLibraryTester::folder(int64_t id) const
{
return Folder::fetch( this, id );
}
std::shared_ptr<Media> MediaLibraryTester::addFile( const std::string& path, IMedia::Type type )
{
return addFile( std::make_shared<mock::NoopFile>( path ),
......
......@@ -47,6 +47,7 @@ public:
// And override the ID getter to return a Media instead of IMedia
std::shared_ptr<Media> media( int64_t id );
FolderPtr folder( const std::string& path ) const override;
FolderPtr folder( int64_t id ) const;
void deleteAlbum( int64_t albumId );
std::shared_ptr<Album> createAlbum( const std::string& title );
std::shared_ptr<Genre> createGenre( const std::string& name );
......
......@@ -452,3 +452,24 @@ TEST_F( Folders, RemoveRootFolder )
ASSERT_EQ( 0u, ml->files().size() );
}
TEST_F( Folders, NbMedia )
{
auto root = ml->folder( 1 );
auto subFolder = ml->folder( 2 );
ASSERT_EQ( "file:///a/", root->mrl() );
ASSERT_EQ( "file:///a/folder/", subFolder->mrl() );
ASSERT_EQ( 2u, root->nbMedia() );
ASSERT_EQ( 1u, subFolder->nbMedia() );
// Do not watch for live changes
ml.reset();
fsMock->removeFile( mock::FileSystemFactory::SubFolder + "subfile.mp4" );
Reload();
root = ml->folder( 1 );
subFolder = ml->folder( 2 );
ASSERT_EQ( 2u, root->nbMedia() );
ASSERT_EQ( 0u, subFolder->nbMedia() );
}
......@@ -174,7 +174,7 @@ TEST_F( DbModel, Upgrade12to13 )
// We can't check for the number of albums anymore since they are deleted
// as part of 13 -> 14 migration
CheckNbTriggers( 30 );
CheckNbTriggers( 32 );
}
TEST_F( DbModel, Upgrade13to14 )
......@@ -216,6 +216,9 @@ TEST_F( DbModel, Upgrade13to14 )
ASSERT_EQ( IMedia::Type::Unknown, externalMedia->type() );
ASSERT_EQ( 0u, std::static_pointer_cast<Media>( externalMedia )->nbPlaylists() );
auto folder = ml->folder( 1 );
ASSERT_NE( nullptr, folder );
ASSERT_EQ( 2u, folder->nbMedia() );
CheckNbTriggers( 30 );
CheckNbTriggers( 32 );
}
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