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

Media: Include labels in media search

parent ecf2457c
......@@ -75,17 +75,23 @@ LabelPtr Label::create(DBConnection dbConnection, const std::string& name )
bool Label::createTable(DBConnection dbConnection)
{
std::string req = "CREATE TABLE IF NOT EXISTS " + policy::LabelTable::Name + "("
static const std::string req = "CREATE TABLE IF NOT EXISTS " + policy::LabelTable::Name + "("
"id_label INTEGER PRIMARY KEY AUTOINCREMENT, "
"name TEXT UNIQUE ON CONFLICT FAIL"
")";
if ( sqlite::Tools::executeRequest( dbConnection, req ) == false )
return false;
req = "CREATE TABLE IF NOT EXISTS LabelFileRelation("
static const std::string relReq = "CREATE TABLE IF NOT EXISTS LabelFileRelation("
"label_id INTEGER,"
"media_id INTEGER,"
"PRIMARY KEY (label_id, media_id),"
"FOREIGN KEY(label_id) REFERENCES Label(id_label) ON DELETE CASCADE,"
"FOREIGN KEY(media_id) REFERENCES Media(id_media) ON DELETE CASCADE);";
return sqlite::Tools::executeRequest( dbConnection, req );
static const std::string ftsTrigger = "CREATE TRIGGER IF NOT EXISTS delete_label_fts "
"BEFORE DELETE ON " + policy::LabelTable::Name +
" BEGIN"
" UPDATE " + policy::MediaTable::Name + "Fts SET labels = TRIM(REPLACE(labels, old.name, ''))"
" WHERE labels MATCH old.name;"
" END";
return sqlite::Tools::executeRequest( dbConnection, req ) &&
sqlite::Tools::executeRequest( dbConnection, relReq ) &&
sqlite::Tools::executeRequest( dbConnection, ftsTrigger );
}
......@@ -348,7 +348,8 @@ bool Media::createTable( DBConnection connection )
")";
static const std::string vtableReq = "CREATE VIRTUAL TABLE IF NOT EXISTS "
+ policy::MediaTable::Name + "Fts USING FTS3("
"title"
"title,"
"labels"
")";
return sqlite::Tools::executeRequest( connection, req ) &&
sqlite::Tools::executeRequest( connection, vtableReq );
......@@ -374,7 +375,7 @@ bool Media::createTriggers( DBConnection connection )
static const std::string vtableInsertTrigger = "CREATE TRIGGER IF NOT EXISTS insert_media_fts"
" AFTER INSERT ON " + policy::MediaTable::Name +
" BEGIN"
" INSERT INTO " + policy::MediaTable::Name + "Fts(rowid,title) VALUES(new.id_media, new.title);"
" INSERT INTO " + policy::MediaTable::Name + "Fts(rowid,title,labels) VALUES(new.id_media, new.title, '');"
" END";
static const std::string vtableDeleteTrigger = "CREATE TRIGGER IF NOT EXISTS delete_media_fts"
" BEFORE DELETE ON " + policy::MediaTable::Name +
......@@ -401,7 +402,11 @@ bool Media::addLabel( LabelPtr label )
return false;
}
const char* req = "INSERT INTO LabelFileRelation VALUES(?, ?)";
return sqlite::Tools::insert( m_dbConnection, req, label->id(), m_id ) != 0;
if ( sqlite::Tools::insert( m_dbConnection, req, label->id(), m_id ) == 0 )
return false;
const std::string reqFts = "UPDATE " + policy::MediaTable::Name + "Fts "
"SET labels = labels || ' ' || ? WHERE rowid = ?";
return sqlite::Tools::executeUpdate( m_dbConnection, reqFts, label->name(), m_id );
}
bool Media::removeLabel( LabelPtr label )
......@@ -412,7 +417,11 @@ bool Media::removeLabel( LabelPtr label )
return false;
}
const char* req = "DELETE FROM LabelFileRelation WHERE label_id = ? AND media_id = ?";
return sqlite::Tools::executeDelete( m_dbConnection, req, label->id(), m_id );
if ( sqlite::Tools::executeDelete( m_dbConnection, req, label->id(), m_id ) == false )
return false;
const std::string reqFts = "UPDATE " + policy::MediaTable::Name + "Fts "
"SET labels = TRIM(REPLACE(labels, ?, '')) WHERE rowid = ?";
return sqlite::Tools::executeUpdate( m_dbConnection, reqFts, label->name(), m_id );
}
......
......@@ -428,6 +428,8 @@ std::vector<AlbumPtr> MediaLibrary::searchAlbums( const std::string& pattern ) c
std::vector<GenrePtr> MediaLibrary::searchGenre( const std::string& genre ) const
{
if ( validateSearchPattern( genre ) == false )
return {};
return Genre::search( m_dbConnection.get(), genre );
}
......
......@@ -194,3 +194,49 @@ TEST_F( Medias, SearchAfterDelete )
media = ml->searchMedia( "media" );
ASSERT_EQ( 0u, media.size() );
}
TEST_F( Medias, SearchByLabel )
{
auto m = ml->addFile( "media.mkv" );
auto media = ml->searchMedia( "otter" );
ASSERT_EQ( 0u, media.size() );
auto l = ml->createLabel( "otter" );
m->addLabel( l );
media = ml->searchMedia( "otter" );
ASSERT_EQ( 1u, media.size() );
auto l2 = ml->createLabel( "pangolins" );
m->addLabel( l2 );
media = ml->searchMedia( "otter" );
ASSERT_EQ( 1u, media.size() );
media = ml->searchMedia( "pangolin" );
ASSERT_EQ( 1u, media.size() );
m->removeLabel( l );
media = ml->searchMedia( "otter" );
ASSERT_EQ( 0u, media.size() );
media = ml->searchMedia( "pangolin" );
ASSERT_EQ( 1u, media.size() );
m->addLabel( l );
media = ml->searchMedia( "otter" );
ASSERT_EQ( 1u, media.size() );
media = ml->searchMedia( "pangolin" );
ASSERT_EQ( 1u, media.size() );
ml->deleteLabel( l );
media = ml->searchMedia( "otter" );
ASSERT_EQ( 0u, media.size() );
media = ml->searchMedia( "pangolin" );
ASSERT_EQ( 1u, media.size() );
}
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