From 78c5f37d50ed5687bd5525954838f62b50de0690 Mon Sep 17 00:00:00 2001 From: Jon Bergli Heier Date: Thu, 6 Jan 2011 04:01:17 +0100 Subject: Reworked "find" to allow for more sophisticated searches. The usage of the "find" command is as follows: find SEARCH where SEARCH is either a simple string to search for, or key:value pairs with the following keys: artist album title --- music.cpp | 70 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 64 insertions(+), 6 deletions(-) (limited to 'music.cpp') diff --git a/music.cpp b/music.cpp index eb16226..7356274 100644 --- a/music.cpp +++ b/music.cpp @@ -24,7 +24,7 @@ void music::init(std::string root) { root_directory = root; } -/** Fetches a MusicListing object from the given path. +/** Fetches a MusicListing object from the given \p path. * Prefixes the given path with the music root directory. * This can be either a track (file) or a directory. */ @@ -52,7 +52,7 @@ MusicListing::p music::get(const HTTP::Connection::PathList& path) { return MusicListing::p(); } -/** Fetches a MusicListing object from the given path. +/** Fetches a MusicListing object from the given \p path. * Splits the given string and calls the above function. */ MusicListing::p music::get(const std::string& path) { @@ -74,21 +74,76 @@ MusicDirectory::p music::get_directory(const std::string& path) { return dir; } -std::vector music::find_artist(const std::string artist) { +/** Find tracks in the database. + * Does a search on specific fields given by \p search. + */ +std::vector music::find(std::map search) { + soci::session sql(config::vm["audist.database"].as()); + soci::statement st(sql); + std::string filename, artist, album, title; + st.exchange(soci::into(filename)); + std::string query = "SELECT file_name FROM tracks WHERE "; + std::vector where_conditions; + + if(search.find("artist") != search.end()) { + where_conditions.push_back("artist_id IN (SELECT id FROM artists WHERE name LIKE :artist)"); + artist = "%"+search["artist"]+"%"; + st.exchange(soci::use(artist, "artist")); + } + + if(search.find("album") != search.end()) { + where_conditions.push_back("album_id IN (SELECT id FROM albums WHERE name LIKE :album)"); + album = "%"+search["album"]+"%"; + st.exchange(soci::use(album, "album")); + } + + if(search.find("title") != search.end()) { + where_conditions.push_back("name LIKE :title"); + artist = "%"+search["title"]+"%"; + st.exchange(soci::use(title, "title")); + } + + query += boost::algorithm::join(where_conditions, " AND "); + st.alloc(); + st.prepare(query); + st.define_and_bind(); + std::cout << "query: " << query << std::endl; + std::cout << "st.execute: " << st.execute(true) << std::endl; + std::cout << "st.got_data: " << st.got_data() << std::endl; + + std::vector results; + while(st.fetch()) { + MusicListing::p ml(new MusicTrack(filename)); + results.push_back(ml); + } + sql.close(); + + return results; +} + +/** Find tracks in the database. + * Returns tracks where title, artist, album or filename matches \p search. + */ +std::vector music::find(std::string search) { soci::session sql(config::vm["audist.database"].as()); - soci::rowset rs = (sql.prepare << "SELECT file_name FROM tracks WHERE artist_id IN (SELECT id FROM artists WHERE name LIKE :name)", - soci::use("%"+artist+"%")); + search = "%"+search+"%"; + soci::rowset rs = (sql.prepare << "SELECT DISTINCT file_name FROM tracks WHERE name LIKE :search OR file_name LIKE :search OR " + "artist_id IN (SELECT id FROM artists WHERE name LIKE :search) OR album_id IN (SELECT id FROM albums WHERE name LIKE :search)", + soci::use(search, "search")); std::vector results; for(soci::rowset::const_iterator it = rs.begin(); it != rs.end(); it++) { - boost::shared_ptr ml(new MusicTrack(*it)); + MusicListing::p ml(new MusicTrack(*it)); results.push_back(ml); } return results; } +/** Initiate an update on \p path and its subdirs. + * music::update does the actual work. + */ void music::begin_update(const std::string path) { MusicDirectory::p dir = get_directory(path); std::cout << boost::format("updater(%s) called") % path << std::endl; @@ -97,7 +152,10 @@ void music::begin_update(const std::string path) { } } +/** Recursively update \p dir and its subdirectories. + */ void music::update(const MusicDirectory& dir) { + // TODO: Fix engine-specific SQL syntax inside this function. soci::session sql(config::vm["audist.database"].as()); BOOST_FOREACH(fs::path t, dir.tracks) { -- cgit v1.2.3