mirror of
https://github.com/clangen/musikcube.git
synced 2025-02-19 15:40:50 +00:00
Fixed broken TrackMetadataQuery, and also implemented generic metadata
queries in CategoryTrackListQuery. CategoryListQuery still unsupported -- that's gonna be the hard one.
This commit is contained in:
parent
14c823fb63
commit
d5ff695eed
src/core/library/query/local
@ -39,7 +39,6 @@
|
||||
|
||||
#include <core/library/track/LibraryTrack.h>
|
||||
#include <core/library/LocalLibraryConstants.h>
|
||||
#include <core/db/Statement.h>
|
||||
|
||||
#include <boost/algorithm/string/case_conv.hpp>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
@ -58,18 +57,15 @@ using namespace musik::core::library::constants;
|
||||
using namespace boost::algorithm;
|
||||
|
||||
static std::map<std::string, std::string> FIELD_TO_FOREIGN_KEY = {
|
||||
std::make_pair(Track::ALBUM, Track::ALBUM_ID),
|
||||
std::make_pair(Track::ARTIST, Track::ARTIST_ID),
|
||||
std::make_pair(Track::GENRE, Track::GENRE_ID),
|
||||
std::make_pair(Track::ALBUM_ARTIST, Track::ALBUM_ARTIST_ID),
|
||||
std::make_pair(Playlists::TABLE_NAME, Playlists::TABLE_NAME)
|
||||
{ Track::ALBUM, Track::ALBUM_ID },
|
||||
{ Track::ARTIST, Track::ARTIST_ID },
|
||||
{ Track::GENRE, Track::GENRE_ID },
|
||||
{ Track::ALBUM_ARTIST, Track::ALBUM_ARTIST_ID },
|
||||
{ Playlists::TABLE_NAME, Playlists::TABLE_NAME }
|
||||
};
|
||||
|
||||
CategoryTrackListQuery::CategoryTrackListQuery(
|
||||
ILibraryPtr library,
|
||||
const std::string& column,
|
||||
int64_t id,
|
||||
const std::string& filter)
|
||||
ILibraryPtr library, const std::string& column, int64_t id, const std::string& filter)
|
||||
{
|
||||
this->library = library;
|
||||
this->id = id;
|
||||
@ -81,11 +77,14 @@ CategoryTrackListQuery::CategoryTrackListQuery(
|
||||
this->filter = "%" + trim_copy(to_lower_copy(filter)) + "%";
|
||||
}
|
||||
|
||||
if (FIELD_TO_FOREIGN_KEY.find(column) == FIELD_TO_FOREIGN_KEY.end()) {
|
||||
throw std::runtime_error("invalid input column specified");
|
||||
if (FIELD_TO_FOREIGN_KEY.find(column) != FIELD_TO_FOREIGN_KEY.end()) {
|
||||
this->type = (column == Playlists::TABLE_NAME) ? Playlist : Regular;
|
||||
this->column = FIELD_TO_FOREIGN_KEY[column]; /* optimized query */
|
||||
}
|
||||
else {
|
||||
this->type = Extended;
|
||||
this->column = column; /* generalized query */
|
||||
}
|
||||
|
||||
this->column = FIELD_TO_FOREIGN_KEY[column];
|
||||
}
|
||||
|
||||
CategoryTrackListQuery::~CategoryTrackListQuery() {
|
||||
@ -111,64 +110,121 @@ size_t CategoryTrackListQuery::GetQueryHash() {
|
||||
return this->hash;
|
||||
}
|
||||
|
||||
bool CategoryTrackListQuery::OnRun(Connection& db) {
|
||||
if (result) {
|
||||
result.reset(new musik::core::TrackList(this->library));
|
||||
headers.reset(new std::set<size_t>());
|
||||
void CategoryTrackListQuery::PlaylistQuery(musik::core::db::Connection &db) {
|
||||
/* playlists are a special case. we already have a query for this, so
|
||||
delegate to that. */
|
||||
GetPlaylistQuery query(this->library, this->id);
|
||||
query.Run(db);
|
||||
this->result = query.GetResult();
|
||||
}
|
||||
|
||||
void CategoryTrackListQuery::RegularQuery(musik::core::db::Connection &db) {
|
||||
/* these are the most common queries in the app, and are more optimized
|
||||
than extended metadata queries. */
|
||||
std::string query =
|
||||
"SELECT DISTINCT t.id, al.name "
|
||||
"FROM tracks t, albums al, artists ar, genres gn "
|
||||
"WHERE t.visible=1 AND t.%s=? AND t.album_id=al.id AND t.visual_genre_id=gn.id AND t.visual_artist_id=ar.id ";
|
||||
|
||||
if (this->filter.size()) {
|
||||
query += " AND (t.title LIKE ? OR al.name LIKE ? OR ar.name LIKE ? OR gn.name LIKE ?) ";
|
||||
}
|
||||
|
||||
if (this->column == Playlists::TABLE_NAME) {
|
||||
/* playlists are a special case. we already have a query for this, so
|
||||
delegate to that. */
|
||||
query += "ORDER BY al.name, disc, track, ar.name %s";
|
||||
query = boost::str(boost::format(query) % this->column % this->GetLimitAndOffset());
|
||||
|
||||
GetPlaylistQuery query(this->library, this->id);
|
||||
query.Run(db);
|
||||
this->result = query.GetResult();
|
||||
Statement trackQuery(query.c_str(), db);
|
||||
|
||||
if (this->filter.size()) {
|
||||
trackQuery.BindInt64(0, this->id);
|
||||
trackQuery.BindText(1, this->filter);
|
||||
trackQuery.BindText(2, this->filter);
|
||||
trackQuery.BindText(3, this->filter);
|
||||
trackQuery.BindText(4, this->filter);
|
||||
}
|
||||
else {
|
||||
/* regular old category query... */
|
||||
trackQuery.BindInt64(0, this->id);
|
||||
}
|
||||
|
||||
std::string lastAlbum;
|
||||
size_t index = 0;
|
||||
this->ProcessResult(trackQuery);
|
||||
}
|
||||
|
||||
void CategoryTrackListQuery::ExtendedQuery(musik::core::db::Connection &db) {
|
||||
int64_t keyId = 0;
|
||||
|
||||
{
|
||||
Statement keyQuery("SELECT DISTINCT id FROM meta_keys WHERE LOWER(name)=LOWER(?)", db);
|
||||
keyQuery.BindText(0, this->column);
|
||||
if (keyQuery.Step() == db::Row) {
|
||||
keyId = keyQuery.ColumnInt64(0);
|
||||
}
|
||||
}
|
||||
|
||||
if (keyId > 0) {
|
||||
/* the core library allows for storage of arbitrary metadata in the form
|
||||
of key/value pairs linked to tracks. they are slower and require additional
|
||||
joins and subqueries, but are fully supported here. */
|
||||
std::string query =
|
||||
"SELECT DISTINCT t.id, al.name "
|
||||
"FROM tracks t, albums al, artists ar, genres gn "
|
||||
"WHERE t.visible=1 AND t.%s=? AND t.album_id=al.id AND t.visual_genre_id=gn.id AND t.visual_artist_id=ar.id ";
|
||||
"FROM tracks t, albums al, artists ar, genres gn, track_meta tm, meta_keys mk, meta_values mv "
|
||||
"WHERE t.visible=1 "
|
||||
" AND t.album_id=al.id AND t.visual_genre_id=gn.id AND t.visual_artist_id=ar.id "
|
||||
" AND t.id=tm.track_id AND tm.meta_value_id=mv.id AND mv.meta_key_id=mk.id "
|
||||
" AND mk.id=? AND mv.id=? ";
|
||||
|
||||
if (this->filter.size()) {
|
||||
query += " AND (t.title LIKE ? OR al.name LIKE ? OR ar.name LIKE ? OR gn.name LIKE ?) ";
|
||||
}
|
||||
|
||||
query += "ORDER BY al.name, disc, track, ar.name %s";
|
||||
|
||||
query = boost::str(boost::format(query) % this->column % this->GetLimitAndOffset());
|
||||
query = boost::str(boost::format(query) % this->GetLimitAndOffset());
|
||||
|
||||
Statement trackQuery(query.c_str(), db);
|
||||
|
||||
int bindOffset = 0;
|
||||
trackQuery.BindInt64(bindOffset++, keyId);
|
||||
trackQuery.BindInt64(bindOffset++, this->id);
|
||||
|
||||
if (this->filter.size()) {
|
||||
trackQuery.BindInt64(0, this->id);
|
||||
trackQuery.BindText(1, this->filter);
|
||||
trackQuery.BindText(2, this->filter);
|
||||
trackQuery.BindText(3, this->filter);
|
||||
trackQuery.BindText(4, this->filter);
|
||||
}
|
||||
else {
|
||||
trackQuery.BindInt64(0, this->id);
|
||||
trackQuery.BindText(bindOffset++, this->filter);
|
||||
trackQuery.BindText(bindOffset++, this->filter);
|
||||
trackQuery.BindText(bindOffset++, this->filter);
|
||||
trackQuery.BindText(bindOffset++, this->filter);
|
||||
}
|
||||
|
||||
while (trackQuery.Step() == Row) {
|
||||
int64_t id = trackQuery.ColumnInt64(0);
|
||||
std::string album = trackQuery.ColumnText(1);
|
||||
|
||||
if (album != lastAlbum) {
|
||||
headers->insert(index);
|
||||
lastAlbum = album;
|
||||
}
|
||||
|
||||
result->Add(id);
|
||||
++index;
|
||||
}
|
||||
this->ProcessResult(trackQuery);
|
||||
}
|
||||
}
|
||||
|
||||
void CategoryTrackListQuery::ProcessResult(musik::core::db::Statement& trackQuery) {
|
||||
std::string lastAlbum;
|
||||
size_t index = 0;
|
||||
|
||||
while (trackQuery.Step() == Row) {
|
||||
int64_t id = trackQuery.ColumnInt64(0);
|
||||
std::string album = trackQuery.ColumnText(1);
|
||||
|
||||
if (album != lastAlbum) {
|
||||
headers->insert(index);
|
||||
lastAlbum = album;
|
||||
}
|
||||
|
||||
result->Add(id);
|
||||
++index;
|
||||
}
|
||||
}
|
||||
|
||||
bool CategoryTrackListQuery::OnRun(Connection& db) {
|
||||
if (result) {
|
||||
result.reset(new musik::core::TrackList(this->library));
|
||||
headers.reset(new std::set<size_t>());
|
||||
}
|
||||
|
||||
switch (this->type) {
|
||||
case Playlist: this->PlaylistQuery(db); break;
|
||||
case Regular: this->RegularQuery(db); break;
|
||||
case Extended: this->ExtendedQuery(db); break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -37,6 +37,7 @@
|
||||
#include <core/db/Connection.h>
|
||||
#include <core/library/track/Track.h>
|
||||
#include <core/library/query/local/LocalQueryBase.h>
|
||||
#include <core/db/Statement.h>
|
||||
|
||||
#include "TrackListQueryBase.h"
|
||||
|
||||
@ -62,10 +63,18 @@ namespace musik { namespace core { namespace db { namespace local {
|
||||
virtual bool OnRun(musik::core::db::Connection &db);
|
||||
|
||||
private:
|
||||
enum Type { Playlist, Regular, Extended };
|
||||
|
||||
void PlaylistQuery(musik::core::db::Connection &db);
|
||||
void RegularQuery(musik::core::db::Connection &db);
|
||||
void ExtendedQuery(musik::core::db::Connection &db);
|
||||
void ProcessResult(musik::core::db::Statement& stmt);
|
||||
|
||||
musik::core::ILibraryPtr library;
|
||||
Result result;
|
||||
Headers headers;
|
||||
std::string column;
|
||||
Type type;
|
||||
int64_t id;
|
||||
size_t hash;
|
||||
std::string filter;
|
||||
|
@ -104,21 +104,20 @@ bool TrackMetadataQuery::OnRun(Connection& db) {
|
||||
result->SetValue(constants::Track::BPM, trackQuery.ColumnText(2));
|
||||
result->SetValue(constants::Track::DURATION, trackQuery.ColumnText(3));
|
||||
result->SetValue(constants::Track::FILESIZE, trackQuery.ColumnText(4));
|
||||
result->SetValue(constants::Track::YEAR, trackQuery.ColumnText(5));
|
||||
result->SetValue(constants::Track::TITLE, trackQuery.ColumnText(6));
|
||||
result->SetValue(constants::Track::FILENAME, trackQuery.ColumnText(7));
|
||||
result->SetValue(constants::Track::THUMBNAIL_ID, trackQuery.ColumnText(8));
|
||||
result->SetValue(constants::Track::ALBUM, trackQuery.ColumnText(9));
|
||||
result->SetValue(constants::Track::ALBUM_ARTIST, trackQuery.ColumnText(10));
|
||||
result->SetValue(constants::Track::GENRE, trackQuery.ColumnText(11));
|
||||
result->SetValue(constants::Track::ARTIST, trackQuery.ColumnText(12));
|
||||
result->SetValue(constants::Track::FILETIME, trackQuery.ColumnText(13));
|
||||
result->SetValue(constants::Track::GENRE_ID, trackQuery.ColumnText(14));
|
||||
result->SetValue(constants::Track::ARTIST_ID, trackQuery.ColumnText(15));
|
||||
result->SetValue(constants::Track::ALBUM_ARTIST_ID, trackQuery.ColumnText(16));
|
||||
result->SetValue(constants::Track::ALBUM_ID, trackQuery.ColumnText(17));
|
||||
result->SetValue(constants::Track::SOURCE_ID, trackQuery.ColumnText(18));
|
||||
result->SetValue(constants::Track::EXTERNAL_ID, trackQuery.ColumnText(19));
|
||||
result->SetValue(constants::Track::TITLE, trackQuery.ColumnText(5));
|
||||
result->SetValue(constants::Track::FILENAME, trackQuery.ColumnText(6));
|
||||
result->SetValue(constants::Track::THUMBNAIL_ID, trackQuery.ColumnText(7));
|
||||
result->SetValue(constants::Track::ALBUM, trackQuery.ColumnText(8));
|
||||
result->SetValue(constants::Track::ALBUM_ARTIST, trackQuery.ColumnText(9));
|
||||
result->SetValue(constants::Track::GENRE, trackQuery.ColumnText(10));
|
||||
result->SetValue(constants::Track::ARTIST, trackQuery.ColumnText(11));
|
||||
result->SetValue(constants::Track::FILETIME, trackQuery.ColumnText(12));
|
||||
result->SetValue(constants::Track::GENRE_ID, trackQuery.ColumnText(13));
|
||||
result->SetValue(constants::Track::ARTIST_ID, trackQuery.ColumnText(14));
|
||||
result->SetValue(constants::Track::ALBUM_ARTIST_ID, trackQuery.ColumnText(15));
|
||||
result->SetValue(constants::Track::ALBUM_ID, trackQuery.ColumnText(16));
|
||||
result->SetValue(constants::Track::SOURCE_ID, trackQuery.ColumnText(17));
|
||||
result->SetValue(constants::Track::EXTERNAL_ID, trackQuery.ColumnText(18));
|
||||
}
|
||||
else {
|
||||
result->SetValue(constants::Track::EXTERNAL_ID, trackQuery.ColumnText(0));
|
||||
|
Loading…
x
Reference in New Issue
Block a user