MythTV master
musicdbcheck.cpp
Go to the documentation of this file.
1// C++
2#include <iostream>
3
4// Qt
5#include <QString>
6#include <QDir>
7#include <QSqlError>
8
9// MythTV
12#include <libmythbase/mythdb.h>
16
17// MythMusic
18#include "musicdbcheck.h"
19
20const QString currentDatabaseVersion = "1025";
21const QString MythMusicVersionName = "MusicDBSchemaVer";
22
23static bool doUpgradeMusicDatabaseSchema(QString &dbver);
25
27{
28#ifdef IGNORE_SCHEMA_VER_MISMATCH
29 return true;
30#endif
31 // Suppress DB messages and turn of the settings cache,
32 // These are likely to confuse the users and the code, respectively.
33 GetMythDB()->SetSuppressDBMessages(true);
35
36 // Get the schema upgrade lock
38 bool locked = DBUtil::TryLockSchema(query, 1);
39 for (uint i = 0; i < 2*60 && !locked; i++)
40 {
41 LOG(VB_GENERAL, LOG_INFO, "Waiting for database schema upgrade lock");
42 locked = DBUtil::TryLockSchema(query, 1);
43 if (locked)
44 LOG(VB_GENERAL, LOG_INFO, "Got schema upgrade lock");
45 }
46 if (!locked)
47 {
48 LOG(VB_GENERAL, LOG_INFO, "Failed to get schema upgrade lock");
49 GetMythDB()->SetSuppressDBMessages(false);
51 return false;
52 }
53
54 bool success = tryUpgradeMusicDatabaseSchema();
55
56 // On any exit we want to re-enable the DB messages so errors
57 // are reported and we want to make sure the setting cache is
58 // enabled for good performance and we must unlock the schema
59 // lock.
60 GetMythDB()->SetSuppressDBMessages(false);
63 return success;
64}
65
67{
69 "MusicDBSchemaVer", "MythMusic", currentDatabaseVersion);
70
71 if (schema_wizard->Compare() == 0) // DB schema is what we need it to be..
72 return true;
73
74 if (schema_wizard->m_DBver.isEmpty())
75 {
76 // We need to create a database from scratch
77 return doUpgradeMusicDatabaseSchema(schema_wizard->m_DBver);
78 }
79
80 // Pop up messages, questions, warnings, et c.
81 switch (schema_wizard->PromptForUpgrade("Music", true, false))
82 {
84 return true;
87 return false;
89 break;
90 }
91
92 if (!doUpgradeMusicDatabaseSchema(schema_wizard->m_DBver))
93 {
94 LOG(VB_GENERAL, LOG_ERR, "Database schema upgrade failed.");
95 return false;
96 }
97
98 LOG(VB_GENERAL, LOG_INFO, "MythMusic database schema upgrade complete.");
99
100 return true;
101}
102
103static bool doUpgradeMusicDatabaseSchema(QString &dbver)
104{
105 if (dbver.isEmpty())
106 {
107 LOG(VB_GENERAL, LOG_NOTICE,
108 "Inserting MythMusic initial database information.");
109
110 DBUpdates updates
111 {
112 "CREATE TABLE IF NOT EXISTS musicmetadata ("
113 " intid INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,"
114 " artist VARCHAR(128) NOT NULL,"
115 " album VARCHAR(128) NOT NULL,"
116 " title VARCHAR(128) NOT NULL,"
117 " genre VARCHAR(128) NOT NULL,"
118 " year INT UNSIGNED NOT NULL,"
119 " tracknum INT UNSIGNED NOT NULL,"
120 " length INT UNSIGNED NOT NULL,"
121 " filename TEXT NOT NULL,"
122 " rating INT UNSIGNED NOT NULL DEFAULT 5,"
123 " lastplay TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP "
124 " ON UPDATE CURRENT_TIMESTAMP,"
125 " playcount INT UNSIGNED NOT NULL DEFAULT 0,"
126 " INDEX (artist),"
127 " INDEX (album),"
128 " INDEX (title),"
129 " INDEX (genre)"
130 ");",
131 "CREATE TABLE IF NOT EXISTS musicplaylist ("
132 " playlistid INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,"
133 " name VARCHAR(128) NOT NULL,"
134 " hostname VARCHAR(255),"
135 " songlist TEXT NOT NULL"
136 ");"
137 };
138
140 updates, "1000", dbver))
141 return false;
142 }
143
144 if (dbver == "1000")
145 {
146 QString startdir = gCoreContext->GetSetting("MusicLocation");
147 startdir = QDir::cleanPath(startdir);
148 if (!startdir.endsWith("/"))
149 startdir += "/";
150
152 // urls as filenames are NOT officially supported yet
153 if (query.exec("SELECT filename, intid FROM musicmetadata WHERE "
154 "filename NOT LIKE ('%://%');"))
155 {
156 int i = 0;
157 QString intid;
158 QString name;
159 QString newname;
160
162 while (query.next())
163 {
164 name = query.value(0).toString();
165 newname = name;
166 intid = query.value(1).toString();
167
168 if (newname.startsWith(startdir))
169 {
170 newname.remove(0, startdir.length());
171 if (modify.exec(QString("UPDATE musicmetadata SET "
172 "filename = \"%1\" "
173 "WHERE filename = \"%2\" AND intid = %3;")
174 .arg(newname, name, intid)))
175 i += modify.numRowsAffected();
176 }
177 }
178 LOG(VB_GENERAL, LOG_NOTICE,
179 QString("Modified %1 entries for db schema 1001").arg(i));
180 }
181
182 if (!UpdateDBVersionNumber("MythMusic", MythMusicVersionName, "1001", dbver))
183 return false;
184 }
185
186 if (dbver == "1001")
187 {
188 DBUpdates updates
189 {
190 "ALTER TABLE musicmetadata ADD mythdigest VARCHAR(255);",
191 "ALTER TABLE musicmetadata ADD size BIGINT UNSIGNED;",
192 "ALTER TABLE musicmetadata ADD date_added DATETIME;",
193 "ALTER TABLE musicmetadata ADD date_modified DATETIME;",
194 "ALTER TABLE musicmetadata ADD format VARCHAR(4);",
195 "ALTER TABLE musicmetadata ADD description VARCHAR(255);",
196 "ALTER TABLE musicmetadata ADD comment VARCHAR(255);",
197 "ALTER TABLE musicmetadata ADD compilation TINYINT DEFAULT 0;",
198 "ALTER TABLE musicmetadata ADD composer VARCHAR(255);",
199 "ALTER TABLE musicmetadata ADD disc_count SMALLINT UNSIGNED DEFAULT 0;",
200 "ALTER TABLE musicmetadata ADD disc_number SMALLINT UNSIGNED DEFAULT 0;",
201 "ALTER TABLE musicmetadata ADD track_count SMALLINT UNSIGNED DEFAULT 0;",
202 "ALTER TABLE musicmetadata ADD start_time INT UNSIGNED DEFAULT 0;",
203 "ALTER TABLE musicmetadata ADD stop_time INT UNSIGNED;",
204 "ALTER TABLE musicmetadata ADD eq_preset VARCHAR(255);",
205 "ALTER TABLE musicmetadata ADD relative_volume TINYINT DEFAULT 0;",
206 "ALTER TABLE musicmetadata ADD sample_rate INT UNSIGNED;",
207 "ALTER TABLE musicmetadata ADD bpm SMALLINT UNSIGNED;",
208 "ALTER TABLE musicmetadata ADD INDEX (mythdigest);"
209 };
210
212 updates, "1002", dbver))
213 return false;
214 }
215
216 if (dbver == "1002")
217 {
218 LOG(VB_GENERAL, LOG_NOTICE,
219 "Updating music metadata to be UTF-8 in the database");
220
222 query.prepare("SELECT intid, artist, album, title, genre, "
223 "filename FROM musicmetadata ORDER BY intid;");
224
225 if (query.exec() && query.isActive() && query.size() > 0)
226 {
227 while (query.next())
228 {
229 int id = query.value(0).toInt();
230 QString artist = query.value(1).toString();
231 QString album = query.value(2).toString();
232 QString title = query.value(3).toString();
233 QString genre = query.value(4).toString();
234 QString filename = query.value(5).toString();
235
236 MSqlQuery subquery(MSqlQuery::InitCon());
237 subquery.prepare("UPDATE musicmetadata SET "
238 "artist = :ARTIST, album = :ALBUM, "
239 "title = :TITLE, genre = :GENRE, "
240 "filename = :FILENAME "
241 "WHERE intid = :ID;");
242 subquery.bindValue(":ARTIST", QString(artist.toUtf8()));
243 subquery.bindValue(":ALBUM", QString(album.toUtf8()));
244 subquery.bindValue(":TITLE", QString(title.toUtf8()));
245 subquery.bindValue(":GENRE", QString(genre.toUtf8()));
246 subquery.bindValue(":FILENAME", QString(filename.toUtf8()));
247 subquery.bindValue(":ID", id);
248
249 if (!subquery.exec() || !subquery.isActive())
250 MythDB::DBError("music utf8 update", subquery);
251 }
252 }
253
254 query.prepare("SELECT playlistid, name FROM musicplaylist "
255 "ORDER BY playlistid;");
256
257 if (query.exec() && query.isActive() && query.size() > 0)
258 {
259 while (query.next())
260 {
261 int id = query.value(0).toInt();
262 QString name = query.value(1).toString();
263
264 MSqlQuery subquery(MSqlQuery::InitCon());
265 subquery.prepare("UPDATE musicplaylist SET "
266 "name = :NAME WHERE playlistid = :ID ;");
267 subquery.bindValue(":NAME", QString(name.toUtf8()));
268 subquery.bindValue(":ID", id);
269
270 if (!subquery.exec() || !subquery.isActive())
271 MythDB::DBError("music playlist utf8 update", subquery);
272 }
273 }
274
275 LOG(VB_GENERAL, LOG_NOTICE, "Done updating music metadata to UTF-8");
276
277 if (!UpdateDBVersionNumber("MythMusic", MythMusicVersionName, "1003", dbver))
278 return false;
279 }
280
281 if (dbver == "1003")
282 {
283 DBUpdates updates
284 {
285 "DROP TABLE IF EXISTS smartplaylistcategory;",
286 "CREATE TABLE smartplaylistcategory ("
287 " categoryid INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,"
288 " name VARCHAR(128) NOT NULL,"
289 " INDEX (name)"
290 ");",
291
292 // NOLINTNEXTLINE(bugprone-suspicious-missing-comma)
293 "INSERT INTO smartplaylistcategory SET categoryid = 1, "
294 " name = \"Decades\";",
295 "INSERT INTO smartplaylistcategory SET categoryid = 2, "
296 " name = \"Favourite Tracks\";",
297 "INSERT INTO smartplaylistcategory SET categoryid = 3, "
298 " name = \"New Tracks\";",
299
300 "DROP TABLE IF EXISTS smartplaylist;",
301 "CREATE TABLE smartplaylist ("
302 " smartplaylistid INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,"
303 " name VARCHAR(128) NOT NULL,"
304 " categoryid INT UNSIGNED NOT NULL,"
305 " matchtype SET('All', 'Any') NOT NULL DEFAULT 'All',"
306 " orderby VARCHAR(128) NOT NULL DEFAULT '',"
307 " limitto INT UNSIGNED NOT NULL DEFAULT 0,"
308 " INDEX (name),"
309 " INDEX (categoryid)"
310 ");",
311 "DROP TABLE IF EXISTS smartplaylistitem;",
312 "CREATE TABLE smartplaylistitem ("
313 " smartplaylistitemid INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,"
314 " smartplaylistid INT UNSIGNED NOT NULL,"
315 " field VARCHAR(50) NOT NULL,"
316 " operator VARCHAR(20) NOT NULL,"
317 " value1 VARCHAR(255) NOT NULL,"
318 " value2 VARCHAR(255) NOT NULL,"
319 " INDEX (smartplaylistid)"
320 ");",
321 "INSERT INTO smartplaylist SET smartplaylistid = 1, name = \"1960's\", "
322 " categoryid = 1, matchtype = \"All\", orderby = \"Artist (A)\","
323 " limitto = 0;",
324 "INSERT INTO smartplaylistitem SET smartplaylistid = 1, field = \"Year\","
325 " operator = \"is between\", value1 = \"1960\", value2 = \"1969\";",
326
327 "INSERT INTO smartplaylist SET smartplaylistid = 2, name = \"1970's\", "
328 " categoryid = 1, matchtype = \"All\", orderby = \"Artist (A)\","
329 " limitto = 0;",
330 "INSERT INTO smartplaylistitem SET smartplaylistid = 2, field = \"Year\","
331 " operator = \"is between\", value1 = \"1970\", value2 = \"1979\";",
332
333 "INSERT INTO smartplaylist SET smartplaylistid = 3, name = \"1980's\", "
334 " categoryid = 1, matchtype = \"All\", orderby = \"Artist (A)\","
335 " limitto = 0;",
336 "INSERT INTO smartplaylistitem SET smartplaylistid = 3, field = \"Year\","
337 " operator = \"is between\", value1 = \"1980\", value2 = \"1989\";",
338
339 "INSERT INTO smartplaylist SET smartplaylistid = 4, name = \"1990's\", "
340 " categoryid = 1, matchtype = \"All\", orderby = \"Artist (A)\","
341 " limitto = 0;",
342 "INSERT INTO smartplaylistitem SET smartplaylistid = 4, field = \"Year\","
343 " operator = \"is between\", value1 = \"1990\", value2 = \"1999\";",
344
345 "INSERT INTO smartplaylist SET smartplaylistid = 5, name = \"2000's\", "
346 " categoryid = 1, matchtype = \"All\", orderby = \"Artist (A)\","
347 " limitto = 0;",
348 "INSERT INTO smartplaylistitem SET smartplaylistid = 5, field = \"Year\","
349 " operator = \"is between\", value1 = \"2000\", value2 = \"2009\";",
350
351 "INSERT INTO smartplaylist SET smartplaylistid = 6, name = \"Favorite Tracks\", "
352 " categoryid = 2, matchtype = \"All\","
353 " orderby = \"Artist (A), Album (A)\", limitto = 0;",
354 "INSERT INTO smartplaylistitem SET smartplaylistid = 6, field = \"Rating\","
355 " operator = \"is greater than\", value1 = \"7\", value2 = \"0\";",
356
357 "INSERT INTO smartplaylist SET smartplaylistid = 7, name = \"100 Most Played Tracks\", "
358 " categoryid = 2, matchtype = \"All\", orderby = \"Play Count (D)\","
359 " limitto = 100;",
360 "INSERT INTO smartplaylistitem SET smartplaylistid = 7, field = \"Play Count\","
361 " operator = \"is greater than\", value1 = \"0\", value2 = \"0\";",
362
363 "INSERT INTO smartplaylist SET smartplaylistid = 8, name = \"Never Played Tracks\", "
364 " categoryid = 3, matchtype = \"All\", orderby = \"Artist (A), Album (A)\","
365 " limitto = 0;",
366 "INSERT INTO smartplaylistitem SET smartplaylistid = 8, field = \"Play Count\","
367 " operator = \"is equal to\", value1 = \"0\", value2 = \"0\";"
368 };
369
371 updates, "1004", dbver))
372 return false;
373 }
374
375 if (dbver == "1004")
376 {
377 DBUpdates updates
378 {
379 "ALTER TABLE musicmetadata ADD compilation_artist VARCHAR(128) NOT NULL AFTER artist;",
380 "ALTER TABLE musicmetadata ADD INDEX (compilation_artist);"
381 };
382
384 updates, "1005", dbver))
385 return false;
386 }
387
388
389 if (dbver == "1005")
390 {
391 DBUpdates updates
392 {
393 "CREATE TABLE music_albums ("
394 " album_id int(11) unsigned NOT NULL auto_increment PRIMARY KEY,"
395 " artist_id int(11) unsigned NOT NULL default '0',"
396 " album_name varchar(255) NOT NULL default '',"
397 " year smallint(6) NOT NULL default '0',"
398 " compilation tinyint(1) unsigned NOT NULL default '0',"
399 " INDEX idx_album_name(album_name)"
400 ");",
401 "CREATE TABLE music_artists ("
402 " artist_id int(11) unsigned NOT NULL auto_increment PRIMARY KEY,"
403 " artist_name varchar(255) NOT NULL default '',"
404 " INDEX idx_artist_name(artist_name)"
405 ");",
406 "CREATE TABLE music_genres ("
407 " genre_id int(11) unsigned NOT NULL auto_increment PRIMARY KEY,"
408 " genre varchar(25) NOT NULL default '',"
409 " INDEX idx_genre(genre)"
410 ");",
411 "CREATE TABLE music_playlists ("
412 " playlist_id int(11) unsigned NOT NULL auto_increment PRIMARY KEY,"
413 " playlist_name varchar(255) NOT NULL default '',"
414 " playlist_songs text NOT NULL,"
415 " last_accessed timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP "
416 " ON UPDATE CURRENT_TIMESTAMP,"
417 " length int(11) unsigned NOT NULL default '0',"
418 " songcount smallint(8) unsigned NOT NULL default '0',"
419 " hostname VARCHAR(255) NOT NULL default ''"
420 ");",
421 "CREATE TABLE music_songs ("
422 " song_id int(11) unsigned NOT NULL auto_increment PRIMARY KEY,"
423 " filename text NOT NULL,"
424 " name varchar(255) NOT NULL default '',"
425 " track smallint(6) unsigned NOT NULL default '0',"
426 " artist_id int(11) unsigned NOT NULL default '0',"
427 " album_id int(11) unsigned NOT NULL default '0',"
428 " genre_id int(11) unsigned NOT NULL default '0',"
429 " year smallint(6) NOT NULL default '0',"
430 " length int(11) unsigned NOT NULL default '0',"
431 " numplays int(11) unsigned NOT NULL default '0',"
432 " rating tinyint(4) unsigned NOT NULL default '0',"
433 " lastplay timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP "
434 " ON UPDATE CURRENT_TIMESTAMP,"
435 " date_entered datetime default NULL,"
436 " date_modified datetime default NULL,"
437 " format varchar(4) NOT NULL default '0',"
438 " mythdigest VARCHAR(255),"
439 " size BIGINT(20) unsigned,"
440 " description VARCHAR(255),"
441 " comment VARCHAR(255),"
442 " disc_count SMALLINT(5) UNSIGNED DEFAULT '0',"
443 " disc_number SMALLINT(5) UNSIGNED DEFAULT '0',"
444 " track_count SMALLINT(5) UNSIGNED DEFAULT '0',"
445 " start_time INT(10) UNSIGNED DEFAULT '0',"
446 " stop_time INT(10) UNSIGNED,"
447 " eq_preset VARCHAR(255),"
448 " relative_volume TINYINT DEFAULT '0',"
449 " sample_rate INT(10) UNSIGNED DEFAULT '0',"
450 " bitrate INT(10) UNSIGNED DEFAULT '0',"
451 " bpm SMALLINT(5) UNSIGNED,"
452 " INDEX idx_name(name),"
453 " INDEX idx_mythdigest(mythdigest)"
454 ");",
455 "CREATE TABLE music_stats ("
456 " num_artists smallint(5) unsigned NOT NULL default '0',"
457 " num_albums smallint(5) unsigned NOT NULL default '0',"
458 " num_songs mediumint(8) unsigned NOT NULL default '0',"
459 " num_genres tinyint(3) unsigned NOT NULL default '0',"
460 " total_time varchar(12) NOT NULL default '0',"
461 " total_size varchar(10) NOT NULL default '0'"
462 ");",
463 "RENAME TABLE smartplaylist TO music_smartplaylists;",
464 "RENAME TABLE smartplaylistitem TO music_smartplaylist_items;",
465 "RENAME TABLE smartplaylistcategory TO music_smartplaylist_categories;",
466 // Run necessary SQL to migrate the table structure
467 // NOLINTNEXTLINE(bugprone-suspicious-missing-comma)
468 "CREATE TEMPORARY TABLE tmp_artists"
469 " SELECT DISTINCT artist FROM musicmetadata;",
470 "INSERT INTO tmp_artists"
471 " SELECT DISTINCT compilation_artist"
472 " FROM musicmetadata"
473 " WHERE compilation_artist<>artist;",
474 "INSERT INTO music_artists (artist_name) SELECT DISTINCT artist FROM tmp_artists;",
475 "INSERT INTO music_albums (artist_id, album_name, year, compilation) "
476 " SELECT artist_id, album, ROUND(AVG(year)) AS year, IF(SUM(compilation),1,0) AS compilation"
477 " FROM musicmetadata"
478 " LEFT JOIN music_artists ON compilation_artist=artist_name"
479 " GROUP BY artist_id, album;",
480 "INSERT INTO music_genres (genre) SELECT DISTINCT genre FROM musicmetadata;",
481 "INSERT INTO music_songs "
482 " (song_id, artist_id, album_id, genre_id, year, lastplay,"
483 " date_entered, date_modified, name, track, length, size, numplays,"
484 " rating, filename)"
485 " SELECT intid, ma.artist_id, mb.album_id, mg.genre_id, mmd.year, lastplay,"
486 " date_added, date_modified, title, tracknum, length, IFNULL(size,0), playcount,"
487 " rating, filename"
488 " FROM musicmetadata AS mmd"
489 " LEFT JOIN music_artists AS ma ON mmd.artist=ma.artist_name"
490 " LEFT JOIN music_artists AS mc ON mmd.compilation_artist=mc.artist_name"
491 " LEFT JOIN music_albums AS mb ON mmd.album=mb.album_name AND mc.artist_id=mb.artist_id"
492 " LEFT JOIN music_genres AS mg ON mmd.genre=mg.genre;",
493 "INSERT INTO music_playlists"
494 " (playlist_id,playlist_name,playlist_songs,hostname)"
495 " SELECT playlistid, name, songlist, hostname"
496 " FROM musicplaylist;",
497 // Set all real playlists to be global by killing the hostname
498 "UPDATE music_playlists"
499 " SET hostname=''"
500 " WHERE playlist_name<>'default_playlist_storage'"
501 " AND playlist_name<>'backup_playlist_storage';"
502 };
503
505 updates, "1006", dbver))
506 return false;
507 }
508
509 if (dbver == "1006")
510 {
511 DBUpdates updates
512 {
513 "ALTER TABLE music_genres MODIFY genre VARCHAR(255) NOT NULL default '';"
514 };
515
517 updates, "1007", dbver))
518 return false;
519 }
520
521 if (dbver == "1007")
522 {
523 DBUpdates updates
524 {
525 "ALTER TABLE music_songs MODIFY lastplay DATETIME DEFAULT NULL;",
526 // NOLINTNEXTLINE(bugprone-suspicious-missing-comma)
527 "CREATE TABLE music_directories (directory_id int(20) NOT NULL AUTO_INCREMENT "
528 "PRIMARY KEY, path TEXT NOT NULL, "
529 "parent_id INT(20) NOT NULL DEFAULT '0') ;",
530 "INSERT IGNORE INTO music_directories (path) SELECT DISTINCT"
531 " SUBSTRING(filename FROM 1 FOR INSTR(filename, "
532 "SUBSTRING_INDEX(filename, '/', -1))-2) FROM music_songs;",
533 "CREATE TEMPORARY TABLE tmp_songs SELECT music_songs.*, directory_id "
534 "FROM music_songs, music_directories WHERE "
535 "music_directories.path=SUBSTRING(filename FROM 1 FOR "
536 "INSTR(filename, SUBSTRING_INDEX(filename, '/', -1))-2);",
537 "UPDATE tmp_songs SET filename=SUBSTRING_INDEX(filename, '/', -1);",
538 "DELETE FROM music_songs;",
539 "ALTER TABLE music_songs ADD COLUMN directory_id int(20) NOT NULL DEFAULT '0';",
540 "INSERT INTO music_songs SELECT * FROM tmp_songs;",
541 "ALTER TABLE music_songs ADD INDEX (directory_id);"
542 };
543
545 updates, "1008", dbver))
546 return false;
547 }
548
549 if (dbver == "1008")
550 {
551 DBUpdates updates
552 {
553 "CREATE TABLE music_albumart (albumart_id int(20) NOT NULL AUTO_INCREMENT "
554 "PRIMARY KEY, filename VARCHAR(255) NOT NULL DEFAULT '', directory_id INT(20) "
555 "NOT NULL DEFAULT '0');"
556 };
557
559 updates, "1009", dbver))
560 return false;
561 }
562
563 if (dbver == "1009")
564 {
565 DBUpdates updates
566 {
567 "ALTER TABLE music_albumart ADD COLUMN imagetype tinyint(3) NOT NULL DEFAULT '0';"
568 };
569
571 updates, "1010", dbver))
572 return false;
573
574 // scan though the music_albumart table and make a guess at what
575 // each image represents from the filename
576
577 LOG(VB_GENERAL, LOG_NOTICE, "Updating music_albumart image types");
578
580 query.prepare("SELECT albumart_id, filename, directory_id, imagetype FROM music_albumart;");
581
582 if (query.exec())
583 {
584 while (query.next())
585 {
586 int id = query.value(0).toInt();
587 QString filename = query.value(1).toString();
588 int directoryID = query.value(2).toInt();
589 MSqlQuery subquery(MSqlQuery::InitCon());
590
591 // guess the type from the filename
593
594 // if type is still unknown check to see how many images are available in the dir
595 // and assume that if this is the only image it must be the front cover
596 if (type == IT_UNKNOWN)
597 {
598 subquery.prepare("SELECT count(directory_id) FROM music_albumart "
599 "WHERE directory_id = :DIR;");
600 subquery.bindValue(":DIR", directoryID);
601 if (!subquery.exec() || !subquery.isActive())
602 MythDB::DBError("album art image count", subquery);
603 subquery.first();
604 if (query.value(0).toInt() == 1)
606 }
607
608 // finally set the type in the music_albumart table
609 subquery.prepare("UPDATE music_albumart "
610 "SET imagetype = :TYPE "
611 "WHERE albumart_id = :ID;");
612 subquery.bindValue(":TYPE", type);
613 subquery.bindValue(":ID", id);
614 if (!subquery.exec() || !subquery.isActive())
615 MythDB::DBError("album art image type update", subquery);
616 }
617 }
618 }
619
620 if (dbver == "1010")
621 {
622 // update the VisualMode setting to the new format
623 QString setting = gCoreContext->GetSetting("VisualMode");
624 setting = setting.simplified();
625 setting = setting.replace(' ', ";");
626 gCoreContext->SaveSetting("VisualMode", setting);
627
628 if (!UpdateDBVersionNumber("MythMusic", MythMusicVersionName, "1011", dbver))
629 return false;
630
631 }
632
633 if (dbver == "1011")
634 {
635 DBUpdates updates
636 {
637 "ALTER TABLE music_albumart ADD COLUMN song_id int(11) NOT NULL DEFAULT '0', "
638 " ADD COLUMN embedded TINYINT(1) NOT NULL DEFAULT '0';"
639 };
640
642 updates, "1012", dbver))
643 return false;
644
645 }
646
647 if (dbver == "1012")
648 {
649 DBUpdates updates
650 {
651 "ALTER TABLE music_songs ADD INDEX album_id (album_id);",
652 "ALTER TABLE music_songs ADD INDEX genre_id (genre_id);",
653 "ALTER TABLE music_songs ADD INDEX artist_id (artist_id);"
654 };
655
657 updates, "1013", dbver))
658 return false;
659
660 }
661
662 if (dbver == "1013")
663 {
664 DBUpdates updates
665 {
666 "DROP TABLE musicmetadata;",
667 "DROP TABLE musicplaylist;"
668 };
669
671 updates, "1014", dbver))
672 return false;
673 }
674
675 if (dbver == "1014")
676 {
677 DBUpdates updates
678 {
679 qPrintable(QString("ALTER DATABASE %1 DEFAULT CHARACTER SET latin1;")
680 .arg(GetMythDB()->GetDatabaseName())),
681 // NOLINTNEXTLINE(bugprone-suspicious-missing-comma)
682 "ALTER TABLE music_albumart"
683 " MODIFY filename varbinary(255) NOT NULL default '';",
684 "ALTER TABLE music_albums"
685 " MODIFY album_name varbinary(255) NOT NULL default '';",
686 "ALTER TABLE music_artists"
687 " MODIFY artist_name varbinary(255) NOT NULL default '';",
688 "ALTER TABLE music_directories"
689 " MODIFY path blob NOT NULL;",
690 "ALTER TABLE music_genres"
691 " MODIFY genre varbinary(255) NOT NULL default '';",
692 "ALTER TABLE music_playlists"
693 " MODIFY playlist_name varbinary(255) NOT NULL default '',"
694 " MODIFY playlist_songs blob NOT NULL,"
695 " MODIFY hostname varbinary(64) NOT NULL default '';",
696 "ALTER TABLE music_smartplaylist_categories"
697 " MODIFY name varbinary(128) NOT NULL;",
698 "ALTER TABLE music_smartplaylist_items"
699 " MODIFY field varbinary(50) NOT NULL,"
700 " MODIFY operator varbinary(20) NOT NULL,"
701 " MODIFY value1 varbinary(255) NOT NULL,"
702 " MODIFY value2 varbinary(255) NOT NULL;",
703 "ALTER TABLE music_smartplaylists"
704 " MODIFY name varbinary(128) NOT NULL,"
705 " MODIFY orderby varbinary(128) NOT NULL default '';",
706 "ALTER TABLE music_songs"
707 " MODIFY filename blob NOT NULL,"
708 " MODIFY name varbinary(255) NOT NULL default '',"
709 " MODIFY format varbinary(4) NOT NULL default '0',"
710 " MODIFY mythdigest varbinary(255) default NULL,"
711 " MODIFY description varbinary(255) default NULL,"
712 " MODIFY comment varbinary(255) default NULL,"
713 " MODIFY eq_preset varbinary(255) default NULL;",
714 "ALTER TABLE music_stats"
715 " MODIFY total_time varbinary(12) NOT NULL default '0',"
716 " MODIFY total_size varbinary(10) NOT NULL default '0';"
717 };
718
720 updates, "1015", dbver))
721 return false;
722 }
723
724
725 if (dbver == "1015")
726 {
727 DBUpdates updates
728 {
729 qPrintable(QString("ALTER DATABASE %1 DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;")
730 .arg(GetMythDB()->GetDatabaseName())),
731 // NOLINTNEXTLINE(bugprone-suspicious-missing-comma)
732 "ALTER TABLE music_albumart"
733 " DEFAULT CHARACTER SET utf8,"
734 " MODIFY filename varchar(255) CHARACTER SET utf8 NOT NULL default '';",
735 "ALTER TABLE music_albums"
736 " DEFAULT CHARACTER SET utf8,"
737 " MODIFY album_name varchar(255) CHARACTER SET utf8 NOT NULL default '';",
738 "ALTER TABLE music_artists"
739 " DEFAULT CHARACTER SET utf8,"
740 " MODIFY artist_name varchar(255) CHARACTER SET utf8 NOT NULL default '';",
741 "ALTER TABLE music_directories"
742 " DEFAULT CHARACTER SET utf8,"
743 " MODIFY path text CHARACTER SET utf8 NOT NULL;",
744 "ALTER TABLE music_genres"
745 " DEFAULT CHARACTER SET utf8,"
746 " MODIFY genre varchar(255) CHARACTER SET utf8 NOT NULL default '';",
747 "ALTER TABLE music_playlists"
748 " DEFAULT CHARACTER SET utf8,"
749 " MODIFY playlist_name varchar(255) CHARACTER SET utf8 NOT NULL default '',"
750 " MODIFY playlist_songs text CHARACTER SET utf8 NOT NULL,"
751 " MODIFY hostname varchar(64) CHARACTER SET utf8 NOT NULL default '';",
752 "ALTER TABLE music_smartplaylist_categories"
753 " DEFAULT CHARACTER SET utf8,"
754 " MODIFY name varchar(128) CHARACTER SET utf8 NOT NULL;",
755 "ALTER TABLE music_smartplaylist_items"
756 " DEFAULT CHARACTER SET utf8,"
757 " MODIFY field varchar(50) CHARACTER SET utf8 NOT NULL,"
758 " MODIFY operator varchar(20) CHARACTER SET utf8 NOT NULL,"
759 " MODIFY value1 varchar(255) CHARACTER SET utf8 NOT NULL,"
760 " MODIFY value2 varchar(255) CHARACTER SET utf8 NOT NULL;",
761 "ALTER TABLE music_smartplaylists"
762 " DEFAULT CHARACTER SET utf8,"
763 " MODIFY name varchar(128) CHARACTER SET utf8 NOT NULL,"
764 " MODIFY orderby varchar(128) CHARACTER SET utf8 NOT NULL default '';",
765 "ALTER TABLE music_songs"
766 " DEFAULT CHARACTER SET utf8,"
767 " MODIFY filename text CHARACTER SET utf8 NOT NULL,"
768 " MODIFY name varchar(255) CHARACTER SET utf8 NOT NULL default '',"
769 " MODIFY format varchar(4) CHARACTER SET utf8 NOT NULL default '0',"
770 " MODIFY mythdigest varchar(255) CHARACTER SET utf8 default NULL,"
771 " MODIFY description varchar(255) CHARACTER SET utf8 default NULL,"
772 " MODIFY comment varchar(255) CHARACTER SET utf8 default NULL,"
773 " MODIFY eq_preset varchar(255) CHARACTER SET utf8 default NULL;",
774 "ALTER TABLE music_stats"
775 " DEFAULT CHARACTER SET utf8,"
776 " MODIFY total_time varchar(12) CHARACTER SET utf8 NOT NULL default '0',"
777 " MODIFY total_size varchar(10) CHARACTER SET utf8 NOT NULL default '0';"
778 };
779
781 updates, "1016", dbver))
782 return false;
783 }
784
785 if (dbver == "1016")
786 {
787 DBUpdates updates
788 {
789 "DELETE FROM keybindings "
790 " WHERE action = 'DELETE' AND context = 'Music';"
791 };
792
794 updates, "1017", dbver))
795 return false;
796 }
797
798 if (dbver == "1017")
799 {
800 DBUpdates updates
801 {
802 "ALTER TABLE music_playlists MODIFY COLUMN last_accessed "
803 " TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP;"
804 };
805
807 updates, "1018", dbver))
808 return false;
809 }
810
811 if (dbver == "1018")
812 {
813 DBUpdates updates
814 {
815 "CREATE TEMPORARY TABLE arttype_tmp ( type INT, name VARCHAR(30) );",
816 "INSERT INTO arttype_tmp VALUES (0,'unknown'),(1,'front'),(2,'back'),(3,'cd'),(4,'inlay');",
817 "UPDATE music_albumart LEFT JOIN arttype_tmp ON type = imagetype "
818 "SET filename = CONCAT(song_id, '-', name, '.jpg') WHERE embedded=1;"
819 };
820
822 updates, "1019", dbver))
823 return false;
824 }
825
826 if (dbver == "1019")
827 {
828 DBUpdates updates
829 {
830 "DROP TABLE IF EXISTS music_radios;",
831 "CREATE TABLE music_radios ("
832 " intid INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,"
833 " station VARCHAR(128) NOT NULL,"
834 " channel VARCHAR(128) NOT NULL,"
835 " url VARCHAR(128) NOT NULL,"
836 " logourl VARCHAR(128) NOT NULL,"
837 " genre VARCHAR(128) NOT NULL,"
838 " metaformat VARCHAR(128) NOT NULL,"
839 " format VARCHAR(10) NOT NULL,"
840 " INDEX (station),"
841 " INDEX (channel)"
842 ");"
843 };
844
846 updates, "1020", dbver))
847 return false;
848 }
849
850 if (dbver == "1020")
851 {
852 DBUpdates updates
853 {
854 "ALTER TABLE music_songs ADD COLUMN hostname VARCHAR(255) NOT NULL default '';",
855 qPrintable(QString("UPDATE music_songs SET hostname = '%1';")
857 };
858
860 updates, "1021", dbver))
861 return false;
862 }
863
864 if (dbver == "1021")
865 {
866 DBUpdates updates
867 {
868 "ALTER TABLE music_albumart ADD COLUMN hostname VARCHAR(255) NOT NULL default '';",
869 qPrintable(QString("UPDATE music_albumart SET hostname = '%1';")
871 };
872
874 updates, "1022", dbver))
875 return false;
876 }
877
878 if (dbver == "1022")
879 {
880 DBUpdates updates
881 {
882 "CREATE INDEX `song_id` ON music_albumart (song_id);",
883 "CREATE INDEX `artist_id` ON music_albums (artist_id);"
884 };
885
887 updates, "1023", dbver))
888 return false;
889 }
890
891 if (dbver == "1023")
892 {
893 DBUpdates updates
894 {
895 "DROP INDEX station ON music_radios;",
896 "ALTER TABLE music_radios CHANGE COLUMN station broadcaster VARCHAR(100) NOT NULL default '';",
897 "ALTER TABLE music_radios MODIFY COLUMN channel VARCHAR(200) NOT NULL default '';",
898 "ALTER TABLE music_radios ADD description TEXT NOT NULL default '' AFTER channel;",
899 "ALTER TABLE music_radios CHANGE COLUMN url url1 VARCHAR(300) NOT NULL default '';",
900 "ALTER TABLE music_radios ADD COLUMN url2 VARCHAR(300) NOT NULL default '' AFTER url1;",
901 "ALTER TABLE music_radios ADD COLUMN url3 VARCHAR(300) NOT NULL default '' AFTER url2;",
902 "ALTER TABLE music_radios ADD COLUMN url4 VARCHAR(300) NOT NULL default '' AFTER url3;",
903 "ALTER TABLE music_radios ADD COLUMN url5 VARCHAR(300) NOT NULL default '' AFTER url4;",
904 "ALTER TABLE music_radios MODIFY COLUMN logourl VARCHAR(300) NOT NULL default '';",
905 "ALTER TABLE music_radios MODIFY COLUMN metaformat VARCHAR(50) NOT NULL default '';",
906 "ALTER TABLE music_radios ADD COLUMN country VARCHAR(50) NOT NULL default '' AFTER logourl;",
907 "ALTER TABLE music_radios ADD COLUMN language VARCHAR(50) NOT NULL default '' AFTER country;",
908 "CREATE INDEX broadcaster ON music_radios (broadcaster);",
909 "DROP TABLE IF EXISTS music_streams;",
910 "CREATE TABLE music_streams ("
911 " intid INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,"
912 " broadcaster VARCHAR(100) NOT NULL default '',"
913 " channel VARCHAR(200) NOT NULL default '',"
914 " description TEXT NOT NULL default '',"
915 " url1 VARCHAR(300) NOT NULL default '',"
916 " url2 VARCHAR(300) NOT NULL default '',"
917 " url3 VARCHAR(300) NOT NULL default '',"
918 " url4 VARCHAR(300) NOT NULL default '',"
919 " url5 VARCHAR(300) NOT NULL default '',"
920 " logourl VARCHAR(300) NOT NULL default '',"
921 " genre VARCHAR(100) NOT NULL default '',"
922 " metaformat VARCHAR(50) NOT NULL default '',"
923 " country VARCHAR(50) NOT NULL default '',"
924 " language VARCHAR(50) NOT NULL default '',"
925 " INDEX (broadcaster),"
926 " INDEX (channel),"
927 " INDEX (country),"
928 " INDEX (language)"
929 ");"
930 };
931
933 updates, "1024", dbver))
934 return false;
935 }
936
937 // Repeat 1016 DBs pre MySQL v8 systems that may have not be set to utf8
938
939 if (dbver == "1024")
940 {
941 DBUpdates updates
942 {
943 "ALTER TABLE music_albumart DEFAULT CHARACTER SET utf8;",
944 "ALTER TABLE music_albums DEFAULT CHARACTER SET utf8;",
945 "ALTER TABLE music_artists DEFAULT CHARACTER SET utf8;",
946 "ALTER TABLE music_directories DEFAULT CHARACTER SET utf8;",
947 "ALTER TABLE music_genres DEFAULT CHARACTER SET utf8;",
948 "ALTER TABLE music_playlists DEFAULT CHARACTER SET utf8;",
949 "ALTER TABLE music_smartplaylist_categories DEFAULT CHARACTER SET utf8;",
950 "ALTER TABLE music_smartplaylist_items DEFAULT CHARACTER SET utf8;",
951 "ALTER TABLE music_smartplaylists DEFAULT CHARACTER SET utf8;",
952 "ALTER TABLE music_songs DEFAULT CHARACTER SET utf8;",
953 "ALTER TABLE music_stats DEFAULT CHARACTER SET utf8;"
954 };
955
957 updates, "1025", dbver))
958 return false;
959 }
960
961 return true;
962
963}
static ImageType guessImageType(const QString &filename)
static void UnlockSchema(MSqlQuery &query)
Definition: dbutil.cpp:853
static bool TryLockSchema(MSqlQuery &query, uint timeout_secs)
Try to get a lock on the table schemalock.
Definition: dbutil.cpp:846
QSqlQuery wrapper that fetches a DB connection from the connection pool.
Definition: mythdbcon.h:128
bool prepare(const QString &query)
QSqlQuery::prepare() is not thread safe in Qt <= 3.3.2.
Definition: mythdbcon.cpp:837
bool first(void)
Wrap QSqlQuery::first() so we can display the query results.
Definition: mythdbcon.cpp:822
QVariant value(int i) const
Definition: mythdbcon.h:204
int size(void) const
Definition: mythdbcon.h:214
int numRowsAffected() const
Definition: mythdbcon.h:217
bool isActive(void) const
Definition: mythdbcon.h:215
bool exec(void)
Wrap QSqlQuery::exec() so we can display SQL.
Definition: mythdbcon.cpp:618
void bindValue(const QString &placeholder, const QVariant &val)
Add a single binding.
Definition: mythdbcon.cpp:888
bool next(void)
Wrap QSqlQuery::next() so we can display the query results.
Definition: mythdbcon.cpp:812
static MSqlQueryInfo InitCon(ConnectionReuse _reuse=kNormalConnection)
Only use this in combination with MSqlQuery constructor.
Definition: mythdbcon.cpp:550
void ActivateSettingsCache(bool activate=true)
void SaveSetting(const QString &key, int newValue)
QString GetSetting(const QString &key, const QString &defaultval="")
QString GetMasterHostName(void)
static void DBError(const QString &where, const MSqlQuery &query)
Definition: mythdb.cpp:226
Provides UI and helper functions for DB Schema updates.
Definition: schemawizard.h:26
enum MythSchemaUpgrade PromptForUpgrade(const char *name, bool upgradeAllowed, bool upgradeIfNoUI, int minDBMSmajor=0, int minDBMSminor=0, int minDBMSpoint=0)
Query user, to prevent silent, automatic database upgrades.
QString m_DBver
Schema version in the database.
Definition: schemawizard.h:55
static SchemaUpgradeWizard * Get(const QString &DBSchemaSetting, const QString &appName, const QString &upgradeSchemaVal)
Instead of creating a new wizard, use the existing one for its DB backup file & results and expert se...
int Compare(void)
How many schema versions old is the DB?
bool performActualUpdate(const QString &component, const QString &versionkey, const DBUpdates &updates, const QString &version, QString &dbver)
bool UpdateDBVersionNumber(const QString &component, const QString &versionkey, const QString &newnumber, QString &dbver)
Updates the schema version stored in the database.
unsigned int uint
Definition: freesurround.h:24
static bool tryUpgradeMusicDatabaseSchema()
const QString currentDatabaseVersion
const QString MythMusicVersionName
bool UpgradeMusicDatabaseSchema(void)
static bool doUpgradeMusicDatabaseSchema(QString &dbver)
@ IT_UNKNOWN
Definition: musicmetadata.h:36
@ IT_FRONTCOVER
Definition: musicmetadata.h:37
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
MythDB * GetMythDB(void)
Definition: mythdb.cpp:51
std::vector< std::string > DBUpdates
Definition: mythdbcheck.h:9
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
@ MYTH_SCHEMA_ERROR
Definition: schemawizard.h:17
@ MYTH_SCHEMA_UPGRADE
Definition: schemawizard.h:18
@ MYTH_SCHEMA_EXIT
Definition: schemawizard.h:16
@ MYTH_SCHEMA_USE_EXISTING
Definition: schemawizard.h:19