Added embedded/external lyrics support: parsing + indexing, ref #379
This commit is contained in:
@@ -46,7 +46,7 @@ namespace lms::db
|
||||
{
|
||||
session.checkWriteTransaction();
|
||||
|
||||
session.getDboSession()->execute("DELETE FROM auth_token WHERE expiry < ?").bind(now);
|
||||
utils::executeCommand(*session.getDboSession(), "DELETE FROM auth_token WHERE expiry < ?", now);
|
||||
}
|
||||
|
||||
AuthToken::pointer AuthToken::find(Session& session, std::string_view value)
|
||||
|
||||
@@ -169,9 +169,11 @@ namespace lms::db
|
||||
query.leftJoin("directory d_child ON d.id = d_child.parent_directory_id");
|
||||
query.leftJoin("track t ON d.id = t.directory_id");
|
||||
query.leftJoin("image i ON d.id = i.directory_id");
|
||||
query.leftJoin("track_lyrics l_lrc ON d.id = l_lrc.directory_id");
|
||||
query.where("d_child.id IS NULL");
|
||||
query.where("t.directory_id IS NULL");
|
||||
query.where("i.directory_id IS NULL");
|
||||
query.where("l_lrc.directory_id IS NULL");
|
||||
|
||||
return utils::execRangeQuery<DirectoryId>(query, range);
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ namespace lms::db
|
||||
{
|
||||
namespace
|
||||
{
|
||||
static constexpr Version LMS_DATABASE_VERSION{ 70 };
|
||||
static constexpr Version LMS_DATABASE_VERSION{ 71 };
|
||||
}
|
||||
|
||||
VersionInfo::VersionInfo()
|
||||
@@ -92,7 +92,7 @@ namespace lms::db::Migration
|
||||
{
|
||||
// remove name from track_artist_link
|
||||
// Drop Auth mode
|
||||
session.getDboSession()->execute(R"(
|
||||
utils::executeCommand(*session.getDboSession(), R"(
|
||||
CREATE TABLE IF NOT EXISTS "track_artist_link_backup" (
|
||||
"id" integer primary key autoincrement,
|
||||
"version" integer not null,
|
||||
@@ -103,49 +103,49 @@ CREATE TABLE IF NOT EXISTS "track_artist_link_backup" (
|
||||
constraint "fk_track_artist_link_artist" foreign key ("artist_id") references "artist" ("id") on delete cascade deferrable initially deferred
|
||||
);
|
||||
))");
|
||||
session.getDboSession()->execute("INSERT INTO track_artist_link_backup SELECT id, version, type, track_id, artist_id FROM track_artist_link");
|
||||
session.getDboSession()->execute("DROP TABLE track_artist_link");
|
||||
session.getDboSession()->execute("ALTER TABLE track_artist_link_backup RENAME TO track_artist_link");
|
||||
utils::executeCommand(*session.getDboSession(), "INSERT INTO track_artist_link_backup SELECT id, version, type, track_id, artist_id FROM track_artist_link");
|
||||
utils::executeCommand(*session.getDboSession(), "DROP TABLE track_artist_link");
|
||||
utils::executeCommand(*session.getDboSession(), "ALTER TABLE track_artist_link_backup RENAME TO track_artist_link");
|
||||
}
|
||||
|
||||
void migrateFromV34(Session& session)
|
||||
{
|
||||
// Add scrobbling state
|
||||
// By default, everything needs to be sent
|
||||
session.getDboSession()->execute("ALTER TABLE starred_artist ADD scrobbling_state INTEGER NOT NULL DEFAULT(" + std::to_string(static_cast<int>(/*ScrobblingState::PendingAdd*/ 0)) + ")");
|
||||
session.getDboSession()->execute("ALTER TABLE starred_release ADD scrobbling_state INTEGER NOT NULL DEFAULT(" + std::to_string(static_cast<int>(/*ScrobblingState::PendingAdd*/ 0)) + ")");
|
||||
session.getDboSession()->execute("ALTER TABLE starred_track ADD scrobbling_state INTEGER NOT NULL DEFAULT(" + std::to_string(static_cast<int>(/*ScrobblingState::PendingAdd*/ 0)) + ")");
|
||||
utils::executeCommand(*session.getDboSession(), "ALTER TABLE starred_artist ADD scrobbling_state INTEGER NOT NULL DEFAULT(" + std::to_string(static_cast<int>(/*ScrobblingState::PendingAdd*/ 0)) + ")");
|
||||
utils::executeCommand(*session.getDboSession(), "ALTER TABLE starred_release ADD scrobbling_state INTEGER NOT NULL DEFAULT(" + std::to_string(static_cast<int>(/*ScrobblingState::PendingAdd*/ 0)) + ")");
|
||||
utils::executeCommand(*session.getDboSession(), "ALTER TABLE starred_track ADD scrobbling_state INTEGER NOT NULL DEFAULT(" + std::to_string(static_cast<int>(/*ScrobblingState::PendingAdd*/ 0)) + ")");
|
||||
}
|
||||
|
||||
void migrateFromV35(Session& session)
|
||||
{
|
||||
// Add creattion/last modif date time for tracklists
|
||||
session.getDboSession()->execute("ALTER TABLE tracklist ADD creation_date_time TEXT");
|
||||
session.getDboSession()->execute("ALTER TABLE tracklist ADD last_modified_date_time TEXT");
|
||||
utils::executeCommand(*session.getDboSession(), "ALTER TABLE tracklist ADD creation_date_time TEXT");
|
||||
utils::executeCommand(*session.getDboSession(), "ALTER TABLE tracklist ADD last_modified_date_time TEXT");
|
||||
}
|
||||
|
||||
void migrateFromV36(Session& session)
|
||||
{
|
||||
// Increased precision for track durations (now in milliseconds instead of secodns)
|
||||
// Just increment the scan version of the settings to make the next scheduled scan rescan everything
|
||||
session.getDboSession()->execute("UPDATE scan_settings SET scan_version = scan_version + 1");
|
||||
utils::executeCommand(*session.getDboSession(), "UPDATE scan_settings SET scan_version = scan_version + 1");
|
||||
}
|
||||
|
||||
void migrateFromV37(Session& session)
|
||||
{
|
||||
// Support Performer tags (via subtypes)
|
||||
session.getDboSession()->execute("ALTER TABLE track_artist_link ADD subtype TEXT");
|
||||
utils::executeCommand(*session.getDboSession(), "ALTER TABLE track_artist_link ADD subtype TEXT");
|
||||
|
||||
// Just increment the scan version of the settings to make the next scheduled scan rescan everything
|
||||
session.getDboSession()->execute("UPDATE scan_settings SET scan_version = scan_version + 1");
|
||||
utils::executeCommand(*session.getDboSession(), "UPDATE scan_settings SET scan_version = scan_version + 1");
|
||||
}
|
||||
|
||||
void migrateFromV38(Session& session)
|
||||
{
|
||||
// migrate release-specific tags from Track to Release
|
||||
session.getDboSession()->execute("ALTER TABLE release ADD total_disc INTEGER");
|
||||
utils::executeCommand(*session.getDboSession(), "ALTER TABLE release ADD total_disc INTEGER");
|
||||
|
||||
session.getDboSession()->execute(R"(
|
||||
utils::executeCommand(*session.getDboSession(), R"(
|
||||
CREATE TABLE IF NOT EXISTS "track_backup" (
|
||||
"id" integer primary key autoincrement,
|
||||
"version" integer not null,
|
||||
@@ -172,158 +172,158 @@ CREATE TABLE IF NOT EXISTS "track_backup" (
|
||||
constraint "fk_track_release" foreign key ("release_id") references "release" ("id") on delete cascade deferrable initially deferred
|
||||
);
|
||||
))");
|
||||
session.getDboSession()->execute("INSERT INTO track_backup SELECT id, version, scan_version, track_number, disc_number, total_track, disc_subtitle, name, duration, date, original_date, file_path, file_last_write, file_added, has_cover, mbid, recording_mbid, copyright, copyright_url, track_replay_gain, release_replay_gain, release_id FROM track");
|
||||
session.getDboSession()->execute("DROP TABLE track");
|
||||
session.getDboSession()->execute("ALTER TABLE track_backup RENAME TO track");
|
||||
utils::executeCommand(*session.getDboSession(), "INSERT INTO track_backup SELECT id, version, scan_version, track_number, disc_number, total_track, disc_subtitle, name, duration, date, original_date, file_path, file_last_write, file_added, has_cover, mbid, recording_mbid, copyright, copyright_url, track_replay_gain, release_replay_gain, release_id FROM track");
|
||||
utils::executeCommand(*session.getDboSession(), "DROP TABLE track");
|
||||
utils::executeCommand(*session.getDboSession(), "ALTER TABLE track_backup RENAME TO track");
|
||||
|
||||
// Just increment the scan version of the settings to make the next scheduled scan rescan everything
|
||||
session.getDboSession()->execute("UPDATE scan_settings SET scan_version = scan_version + 1");
|
||||
utils::executeCommand(*session.getDboSession(), "UPDATE scan_settings SET scan_version = scan_version + 1");
|
||||
}
|
||||
|
||||
void migrateFromV39(Session& session)
|
||||
{
|
||||
// add release type
|
||||
session.getDboSession()->execute("ALTER TABLE release ADD primary_type INTEGER");
|
||||
session.getDboSession()->execute("ALTER TABLE release ADD secondary_types INTEGER");
|
||||
utils::executeCommand(*session.getDboSession(), "ALTER TABLE release ADD primary_type INTEGER");
|
||||
utils::executeCommand(*session.getDboSession(), "ALTER TABLE release ADD secondary_types INTEGER");
|
||||
|
||||
// Just increment the scan version of the settings to make the next scheduled scan rescan everything
|
||||
session.getDboSession()->execute("UPDATE scan_settings SET scan_version = scan_version + 1");
|
||||
utils::executeCommand(*session.getDboSession(), "UPDATE scan_settings SET scan_version = scan_version + 1");
|
||||
}
|
||||
|
||||
void migrateFromV40(Session& session)
|
||||
{
|
||||
// add artist_display_name in Release and Track
|
||||
session.getDboSession()->execute("ALTER TABLE release ADD artist_display_name TEXT NOT NULL DEFAULT ''");
|
||||
session.getDboSession()->execute("ALTER TABLE track ADD artist_display_name TEXT NOT NULL DEFAULT ''");
|
||||
utils::executeCommand(*session.getDboSession(), "ALTER TABLE release ADD artist_display_name TEXT NOT NULL DEFAULT ''");
|
||||
utils::executeCommand(*session.getDboSession(), "ALTER TABLE track ADD artist_display_name TEXT NOT NULL DEFAULT ''");
|
||||
|
||||
// Just increment the scan version of the settings to make the next scheduled scan rescan everything
|
||||
session.getDboSession()->execute("UPDATE scan_settings SET scan_version = scan_version + 1");
|
||||
utils::executeCommand(*session.getDboSession(), "UPDATE scan_settings SET scan_version = scan_version + 1");
|
||||
}
|
||||
|
||||
void migrateFromV41(Session& session)
|
||||
{
|
||||
// add artist_display_name in Release and Track
|
||||
session.getDboSession()->execute("ALTER TABLE user RENAME COLUMN subsonic_transcode_format TO subsonic_default_transcode_format");
|
||||
session.getDboSession()->execute("ALTER TABLE user RENAME COLUMN subsonic_transcode_bitrate TO subsonic_default_transcode_bitrate");
|
||||
session.getDboSession()->execute("ALTER TABLE user DROP COLUMN subsonic_transcode_enable");
|
||||
utils::executeCommand(*session.getDboSession(), "ALTER TABLE user RENAME COLUMN subsonic_transcode_format TO subsonic_default_transcode_format");
|
||||
utils::executeCommand(*session.getDboSession(), "ALTER TABLE user RENAME COLUMN subsonic_transcode_bitrate TO subsonic_default_transcode_bitrate");
|
||||
utils::executeCommand(*session.getDboSession(), "ALTER TABLE user DROP COLUMN subsonic_transcode_enable");
|
||||
}
|
||||
|
||||
void migrateFromV42(Session& session)
|
||||
{
|
||||
session.getDboSession()->execute("DROP INDEX IF EXISTS listen_scrobbler_idx");
|
||||
session.getDboSession()->execute("DROP INDEX IF EXISTS listen_user_scrobbler_idx");
|
||||
session.getDboSession()->execute("DROP INDEX IF EXISTS listen_user_track_scrobbler_date_time_idx");
|
||||
session.getDboSession()->execute("DROP INDEX IF EXISTS starred_artist_user_scrobbler_idx");
|
||||
session.getDboSession()->execute("DROP INDEX IF EXISTS starred_artist_artist_user_scrobbler_idx");
|
||||
session.getDboSession()->execute("DROP INDEX IF EXISTS starred_release_user_scrobbler_idx");
|
||||
session.getDboSession()->execute("DROP INDEX IF EXISTS starred_release_release_user_scrobbler_idx");
|
||||
session.getDboSession()->execute("DROP INDEX IF EXISTS starred_track_user_scrobbler_idx");
|
||||
session.getDboSession()->execute("DROP INDEX IF EXISTS starred_track_track_user_scrobbler_idx");
|
||||
utils::executeCommand(*session.getDboSession(), "DROP INDEX IF EXISTS listen_scrobbler_idx");
|
||||
utils::executeCommand(*session.getDboSession(), "DROP INDEX IF EXISTS listen_user_scrobbler_idx");
|
||||
utils::executeCommand(*session.getDboSession(), "DROP INDEX IF EXISTS listen_user_track_scrobbler_date_time_idx");
|
||||
utils::executeCommand(*session.getDboSession(), "DROP INDEX IF EXISTS starred_artist_user_scrobbler_idx");
|
||||
utils::executeCommand(*session.getDboSession(), "DROP INDEX IF EXISTS starred_artist_artist_user_scrobbler_idx");
|
||||
utils::executeCommand(*session.getDboSession(), "DROP INDEX IF EXISTS starred_release_user_scrobbler_idx");
|
||||
utils::executeCommand(*session.getDboSession(), "DROP INDEX IF EXISTS starred_release_release_user_scrobbler_idx");
|
||||
utils::executeCommand(*session.getDboSession(), "DROP INDEX IF EXISTS starred_track_user_scrobbler_idx");
|
||||
utils::executeCommand(*session.getDboSession(), "DROP INDEX IF EXISTS starred_track_track_user_scrobbler_idx");
|
||||
|
||||
// New feedback service that now handles the star/unstar stuff (that was previously handled by the scrobbling service)
|
||||
session.getDboSession()->execute("ALTER TABLE user RENAME COLUMN scrobbler TO scrobbling_backend");
|
||||
session.getDboSession()->execute("ALTER TABLE user ADD feedback_backend INTEGER");
|
||||
session.getDboSession()->execute("ALTER TABLE listen RENAME COLUMN scrobbler TO backend");
|
||||
session.getDboSession()->execute("ALTER TABLE listen RENAME COLUMN scrobbling_state TO sync_state");
|
||||
session.getDboSession()->execute("ALTER TABLE starred_artist RENAME COLUMN scrobbler TO backend");
|
||||
session.getDboSession()->execute("ALTER TABLE starred_artist RENAME COLUMN scrobbling_state TO sync_state");
|
||||
session.getDboSession()->execute("ALTER TABLE starred_release RENAME COLUMN scrobbler TO backend");
|
||||
session.getDboSession()->execute("ALTER TABLE starred_release RENAME COLUMN scrobbling_state TO sync_state");
|
||||
session.getDboSession()->execute("ALTER TABLE starred_track RENAME COLUMN scrobbler TO backend");
|
||||
session.getDboSession()->execute("ALTER TABLE starred_track RENAME COLUMN scrobbling_state TO sync_state");
|
||||
utils::executeCommand(*session.getDboSession(), "ALTER TABLE user RENAME COLUMN scrobbler TO scrobbling_backend");
|
||||
utils::executeCommand(*session.getDboSession(), "ALTER TABLE user ADD feedback_backend INTEGER");
|
||||
utils::executeCommand(*session.getDboSession(), "ALTER TABLE listen RENAME COLUMN scrobbler TO backend");
|
||||
utils::executeCommand(*session.getDboSession(), "ALTER TABLE listen RENAME COLUMN scrobbling_state TO sync_state");
|
||||
utils::executeCommand(*session.getDboSession(), "ALTER TABLE starred_artist RENAME COLUMN scrobbler TO backend");
|
||||
utils::executeCommand(*session.getDboSession(), "ALTER TABLE starred_artist RENAME COLUMN scrobbling_state TO sync_state");
|
||||
utils::executeCommand(*session.getDboSession(), "ALTER TABLE starred_release RENAME COLUMN scrobbler TO backend");
|
||||
utils::executeCommand(*session.getDboSession(), "ALTER TABLE starred_release RENAME COLUMN scrobbling_state TO sync_state");
|
||||
utils::executeCommand(*session.getDboSession(), "ALTER TABLE starred_track RENAME COLUMN scrobbler TO backend");
|
||||
utils::executeCommand(*session.getDboSession(), "ALTER TABLE starred_track RENAME COLUMN scrobbling_state TO sync_state");
|
||||
|
||||
session.getDboSession()->execute("UPDATE user SET feedback_backend = scrobbling_backend");
|
||||
utils::executeCommand(*session.getDboSession(), "UPDATE user SET feedback_backend = scrobbling_backend");
|
||||
}
|
||||
|
||||
void migrateFromV43(Session& session)
|
||||
{
|
||||
// add counts in genre table
|
||||
session.getDboSession()->execute("ALTER TABLE cluster ADD track_count INTEGER");
|
||||
session.getDboSession()->execute("ALTER TABLE cluster ADD release_count INTEGER");
|
||||
utils::executeCommand(*session.getDboSession(), "ALTER TABLE cluster ADD track_count INTEGER");
|
||||
utils::executeCommand(*session.getDboSession(), "ALTER TABLE cluster ADD release_count INTEGER");
|
||||
|
||||
// Just increment the scan version of the settings to make the next scheduled scan rescan everything
|
||||
session.getDboSession()->execute("UPDATE scan_settings SET scan_version = scan_version + 1");
|
||||
utils::executeCommand(*session.getDboSession(), "UPDATE scan_settings SET scan_version = scan_version + 1");
|
||||
}
|
||||
|
||||
void migrateFromV44(Session& session)
|
||||
{
|
||||
// add bitrate
|
||||
session.getDboSession()->execute("ALTER TABLE track ADD bitrate INTEGER NOT NULL DEFAULT 0");
|
||||
utils::executeCommand(*session.getDboSession(), "ALTER TABLE track ADD bitrate INTEGER NOT NULL DEFAULT 0");
|
||||
|
||||
// Just increment the scan version of the settings to make the next scheduled scan rescan everything
|
||||
session.getDboSession()->execute("UPDATE scan_settings SET scan_version = scan_version + 1");
|
||||
utils::executeCommand(*session.getDboSession(), "UPDATE scan_settings SET scan_version = scan_version + 1");
|
||||
}
|
||||
|
||||
void migrateFromV45(Session& session)
|
||||
{
|
||||
// add subsonic_enable_transcoding_by_default, default is disabled
|
||||
session.getDboSession()->execute("ALTER TABLE user ADD subsonic_enable_transcoding_by_default INTEGER NOT NULL DEFAULT(" + std::to_string(static_cast<int>(/*User::defaultSubsonicEnableTranscodingByDefault*/ 0)) + ")");
|
||||
utils::executeCommand(*session.getDboSession(), "ALTER TABLE user ADD subsonic_enable_transcoding_by_default INTEGER NOT NULL DEFAULT(" + std::to_string(static_cast<int>(/*User::defaultSubsonicEnableTranscodingByDefault*/ 0)) + ")");
|
||||
}
|
||||
|
||||
void migrateFromV46(Session& session)
|
||||
{
|
||||
// add extra tags to parse
|
||||
session.getDboSession()->execute(R"(CREATE TABLE IF NOT EXISTS "cluster_type_backup" (
|
||||
utils::executeCommand(*session.getDboSession(), R"(CREATE TABLE IF NOT EXISTS "cluster_type_backup" (
|
||||
"id" integer primary key autoincrement,
|
||||
"version" integer not null,
|
||||
"name" text not null
|
||||
);)");
|
||||
session.getDboSession()->execute("INSERT INTO cluster_type_backup SELECT id, version, name FROM cluster_type");
|
||||
session.getDboSession()->execute("DROP TABLE cluster_type");
|
||||
session.getDboSession()->execute("ALTER TABLE cluster_type_backup RENAME TO cluster_type");
|
||||
utils::executeCommand(*session.getDboSession(), "INSERT INTO cluster_type_backup SELECT id, version, name FROM cluster_type");
|
||||
utils::executeCommand(*session.getDboSession(), "DROP TABLE cluster_type");
|
||||
utils::executeCommand(*session.getDboSession(), "ALTER TABLE cluster_type_backup RENAME TO cluster_type");
|
||||
|
||||
session.getDboSession()->execute("ALTER TABLE scan_settings ADD COLUMN extra_tags_to_scan TEXT");
|
||||
utils::executeCommand(*session.getDboSession(), "ALTER TABLE scan_settings ADD COLUMN extra_tags_to_scan TEXT");
|
||||
|
||||
// Just increment the scan version of the settings to make the next scheduled scan rescan everything
|
||||
session.getDboSession()->execute("UPDATE scan_settings SET scan_version = scan_version + 1");
|
||||
utils::executeCommand(*session.getDboSession(), "UPDATE scan_settings SET scan_version = scan_version + 1");
|
||||
}
|
||||
|
||||
void migrateFromV47(Session& session)
|
||||
{
|
||||
// release type, new way
|
||||
session.getDboSession()->execute("ALTER TABLE release DROP primary_type");
|
||||
session.getDboSession()->execute("ALTER TABLE release DROP secondary_types");
|
||||
utils::executeCommand(*session.getDboSession(), "ALTER TABLE release DROP primary_type");
|
||||
utils::executeCommand(*session.getDboSession(), "ALTER TABLE release DROP secondary_types");
|
||||
|
||||
session.getDboSession()->execute(R"(CREATE TABLE IF NOT EXISTS "release_type" (
|
||||
utils::executeCommand(*session.getDboSession(), R"(CREATE TABLE IF NOT EXISTS "release_type" (
|
||||
"id" integer primary key autoincrement,
|
||||
"version" integer not null,
|
||||
"name" text not null))");
|
||||
|
||||
session.getDboSession()->execute(R"(CREATE TABLE IF NOT EXISTS "release_release_type" (
|
||||
utils::executeCommand(*session.getDboSession(), R"(CREATE TABLE IF NOT EXISTS "release_release_type" (
|
||||
"release_type_id" bigint,
|
||||
"release_id" bigint,
|
||||
primary key ("release_type_id", "release_id"),
|
||||
constraint "fk_release_release_type_key1" foreign key ("release_type_id") references "release_type" ("id") on delete cascade deferrable initially deferred,
|
||||
constraint "fk_release_release_type_key2" foreign key ("release_id") references "release" ("id") on delete cascade deferrable initially deferred
|
||||
))");
|
||||
session.getDboSession()->execute(R"(CREATE INDEX "release_release_type_release_type" on "release_release_type" ("release_type_id"))");
|
||||
session.getDboSession()->execute(R"(CREATE INDEX "release_release_type_release" on "release_release_type" ("release_id"))");
|
||||
utils::executeCommand(*session.getDboSession(), R"(CREATE INDEX "release_release_type_release_type" on "release_release_type" ("release_type_id"))");
|
||||
utils::executeCommand(*session.getDboSession(), R"(CREATE INDEX "release_release_type_release" on "release_release_type" ("release_id"))");
|
||||
|
||||
// Just increment the scan version of the settings to make the next scheduled scan rescan everything
|
||||
session.getDboSession()->execute("UPDATE scan_settings SET scan_version = scan_version + 1");
|
||||
utils::executeCommand(*session.getDboSession(), "UPDATE scan_settings SET scan_version = scan_version + 1");
|
||||
}
|
||||
|
||||
void migrateFromV48(Session& session)
|
||||
{
|
||||
// Regression for the extra tags not being parsed
|
||||
// Just increment the scan version of the settings to make the next scheduled scan rescan everything
|
||||
session.getDboSession()->execute("UPDATE scan_settings SET scan_version = scan_version + 1");
|
||||
utils::executeCommand(*session.getDboSession(), "UPDATE scan_settings SET scan_version = scan_version + 1");
|
||||
}
|
||||
|
||||
void migrateFromV49(Session& session)
|
||||
{
|
||||
// Add year / originalYear fields, as date / originalDate are not enough (we don't want a wrong date but year or nothing)
|
||||
session.getDboSession()->execute("ALTER TABLE track ADD year INTEGER");
|
||||
session.getDboSession()->execute("ALTER TABLE track ADD original_year INTEGER");
|
||||
utils::executeCommand(*session.getDboSession(), "ALTER TABLE track ADD year INTEGER");
|
||||
utils::executeCommand(*session.getDboSession(), "ALTER TABLE track ADD original_year INTEGER");
|
||||
|
||||
// Just increment the scan version of the settings to make the next scheduled scan rescan everything
|
||||
session.getDboSession()->execute("UPDATE scan_settings SET scan_version = scan_version + 1");
|
||||
utils::executeCommand(*session.getDboSession(), "UPDATE scan_settings SET scan_version = scan_version + 1");
|
||||
}
|
||||
|
||||
void migrateFromV50(Session& session)
|
||||
{
|
||||
// MediaLibrary support
|
||||
session.getDboSession()->execute(R"(CREATE TABLE IF NOT EXISTS "media_library" (
|
||||
utils::executeCommand(*session.getDboSession(), R"(CREATE TABLE IF NOT EXISTS "media_library" (
|
||||
"id" integer primary key autoincrement,
|
||||
"version" integer not null,
|
||||
"path" text not null,
|
||||
@@ -333,17 +333,17 @@ CREATE TABLE IF NOT EXISTS "track_backup" (
|
||||
const int scanSettingsId{ session.getDboSession()->query<int>("SELECT id FROM scan_settings") };
|
||||
|
||||
// Convert the existing media_directory in the scan_settings table to a media_library with id '1'
|
||||
session.getDboSession()->execute(R"(INSERT INTO "media_library" ("id", "version", "path", "name")
|
||||
utils::executeCommand(*session.getDboSession(), R"(INSERT INTO "media_library" ("id", "version", "path", "name")
|
||||
SELECT 1, 0, s_s.media_directory, "Main"
|
||||
FROM scan_settings s_s
|
||||
WHERE id = ?)")
|
||||
.bind(scanSettingsId);
|
||||
WHERE id = ?)",
|
||||
scanSettingsId);
|
||||
|
||||
// Remove the outdated column in scan_settings
|
||||
session.getDboSession()->execute("ALTER TABLE scan_settings DROP media_directory");
|
||||
utils::executeCommand(*session.getDboSession(), "ALTER TABLE scan_settings DROP media_directory");
|
||||
|
||||
// Add the media_library column in tracks, with id '1'
|
||||
session.getDboSession()->execute(R"(
|
||||
utils::executeCommand(*session.getDboSession(), R"(
|
||||
CREATE TABLE IF NOT EXISTS "track_backup" (
|
||||
"id" integer primary key autoincrement,
|
||||
"version" integer not null,
|
||||
@@ -377,7 +377,7 @@ CREATE TABLE IF NOT EXISTS "track_backup" (
|
||||
))");
|
||||
|
||||
// Migrate data, with the new media_library_id field set to 1
|
||||
session.getDboSession()->execute(R"(INSERT INTO track_backup
|
||||
utils::executeCommand(*session.getDboSession(), R"(INSERT INTO track_backup
|
||||
SELECT
|
||||
id,
|
||||
version,
|
||||
@@ -407,55 +407,55 @@ SELECT
|
||||
release_id,
|
||||
1
|
||||
FROM track)");
|
||||
session.getDboSession()->execute("DROP TABLE track");
|
||||
session.getDboSession()->execute("ALTER TABLE track_backup RENAME TO track");
|
||||
utils::executeCommand(*session.getDboSession(), "DROP TABLE track");
|
||||
utils::executeCommand(*session.getDboSession(), "ALTER TABLE track_backup RENAME TO track");
|
||||
}
|
||||
|
||||
void migrateFromV51(Session& session)
|
||||
{
|
||||
// Add custom artist tag delimiters, no need to rescan since it has no effect when empty
|
||||
session.getDboSession()->execute("ALTER TABLE scan_settings ADD artist_tag_delimiters TEXT NOT NULL DEFAULT ''");
|
||||
session.getDboSession()->execute("ALTER TABLE scan_settings ADD default_tag_delimiters TEXT NOT NULL DEFAULT ''");
|
||||
utils::executeCommand(*session.getDboSession(), "ALTER TABLE scan_settings ADD artist_tag_delimiters TEXT NOT NULL DEFAULT ''");
|
||||
utils::executeCommand(*session.getDboSession(), "ALTER TABLE scan_settings ADD default_tag_delimiters TEXT NOT NULL DEFAULT ''");
|
||||
}
|
||||
|
||||
void migrateFromV52(Session& session)
|
||||
{
|
||||
// Add sort name for releases
|
||||
session.getDboSession()->execute("ALTER TABLE release ADD sort_name TEXT NOT NULL DEFAULT ''");
|
||||
utils::executeCommand(*session.getDboSession(), "ALTER TABLE release ADD sort_name TEXT NOT NULL DEFAULT ''");
|
||||
|
||||
// Just increment the scan version of the settings to make the next scheduled scan rescan everything
|
||||
session.getDboSession()->execute("UPDATE scan_settings SET scan_version = scan_version + 1");
|
||||
utils::executeCommand(*session.getDboSession(), "UPDATE scan_settings SET scan_version = scan_version + 1");
|
||||
}
|
||||
|
||||
void migrateFromV53(Session& session)
|
||||
{
|
||||
// Add release group mbid
|
||||
session.getDboSession()->execute("ALTER TABLE release ADD group_mbid TEXT NOT NULL DEFAULT ''");
|
||||
utils::executeCommand(*session.getDboSession(), "ALTER TABLE release ADD group_mbid TEXT NOT NULL DEFAULT ''");
|
||||
|
||||
// Just increment the scan version of the settings to make the next scheduled scan rescan everything
|
||||
session.getDboSession()->execute("UPDATE scan_settings SET scan_version = scan_version + 1");
|
||||
utils::executeCommand(*session.getDboSession(), "UPDATE scan_settings SET scan_version = scan_version + 1");
|
||||
}
|
||||
|
||||
void migrateFromV54(Session& session)
|
||||
{
|
||||
// Add file size + relative file path
|
||||
session.getDboSession()->execute("ALTER TABLE track RENAME COLUMN file_path TO absolute_file_path");
|
||||
session.getDboSession()->execute("ALTER TABLE track ADD file_size BIGINT NOT NULL DEFAULT(0)");
|
||||
session.getDboSession()->execute("ALTER TABLE track ADD relative_file_path TEXT NOT NULL DEFAULT ''");
|
||||
utils::executeCommand(*session.getDboSession(), "ALTER TABLE track RENAME COLUMN file_path TO absolute_file_path");
|
||||
utils::executeCommand(*session.getDboSession(), "ALTER TABLE track ADD file_size BIGINT NOT NULL DEFAULT(0)");
|
||||
utils::executeCommand(*session.getDboSession(), "ALTER TABLE track ADD relative_file_path TEXT NOT NULL DEFAULT ''");
|
||||
|
||||
// Just increment the scan version of the settings to make the next scheduled scan rescan everything
|
||||
session.getDboSession()->execute("UPDATE scan_settings SET scan_version = scan_version + 1");
|
||||
utils::executeCommand(*session.getDboSession(), "UPDATE scan_settings SET scan_version = scan_version + 1");
|
||||
}
|
||||
|
||||
void migrateFromV55(Session& session)
|
||||
{
|
||||
// Add bitsPerSample, channelCount and sampleRate
|
||||
session.getDboSession()->execute("ALTER TABLE track ADD bits_per_sample INTEGER NOT NULL DEFAULT(0)");
|
||||
session.getDboSession()->execute("ALTER TABLE track ADD channel_count INTEGER NOT NULL DEFAULT(0)");
|
||||
session.getDboSession()->execute("ALTER TABLE track ADD sample_rate INTEGER NOT NULL DEFAULT(0)");
|
||||
utils::executeCommand(*session.getDboSession(), "ALTER TABLE track ADD bits_per_sample INTEGER NOT NULL DEFAULT(0)");
|
||||
utils::executeCommand(*session.getDboSession(), "ALTER TABLE track ADD channel_count INTEGER NOT NULL DEFAULT(0)");
|
||||
utils::executeCommand(*session.getDboSession(), "ALTER TABLE track ADD sample_rate INTEGER NOT NULL DEFAULT(0)");
|
||||
|
||||
// Just increment the scan version of the settings to make the next scheduled scan rescan everything
|
||||
session.getDboSession()->execute("UPDATE scan_settings SET scan_version = scan_version + 1");
|
||||
utils::executeCommand(*session.getDboSession(), "UPDATE scan_settings SET scan_version = scan_version + 1");
|
||||
}
|
||||
|
||||
void migrateFromV56(Session& session)
|
||||
@@ -463,25 +463,25 @@ SELECT
|
||||
// Make sure we remove all the previoulsy created index, the createIndexesIfNeeded will recreate them all
|
||||
std::vector<std::string> indexeNames{ utils::fetchQueryResults(session.getDboSession()->query<std::string>(R"(SELECT name FROM sqlite_master WHERE type = 'index' AND name LIKE '%_idx')")) };
|
||||
for (const auto& indexName : indexeNames)
|
||||
session.getDboSession()->execute("DROP INDEX " + indexName);
|
||||
utils::executeCommand(*session.getDboSession(), "DROP INDEX " + indexName);
|
||||
}
|
||||
|
||||
void migrateFromV57(Session& session)
|
||||
{
|
||||
// useless index, may have been already removed in the previous step
|
||||
session.getDboSession()->execute("DROP INDEX IF EXISTS cluster_name_idx");
|
||||
utils::executeCommand(*session.getDboSession(), "DROP INDEX IF EXISTS cluster_name_idx");
|
||||
}
|
||||
|
||||
void migrateFromV58(Session& session)
|
||||
{
|
||||
// DSF support
|
||||
session.getDboSession()->execute("UPDATE scan_settings SET audio_file_extensions = audio_file_extensions || ' .dsf'");
|
||||
utils::executeCommand(*session.getDboSession(), "UPDATE scan_settings SET audio_file_extensions = audio_file_extensions || ' .dsf'");
|
||||
}
|
||||
|
||||
void migrateFromV59(Session& session)
|
||||
{
|
||||
// Dedicated image table
|
||||
session.getDboSession()->execute(R"(CREATE TABLE IF NOT EXISTS "image" (
|
||||
utils::executeCommand(*session.getDboSession(), R"(CREATE TABLE IF NOT EXISTS "image" (
|
||||
"id" integer primary key autoincrement,
|
||||
"version" integer not null,
|
||||
"path" text not null,
|
||||
@@ -495,13 +495,13 @@ SELECT
|
||||
))");
|
||||
|
||||
// Just increment the scan version of the settings to make the next scheduled scan rescan everything
|
||||
session.getDboSession()->execute("UPDATE scan_settings SET scan_version = scan_version + 1");
|
||||
utils::executeCommand(*session.getDboSession(), "UPDATE scan_settings SET scan_version = scan_version + 1");
|
||||
}
|
||||
|
||||
void migrateFromV60(Session& session)
|
||||
{
|
||||
// Dedicated directory table
|
||||
session.getDboSession()->execute(R"(CREATE TABLE IF NOT EXISTS "directory" (
|
||||
utils::executeCommand(*session.getDboSession(), R"(CREATE TABLE IF NOT EXISTS "directory" (
|
||||
"id" integer primary key autoincrement,
|
||||
"version" integer not null,
|
||||
"absolute_path" text not null,
|
||||
@@ -511,7 +511,7 @@ SELECT
|
||||
))");
|
||||
|
||||
// Add a ref in track, need to recreate a new table
|
||||
session.getDboSession()->execute(R"(
|
||||
utils::executeCommand(*session.getDboSession(), R"(
|
||||
CREATE TABLE IF NOT EXISTS "track_backup" (
|
||||
"id" integer primary key autoincrement,
|
||||
"version" integer not null,
|
||||
@@ -551,7 +551,7 @@ CREATE TABLE IF NOT EXISTS "track_backup" (
|
||||
constraint "fk_track_directory" foreign key ("directory_id") references "directory" ("id") on delete cascade deferrable initially deferred
|
||||
))");
|
||||
// Migrate data, with the new directory_id field set to null
|
||||
session.getDboSession()->execute(R"(INSERT INTO track_backup
|
||||
utils::executeCommand(*session.getDboSession(), R"(INSERT INTO track_backup
|
||||
SELECT
|
||||
id,
|
||||
version,
|
||||
@@ -587,11 +587,11 @@ SELECT
|
||||
media_library_id,
|
||||
NULL
|
||||
FROM track)");
|
||||
session.getDboSession()->execute("DROP TABLE track");
|
||||
session.getDboSession()->execute("ALTER TABLE track_backup RENAME TO track");
|
||||
utils::executeCommand(*session.getDboSession(), "DROP TABLE track");
|
||||
utils::executeCommand(*session.getDboSession(), "ALTER TABLE track_backup RENAME TO track");
|
||||
|
||||
// Add a ref in image + rename path to absolute_file_path, need to recreate a new table
|
||||
session.getDboSession()->execute(R"(
|
||||
utils::executeCommand(*session.getDboSession(), R"(
|
||||
CREATE TABLE IF NOT EXISTS "image_backup" (
|
||||
"id" integer primary key autoincrement,
|
||||
"version" integer not null,
|
||||
@@ -608,7 +608,7 @@ SELECT
|
||||
))");
|
||||
|
||||
// Migrate data, with the new directory_id field set to null
|
||||
session.getDboSession()->execute(R"(INSERT INTO image_backup
|
||||
utils::executeCommand(*session.getDboSession(), R"(INSERT INTO image_backup
|
||||
SELECT
|
||||
id,
|
||||
version,
|
||||
@@ -622,11 +622,11 @@ SELECT
|
||||
NULL
|
||||
FROM image
|
||||
)");
|
||||
session.getDboSession()->execute("DROP TABLE image");
|
||||
session.getDboSession()->execute("ALTER TABLE image_backup RENAME TO image");
|
||||
utils::executeCommand(*session.getDboSession(), "DROP TABLE image");
|
||||
utils::executeCommand(*session.getDboSession(), "ALTER TABLE image_backup RENAME TO image");
|
||||
|
||||
// Just increment the scan version of the settings to make the next scheduled scan rescan everything
|
||||
session.getDboSession()->execute("UPDATE scan_settings SET scan_version = scan_version + 1");
|
||||
utils::executeCommand(*session.getDboSession(), "UPDATE scan_settings SET scan_version = scan_version + 1");
|
||||
}
|
||||
|
||||
} // namespace
|
||||
@@ -634,7 +634,7 @@ SELECT
|
||||
void migrateFromV61(Session& session)
|
||||
{
|
||||
// Added a media_library_id in Directory
|
||||
session.getDboSession()->execute(R"(
|
||||
utils::executeCommand(*session.getDboSession(), R"(
|
||||
CREATE TABLE IF NOT EXISTS "directory_backup" (
|
||||
"id" integer primary key autoincrement,
|
||||
"version" integer not null,
|
||||
@@ -647,7 +647,7 @@ CREATE TABLE IF NOT EXISTS "directory_backup" (
|
||||
))");
|
||||
|
||||
// Migrate data, with the new directory_id field set to null
|
||||
session.getDboSession()->execute(R"(INSERT INTO directory_backup
|
||||
utils::executeCommand(*session.getDboSession(), R"(INSERT INTO directory_backup
|
||||
SELECT
|
||||
id,
|
||||
version,
|
||||
@@ -657,27 +657,27 @@ SELECT
|
||||
NULL
|
||||
FROM directory)");
|
||||
|
||||
session.getDboSession()->execute("DROP TABLE directory");
|
||||
session.getDboSession()->execute("ALTER TABLE directory_backup RENAME TO directory");
|
||||
utils::executeCommand(*session.getDboSession(), "DROP TABLE directory");
|
||||
utils::executeCommand(*session.getDboSession(), "ALTER TABLE directory_backup RENAME TO directory");
|
||||
|
||||
// Just increment the scan version of the settings to make the next scheduled scan rescan everything
|
||||
session.getDboSession()->execute("UPDATE scan_settings SET scan_version = scan_version + 1");
|
||||
utils::executeCommand(*session.getDboSession(), "UPDATE scan_settings SET scan_version = scan_version + 1");
|
||||
}
|
||||
|
||||
void migrateFromV62(Session& session)
|
||||
{
|
||||
// Add a new column comment
|
||||
session.getDboSession()->execute("ALTER TABLE track ADD comment TEXT NOT NULL DEFAULT ''");
|
||||
utils::executeCommand(*session.getDboSession(), "ALTER TABLE track ADD comment TEXT NOT NULL DEFAULT ''");
|
||||
|
||||
// Just increment the scan version of the settings to make the next scheduled scan rescan everything
|
||||
session.getDboSession()->execute("UPDATE scan_settings SET scan_version = scan_version + 1");
|
||||
utils::executeCommand(*session.getDboSession(), "UPDATE scan_settings SET scan_version = scan_version + 1");
|
||||
}
|
||||
|
||||
void migrateFromV63(Session& session)
|
||||
{
|
||||
// Add a rated entities
|
||||
|
||||
session.getDboSession()->execute(R"(CREATE TABLE IF NOT EXISTS "rated_artist" (
|
||||
utils::executeCommand(*session.getDboSession(), R"(CREATE TABLE IF NOT EXISTS "rated_artist" (
|
||||
"id" integer primary key autoincrement,
|
||||
"version" integer not null,
|
||||
"rating" integer not null,
|
||||
@@ -688,7 +688,7 @@ SELECT
|
||||
constraint "fk_rated_artist_user" foreign key ("user_id") references "user" ("id") on delete cascade deferrable initially deferred
|
||||
))");
|
||||
|
||||
session.getDboSession()->execute(R"(CREATE TABLE IF NOT EXISTS "rated_release" (
|
||||
utils::executeCommand(*session.getDboSession(), R"(CREATE TABLE IF NOT EXISTS "rated_release" (
|
||||
"id" integer primary key autoincrement,
|
||||
"version" integer not null,
|
||||
"rating" integer not null,
|
||||
@@ -699,7 +699,7 @@ SELECT
|
||||
constraint "fk_rated_release_user" foreign key ("user_id") references "user" ("id") on delete cascade deferrable initially deferred
|
||||
))");
|
||||
|
||||
session.getDboSession()->execute(R"(CREATE TABLE IF NOT EXISTS "rated_track" (
|
||||
utils::executeCommand(*session.getDboSession(), R"(CREATE TABLE IF NOT EXISTS "rated_track" (
|
||||
"id" integer primary key autoincrement,
|
||||
"version" integer not null,
|
||||
"rating" bigint not null,
|
||||
@@ -711,43 +711,43 @@ SELECT
|
||||
))");
|
||||
|
||||
// Drop badly named index, will be recreated
|
||||
session.getDboSession()->execute("DROP INDEX IF EXISTS listen_user_backend_date_time");
|
||||
utils::executeCommand(*session.getDboSession(), "DROP INDEX IF EXISTS listen_user_backend_date_time");
|
||||
}
|
||||
|
||||
void migrateFromV64(Session& session)
|
||||
{
|
||||
session.getDboSession()->execute(R"(CREATE TABLE IF NOT EXISTS "label" (
|
||||
utils::executeCommand(*session.getDboSession(), R"(CREATE TABLE IF NOT EXISTS "label" (
|
||||
"id" integer primary key autoincrement,
|
||||
"version" integer not null,
|
||||
"name" text not null
|
||||
))");
|
||||
|
||||
session.getDboSession()->execute(R"(CREATE TABLE IF NOT EXISTS "release_label" (
|
||||
utils::executeCommand(*session.getDboSession(), R"(CREATE TABLE IF NOT EXISTS "release_label" (
|
||||
"label_id" bigint,
|
||||
"release_id" bigint,
|
||||
primary key ("label_id", "release_id"),
|
||||
constraint "fk_release_label_key1" foreign key ("label_id") references "label" ("id") on delete cascade deferrable initially deferred,
|
||||
constraint "fk_release_label_key2" foreign key ("release_id") references "release" ("id") on delete cascade deferrable initially deferred
|
||||
))");
|
||||
session.getDboSession()->execute(R"(CREATE INDEX "release_label_label" on "release_label" ("label_id"))");
|
||||
session.getDboSession()->execute(R"(CREATE INDEX "release_label_release" on "release_label" ("release_id"))");
|
||||
utils::executeCommand(*session.getDboSession(), R"(CREATE INDEX "release_label_label" on "release_label" ("label_id"))");
|
||||
utils::executeCommand(*session.getDboSession(), R"(CREATE INDEX "release_label_release" on "release_label" ("release_id"))");
|
||||
|
||||
// Just increment the scan version of the settings to make the next scheduled scan rescan everything
|
||||
session.getDboSession()->execute("UPDATE scan_settings SET scan_version = scan_version + 1");
|
||||
utils::executeCommand(*session.getDboSession(), "UPDATE scan_settings SET scan_version = scan_version + 1");
|
||||
}
|
||||
|
||||
void migrateFromV65(Session& session)
|
||||
{
|
||||
session.getDboSession()->execute("ALTER TABLE release ADD is_compilation BOOLEAN NOT NULL DEFAULT(false)");
|
||||
utils::executeCommand(*session.getDboSession(), "ALTER TABLE release ADD is_compilation BOOLEAN NOT NULL DEFAULT(false)");
|
||||
|
||||
// Just increment the scan version of the settings to make the next scheduled scan rescan everything
|
||||
session.getDboSession()->execute("UPDATE scan_settings SET scan_version = scan_version + 1");
|
||||
utils::executeCommand(*session.getDboSession(), "UPDATE scan_settings SET scan_version = scan_version + 1");
|
||||
}
|
||||
|
||||
void migrateFromV66(Session& session)
|
||||
{
|
||||
// New way of handling UI settings
|
||||
session.getDboSession()->execute(R"(CREATE TABLE IF NOT EXISTS "ui_state" (
|
||||
utils::executeCommand(*session.getDboSession(), R"(CREATE TABLE IF NOT EXISTS "ui_state" (
|
||||
"id" integer primary key autoincrement,
|
||||
"version" integer not null,
|
||||
"item" text not null,
|
||||
@@ -756,15 +756,15 @@ SELECT
|
||||
constraint "fk_ui_state_user" foreign key ("user_id") references "user" ("id") on delete cascade deferrable initially deferred
|
||||
))");
|
||||
|
||||
session.getDboSession()->execute("ALTER TABLE user DROP COLUMN repeat_all");
|
||||
session.getDboSession()->execute("ALTER TABLE user DROP COLUMN radio");
|
||||
session.getDboSession()->execute("ALTER TABLE user DROP COLUMN cur_playing_track_pos");
|
||||
utils::executeCommand(*session.getDboSession(), "ALTER TABLE user DROP COLUMN repeat_all");
|
||||
utils::executeCommand(*session.getDboSession(), "ALTER TABLE user DROP COLUMN radio");
|
||||
utils::executeCommand(*session.getDboSession(), "ALTER TABLE user DROP COLUMN cur_playing_track_pos");
|
||||
}
|
||||
|
||||
void migrateFromV67(Session& session)
|
||||
{
|
||||
// Add a ref to release in image
|
||||
session.getDboSession()->execute(R"(CREATE TABLE "image_backup" (
|
||||
utils::executeCommand(*session.getDboSession(), R"(CREATE TABLE "image_backup" (
|
||||
"id" integer primary key autoincrement,
|
||||
"version" integer not null,
|
||||
"absolute_file_path" text not null,
|
||||
@@ -782,7 +782,7 @@ SELECT
|
||||
))");
|
||||
|
||||
// Migrate data, with the new release_id field set to null
|
||||
session.getDboSession()->execute(R"(INSERT INTO image_backup
|
||||
utils::executeCommand(*session.getDboSession(), R"(INSERT INTO image_backup
|
||||
SELECT
|
||||
id,
|
||||
version,
|
||||
@@ -797,22 +797,22 @@ SELECT
|
||||
directory_id
|
||||
FROM image
|
||||
)");
|
||||
session.getDboSession()->execute("DROP TABLE image");
|
||||
session.getDboSession()->execute("ALTER TABLE image_backup RENAME TO image");
|
||||
utils::executeCommand(*session.getDboSession(), "DROP TABLE image");
|
||||
utils::executeCommand(*session.getDboSession(), "ALTER TABLE image_backup RENAME TO image");
|
||||
|
||||
// Changed some indexes for the image table -> remove all the previoulsy created index, the createIndexesIfNeeded will recreate them all
|
||||
std::vector<std::string> indexeNames{ utils::fetchQueryResults(session.getDboSession()->query<std::string>(R"(SELECT name FROM sqlite_master WHERE type = 'index' AND name LIKE '%_idx')")) };
|
||||
for (const auto& indexName : indexeNames)
|
||||
session.getDboSession()->execute("DROP INDEX " + indexName);
|
||||
utils::executeCommand(*session.getDboSession(), "DROP INDEX " + indexName);
|
||||
|
||||
// Just increment the scan version of the settings to make the next scheduled scan rescan everything
|
||||
session.getDboSession()->execute("UPDATE scan_settings SET scan_version = scan_version + 1");
|
||||
utils::executeCommand(*session.getDboSession(), "UPDATE scan_settings SET scan_version = scan_version + 1");
|
||||
}
|
||||
|
||||
void migrateFromV68(Session& session)
|
||||
{
|
||||
// Changed the way we ref images from release and artists (several releases and artist can now share the same image)
|
||||
session.getDboSession()->execute(R"(CREATE TABLE "release_backup" (
|
||||
utils::executeCommand(*session.getDboSession(), R"(CREATE TABLE "release_backup" (
|
||||
"id" integer primary key autoincrement,
|
||||
"version" integer not null,
|
||||
"name" text not null,
|
||||
@@ -826,7 +826,7 @@ SELECT
|
||||
constraint "fk_release_image" foreign key ("image_id") references "image" ("id") on delete set null deferrable initially deferred))");
|
||||
|
||||
// Migrate data, with the new image_id field set to null
|
||||
session.getDboSession()->execute(R"(INSERT INTO release_backup
|
||||
utils::executeCommand(*session.getDboSession(), R"(INSERT INTO release_backup
|
||||
SELECT
|
||||
id,
|
||||
version,
|
||||
@@ -840,10 +840,10 @@ SELECT
|
||||
NULL
|
||||
FROM release
|
||||
)");
|
||||
session.getDboSession()->execute("DROP TABLE release");
|
||||
session.getDboSession()->execute("ALTER TABLE release_backup RENAME TO release");
|
||||
utils::executeCommand(*session.getDboSession(), "DROP TABLE release");
|
||||
utils::executeCommand(*session.getDboSession(), "ALTER TABLE release_backup RENAME TO release");
|
||||
|
||||
session.getDboSession()->execute(R"(CREATE TABLE IF NOT EXISTS "artist_backup" (
|
||||
utils::executeCommand(*session.getDboSession(), R"(CREATE TABLE IF NOT EXISTS "artist_backup" (
|
||||
"id" integer primary key autoincrement,
|
||||
"version" integer not null,
|
||||
"name" text not null,
|
||||
@@ -854,7 +854,7 @@ SELECT
|
||||
))");
|
||||
|
||||
// Migrate data, with the new image_id field set to null
|
||||
session.getDboSession()->execute(R"(INSERT INTO artist_backup
|
||||
utils::executeCommand(*session.getDboSession(), R"(INSERT INTO artist_backup
|
||||
SELECT
|
||||
id,
|
||||
version,
|
||||
@@ -865,17 +865,46 @@ SELECT
|
||||
FROM artist
|
||||
)");
|
||||
|
||||
session.getDboSession()->execute("DROP TABLE artist");
|
||||
session.getDboSession()->execute("ALTER TABLE artist_backup RENAME TO artist");
|
||||
utils::executeCommand(*session.getDboSession(), "DROP TABLE artist");
|
||||
utils::executeCommand(*session.getDboSession(), "ALTER TABLE artist_backup RENAME TO artist");
|
||||
|
||||
// Just increment the scan version of the settings to make the next scheduled scan rescan everything
|
||||
session.getDboSession()->execute("UPDATE scan_settings SET scan_version = scan_version + 1");
|
||||
utils::executeCommand(*session.getDboSession(), "UPDATE scan_settings SET scan_version = scan_version + 1");
|
||||
}
|
||||
|
||||
void migrateFromV69(Session& session)
|
||||
{
|
||||
// Add a field in UI settings
|
||||
session.getDboSession()->execute("ALTER TABLE user ADD COLUMN ui_artist_release_sort_method NOT NULL DEFAULT 7"); // 7 = ReleaseSortMethod::OriginalDateDesc
|
||||
utils::executeCommand(*session.getDboSession(), "ALTER TABLE user ADD COLUMN ui_artist_release_sort_method NOT NULL DEFAULT 7"); // 7 = ReleaseSortMethod::OriginalDateDesc
|
||||
}
|
||||
|
||||
void migrateFromV70(Session& session)
|
||||
{
|
||||
// Add a file name/stem in tracks
|
||||
utils::executeCommand(*session.getDboSession(), "ALTER TABLE track ADD COLUMN file_stem TEXT NOT NULL DEFAULT ''");
|
||||
|
||||
// New table TrackLyrics
|
||||
utils::executeCommand(*session.getDboSession(), R"(CREATE TABLE IF NOT EXISTS "track_lyrics" (
|
||||
"id" integer primary key autoincrement,
|
||||
"version" integer not null,
|
||||
"absolute_file_path" text not null,
|
||||
"stem" text not null,
|
||||
"file_last_write" text,
|
||||
"file_size" integer not null,
|
||||
"lines" text not null,
|
||||
"language" text not null,
|
||||
"offset" integer,
|
||||
"display_artist" text not null,
|
||||
"display_title" text not null,
|
||||
"synchronized" boolean not null,
|
||||
"track_id" bigint,
|
||||
"directory_id" bigint,
|
||||
constraint "fk_track_lyrics_track" foreign key ("track_id") references "track" ("id") on delete cascade deferrable initially deferred,
|
||||
constraint "fk_track_lyrics_directory" foreign key ("directory_id") references "directory" ("id") on delete cascade deferrable initially deferred
|
||||
))");
|
||||
|
||||
// Just increment the scan version of the settings to make the next scheduled scan rescan everything
|
||||
utils::executeCommand(*session.getDboSession(), "UPDATE scan_settings SET scan_version = scan_version + 1");
|
||||
}
|
||||
|
||||
bool doDbMigration(Session& session)
|
||||
@@ -924,6 +953,7 @@ SELECT
|
||||
{ 67, migrateFromV67 },
|
||||
{ 68, migrateFromV68 },
|
||||
{ 69, migrateFromV69 },
|
||||
{ 70, migrateFromV70 },
|
||||
};
|
||||
|
||||
bool migrationPerformed{};
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
#include "database/TrackBookmark.hpp"
|
||||
#include "database/TrackFeatures.hpp"
|
||||
#include "database/TrackList.hpp"
|
||||
#include "database/TrackLyrics.hpp"
|
||||
#include "database/TransactionChecker.hpp"
|
||||
#include "database/UIState.hpp"
|
||||
#include "database/User.hpp"
|
||||
@@ -118,6 +119,7 @@ namespace lms::db
|
||||
_session.mapClass<TrackFeatures>("track_features");
|
||||
_session.mapClass<TrackList>("tracklist");
|
||||
_session.mapClass<TrackListEntry>("tracklist_entry");
|
||||
_session.mapClass<TrackLyrics>("track_lyrics");
|
||||
_session.mapClass<UIState>("ui_state");
|
||||
_session.mapClass<User>("user");
|
||||
}
|
||||
@@ -134,7 +136,7 @@ namespace lms::db
|
||||
|
||||
void Session::execute(std::string_view statement)
|
||||
{
|
||||
_session.execute(std::string{ statement });
|
||||
utils::executeCommand(_session, std::string{ statement });
|
||||
}
|
||||
|
||||
void Session::prepareTablesIfNeeded()
|
||||
@@ -178,92 +180,97 @@ namespace lms::db
|
||||
LMS_LOG(DB, INFO, "Creating indexes... This may take a while...");
|
||||
|
||||
auto transaction{ createWriteTransaction() };
|
||||
_session.execute("CREATE INDEX IF NOT EXISTS artist_id_idx ON artist(id)");
|
||||
_session.execute("CREATE INDEX IF NOT EXISTS artist_image_idx ON artist(image_id)");
|
||||
_session.execute("CREATE INDEX IF NOT EXISTS artist_name_idx ON artist(name)");
|
||||
_session.execute("CREATE INDEX IF NOT EXISTS artist_sort_name_nocase_idx ON artist(sort_name COLLATE NOCASE)");
|
||||
_session.execute("CREATE INDEX IF NOT EXISTS artist_mbid_idx ON artist(mbid)");
|
||||
utils::executeCommand(_session, "CREATE INDEX IF NOT EXISTS artist_id_idx ON artist(id)");
|
||||
utils::executeCommand(_session, "CREATE INDEX IF NOT EXISTS artist_image_idx ON artist(image_id)");
|
||||
utils::executeCommand(_session, "CREATE INDEX IF NOT EXISTS artist_name_idx ON artist(name)");
|
||||
utils::executeCommand(_session, "CREATE INDEX IF NOT EXISTS artist_sort_name_nocase_idx ON artist(sort_name COLLATE NOCASE)");
|
||||
utils::executeCommand(_session, "CREATE INDEX IF NOT EXISTS artist_mbid_idx ON artist(mbid)");
|
||||
|
||||
_session.execute("CREATE INDEX IF NOT EXISTS auth_token_user_idx ON auth_token(user_id)");
|
||||
_session.execute("CREATE INDEX IF NOT EXISTS auth_token_expiry_idx ON auth_token(expiry)");
|
||||
_session.execute("CREATE INDEX IF NOT EXISTS auth_token_value_idx ON auth_token(value)");
|
||||
utils::executeCommand(_session, "CREATE INDEX IF NOT EXISTS auth_token_user_idx ON auth_token(user_id)");
|
||||
utils::executeCommand(_session, "CREATE INDEX IF NOT EXISTS auth_token_expiry_idx ON auth_token(expiry)");
|
||||
utils::executeCommand(_session, "CREATE INDEX IF NOT EXISTS auth_token_value_idx ON auth_token(value)");
|
||||
|
||||
_session.execute("CREATE INDEX IF NOT EXISTS cluster_cluster_type_idx ON cluster(cluster_type_id)");
|
||||
_session.execute("CREATE INDEX IF NOT EXISTS cluster_type_name_idx ON cluster_type(name)");
|
||||
utils::executeCommand(_session, "CREATE INDEX IF NOT EXISTS cluster_cluster_type_idx ON cluster(cluster_type_id)");
|
||||
utils::executeCommand(_session, "CREATE INDEX IF NOT EXISTS cluster_type_name_idx ON cluster_type(name)");
|
||||
|
||||
_session.execute("CREATE INDEX IF NOT EXISTS directory_id_idx ON directory(id)");
|
||||
_session.execute("CREATE INDEX IF NOT EXISTS directory_parent_directory_idx ON directory(parent_directory_id)");
|
||||
_session.execute("CREATE INDEX IF NOT EXISTS directory_path_idx ON directory(absolute_path)");
|
||||
_session.execute("CREATE INDEX IF NOT EXISTS directory_media_library_idx ON directory(media_library_id)");
|
||||
utils::executeCommand(_session, "CREATE INDEX IF NOT EXISTS directory_id_idx ON directory(id)");
|
||||
utils::executeCommand(_session, "CREATE INDEX IF NOT EXISTS directory_parent_directory_idx ON directory(parent_directory_id)");
|
||||
utils::executeCommand(_session, "CREATE INDEX IF NOT EXISTS directory_path_idx ON directory(absolute_path)");
|
||||
utils::executeCommand(_session, "CREATE INDEX IF NOT EXISTS directory_media_library_idx ON directory(media_library_id)");
|
||||
|
||||
_session.execute("CREATE INDEX IF NOT EXISTS image_directory_stem_idx ON image(directory_id, stem COLLATE NOCASE)");
|
||||
_session.execute("CREATE INDEX IF NOT EXISTS image_id_idx ON image(id)");
|
||||
_session.execute("CREATE INDEX IF NOT EXISTS image_path_idx ON image(absolute_file_path)");
|
||||
_session.execute("CREATE INDEX IF NOT EXISTS image_stem_idx ON image(stem COLLATE NOCASE)");
|
||||
utils::executeCommand(_session, "CREATE INDEX IF NOT EXISTS image_directory_stem_idx ON image(directory_id, stem COLLATE NOCASE)");
|
||||
utils::executeCommand(_session, "CREATE INDEX IF NOT EXISTS image_id_idx ON image(id)");
|
||||
utils::executeCommand(_session, "CREATE INDEX IF NOT EXISTS image_path_idx ON image(absolute_file_path)");
|
||||
utils::executeCommand(_session, "CREATE INDEX IF NOT EXISTS image_stem_idx ON image(stem COLLATE NOCASE)");
|
||||
|
||||
_session.execute("CREATE INDEX IF NOT EXISTS label_name_idx ON label(name)");
|
||||
utils::executeCommand(_session, "CREATE INDEX IF NOT EXISTS label_name_idx ON label(name)");
|
||||
|
||||
_session.execute("CREATE INDEX IF NOT EXISTS listen_backend_idx ON listen(backend)");
|
||||
_session.execute("CREATE INDEX IF NOT EXISTS listen_id_idx ON listen(id)");
|
||||
_session.execute("CREATE INDEX IF NOT EXISTS listen_user_backend_idx ON listen(user_id,backend)");
|
||||
_session.execute("CREATE INDEX IF NOT EXISTS listen_user_backend_date_time_idx ON listen(user_id, backend, date_time DESC)");
|
||||
_session.execute("CREATE INDEX IF NOT EXISTS listen_track_user_backend_idx ON listen(track_id,user_id,backend)");
|
||||
_session.execute("CREATE INDEX IF NOT EXISTS listen_user_track_backend_date_time_idx ON listen(user_id,track_id,backend,date_time)");
|
||||
utils::executeCommand(_session, "CREATE INDEX IF NOT EXISTS listen_backend_idx ON listen(backend)");
|
||||
utils::executeCommand(_session, "CREATE INDEX IF NOT EXISTS listen_id_idx ON listen(id)");
|
||||
utils::executeCommand(_session, "CREATE INDEX IF NOT EXISTS listen_user_backend_idx ON listen(user_id,backend)");
|
||||
utils::executeCommand(_session, "CREATE INDEX IF NOT EXISTS listen_user_backend_date_time_idx ON listen(user_id, backend, date_time DESC)");
|
||||
utils::executeCommand(_session, "CREATE INDEX IF NOT EXISTS listen_track_user_backend_idx ON listen(track_id,user_id,backend)");
|
||||
utils::executeCommand(_session, "CREATE INDEX IF NOT EXISTS listen_user_track_backend_date_time_idx ON listen(user_id,track_id,backend,date_time)");
|
||||
|
||||
_session.execute("CREATE INDEX IF NOT EXISTS media_library_id_idx ON media_library(id)");
|
||||
utils::executeCommand(_session, "CREATE INDEX IF NOT EXISTS media_library_id_idx ON media_library(id)");
|
||||
|
||||
_session.execute("CREATE INDEX IF NOT EXISTS rated_artist_user_artist_idx ON rated_artist(user_id,artist_id)");
|
||||
_session.execute("CREATE INDEX IF NOT EXISTS rated_release_user_release_idx ON rated_release(user_id,release_id)");
|
||||
_session.execute("CREATE INDEX IF NOT EXISTS rated_track_user_track_idx ON rated_track(user_id,track_id)");
|
||||
utils::executeCommand(_session, "CREATE INDEX IF NOT EXISTS rated_artist_user_artist_idx ON rated_artist(user_id,artist_id)");
|
||||
utils::executeCommand(_session, "CREATE INDEX IF NOT EXISTS rated_release_user_release_idx ON rated_release(user_id,release_id)");
|
||||
utils::executeCommand(_session, "CREATE INDEX IF NOT EXISTS rated_track_user_track_idx ON rated_track(user_id,track_id)");
|
||||
|
||||
_session.execute("CREATE INDEX IF NOT EXISTS release_id_idx ON release(id)");
|
||||
_session.execute("CREATE INDEX IF NOT EXISTS release_image_idx ON release(image_id)");
|
||||
_session.execute("CREATE INDEX IF NOT EXISTS release_mbid_idx ON release(mbid)");
|
||||
_session.execute("CREATE INDEX IF NOT EXISTS release_name_idx ON release(name)");
|
||||
_session.execute("CREATE INDEX IF NOT EXISTS release_name_nocase_idx ON release(name COLLATE NOCASE)");
|
||||
_session.execute("CREATE INDEX IF NOT EXISTS release_type_name_idx ON release_type(name)");
|
||||
utils::executeCommand(_session, "CREATE INDEX IF NOT EXISTS release_id_idx ON release(id)");
|
||||
utils::executeCommand(_session, "CREATE INDEX IF NOT EXISTS release_image_idx ON release(image_id)");
|
||||
utils::executeCommand(_session, "CREATE INDEX IF NOT EXISTS release_mbid_idx ON release(mbid)");
|
||||
utils::executeCommand(_session, "CREATE INDEX IF NOT EXISTS release_name_idx ON release(name)");
|
||||
utils::executeCommand(_session, "CREATE INDEX IF NOT EXISTS release_name_nocase_idx ON release(name COLLATE NOCASE)");
|
||||
utils::executeCommand(_session, "CREATE INDEX IF NOT EXISTS release_type_name_idx ON release_type(name)");
|
||||
|
||||
_session.execute("CREATE INDEX IF NOT EXISTS track_id_idx ON track(id)");
|
||||
_session.execute("CREATE INDEX IF NOT EXISTS track_absolute_path_idx ON track(absolute_file_path)");
|
||||
_session.execute("CREATE INDEX IF NOT EXISTS track_date_idx ON track(date)");
|
||||
_session.execute("CREATE INDEX IF NOT EXISTS track_directory_release_idx ON track(directory_id, release_id);");
|
||||
_session.execute("CREATE INDEX IF NOT EXISTS track_file_last_write_idx ON track(file_last_write)");
|
||||
_session.execute("CREATE INDEX IF NOT EXISTS track_media_library_idx ON track(media_library_id)");
|
||||
_session.execute("CREATE INDEX IF NOT EXISTS track_media_library_release_idx ON track(media_library_id, release_id)");
|
||||
_session.execute("CREATE INDEX IF NOT EXISTS track_mbid_idx ON track(mbid)");
|
||||
_session.execute("CREATE INDEX IF NOT EXISTS track_name_idx ON track(name)");
|
||||
_session.execute("CREATE INDEX IF NOT EXISTS track_name_nocase_idx ON track(name COLLATE NOCASE)");
|
||||
_session.execute("CREATE INDEX IF NOT EXISTS track_original_date_idx ON track(original_date)");
|
||||
_session.execute("CREATE INDEX IF NOT EXISTS track_original_year_idx ON track(original_year)");
|
||||
_session.execute("CREATE INDEX IF NOT EXISTS track_recording_mbid_idx ON track(recording_mbid)");
|
||||
_session.execute("CREATE INDEX IF NOT EXISTS track_release_idx ON track(release_id)");
|
||||
_session.execute("CREATE INDEX IF NOT EXISTS track_release_file_last_write_idx ON track(release_id, file_last_write)");
|
||||
_session.execute("CREATE INDEX IF NOT EXISTS track_release_year_idx ON track(release_id, year)");
|
||||
_session.execute("CREATE INDEX IF NOT EXISTS track_year_idx ON track(year)");
|
||||
utils::executeCommand(_session, "CREATE INDEX IF NOT EXISTS track_id_idx ON track(id)");
|
||||
utils::executeCommand(_session, "CREATE INDEX IF NOT EXISTS track_absolute_path_idx ON track(absolute_file_path)");
|
||||
utils::executeCommand(_session, "CREATE INDEX IF NOT EXISTS track_date_idx ON track(date)");
|
||||
utils::executeCommand(_session, "CREATE INDEX IF NOT EXISTS track_directory_release_idx ON track(directory_id, release_id);");
|
||||
utils::executeCommand(_session, "CREATE INDEX IF NOT EXISTS track_directory_file_stem_idx ON track(directory_id, file_stem);");
|
||||
utils::executeCommand(_session, "CREATE INDEX IF NOT EXISTS track_file_last_write_idx ON track(file_last_write)");
|
||||
utils::executeCommand(_session, "CREATE INDEX IF NOT EXISTS track_media_library_idx ON track(media_library_id)");
|
||||
utils::executeCommand(_session, "CREATE INDEX IF NOT EXISTS track_media_library_release_idx ON track(media_library_id, release_id)");
|
||||
utils::executeCommand(_session, "CREATE INDEX IF NOT EXISTS track_mbid_idx ON track(mbid)");
|
||||
utils::executeCommand(_session, "CREATE INDEX IF NOT EXISTS track_name_idx ON track(name)");
|
||||
utils::executeCommand(_session, "CREATE INDEX IF NOT EXISTS track_name_nocase_idx ON track(name COLLATE NOCASE)");
|
||||
utils::executeCommand(_session, "CREATE INDEX IF NOT EXISTS track_original_date_idx ON track(original_date)");
|
||||
utils::executeCommand(_session, "CREATE INDEX IF NOT EXISTS track_original_year_idx ON track(original_year)");
|
||||
utils::executeCommand(_session, "CREATE INDEX IF NOT EXISTS track_recording_mbid_idx ON track(recording_mbid)");
|
||||
utils::executeCommand(_session, "CREATE INDEX IF NOT EXISTS track_release_idx ON track(release_id)");
|
||||
utils::executeCommand(_session, "CREATE INDEX IF NOT EXISTS track_release_file_last_write_idx ON track(release_id, file_last_write)");
|
||||
utils::executeCommand(_session, "CREATE INDEX IF NOT EXISTS track_release_year_idx ON track(release_id, year)");
|
||||
utils::executeCommand(_session, "CREATE INDEX IF NOT EXISTS track_year_idx ON track(year)");
|
||||
|
||||
_session.execute("CREATE INDEX IF NOT EXISTS tracklist_name_idx ON tracklist(name)");
|
||||
_session.execute("CREATE INDEX IF NOT EXISTS tracklist_user_idx ON tracklist(user_id)");
|
||||
utils::executeCommand(_session, "CREATE INDEX IF NOT EXISTS tracklist_name_idx ON tracklist(name)");
|
||||
utils::executeCommand(_session, "CREATE INDEX IF NOT EXISTS tracklist_user_idx ON tracklist(user_id)");
|
||||
|
||||
_session.execute("CREATE INDEX IF NOT EXISTS track_features_track_idx ON track_features(track_id)");
|
||||
utils::executeCommand(_session, "CREATE INDEX IF NOT EXISTS track_artist_link_artist_idx ON track_artist_link(artist_id)");
|
||||
utils::executeCommand(_session, "CREATE INDEX IF NOT EXISTS track_artist_link_artist_track_idx ON track_artist_link(artist_id, track_id)");
|
||||
utils::executeCommand(_session, "CREATE INDEX IF NOT EXISTS track_artist_link_artist_type_idx ON track_artist_link(artist_id,type)");
|
||||
utils::executeCommand(_session, "CREATE INDEX IF NOT EXISTS track_artist_link_track_artist_idx ON track_artist_link(track_id, artist_id)");
|
||||
utils::executeCommand(_session, "CREATE INDEX IF NOT EXISTS track_artist_link_track_type_idx ON track_artist_link(track_id,type)");
|
||||
utils::executeCommand(_session, "CREATE INDEX IF NOT EXISTS track_artist_link_type_track_artist_idx ON track_artist_link(type, track_id, artist_id)");
|
||||
|
||||
_session.execute("CREATE INDEX IF NOT EXISTS track_artist_link_artist_idx ON track_artist_link(artist_id)");
|
||||
_session.execute("CREATE INDEX IF NOT EXISTS track_artist_link_artist_track_idx ON track_artist_link(artist_id, track_id)");
|
||||
_session.execute("CREATE INDEX IF NOT EXISTS track_artist_link_artist_type_idx ON track_artist_link(artist_id,type)");
|
||||
_session.execute("CREATE INDEX IF NOT EXISTS track_artist_link_track_artist_idx ON track_artist_link(track_id, artist_id)");
|
||||
_session.execute("CREATE INDEX IF NOT EXISTS track_artist_link_track_type_idx ON track_artist_link(track_id,type)");
|
||||
_session.execute("CREATE INDEX IF NOT EXISTS track_artist_link_type_track_artist_idx ON track_artist_link(type, track_id, artist_id)");
|
||||
utils::executeCommand(_session, "CREATE INDEX IF NOT EXISTS track_features_track_idx ON track_features(track_id)");
|
||||
|
||||
_session.execute("CREATE INDEX IF NOT EXISTS track_bookmark_user_idx ON track_bookmark(user_id)");
|
||||
_session.execute("CREATE INDEX IF NOT EXISTS track_bookmark_user_track_idx ON track_bookmark(user_id,track_id)");
|
||||
utils::executeCommand(_session, "CREATE INDEX IF NOT EXISTS track_lyrics_id_idx ON track_lyrics(id)");
|
||||
utils::executeCommand(_session, "CREATE INDEX IF NOT EXISTS track_lyrics_absolute_file_path_idx ON track_lyrics(absolute_file_path)");
|
||||
utils::executeCommand(_session, "CREATE INDEX IF NOT EXISTS track_lyrics_track_idx ON track_lyrics(track_id)");
|
||||
|
||||
_session.execute("CREATE INDEX IF NOT EXISTS starred_artist_user_backend_idx ON starred_artist(user_id,backend)");
|
||||
_session.execute("CREATE INDEX IF NOT EXISTS starred_artist_artist_user_backend_idx ON starred_artist(artist_id,user_id,backend)");
|
||||
utils::executeCommand(_session, "CREATE INDEX IF NOT EXISTS track_bookmark_user_idx ON track_bookmark(user_id)");
|
||||
utils::executeCommand(_session, "CREATE INDEX IF NOT EXISTS track_bookmark_user_track_idx ON track_bookmark(user_id,track_id)");
|
||||
|
||||
_session.execute("CREATE INDEX IF NOT EXISTS starred_release_user_backend_idx ON starred_release(user_id,backend)");
|
||||
_session.execute("CREATE INDEX IF NOT EXISTS starred_release_release_user_backend_idx ON starred_release(release_id,user_id,backend)");
|
||||
utils::executeCommand(_session, "CREATE INDEX IF NOT EXISTS starred_artist_user_backend_idx ON starred_artist(user_id,backend)");
|
||||
utils::executeCommand(_session, "CREATE INDEX IF NOT EXISTS starred_artist_artist_user_backend_idx ON starred_artist(artist_id,user_id,backend)");
|
||||
|
||||
_session.execute("CREATE INDEX IF NOT EXISTS starred_track_user_backend_idx ON starred_track(user_id,backend)");
|
||||
_session.execute("CREATE INDEX IF NOT EXISTS starred_track_track_user_backend_idx ON starred_track(track_id,user_id,backend)");
|
||||
utils::executeCommand(_session, "CREATE INDEX IF NOT EXISTS starred_release_user_backend_idx ON starred_release(user_id,backend)");
|
||||
utils::executeCommand(_session, "CREATE INDEX IF NOT EXISTS starred_release_release_user_backend_idx ON starred_release(release_id,user_id,backend)");
|
||||
|
||||
utils::executeCommand(_session, "CREATE INDEX IF NOT EXISTS starred_track_user_backend_idx ON starred_track(user_id,backend)");
|
||||
utils::executeCommand(_session, "CREATE INDEX IF NOT EXISTS starred_track_track_user_backend_idx ON starred_track(track_id,user_id,backend)");
|
||||
|
||||
LMS_LOG(DB, INFO, "Indexes created!");
|
||||
}
|
||||
@@ -341,11 +348,10 @@ namespace lms::db
|
||||
|
||||
void Session::analyzeEntry(const std::string& entry)
|
||||
{
|
||||
LMS_SCOPED_TRACE_DETAILED_WITH_ARG("Database", "AnalyzeEntry", "Entry", entry);
|
||||
LMS_LOG(DB, DEBUG, "Analyzing " << entry);
|
||||
{
|
||||
auto transaction{ createWriteTransaction() };
|
||||
_session.execute("ANALYZE " + entry);
|
||||
utils::executeCommand(_session, "ANALYZE " + entry);
|
||||
}
|
||||
LMS_LOG(DB, DEBUG, "Analyzing " << entry << ": done!");
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include "database/Session.hpp"
|
||||
#include "database/TrackArtistLink.hpp"
|
||||
#include "database/TrackFeatures.hpp"
|
||||
#include "database/TrackLyrics.hpp"
|
||||
#include "database/User.hpp"
|
||||
|
||||
#include "IdTypeTraits.hpp"
|
||||
@@ -53,6 +54,9 @@ namespace lms::db
|
||||
for (std::string_view keyword : params.keywords)
|
||||
query.where("t.name LIKE ? ESCAPE '" ESCAPE_CHAR_STR "'").bind("%" + utils::escapeLikeKeyword(keyword) + "%");
|
||||
|
||||
if (!params.stem.empty())
|
||||
query.where("t.file_stem = ?").bind(params.stem);
|
||||
|
||||
if (!params.name.empty())
|
||||
query.where("t.name = ?").bind(params.name);
|
||||
|
||||
@@ -372,11 +376,15 @@ namespace lms::db
|
||||
{
|
||||
assert(filePath.is_absolute());
|
||||
_absoluteFilePath = filePath;
|
||||
_fileStem = filePath.stem();
|
||||
}
|
||||
|
||||
void Track::setRelativeFilePath(const std::filesystem::path& filePath)
|
||||
{
|
||||
assert(filePath.is_relative());
|
||||
|
||||
assert(_absoluteFilePath.filename() == filePath.filename()); // must be compatible with previous setAbsoluteFilePath call
|
||||
_fileStem = filePath.stem(); // lazy migration (_fileStem added later, could be set only with setAbsoluteFilePath)
|
||||
_relativeFilePath = filePath;
|
||||
}
|
||||
|
||||
@@ -418,6 +426,21 @@ namespace lms::db
|
||||
_clusters.insert(getDboPtr(cluster));
|
||||
}
|
||||
|
||||
void Track::clearLyrics()
|
||||
{
|
||||
_trackLyrics.clear();
|
||||
}
|
||||
|
||||
void Track::clearEmbeddedLyrics()
|
||||
{
|
||||
utils::executeCommand(*session(), "DELETE FROM track_lyrics WHERE absolute_file_path = '' AND track_id = ?", getId());
|
||||
}
|
||||
|
||||
void Track::addLyrics(const ObjectPtr<TrackLyrics>& lyrics)
|
||||
{
|
||||
_trackLyrics.insert(getDboPtr(lyrics));
|
||||
}
|
||||
|
||||
std::optional<std::string> Track::getCopyright() const
|
||||
{
|
||||
return _copyright != "" ? std::make_optional<std::string>(_copyright) : std::nullopt;
|
||||
|
||||
@@ -0,0 +1,187 @@
|
||||
/*
|
||||
* Copyright (C) 2024 Emeric Poupon
|
||||
*
|
||||
* This file is part of LMS.
|
||||
*
|
||||
* LMS is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* LMS is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "database/TrackLyrics.hpp"
|
||||
|
||||
#include <Wt/Dbo/SqlTraits.h>
|
||||
#include <Wt/Dbo/WtSqlTraits.h>
|
||||
|
||||
#include "database/Artist.hpp"
|
||||
#include "database/Directory.hpp"
|
||||
#include "database/Release.hpp"
|
||||
#include "database/Session.hpp"
|
||||
#include "database/Track.hpp"
|
||||
|
||||
#include "IdTypeTraits.hpp"
|
||||
#include "PathTraits.hpp"
|
||||
#include "Utils.hpp"
|
||||
|
||||
namespace lms::db
|
||||
{
|
||||
TrackLyrics::pointer TrackLyrics::create(Session& session)
|
||||
{
|
||||
return session.getDboSession()->add(std::unique_ptr<TrackLyrics>{ new TrackLyrics{} });
|
||||
}
|
||||
|
||||
std::size_t TrackLyrics::getCount(Session& session)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
return utils::fetchQuerySingleResult(session.getDboSession()->query<int>("SELECT COUNT(*) FROM track_lyrics"));
|
||||
}
|
||||
|
||||
std::size_t TrackLyrics::getExternalLyricsCount(Session& session)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
return utils::fetchQuerySingleResult(session.getDboSession()->query<int>("SELECT COUNT(t_lrc.id) FROM track_lyrics t_lrc").where("t_lrc.absolute_file_path <> ''"));
|
||||
}
|
||||
|
||||
TrackLyrics::pointer TrackLyrics::find(Session& session, TrackLyricsId id)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
return utils::fetchQuerySingleResult(session.getDboSession()->query<Wt::Dbo::ptr<TrackLyrics>>("SELECT t_lrc from track_lyrics t_lrc").where("t_lrc.id = ?").bind(id));
|
||||
}
|
||||
|
||||
TrackLyrics::pointer TrackLyrics::find(Session& session, const std::filesystem::path& path)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
return utils::fetchQuerySingleResult(session.getDboSession()->query<Wt::Dbo::ptr<TrackLyrics>>("SELECT t_lrc from track_lyrics t_lrc").where("t_lrc.absolute_file_path = ?").bind(path));
|
||||
}
|
||||
|
||||
void TrackLyrics::find(Session& session, TrackId trackId, const std::function<void(const TrackLyrics::pointer&)>& func)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
auto query{ session.getDboSession()->query<Wt::Dbo::ptr<TrackLyrics>>("SELECT t_lrc from track_lyrics t_lrc").where("t_lrc.track_id = ?").bind(trackId) };
|
||||
|
||||
utils::forEachQueryResult(query, [&](const TrackLyrics::pointer& lyrics) {
|
||||
func(lyrics);
|
||||
});
|
||||
}
|
||||
|
||||
void TrackLyrics::find(Session& session, TrackLyricsId& lastRetrievedId, std::size_t count, const std::function<void(const TrackLyrics::pointer&)>& func)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
auto query{ session.getDboSession()->query<Wt::Dbo::ptr<TrackLyrics>>("SELECT t_lrc from track_lyrics t_lrc").orderBy("t_lrc.id").where("t_lrc.id > ?").bind(lastRetrievedId).limit(static_cast<int>(count)) };
|
||||
|
||||
utils::forEachQueryResult(query, [&](const TrackLyrics::pointer& lyrics) {
|
||||
func(lyrics);
|
||||
lastRetrievedId = lyrics->getId();
|
||||
});
|
||||
}
|
||||
|
||||
RangeResults<TrackLyricsId> TrackLyrics::findOrphanIds(Session& session, std::optional<Range> range)
|
||||
{
|
||||
session.checkReadTransaction();
|
||||
|
||||
auto query{ session.getDboSession()->query<TrackLyricsId>("select t_lrc.id from track_lyrics t_lrc") };
|
||||
query.leftJoin("track t ON t_lrc.track_id = t.id");
|
||||
query.where("t.id IS NULL");
|
||||
|
||||
return utils::execRangeQuery<TrackLyricsId>(query, range);
|
||||
}
|
||||
|
||||
TrackLyrics::SynchronizedLines TrackLyrics::getSynchronizedLines() const
|
||||
{
|
||||
SynchronizedLines synchronizedLines;
|
||||
assert(_synchronized);
|
||||
|
||||
{
|
||||
Wt::Json::Object root;
|
||||
Wt::Json::parse(_lines, root);
|
||||
|
||||
assert(root.type("lines") == Wt::Json::Type::Array);
|
||||
const Wt::Json::Array& linesArray = root.get("lines");
|
||||
for (const Wt::Json::Value& line : linesArray)
|
||||
{
|
||||
assert(line.type() == Wt::Json::Type::Object);
|
||||
const Wt::Json::Object& entry = line;
|
||||
std::chrono::milliseconds timestamp{ entry.get("timestamp") };
|
||||
std::string lineText{ static_cast<std::string>(entry.get("value")) };
|
||||
synchronizedLines.emplace(timestamp, std::move(lineText));
|
||||
}
|
||||
}
|
||||
|
||||
return synchronizedLines;
|
||||
}
|
||||
|
||||
std::vector<std::string> TrackLyrics::getUnsynchronizedLines() const
|
||||
{
|
||||
std::vector<std::string> unsynchronizedLines;
|
||||
assert(!_synchronized);
|
||||
|
||||
{
|
||||
Wt::Json::Object root;
|
||||
Wt::Json::parse(_lines, root);
|
||||
|
||||
assert(root.type("lines") == Wt::Json::Type::Array);
|
||||
const Wt::Json::Array& linesArray = root.get("lines");
|
||||
for (const Wt::Json::Value& line : linesArray)
|
||||
unsynchronizedLines.push_back(line.toString());
|
||||
}
|
||||
|
||||
return unsynchronizedLines;
|
||||
}
|
||||
|
||||
void TrackLyrics::setAbsoluteFilePath(const std::filesystem::path& p)
|
||||
{
|
||||
assert(p.is_absolute());
|
||||
_fileAbsolutePath = p;
|
||||
_fileStem = p.stem().string();
|
||||
}
|
||||
|
||||
void TrackLyrics::setSynchronizedLines(const SynchronizedLines& synchronizedLines)
|
||||
{
|
||||
Wt::Json::Object root;
|
||||
|
||||
Wt::Json::Array lines;
|
||||
for (const auto& [timestamp, lineText] : synchronizedLines)
|
||||
{
|
||||
Wt::Json::Object line;
|
||||
line["timestamp"] = Wt::Json::Value{ timestamp.count() };
|
||||
line["value"] = Wt::Json::Value{ lineText };
|
||||
|
||||
lines.push_back(std::move(line));
|
||||
}
|
||||
|
||||
root["lines"] = std::move(lines);
|
||||
|
||||
_synchronized = true;
|
||||
_lines = Wt::Json::serialize(root);
|
||||
}
|
||||
|
||||
void TrackLyrics::setUnsynchronizedLines(std::span<const std::string> unsynchronizedLines)
|
||||
{
|
||||
Wt::Json::Object root;
|
||||
|
||||
Wt::Json::Array lines;
|
||||
for (const auto& lineText : unsynchronizedLines)
|
||||
lines.push_back(Wt::Json::Value{ lineText });
|
||||
|
||||
root["lines"] = std::move(lines);
|
||||
|
||||
_synchronized = false;
|
||||
_lines = Wt::Json::serialize(root);
|
||||
}
|
||||
|
||||
} // namespace lms::db
|
||||
@@ -172,5 +172,14 @@ namespace lms::db::utils
|
||||
}
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
void executeCommand(Wt::Dbo::Session& session, std::string_view command, const Args&... args)
|
||||
{
|
||||
LMS_SCOPED_TRACE_DETAILED_WITH_ARG("Database", "ExecuteCommand", "Command", command);
|
||||
|
||||
Wt::Dbo::Call call{ session.execute(std::string{ command }) };
|
||||
(call.bind(args), ...);
|
||||
}
|
||||
|
||||
Wt::WDateTime normalizeDateTime(const Wt::WDateTime& dateTime);
|
||||
} // namespace lms::db::utils
|
||||
Reference in New Issue
Block a user