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

Genre: Add search

parent 38a2b060
......@@ -118,6 +118,7 @@ class IMediaLibrary
virtual std::vector<MediaPtr> searchMedia( const std::string& pattern ) const = 0;
virtual std::vector<PlaylistPtr> searchPlaylists( const std::string& name ) const = 0;
virtual std::vector<AlbumPtr> searchAlbums( const std::string& pattern ) const = 0;
virtual std::vector<GenrePtr> searchGenre( const std::string& genre ) const = 0;
/**
* @brief discover Launch a discovery on the provided entry point.
......
......@@ -83,7 +83,25 @@ bool Genre::createTable( DBConnection dbConn )
"id_genre INTEGER PRIMARY KEY AUTOINCREMENT,"
"name TEXT UNIQUE ON CONFLICT FAIL"
")";
return sqlite::Tools::executeRequest( dbConn, req );
static const std::string vtableReq = "CREATE VIRTUAL TABLE IF NOT EXISTS "
+ policy::GenreTable::Name + "Fts USING FTS3("
"name"
")";
static const std::string vtableInsertTrigger = "CREATE TRIGGER IF NOT EXISTS insert_genre_fts"
" AFTER INSERT ON " + policy::GenreTable::Name +
" BEGIN"
" INSERT INTO " + policy::GenreTable::Name + "Fts(rowid,name) VALUES(new.id_genre, new.name);"
" END";
static const std::string vtableDeleteTrigger = "CREATE TRIGGER IF NOT EXISTS delete_genre_fts"
" BEFORE DELETE ON " + policy::GenreTable::Name +
" BEGIN"
" DELETE FROM " + policy::GenreTable::Name + "Fts WHERE rowid = old.id_genre;"
" END";
return sqlite::Tools::executeRequest( dbConn, req ) &&
sqlite::Tools::executeRequest( dbConn, vtableReq ) &&
sqlite::Tools::executeRequest( dbConn, vtableInsertTrigger ) &&
sqlite::Tools::executeRequest( dbConn, vtableDeleteTrigger );
}
std::shared_ptr<Genre> Genre::create( DBConnection dbConn, const std::string& name )
......@@ -103,3 +121,10 @@ std::shared_ptr<Genre> Genre::fromName(DBConnection dbConn, const std::string& n
return fetch( dbConn, req, name );
}
std::vector<GenrePtr> Genre::search( DBConnection dbConn, const std::string& name )
{
static const std::string req = "SELECT * FROM " + policy::GenreTable::Name + " WHERE id_genre IN "
"(SELECT rowid FROM " + policy::GenreTable::Name + "Fts WHERE name MATCH ?)";
return fetchAll<IGenre>( dbConn, req, name + "*" );
}
......@@ -52,6 +52,7 @@ public:
static bool createTable( DBConnection dbConn );
static std::shared_ptr<Genre> create( DBConnection dbConn, const std::string& name );
static std::shared_ptr<Genre> fromName( DBConnection dbConn, const std::string& name );
static std::vector<GenrePtr> search( DBConnection dbConn, const std::string& name );
private:
DBConnection m_dbConnection;
......
......@@ -377,7 +377,7 @@ bool Media::createTriggers( DBConnection connection )
" INSERT INTO " + policy::MediaTable::Name + "Fts(rowid,title) VALUES(new.id_media, new.title);"
" END";
static const std::string vtableDeleteTrigger = "CREATE TRIGGER IF NOT EXISTS delete_media_fts"
" AFTER DELETE ON " + policy::MediaTable::Name +
" BEFORE DELETE ON " + policy::MediaTable::Name +
" BEGIN"
" DELETE FROM " + policy::MediaTable::Name + "Fts WHERE rowid = old.id_media;"
" END";
......
......@@ -431,6 +431,11 @@ std::vector<AlbumPtr> MediaLibrary::searchAlbums( const std::string& pattern ) c
return Album::search( m_dbConnection.get(), pattern );
}
std::vector<GenrePtr> MediaLibrary::searchGenre( const std::string& genre ) const
{
return Genre::search( m_dbConnection.get(), genre );
}
void MediaLibrary::startParser()
{
m_parser.reset( new Parser( m_dbConnection.get(), this, m_callback ) );
......
......@@ -93,6 +93,7 @@ class MediaLibrary : public IMediaLibrary
virtual std::vector<MediaPtr> searchMedia( const std::string& title ) const override;
virtual std::vector<PlaylistPtr> searchPlaylists( const std::string& name ) const override;
virtual std::vector<AlbumPtr> searchAlbums( const std::string& pattern ) const override;
virtual std::vector<GenrePtr> searchGenre( const std::string& genre ) const override;
virtual void discover( const std::string& entryPoint ) override;
bool banFolder( const std::string& path ) override;
......
......@@ -138,3 +138,23 @@ TEST_F( Genres, ListAlbums )
}
}
}
TEST_F( Genres, Search )
{
ml->createGenre( "something" );
ml->createGenre( "blork" );
auto genres = ml->searchGenre( "genr" );
ASSERT_EQ( 1u, genres.size() );
}
TEST_F( Genres, SearchAfterDelete )
{
auto genres = ml->searchGenre( "genre" );
ASSERT_EQ( 1u, genres.size() );
ml->deleteGenre( g->id() );
genres = ml->searchGenre( "genre" );
ASSERT_EQ( 0u, genres.size() );
}
......@@ -31,6 +31,7 @@
#include "utils/Filename.h"
#include "discoverer/FsDiscoverer.h"
#include "mocks/FileSystem.h"
#include "Genre.h"
#include "Media.h"
#include "Folder.h"
#include "Playlist.h"
......@@ -130,3 +131,8 @@ void MediaLibraryTester::deleteAlbum( unsigned int albumId )
{
Album::destroy( m_dbConnection.get(), albumId );
}
void MediaLibraryTester::deleteGenre( unsigned int genreId )
{
Genre::destroy( m_dbConnection.get(), genreId );
}
......@@ -38,6 +38,7 @@ public:
std::shared_ptr<Media> addFile( const std::string& path );
std::shared_ptr<Playlist> playlist( unsigned int playlistId );
void deleteAlbum( unsigned int albumId );
void deleteGenre( unsigned int genreId );
private:
std::unique_ptr<fs::IDirectory> dummyDirectory;
......
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