Permalink
Browse files

musicdb: adjust/extend SQL queries to better support WHERE clauses fo…

…r filtering
  • Loading branch information...
1 parent 9fc3069 commit b00cd0567167bb79731d4bbba26ddb587c77c5d6 @Montellese committed Jul 23, 2012
Showing with 89 additions and 32 deletions.
  1. +2 −2 xbmc/interfaces/json-rpc/AudioLibrary.cpp
  2. +82 −25 xbmc/music/MusicDatabase.cpp
  3. +5 −5 xbmc/music/MusicDatabase.h
@@ -76,7 +76,7 @@ JSONRPC_STATUS CAudioLibrary::GetArtists(const CStdString &method, ITransportLay
return InvalidParams;
CFileItemList items;
- if (!musicdatabase.GetArtistsNav(musicUrl.ToString(), items, albumArtistsOnly, genreID, albumID, songID, sorting))
+ if (!musicdatabase.GetArtistsNav(musicUrl.ToString(), items, albumArtistsOnly, genreID, albumID, songID, CDatabase::Filter(), sorting))
return InternalError;
// Add "artist" to "properties" array by default
@@ -154,7 +154,7 @@ JSONRPC_STATUS CAudioLibrary::GetAlbums(const CStdString &method, ITransportLaye
return InvalidParams;
CFileItemList items;
- if (!musicdatabase.GetAlbumsNav(musicUrl.ToString(), items, genreID, artistID, sorting))
+ if (!musicdatabase.GetAlbumsNav(musicUrl.ToString(), items, genreID, artistID, CDatabase::Filter(), sorting))
return InternalError;
int size = items.Size();
@@ -2621,29 +2621,53 @@ void CMusicDatabase::Clean()
}
}
-bool CMusicDatabase::GetGenresNav(const CStdString& strBaseDir, CFileItemList& items)
+bool CMusicDatabase::GetGenresNav(const CStdString& strBaseDir, CFileItemList& items, const Filter &filter /* = Filter() */, bool countOnly /* = false */)
{
try
{
if (NULL == m_pDB.get()) return false;
if (NULL == m_pDS.get()) return false;
+ // get primary genres for songs - could be simplified to just SELECT * FROM genre?
+ CStdString strSQL = "SELECT %s FROM genre ";
+
+ Filter extFilter = filter;
CMusicDbUrl musicUrl;
- if (!musicUrl.FromString(strBaseDir))
+ if (!musicUrl.FromString(strBaseDir) || !GetFilter(musicUrl, extFilter))
return false;
- // get primary genres for songs - could be simplified to just SELECT * FROM genre?
- CStdString strSQL="SELECT * "
- " FROM genre "
- " WHERE idGenre IN"
- "(SELECT song_genre.idGenre "
- " FROM song_genre) ";
+ // if there are extra WHERE conditions we might need access
+ // to songview or albumview for these conditions
+ if (extFilter.where.size() > 0)
+ {
+ if (extFilter.where.find("artistview") != string::npos)
+ extFilter.AppendJoin("JOIN song_genre ON song_genre.idGenre = genre.idGenre JOIN songview ON songview.idSong = song_genre.idSong "
+ "JOIN song_artist ON song_artist.idSong = songview.idSong JOIN artistview ON artistview.idArtist = song_artist.idArtist");
+ else if (extFilter.where.find("songview") != string::npos)
+ extFilter.AppendJoin("JOIN song_genre ON song_genre.idGenre = genre.idGenre JOIN songview ON songview.idSong = song_genre.idSong");
+ else if (extFilter.where.find("albumview") != string::npos)
+ extFilter.AppendJoin("JOIN album_genre ON album_genre.idGenre = genre.idGenre JOIN albumview ON albumview.idAlbum = album_genre.idAlbum");
- // block null strings
- strSQL += " AND genre.strGenre != \"\"";
+ extFilter.AppendGroup("genre.idGenre");
+ }
+ extFilter.AppendWhere("genre.strGenre != ''");
+
+ if (countOnly)
+ {
+ extFilter.fields = "COUNT(DISTINCT genre.idGenre)";
+ extFilter.group.clear();
+ extFilter.order.clear();
+ }
+
+ CStdString strSQLExtra;
+ if (!BuildSQL(strSQLExtra, extFilter, strSQLExtra))
+ return false;
+
+ strSQL = PrepareSQL(strSQL.c_str(), !extFilter.fields.empty() && extFilter.fields.compare("*") != 0 ? extFilter.fields.c_str() : "genre.*") + strSQLExtra;
// run query
CLog::Log(LOGDEBUG, "%s query: %s", __FUNCTION__, strSQL.c_str());
+
if (!m_pDS->query(strSQL.c_str()))
return false;
int iRowsFound = m_pDS->num_rows();
@@ -2653,15 +2677,25 @@ bool CMusicDatabase::GetGenresNav(const CStdString& strBaseDir, CFileItemList& i
return true;
}
+ if (countOnly)
+ {
+ CFileItemPtr pItem(new CFileItem());
+ pItem->SetProperty("total", iRowsFound == 1 ? m_pDS->fv(0).get_asInt() : iRowsFound);
+ items.Add(pItem);
+
+ m_pDS->close();
+ return true;
+ }
+
// get data from returned rows
while (!m_pDS->eof())
{
- CFileItemPtr pItem(new CFileItem(m_pDS->fv("strGenre").get_asString()));
- pItem->GetMusicInfoTag()->SetGenre(m_pDS->fv("strGenre").get_asString());
- pItem->GetMusicInfoTag()->SetDatabaseId(m_pDS->fv("idGenre").get_asInt(), "genre");
+ CFileItemPtr pItem(new CFileItem(m_pDS->fv("genre.strGenre").get_asString()));
+ pItem->GetMusicInfoTag()->SetGenre(m_pDS->fv("genre.strGenre").get_asString());
+ pItem->GetMusicInfoTag()->SetDatabaseId(m_pDS->fv("genre.idGenre").get_asInt(), "genre");
CMusicDbUrl itemUrl = musicUrl;
- CStdString strDir; strDir.Format("%ld/", m_pDS->fv("idGenre").get_asInt());
+ CStdString strDir; strDir.Format("%ld/", m_pDS->fv("genre.idGenre").get_asInt());
itemUrl.AppendPath(strDir);
pItem->SetPath(itemUrl.ToString());
@@ -2751,7 +2785,7 @@ bool CMusicDatabase::GetAlbumsByYear(const CStdString& strBaseDir, CFileItemList
return GetAlbumsByWhere(musicUrl.ToString(), filter, items);
}
-bool CMusicDatabase::GetArtistsNav(const CStdString& strBaseDir, CFileItemList& items, bool albumArtistsOnly /* = false */, int idGenre /* = -1 */, int idAlbum /* = -1 */, int idSong /* = -1 */, const SortDescription &sortDescription /* = SortDescription() */)
+bool CMusicDatabase::GetArtistsNav(const CStdString& strBaseDir, CFileItemList& items, bool albumArtistsOnly /* = false */, int idGenre /* = -1 */, int idAlbum /* = -1 */, int idSong /* = -1 */, const Filter &filter /* = Filter() */, const SortDescription &sortDescription /* = SortDescription() */, bool countOnly /* = false */)
{
if (NULL == m_pDB.get()) return false;
if (NULL == m_pDS.get()) return false;
@@ -2772,8 +2806,7 @@ bool CMusicDatabase::GetArtistsNav(const CStdString& strBaseDir, CFileItemList&
musicUrl.AddOption("albumartistsonly", albumArtistsOnly);
- Filter filter;
- bool result = GetArtistsByWhere(musicUrl.ToString(), filter, items, sortDescription);
+ bool result = GetArtistsByWhere(musicUrl.ToString(), filter, items, sortDescription, countOnly);
CLog::Log(LOGDEBUG,"Time to retrieve artists from dataset = %i", XbmcThreads::SystemClockMillis() - time);
return result;
@@ -2786,7 +2819,7 @@ bool CMusicDatabase::GetArtistsNav(const CStdString& strBaseDir, CFileItemList&
return false;
}
-bool CMusicDatabase::GetArtistsByWhere(const CStdString& strBaseDir, const Filter &filter, CFileItemList& items, const SortDescription &sortDescription /* = SortDescription() */)
+bool CMusicDatabase::GetArtistsByWhere(const CStdString& strBaseDir, const Filter &filter, CFileItemList& items, const SortDescription &sortDescription /* = SortDescription() */, bool countOnly /* = false */)
{
if (NULL == m_pDB.get()) return false;
if (NULL == m_pDS.get()) return false;
@@ -2796,7 +2829,7 @@ bool CMusicDatabase::GetArtistsByWhere(const CStdString& strBaseDir, const Filte
int total = -1;
CStdString strSQL = "SELECT %s FROM artistview ";
-
+
Filter extFilter = filter;
CMusicDbUrl musicUrl;
if (!musicUrl.FromString(strBaseDir) || !GetFilter(musicUrl, extFilter))
@@ -2822,6 +2855,13 @@ bool CMusicDatabase::GetArtistsByWhere(const CStdString& strBaseDir, const Filte
extFilter.AppendGroup("artistview.idArtist");
}
+ if (countOnly)
+ {
+ extFilter.fields = "COUNT(DISTINCT artistview.idArtist)";
+ extFilter.group.clear();
+ extFilter.order.clear();
+ }
+
CStdString strSQLExtra;
if (!BuildSQL(strSQLExtra, extFilter, strSQLExtra))
return false;
@@ -2847,6 +2887,16 @@ bool CMusicDatabase::GetArtistsByWhere(const CStdString& strBaseDir, const Filte
return true;
}
+ if (countOnly)
+ {
+ CFileItemPtr pItem(new CFileItem());
+ pItem->SetProperty("total", iRowsFound == 1 ? m_pDS->fv(0).get_asInt() : iRowsFound);
+ items.Add(pItem);
+
+ m_pDS->close();
+ return true;
+ }
+
// store the total value of items as a property
if (total < iRowsFound)
total = iRowsFound;
@@ -2964,7 +3014,7 @@ bool CMusicDatabase::GetAlbumFromSong(const CSong &song, CAlbum &album)
return false;
}
-bool CMusicDatabase::GetAlbumsNav(const CStdString& strBaseDir, CFileItemList& items, int idGenre /* = -1 */, int idArtist /* = -1 */, const SortDescription &sortDescription /* = SortDescription() */)
+bool CMusicDatabase::GetAlbumsNav(const CStdString& strBaseDir, CFileItemList& items, int idGenre /* = -1 */, int idArtist /* = -1 */, const Filter &filter /* = Filter() */, const SortDescription &sortDescription /* = SortDescription() */, bool countOnly /* = false */)
{
CMusicDbUrl musicUrl;
if (!musicUrl.FromString(strBaseDir))
@@ -2977,11 +3027,10 @@ bool CMusicDatabase::GetAlbumsNav(const CStdString& strBaseDir, CFileItemList& i
if (idArtist > 0)
musicUrl.AddOption("artistid", idArtist);
- Filter filter;
- return GetAlbumsByWhere(musicUrl.ToString(), filter, items, sortDescription);
+ return GetAlbumsByWhere(musicUrl.ToString(), filter, items, sortDescription, countOnly);
}
-bool CMusicDatabase::GetAlbumsByWhere(const CStdString &baseDir, const Filter &filter, CFileItemList &items, const SortDescription &sortDescription /* = SortDescription() */)
+bool CMusicDatabase::GetAlbumsByWhere(const CStdString &baseDir, const Filter &filter, CFileItemList &items, const SortDescription &sortDescription /* = SortDescription() */, bool countOnly /* = false */)
{
if (m_pDB.get() == NULL || m_pDS.get() == NULL)
return false;
@@ -3039,6 +3088,16 @@ bool CMusicDatabase::GetAlbumsByWhere(const CStdString &baseDir, const Filter &f
if (total < iRowsFound)
total = iRowsFound;
items.SetProperty("total", total);
+
+ if (countOnly)
+ {
+ CFileItemPtr pItem(new CFileItem());
+ pItem->SetProperty("total", total);
+ items.Add(pItem);
+
+ m_pDS->close();
+ return true;
+ }
DatabaseResults results;
results.reserve(iRowsFound);
@@ -5272,8 +5331,6 @@ bool CMusicDatabase::GetFilter(const CDbUrl &musicUrl, Filter &filter)
" OR songview.idSong IN (SELECT song.idSong FROM song JOIN album_artist ON song.idAlbum=album_artist.idAlbum JOIN artist ON artist.idArtist = album_artist.idArtist WHERE artist.strArtist like '%s')", // album artists
option->second.asString().c_str(), option->second.asString().c_str()));
}
- else
- return false;
option = options.find("xsp");
if (option != options.end())
@@ -154,16 +154,16 @@ class CMusicDatabase : public CDatabase
bool GetPaths(std::set<CStdString> &paths);
bool SetPathHash(const CStdString &path, const CStdString &hash);
bool GetPathHash(const CStdString &path, CStdString &hash);
- bool GetGenresNav(const CStdString& strBaseDir, CFileItemList& items);
+ bool GetGenresNav(const CStdString& strBaseDir, CFileItemList& items, const Filter &filter = Filter(), bool countOnly = false);
bool GetYearsNav(const CStdString& strBaseDir, CFileItemList& items);
- bool GetArtistsNav(const CStdString& strBaseDir, CFileItemList& items, bool albumArtistsOnly = false, int idGenre = -1, int idAlbum = -1, int idSong = -1, const SortDescription &sortDescription = SortDescription());
- bool GetAlbumsNav(const CStdString& strBaseDir, CFileItemList& items, int idGenre = -1, int idArtist = -1, const SortDescription &sortDescription = SortDescription());
+ bool GetArtistsNav(const CStdString& strBaseDir, CFileItemList& items, bool albumArtistsOnly = false, int idGenre = -1, int idAlbum = -1, int idSong = -1, const Filter &filter = Filter(), const SortDescription &sortDescription = SortDescription(), bool countOnly = false);
+ bool GetAlbumsNav(const CStdString& strBaseDir, CFileItemList& items, int idGenre = -1, int idArtist = -1, const Filter &filter = Filter(), const SortDescription &sortDescription = SortDescription(), bool countOnly = false);
bool GetAlbumsByYear(const CStdString &strBaseDir, CFileItemList& items, int year);
bool GetSongsNav(const CStdString& strBaseDir, CFileItemList& items, int idGenre, int idArtist,int idAlbum, const SortDescription &sortDescription = SortDescription());
bool GetSongsByYear(const CStdString& baseDir, CFileItemList& items, int year);
bool GetSongsByWhere(const CStdString &baseDir, const Filter &filter, CFileItemList& items, const SortDescription &sortDescription = SortDescription());
- bool GetAlbumsByWhere(const CStdString &baseDir, const Filter &filter, CFileItemList &items, const SortDescription &sortDescription = SortDescription());
- bool GetArtistsByWhere(const CStdString& strBaseDir, const Filter &filter, CFileItemList& items, const SortDescription &sortDescription = SortDescription());
+ bool GetAlbumsByWhere(const CStdString &baseDir, const Filter &filter, CFileItemList &items, const SortDescription &sortDescription = SortDescription(), bool countOnly = false);
+ bool GetArtistsByWhere(const CStdString& strBaseDir, const Filter &filter, CFileItemList& items, const SortDescription &sortDescription = SortDescription(), bool countOnly = false);
bool GetRandomSong(CFileItem* item, int& idSong, const Filter &filter);
int GetKaraokeSongsCount();
int GetSongsCount(const Filter &filter = Filter());

0 comments on commit b00cd05

Please sign in to comment.