diff --git a/src/collection/collectionbackend.cpp b/src/collection/collectionbackend.cpp index 826664ee..3809656a 100644 --- a/src/collection/collectionbackend.cpp +++ b/src/collection/collectionbackend.cpp @@ -612,12 +612,14 @@ void CollectionBackend::MarkSongsUnavailable(const SongList &songs, const bool u QStringList CollectionBackend::GetAll(const QString &column, const QueryOptions &opt) { - CollectionQuery query(opt); + QMutexLocker l(db_->Mutex()); + QSqlDatabase db(db_->Connect()); + + CollectionQuery query(db, songs_table_, fts_table_, opt); query.SetColumnSpec("DISTINCT " + column); query.AddCompilationRequirement(false); - QMutexLocker l(db_->Mutex()); - if (!ExecQuery(&query)) return QStringList(); + if (!query.Exec()) return QStringList(); QStringList ret; while (query.Next()) { @@ -634,24 +636,24 @@ QStringList CollectionBackend::GetAllArtists(const QueryOptions &opt) { QStringList CollectionBackend::GetAllArtistsWithAlbums(const QueryOptions &opt) { + QMutexLocker l(db_->Mutex()); + QSqlDatabase db(db_->Connect()); + // Albums with 'albumartist' field set: - CollectionQuery query(opt); + CollectionQuery query(db, songs_table_, fts_table_, opt); query.SetColumnSpec("DISTINCT albumartist"); query.AddCompilationRequirement(false); query.AddWhere("album", "", "!="); // Albums with no 'albumartist' (extract 'artist'): - CollectionQuery query2(opt); + CollectionQuery query2(db, songs_table_, fts_table_, opt); query2.SetColumnSpec("DISTINCT artist"); query2.AddCompilationRequirement(false); query2.AddWhere("album", "", "!="); query2.AddWhere("albumartist", "", "="); - { - QMutexLocker l(db_->Mutex()); - if (!ExecQuery(&query) || !ExecQuery(&query2)) { - return QStringList(); - } + if (!query.Exec() || !query2.Exec()) { + return QStringList(); } QSet artists; @@ -677,28 +679,40 @@ CollectionBackend::AlbumList CollectionBackend::GetAlbumsByArtist(const QString SongList CollectionBackend::GetArtistSongs(const QString &effective_albumartist, const QueryOptions &opt) { - CollectionQuery query(opt); + QSqlDatabase db(db_->Connect()); + QMutexLocker l(db_->Mutex()); + + CollectionQuery query(db, songs_table_, fts_table_, opt); query.AddCompilationRequirement(false); query.AddWhere("effective_albumartist", effective_albumartist); + return ExecCollectionQuery(&query); } SongList CollectionBackend::GetAlbumSongs(const QString &effective_albumartist, const QString &album, const QueryOptions &opt) { - CollectionQuery query(opt); + QSqlDatabase db(db_->Connect()); + QMutexLocker l(db_->Mutex()); + + CollectionQuery query(db, songs_table_, fts_table_, opt); query.AddCompilationRequirement(false); query.AddWhere("effective_albumartist", effective_albumartist); query.AddWhere("album", album); + return ExecCollectionQuery(&query); } SongList CollectionBackend::GetSongsByAlbum(const QString &album, const QueryOptions &opt) { - CollectionQuery query(opt); + QSqlDatabase db(db_->Connect()); + QMutexLocker l(db_->Mutex()); + + CollectionQuery query(db, songs_table_, fts_table_, opt); query.AddCompilationRequirement(false); query.AddWhere("album", album); + return ExecCollectionQuery(&query); } @@ -706,8 +720,8 @@ SongList CollectionBackend::GetSongsByAlbum(const QString &album, const QueryOpt SongList CollectionBackend::ExecCollectionQuery(CollectionQuery *query) { query->SetColumnSpec("%songs_table.ROWID, " + Song::kColumnSpec); - QMutexLocker l(db_->Mutex()); - if (!ExecQuery(query)) return SongList(); + + if (!query->Exec()) return SongList(); SongList ret; while (query->Next()) { @@ -720,12 +734,15 @@ SongList CollectionBackend::ExecCollectionQuery(CollectionQuery *query) { } Song CollectionBackend::GetSongById(const int id) { + QMutexLocker l(db_->Mutex()); QSqlDatabase db(db_->Connect()); return GetSongById(id, db); + } SongList CollectionBackend::GetSongsById(const QList &ids) { + QMutexLocker l(db_->Mutex()); QSqlDatabase db(db_->Connect()); @@ -735,13 +752,16 @@ SongList CollectionBackend::GetSongsById(const QList &ids) { } return GetSongsById(str_ids, db); + } SongList CollectionBackend::GetSongsById(const QStringList &ids) { + QMutexLocker l(db_->Mutex()); QSqlDatabase db(db_->Connect()); return GetSongsById(ids, db); + } SongList CollectionBackend::GetSongsByForeignId(const QStringList &ids, const QString &table, const QString &column) { @@ -769,9 +789,11 @@ SongList CollectionBackend::GetSongsByForeignId(const QStringList &ids, const QS } Song CollectionBackend::GetSongById(const int id, QSqlDatabase &db) { + SongList list = GetSongsById(QStringList() << QString::number(id), db); if (list.isEmpty()) return Song(); return list.first(); + } SongList CollectionBackend::GetSongsById(const QStringList &ids, QSqlDatabase &db) { @@ -897,13 +919,15 @@ CollectionBackend::AlbumList CollectionBackend::GetCompilationAlbums(const Query SongList CollectionBackend::GetCompilationSongs(const QString &album, const QueryOptions &opt) { - CollectionQuery query(opt); + QMutexLocker l(db_->Mutex()); + QSqlDatabase db(db_->Connect()); + + CollectionQuery query(db, songs_table_, fts_table_, opt); query.SetColumnSpec("%songs_table.ROWID, " + Song::kColumnSpec); query.AddCompilationRequirement(true); query.AddWhere("album", album); - QMutexLocker l(db_->Mutex()); - if (!ExecQuery(&query)) return SongList(); + if (!query.Exec()) return SongList(); SongList ret; while (query.Next()) { @@ -1022,7 +1046,10 @@ void CollectionBackend::UpdateCompilations(QSqlQuery &find_song, QSqlQuery &upda CollectionBackend::AlbumList CollectionBackend::GetAlbums(const QString &artist, const bool compilation_required, const QueryOptions &opt) { - CollectionQuery query(opt); + QMutexLocker l(db_->Mutex()); + QSqlDatabase db(db_->Connect()); + + CollectionQuery query(db, songs_table_, fts_table_, opt); query.SetColumnSpec("url, effective_albumartist, album, compilation_effective, art_automatic, art_manual, filetype, cue_path"); query.SetOrderBy("effective_albumartist, album, url"); @@ -1034,10 +1061,7 @@ CollectionBackend::AlbumList CollectionBackend::GetAlbums(const QString &artist, query.AddWhere("effective_albumartist", artist); } - { - QMutexLocker l(db_->Mutex()); - if (!ExecQuery(&query)) return AlbumList(); - } + if (!query.Exec()) return AlbumList(); QMap albums; while (query.Next()) { @@ -1100,19 +1124,21 @@ CollectionBackend::AlbumList CollectionBackend::GetAlbums(const QString &artist, CollectionBackend::Album CollectionBackend::GetAlbumArt(const QString &effective_albumartist, const QString &album) { + QMutexLocker l(db_->Mutex()); + QSqlDatabase db(db_->Connect()); + Album ret; ret.album = album; ret.album_artist = effective_albumartist; - CollectionQuery query = CollectionQuery(QueryOptions()); + CollectionQuery query(db, songs_table_, fts_table_, QueryOptions()); query.SetColumnSpec("art_automatic, art_manual, url"); if (!effective_albumartist.isEmpty()) { query.AddWhere("effective_albumartist", effective_albumartist); } query.AddWhere("album", album); - QMutexLocker l(db_->Mutex()); - if (!ExecQuery(&query)) return ret; + if (!query.Exec()) return ret; if (query.Next()) { ret.art_automatic = QUrl::fromEncoded(query.Value(0).toByteArray()); @@ -1136,12 +1162,12 @@ void CollectionBackend::UpdateManualAlbumArt(const QString &effective_albumartis QSqlDatabase db(db_->Connect()); // Get the songs before they're updated - CollectionQuery query; + CollectionQuery query(db, songs_table_, fts_table_); query.SetColumnSpec("ROWID, " + Song::kColumnSpec); query.AddWhere("effective_albumartist", effective_albumartist); query.AddWhere("album", album); - if (!ExecQuery(&query)) return; + if (!query.Exec()) return; SongList deleted_songs; while (query.Next()) { @@ -1167,7 +1193,7 @@ void CollectionBackend::UpdateManualAlbumArt(const QString &effective_albumartis db_->CheckErrors(q); // Now get the updated songs - if (!ExecQuery(&query)) return; + if (!query.Exec()) return; SongList added_songs; while (query.Next()) { @@ -1195,12 +1221,12 @@ void CollectionBackend::UpdateAutomaticAlbumArt(const QString &effective_albumar QSqlDatabase db(db_->Connect()); // Get the songs before they're updated - CollectionQuery query; + CollectionQuery query(db, songs_table_, fts_table_); query.SetColumnSpec("ROWID, " + Song::kColumnSpec); query.AddWhere("effective_albumartist", effective_albumartist); query.AddWhere("album", album); - if (!ExecQuery(&query)) return; + if (!query.Exec()) return; SongList deleted_songs; while (query.Next()) { @@ -1222,7 +1248,7 @@ void CollectionBackend::UpdateAutomaticAlbumArt(const QString &effective_albumar db_->CheckErrors(q); // Now get the updated songs - if (!ExecQuery(&query)) return; + if (!query.Exec()) return; SongList added_songs; while (query.Next()) { @@ -1246,12 +1272,12 @@ void CollectionBackend::ForceCompilation(const QString &album, const QListCheckErrors(q); // Now get the updated songs - if (!ExecQuery(&query)) return; + if (!query.Exec()) return; while (query.Next()) { Song song(source_); @@ -1290,10 +1316,6 @@ void CollectionBackend::ForceCompilation(const QString &album, const QListCheckErrors(q->Exec(db_->Connect(), songs_table_, fts_table_)); -} - void CollectionBackend::IncrementPlayCount(const int id) { if (id == -1) return; diff --git a/src/collection/collectionbackend.h b/src/collection/collectionbackend.h index de3eef7b..4dcf2062 100644 --- a/src/collection/collectionbackend.h +++ b/src/collection/collectionbackend.h @@ -71,6 +71,9 @@ class CollectionBackendInterface : public QObject { typedef QList AlbumList; virtual QString songs_table() const = 0; + virtual QString fts_table() const = 0; + + virtual Database *db() const = 0; // Get a list of directories in the collection. Emits DirectoriesDiscovered. virtual void LoadDirectoriesAsync() = 0; @@ -111,8 +114,6 @@ class CollectionBackendInterface : public QObject { virtual void AddDirectory(const QString &path) = 0; virtual void RemoveDirectory(const Directory &dir) = 0; - - virtual bool ExecQuery(CollectionQuery *q) = 0; }; class CollectionBackend : public CollectionBackendInterface { @@ -127,9 +128,10 @@ class CollectionBackend : public CollectionBackendInterface { void ExitAsync(); - Database *db() const { return db_; } + Database *db() const override { return db_; } QString songs_table() const override { return songs_table_; } + QString fts_table() const override { return fts_table_; } QString dirs_table() const { return dirs_table_; } QString subdirs_table() const { return subdirs_table_; } @@ -174,7 +176,6 @@ class CollectionBackend : public CollectionBackendInterface { void AddDirectory(const QString &path) override; void RemoveDirectory(const Directory &dir) override; - bool ExecQuery(CollectionQuery *q) override; SongList ExecCollectionQuery(CollectionQuery *query); void IncrementPlayCountAsync(const int id); diff --git a/src/collection/collectionmodel.cpp b/src/collection/collectionmodel.cpp index 83b97d3c..36f7746f 100644 --- a/src/collection/collectionmodel.cpp +++ b/src/collection/collectionmodel.cpp @@ -815,14 +815,20 @@ QVariant CollectionModel::data(const CollectionItem *item, const int role) const } -bool CollectionModel::HasCompilations(const CollectionQuery &query) { +bool CollectionModel::HasCompilations(const QSqlDatabase &db, const CollectionQuery &query) { - CollectionQuery q = query; + CollectionQuery q(db, backend_->songs_table(), backend_->fts_table(), query_options_); + + q.SetColumnSpec(query.column_spec()); + q.SetOrderBy(query.order_by()); + q.SetWhereClauses(query.where_clauses()); + q.SetBoundValues(query.bound_values()); + q.SetIncludeUnavailable(query.include_unavailable()); + q.SetDuplicatesOnly(query.duplicates_only()); q.AddCompilationRequirement(true); q.SetLimit(1); - QMutexLocker l(backend_->db()->Mutex()); - if (!backend_->ExecQuery(&q)) return false; + if (!q.Exec()) return false; return q.Next(); @@ -837,33 +843,39 @@ CollectionModel::QueryResult CollectionModel::RunQuery(CollectionItem *parent) { GroupBy child_type = child_level >= 3 ? GroupBy_None : group_by_[child_level]; // Initialize the query. child_type says what type of thing we want (artists, songs, etc.) - CollectionQuery q(query_options_); - InitQuery(child_type, &q); - // Walk up through the item's parents adding filters as necessary - CollectionItem *p = parent; - while (p && p->type == CollectionItem::Type_Container) { - FilterQuery(group_by_[p->container_level], p, &q); - p = p->parent; - } + { + QMutexLocker l(backend_->db()->Mutex()); + QSqlDatabase db(backend_->db()->Connect()); - // Artists GroupBy is special - we don't want compilation albums appearing - if (IsArtistGroupBy(child_type)) { - // Add the special Various artists node - if (show_various_artists_ && HasCompilations(q)) { - result.create_va = true; + CollectionQuery q(db, backend_->songs_table(), backend_->fts_table(), query_options_); + InitQuery(child_type, &q); + + // Walk up through the item's parents adding filters as necessary + CollectionItem *p = parent; + while (p && p->type == CollectionItem::Type_Container) { + FilterQuery(group_by_[p->container_level], p, &q); + p = p->parent; } - // Don't show compilations again outside the Various artists node - q.AddCompilationRequirement(false); - } + // Artists GroupBy is special - we don't want compilation albums appearing + if (IsArtistGroupBy(child_type)) { + // Add the special Various artists node + if (show_various_artists_ && HasCompilations(db, q)) { + result.create_va = true; + } - // Execute the query - QMutexLocker l(backend_->db()->Mutex()); - if (backend_->ExecQuery(&q)) { - while (q.Next()) { - result.rows << SqlRow(q); + // Don't show compilations again outside the Various artists node + q.AddCompilationRequirement(false); } + + // Execute the query + if (q.Exec()) { + while (q.Next()) { + result.rows << SqlRow(q); + } + } + } if (QThread::currentThread() != thread() && QThread::currentThread() != backend_->thread()) { diff --git a/src/collection/collectionmodel.h b/src/collection/collectionmodel.h index 76f4a347..41303335 100644 --- a/src/collection/collectionmodel.h +++ b/src/collection/collectionmodel.h @@ -239,7 +239,7 @@ class CollectionModel : public SimpleTreeModel { QueryResult RunQuery(CollectionItem *parent); void PostQuery(CollectionItem *parent, const QueryResult &result, const bool signal); - bool HasCompilations(const CollectionQuery &query); + bool HasCompilations(const QSqlDatabase &db, const CollectionQuery &query); void BeginReset(); diff --git a/src/collection/collectionquery.cpp b/src/collection/collectionquery.cpp index 5fa3b544..f1044c94 100644 --- a/src/collection/collectionquery.cpp +++ b/src/collection/collectionquery.cpp @@ -31,14 +31,23 @@ #include #include #include +#include + +#include "core/logging.h" +#include "core/song.h" #include "collectionquery.h" -#include "core/song.h" QueryOptions::QueryOptions() : max_age_(-1), query_mode_(QueryMode_All) {} -CollectionQuery::CollectionQuery(const QueryOptions &options) - : include_unavailable_(false), join_with_fts_(false), limit_(-1) { +CollectionQuery::CollectionQuery(const QSqlDatabase &db, const QString &songs_table, const QString &fts_table, const QueryOptions &options) : + QSqlQuery(db), + songs_table_(songs_table), + fts_table_(fts_table), + include_unavailable_(false), + join_with_fts_(false), + duplicates_only_(false), + limit_(-1) { if (!options.filter().isEmpty()) { // We need to munge the filter text a little bit to get it to work as expected with sqlite's FTS5: @@ -98,7 +107,7 @@ CollectionQuery::CollectionQuery(const QueryOptions &options) bound_values_ << cutoff; } - // TODO: Currently you cannot use any QueryMode other than All and fts at the same time. + // TODO: Currently you cannot use any QueryMode other than All and FTS at the same time. // Joining songs, duplicated_songs and songs_fts all together takes a huge amount of time. // The query takes about 20 seconds on my machine then. Why? // Untagged mode could work with additional filtering but I'm disabling it just to be consistent @@ -123,7 +132,7 @@ QString CollectionQuery::GetInnerQuery() { void CollectionQuery::AddWhere(const QString &column, const QVariant &value, const QString &op) { - // ignore 'literal' for IN + // Ignore 'literal' for IN if (!op.compare("IN", Qt::CaseInsensitive)) { QStringList final; for (const QString &single_value : value.toStringList()) { @@ -168,7 +177,7 @@ void CollectionQuery::AddWhereArtist(const QVariant &value) { } -void CollectionQuery::AddCompilationRequirement(bool compilation) { +void CollectionQuery::AddCompilationRequirement(const bool compilation) { // The unary + is added to prevent sqlite from using the index idx_comp_artist. // When joining with fts, sqlite 3.8 has a tendency to use this index and thereby nesting the tables in an order which gives very poor performance @@ -176,15 +185,15 @@ void CollectionQuery::AddCompilationRequirement(bool compilation) { } -QSqlQuery CollectionQuery::Exec(QSqlDatabase db, const QString &songs_table, const QString &fts_table) { +bool CollectionQuery::Exec() { QString sql; if (join_with_fts_) { - sql = QString("SELECT %1 FROM %2 INNER JOIN %3 AS fts ON %2.ROWID = fts.ROWID").arg(column_spec_, songs_table, fts_table); + sql = QString("SELECT %1 FROM %2 INNER JOIN %3 AS fts ON %2.ROWID = fts.ROWID").arg(column_spec_, songs_table_, fts_table_); } else { - sql = QString("SELECT %1 FROM %2 %3").arg(column_spec_, songs_table, GetInnerQuery()); + sql = QString("SELECT %1 FROM %2 %3").arg(column_spec_, songs_table_, GetInnerQuery()); } QStringList where_clauses(where_clauses_); @@ -198,31 +207,40 @@ QSqlQuery CollectionQuery::Exec(QSqlDatabase db, const QString &songs_table, con if (limit_ != -1) sql += " LIMIT " + QString::number(limit_); - sql.replace("%songs_table", songs_table); - sql.replace("%fts_table_noprefix", fts_table.section('.', -1, -1)); - sql.replace("%fts_table", fts_table); + sql.replace("%songs_table", songs_table_); + sql.replace("%fts_table_noprefix", fts_table_.section('.', -1, -1)); + sql.replace("%fts_table", fts_table_); - query_ = QSqlQuery(db); - query_.prepare(sql); + prepare(sql); // Bind values for (const QVariant &value : bound_values_) { - query_.addBindValue(value); + addBindValue(value); } - query_.exec(); - return query_; + const bool result = exec(); + + if (!result) { + QSqlError last_error = lastError(); + if (last_error.isValid()) { + qLog(Error) << "DB error: " << last_error; + qLog(Error) << "Faulty query: " << lastQuery(); + qLog(Error) << "Bound values: " << boundValues(); + } + } + + return result; } -bool CollectionQuery::Next() { return query_.next(); } +bool CollectionQuery::Next() { return next(); } -QVariant CollectionQuery::Value(int column) const { return query_.value(column); } +QVariant CollectionQuery::Value(const int column) const { return value(column); } bool QueryOptions::Matches(const Song &song) const { if (max_age_ != -1) { - const uint cutoff = QDateTime::currentDateTime().toSecsSinceEpoch() - max_age_; + const qint64 cutoff = QDateTime::currentDateTime().toSecsSinceEpoch() - max_age_; if (song.ctime() <= cutoff) return false; } diff --git a/src/collection/collectionquery.h b/src/collection/collectionquery.h index 3af8e392..a995276d 100644 --- a/src/collection/collectionquery.h +++ b/src/collection/collectionquery.h @@ -39,7 +39,7 @@ struct QueryOptions { // - use the all songs table // - use the duplicated songs view; by duplicated we mean those songs for which the (artist, album, title) tuple is found more than once in the songs table // - use the untagged songs view; by untagged we mean those for which at least one of the (artist, album, title) tags is empty - // Please note that additional filtering based on fts table (the filter attribute) won't work in Duplicates and Untagged modes. + // Please note that additional filtering based on FTS table (the filter attribute) won't work in Duplicates and Untagged modes. enum QueryMode { QueryMode_All, QueryMode_Duplicates, @@ -71,12 +71,13 @@ struct QueryOptions { QueryMode query_mode_; }; -class CollectionQuery { +class CollectionQuery : public QSqlQuery { public: - explicit CollectionQuery(const QueryOptions &options = QueryOptions()); + explicit CollectionQuery(const QSqlDatabase &db, const QString &songs_table, const QString &fts_table, const QueryOptions &options = QueryOptions()); // Sets contents of SELECT clause on the query (list of columns to get). void SetColumnSpec(const QString &spec) { column_spec_ = spec; } + // Sets an ORDER BY clause on the query. void SetOrderBy(const QString &order_by) { order_by_ = order_by; } @@ -85,29 +86,42 @@ class CollectionQuery { void AddWhere(const QString &column, const QVariant &value, const QString &op = "="); void AddWhereArtist(const QVariant &value); - void AddCompilationRequirement(bool compilation); - void SetLimit(int limit) { limit_ = limit; } - void SetIncludeUnavailable(bool include_unavailable) { include_unavailable_ = include_unavailable; } + void SetWhereClauses(const QStringList &where_clauses) { where_clauses_ = where_clauses; } + void SetBoundValues(const QVariantList &bound_values) { bound_values_ = bound_values; } + void SetDuplicatesOnly(const bool duplicates_only) { duplicates_only_ = duplicates_only; } + void SetIncludeUnavailable(const bool include_unavailable) { include_unavailable_ = include_unavailable; } + void SetLimit(const int limit) { limit_ = limit; } + void AddCompilationRequirement(const bool compilation); - QSqlQuery Exec(QSqlDatabase db, const QString &songs_table, const QString &fts_table); + bool Exec(); bool Next(); - QVariant Value(int column) const; + QVariant Value(const int column) const; - operator const QSqlQuery &() const { return query_; } + QString column_spec() const { return column_spec_; } + QString order_by() const { return order_by_; } + QStringList where_clauses() const { return where_clauses_; } + QVariantList bound_values() const { return bound_values_; } + bool include_unavailable() const { return include_unavailable_; } + bool join_with_fts() const { return join_with_fts_; } + bool duplicates_only() const { return duplicates_only_; } + int limit() const { return limit_; } private: QString GetInnerQuery(); - bool include_unavailable_; - bool join_with_fts_; + QSqlDatabase db_; + QString songs_table_; + QString fts_table_; + QString column_spec_; QString order_by_; QStringList where_clauses_; QVariantList bound_values_; - int limit_; - bool duplicates_only_; - QSqlQuery query_; + bool include_unavailable_; + bool join_with_fts_; + bool duplicates_only_; + int limit_; }; #endif // COLLECTIONQUERY_H diff --git a/src/collection/sqlrow.cpp b/src/collection/sqlrow.cpp index 4f72470b..79d94055 100644 --- a/src/collection/sqlrow.cpp +++ b/src/collection/sqlrow.cpp @@ -30,8 +30,6 @@ SqlRow::SqlRow(const QSqlQuery &query) { Init(query); } -SqlRow::SqlRow(const CollectionQuery &query) { Init(query); } - void SqlRow::Init(const QSqlQuery &query) { int rows = query.record().count(); diff --git a/src/collection/sqlrow.h b/src/collection/sqlrow.h index 8d208b0c..dc7c81cc 100644 --- a/src/collection/sqlrow.h +++ b/src/collection/sqlrow.h @@ -32,9 +32,7 @@ class CollectionQuery; class SqlRow { public: - // WARNING: Implicit construction from QSqlQuery and CollectionQuery. SqlRow(const QSqlQuery &query); - SqlRow(const CollectionQuery &query); const QVariant &value(int i) const { return columns_[i]; } diff --git a/src/context/contextalbumsmodel.cpp b/src/context/contextalbumsmodel.cpp index 7c802329..25f0968e 100644 --- a/src/context/contextalbumsmodel.cpp +++ b/src/context/contextalbumsmodel.cpp @@ -249,8 +249,11 @@ QVariant ContextAlbumsModel::data(const CollectionItem *item, int role) const { ContextAlbumsModel::QueryResult ContextAlbumsModel::RunQuery(CollectionItem *parent) { + QMutexLocker l(backend_->db()->Mutex()); + QSqlDatabase db(backend_->db()->Connect()); + QueryResult result; - CollectionQuery q(query_options_); + CollectionQuery q(db, backend_->songs_table(), backend_->fts_table(), query_options_); q.SetColumnSpec("%songs_table.ROWID, " + Song::kColumnSpec); // Walk up through the item's parents adding filters as necessary @@ -263,9 +266,7 @@ ContextAlbumsModel::QueryResult ContextAlbumsModel::RunQuery(CollectionItem *par } // Execute the query - QMutexLocker l(backend_->db()->Mutex()); - - if (!backend_->ExecQuery(&q)) return result; + if (!q.Exec()) return result; while (q.Next()) { result.rows << SqlRow(q); diff --git a/src/core/songloader.cpp b/src/core/songloader.cpp index 44dd2ab9..6a1a7071 100644 --- a/src/core/songloader.cpp +++ b/src/core/songloader.cpp @@ -52,6 +52,7 @@ #include "song.h" #include "songloader.h" #include "tagreaderclient.h" +#include "database.h" #include "engine/enginetype.h" #include "engine/enginebase.h" #include "collection/collectionbackend.h" @@ -222,11 +223,14 @@ SongLoader::Result SongLoader::LoadLocal(const QString &filename) { // Search in the database. QUrl url = QUrl::fromLocalFile(filename); - CollectionQuery query; + QMutexLocker l(collection_->db()->Mutex()); + QSqlDatabase db(collection_->db()->Connect()); + + CollectionQuery query(db, collection_->songs_table(), collection_->fts_table()); query.SetColumnSpec("%songs_table.ROWID, " + Song::kColumnSpec); query.AddWhere("url", url.toEncoded()); - if (collection_->ExecQuery(&query) && query.Next()) { + if (query.Exec() && query.Next()) { // We may have many results when the file has many sections do { Song song(Song::Source_Collection); diff --git a/src/covermanager/albumcovermanager.cpp b/src/covermanager/albumcovermanager.cpp index 2ce8cdba..9af9daa0 100644 --- a/src/covermanager/albumcovermanager.cpp +++ b/src/covermanager/albumcovermanager.cpp @@ -70,6 +70,7 @@ #include "core/utilities.h" #include "core/imageutils.h" #include "core/tagreaderclient.h" +#include "core/database.h" #include "widgets/forcescrollperpixel.h" #include "widgets/qsearchfield.h" #include "collection/sqlrow.h" @@ -888,7 +889,10 @@ SongList AlbumCoverManager::GetSongsInAlbum(const QModelIndex &idx) const { SongList ret; - CollectionQuery q; + QMutexLocker l(collection_backend_->db()->Mutex()); + QSqlDatabase db(collection_backend_->db()->Connect()); + + CollectionQuery q(db, collection_backend_->songs_table(), collection_backend_->fts_table()); q.SetColumnSpec("ROWID," + Song::kColumnSpec); q.AddWhere("album", idx.data(Role_Album).toString()); q.SetOrderBy("disc, track, title"); @@ -900,7 +904,7 @@ SongList AlbumCoverManager::GetSongsInAlbum(const QModelIndex &idx) const { q.AddCompilationRequirement(albumartist.isEmpty()); - if (!collection_backend_->ExecQuery(&q)) return ret; + if (!q.Exec()) return ret; while (q.Next()) { Song song;