594
/* Maintenance and DB hygiene */
598
char *query = "ANALYZE;";
602
DPRINTF(E_DBG, L_DB, "Running query '%s'\n", query);
604
ret = db_exec(query, &errmsg);
605
if (ret != SQLITE_OK)
607
DPRINTF(E_LOG, L_DB, "ANALYZE failed: %s\n", errmsg);
609
sqlite3_free(errmsg);
614
db_hook_post_scan(void)
616
DPRINTF(E_DBG, L_DB, "Running post-scan DB maintenance tasks...\n");
620
DPRINTF(E_DBG, L_DB, "Done with post-scan DB maintenance\n");
595
624
db_purge_cruft(time_t ref)
751
785
sort = sort_clause[qp->sort];
753
787
if (idx && qp->filter)
754
query = sqlite3_mprintf("SELECT * FROM files WHERE disabled = 0 AND %s %s %s;", qp->filter, sort, idx);
788
query = sqlite3_mprintf("SELECT f.* FROM files f WHERE f.disabled = 0 AND %s %s %s;", qp->filter, sort, idx);
756
query = sqlite3_mprintf("SELECT * FROM files WHERE disabled = 0 %s %s;", sort, idx);
790
query = sqlite3_mprintf("SELECT f.* FROM files f WHERE f.disabled = 0 %s %s;", sort, idx);
757
791
else if (qp->filter)
758
query = sqlite3_mprintf("SELECT * FROM files WHERE disabled = 0 AND %s %s;", qp->filter, sort);
792
query = sqlite3_mprintf("SELECT f.* FROM files f WHERE f.disabled = 0 AND %s %s;", qp->filter, sort);
760
query = sqlite3_mprintf("SELECT * FROM files WHERE disabled = 0 %s;", sort);
794
query = sqlite3_mprintf("SELECT f.* FROM files f WHERE f.disabled = 0 %s;", sort);
789
823
if (idx && qp->filter)
790
query = sqlite3_mprintf("SELECT * FROM playlists WHERE disabled = 0 AND %s %s;", qp->filter, idx);
824
query = sqlite3_mprintf("SELECT f.* FROM playlists f WHERE f.disabled = 0 AND %s %s;", qp->filter, idx);
792
query = sqlite3_mprintf("SELECT * FROM playlists WHERE disabled = 0 %s;", idx);
826
query = sqlite3_mprintf("SELECT f.* FROM playlists f WHERE f.disabled = 0 %s;", idx);
793
827
else if (qp->filter)
794
query = sqlite3_mprintf("SELECT * FROM playlists WHERE disabled = 0 AND %s;", qp->filter);
828
query = sqlite3_mprintf("SELECT f.* FROM playlists f WHERE f.disabled = 0 AND %s;", qp->filter);
796
query = sqlite3_mprintf("SELECT * FROM playlists WHERE disabled = 0;");
830
query = sqlite3_mprintf("SELECT f.* FROM playlists f WHERE f.disabled = 0;");
818
count = sqlite3_mprintf("SELECT COUNT(*) FROM files JOIN playlistitems ON files.path = playlistitems.filepath"
819
" WHERE playlistitems.playlistid = %d AND files.disabled = 0 AND %s;", qp->id, qp->filter);
852
count = sqlite3_mprintf("SELECT COUNT(*) FROM files f JOIN playlistitems pi ON f.path = pi.filepath"
853
" WHERE pi.playlistid = %d AND f.disabled = 0 AND %s;", qp->id, qp->filter);
821
count = sqlite3_mprintf("SELECT COUNT(*) FROM files JOIN playlistitems ON files.path = playlistitems.filepath"
822
" WHERE playlistitems.playlistid = %d AND files.disabled = 0;", qp->id);
855
count = sqlite3_mprintf("SELECT COUNT(*) FROM files f JOIN playlistitems pi ON f.path = pi.filepath"
856
" WHERE pi.playlistid = %d AND f.disabled = 0;", qp->id);
842
876
if (idx && qp->filter)
843
query = sqlite3_mprintf("SELECT files.* FROM files JOIN playlistitems ON files.path = playlistitems.filepath"
844
" WHERE playlistitems.playlistid = %d AND files.disabled = 0 AND %s ORDER BY playlistitems.id ASC %s;",
877
query = sqlite3_mprintf("SELECT f.* FROM files f JOIN playlistitems pi ON f.path = pi.filepath"
878
" WHERE pi.playlistid = %d AND f.disabled = 0 AND %s ORDER BY pi.id ASC %s;",
845
879
qp->id, qp->filter, idx);
847
query = sqlite3_mprintf("SELECT files.* FROM files JOIN playlistitems ON files.path = playlistitems.filepath"
848
" WHERE playlistitems.playlistid = %d AND files.disabled = 0 ORDER BY playlistitems.id ASC %s;",
881
query = sqlite3_mprintf("SELECT f.* FROM files f JOIN playlistitems pi ON f.path = pi.filepath"
882
" WHERE pi.playlistid = %d AND f.disabled = 0 ORDER BY pi.id ASC %s;",
850
884
else if (qp->filter)
851
query = sqlite3_mprintf("SELECT files.* FROM files JOIN playlistitems ON files.path = playlistitems.filepath"
852
" WHERE playlistitems.playlistid = %d AND files.disabled = 0 AND %s ORDER BY playlistitems.id ASC;",
885
query = sqlite3_mprintf("SELECT f.* FROM files f JOIN playlistitems pi ON f.path = pi.filepath"
886
" WHERE pi.playlistid = %d AND f.disabled = 0 AND %s ORDER BY pi.id ASC;",
853
887
qp->id, qp->filter);
855
query = sqlite3_mprintf("SELECT files.* FROM files JOIN playlistitems ON files.path = playlistitems.filepath"
856
" WHERE playlistitems.playlistid = %d AND files.disabled = 0 ORDER BY playlistitems.id ASC;",
889
query = sqlite3_mprintf("SELECT f.* FROM files f JOIN playlistitems pi ON f.path = pi.filepath"
890
" WHERE pi.playlistid = %d AND f.disabled = 0 ORDER BY pi.id ASC;",
974
1008
if (idx && qp->filter)
975
query = sqlite3_mprintf("SELECT COUNT(*), g.id, g.persistentid, f.album_artist, g.name FROM files f JOIN groups g ON f.songalbumid = g.persistentid GROUP BY f.album, g.name HAVING g.type = %d AND disabled = 0 AND %s %s;", G_ALBUMS, qp->filter, idx);
1009
query = sqlite3_mprintf("SELECT COUNT(*), g.id, g.persistentid, f.album_artist, g.name FROM files f, groups g WHERE f.songalbumid = g.persistentid AND g.type = %d AND f.disabled = 0 AND %s GROUP BY f.album, g.name %s;", G_ALBUMS, qp->filter, idx);
977
query = sqlite3_mprintf("SELECT COUNT(*), g.id, g.persistentid, f.album_artist, g.name FROM files f JOIN groups g ON f.songalbumid = g.persistentid GROUP BY f.album, g.name HAVING g.type = %d AND disabled = 0 %s;", G_ALBUMS, idx);
1011
query = sqlite3_mprintf("SELECT COUNT(*), g.id, g.persistentid, f.album_artist, g.name FROM files f, groups g WHERE f.songalbumid = g.persistentid AND g.type = %d AND f.disabled = 0 GROUP BY f.album, g.name %s;", G_ALBUMS, idx);
978
1012
else if (qp->filter)
979
query = sqlite3_mprintf("SELECT COUNT(*), g.id, g.persistentid, f.album_artist, g.name FROM files f JOIN groups g ON f.songalbumid = g.persistentid GROUP BY f.album, g.name HAVING g.type = %d AND disabled = 0 AND %s;", G_ALBUMS, qp->filter);
1013
query = sqlite3_mprintf("SELECT COUNT(*), g.id, g.persistentid, f.album_artist, g.name FROM files f, groups g WHERE f.songalbumid = g.persistentid AND g.type = %d AND f.disabled = 0 AND %s GROUP BY f.album, g.name;", G_ALBUMS, qp->filter);
981
query = sqlite3_mprintf("SELECT COUNT(*), g.id, g.persistentid, f.album_artist, g.name FROM files f JOIN groups g ON f.songalbumid = g.persistentid GROUP BY f.album, g.name HAVING g.type = %d AND disabled = 0;", G_ALBUMS);
1015
query = sqlite3_mprintf("SELECT COUNT(*), g.id, g.persistentid, f.album_artist, g.name FROM files f, groups g WHERE f.songalbumid = g.persistentid AND g.type = %d AND f.disabled = 0 GROUP BY f.album, g.name;", G_ALBUMS);
1135
1169
if (idx && qp->filter)
1136
query = sqlite3_mprintf("SELECT DISTINCT %s, %s FROM files WHERE data_kind = 0 AND disabled = 0 AND %s != ''"
1170
query = sqlite3_mprintf("SELECT DISTINCT f.%s, f.%s FROM files f WHERE f.data_kind = 0 AND f.disabled = 0 AND f.%s != ''"
1137
1171
" AND %s %s;", field, field, field, qp->filter, idx);
1139
query = sqlite3_mprintf("SELECT DISTINCT %s, %s FROM files WHERE data_kind = 0 AND disabled = 0 AND %s != ''"
1173
query = sqlite3_mprintf("SELECT DISTINCT f.%s, f.%s FROM files f WHERE f.data_kind = 0 AND f.disabled = 0 AND f.%s != ''"
1140
1174
" %s;", field, field, field, idx);
1141
1175
else if (qp->filter)
1142
query = sqlite3_mprintf("SELECT DISTINCT %s, %s FROM files WHERE data_kind = 0 AND disabled = 0 AND %s != ''"
1176
query = sqlite3_mprintf("SELECT DISTINCT f.%s, f.%s FROM files f WHERE f.data_kind = 0 AND f.disabled = 0 AND f.%s != ''"
1143
1177
" AND %s;", field, field, field, qp->filter);
1145
query = sqlite3_mprintf("SELECT DISTINCT %s, %s FROM files WHERE data_kind = 0 AND disabled = 0 AND %s != ''",
1179
query = sqlite3_mprintf("SELECT DISTINCT f.%s, f.%s FROM files f WHERE f.data_kind = 0 AND f.disabled = 0 AND f.%s != ''",
1146
1180
field, field, field);
2574
2633
db_pl_add(char *title, char *path, int *id)
2576
#define QDUP_TMPL "SELECT COUNT(*) FROM playlists WHERE title = '%q' AND path = '%q';"
2635
#define QDUP_TMPL "SELECT COUNT(*) FROM playlists p WHERE p.title = '%q' AND p.path = '%q';"
2577
2636
#define QADD_TMPL "INSERT INTO playlists (title, type, query, db_timestamp, disabled, path, idx, special_id)" \
2578
2637
" VALUES ('%q', 0, NULL, %" PRIi64 ", 0, '%q', 0, 0);"
3670
3749
db_xprofile(void *notused, const char *pquery, sqlite3_uint64 ptime)
3672
DPRINTF(E_DBG, L_DB, "SQL PROFILE query: %s\n", pquery);
3673
DPRINTF(E_DBG, L_DB, "SQL PROFILE time: %" PRIu64 "\n", (uint64_t)ptime);
3755
DPRINTF(E_DBG, L_DBPERF, "SQL PROFILE query: %s\n", pquery);
3756
DPRINTF(E_DBG, L_DBPERF, "SQL PROFILE time: %" PRIu64 " ms\n", ((uint64_t)ptime / 1000000));
3758
if ((strncmp(pquery, "SELECT", 6) != 0)
3759
&& (strncmp(pquery, "UPDATE", 6) != 0)
3760
&& (strncmp(pquery, "DELETE", 6) != 0))
3763
/* Disable profiling callback */
3764
sqlite3_profile(pool_hdl->hdl, NULL, NULL);
3766
query = sqlite3_mprintf("EXPLAIN QUERY PLAN %s", pquery);
3769
DPRINTF(E_DBG, L_DBPERF, "Query plan: Out of memory\n");
3774
ret = db_blocking_prepare_v2(query, -1, &stmt, NULL);
3775
sqlite3_free(query);
3776
if (ret != SQLITE_OK)
3778
DPRINTF(E_DBG, L_DBPERF, "Query plan: Could not prepare statement: %s\n", sqlite3_errmsg(pool_hdl->hdl));
3783
DPRINTF(E_DBG, L_DBPERF, "Query plan:\n");
3785
while ((ret = db_blocking_step(stmt)) == SQLITE_ROW)
3787
DPRINTF(E_DBG, L_DBPERF, "(%d,%d,%d) %s\n",
3788
sqlite3_column_int(stmt, 0), sqlite3_column_int(stmt, 1), sqlite3_column_int(stmt, 2),
3789
sqlite3_column_text(stmt, 3));
3792
if (ret != SQLITE_DONE)
3793
DPRINTF(E_DBG, L_DBPERF, "Query plan: Could not step: %s\n", sqlite3_errmsg(pool_hdl->hdl));
3795
DPRINTF(E_DBG, L_DBPERF, "---\n");
3797
sqlite3_finalize(stmt);
3800
/* Reenable profiling callback */
3801
sqlite3_profile(pool_hdl->hdl, db_xprofile, NULL);
4161
4289
" path VARCHAR(4096) NOT NULL" \
4165
"CREATE INDEX IF NOT EXISTS idx_path ON files(path, idx);"
4293
"CREATE INDEX IF NOT EXISTS idx_rescan ON files(path, db_timestamp);"
4295
#define I_SONGALBUMID \
4296
"CREATE INDEX IF NOT EXISTS idx_sai ON files(songalbumid);"
4298
#define I_STATEMKINDSAI \
4299
"CREATE INDEX IF NOT EXISTS idx_state_mkind_sai ON files(disabled, media_kind, songalbumid);"
4302
"CREATE INDEX IF NOT EXISTS idx_artist ON files(artist, artist_sort);"
4304
#define I_ALBUMARTIST \
4305
"CREATE INDEX IF NOT EXISTS idx_albumartist ON files(album_artist, album_artist_sort);"
4307
#define I_COMPOSER \
4308
"CREATE INDEX IF NOT EXISTS idx_composer ON files(composer, composer_sort);"
4311
"CREATE INDEX IF NOT EXISTS idx_title ON files(title, title_sort);"
4314
"CREATE INDEX IF NOT EXISTS idx_album ON files(album, album_sort);"
4317
"CREATE INDEX IF NOT EXISTS idx_pl_path ON playlists(path);"
4319
#define I_PL_DISABLED \
4320
"CREATE INDEX IF NOT EXISTS idx_pl_disabled ON playlists(disabled);"
4167
4322
#define I_FILEPATH \
4168
4323
"CREATE INDEX IF NOT EXISTS idx_filepath ON playlistitems(filepath ASC);"
4201
4351
#define Q_PL2 \
4202
4352
"INSERT INTO playlists (id, title, type, query, db_timestamp, path, idx, special_id)" \
4203
" VALUES(2, 'Music', 1, 'media_kind = 1', 0, '', 0, 6);"
4353
" VALUES(2, 'Music', 1, 'f.media_kind = 1', 0, '', 0, 6);"
4205
4355
#define Q_PL3 \
4206
4356
"INSERT INTO playlists (id, title, type, query, db_timestamp, path, idx, special_id)" \
4207
" VALUES(3, 'Movies', 1, 'media_kind = 2', 0, '', 0, 4);"
4357
" VALUES(3, 'Movies', 1, 'f.media_kind = 2', 0, '', 0, 4);"
4209
4359
#define Q_PL4 \
4210
4360
"INSERT INTO playlists (id, title, type, query, db_timestamp, path, idx, special_id)" \
4211
" VALUES(4, 'TV Shows', 1, 'media_kind = 64', 0, '', 0, 5);"
4361
" VALUES(4, 'TV Shows', 1, 'f.media_kind = 64', 0, '', 0, 5);"
4213
4363
/* These are the remaining automatically-created iTunes playlists, but
4214
4364
* their query is unknown
4238
4388
{ T_SPEAKERS, "create table speakers" },
4239
4389
{ T_INOTIFY, "create table inotify" },
4241
{ I_PATH, "create file path index" },
4391
{ I_RESCAN, "create rescan index" },
4392
{ I_SONGALBUMID, "create songalbumid index" },
4393
{ I_STATEMKINDSAI, "create state/mkind/sai index" },
4395
{ I_ARTIST, "create artist index" },
4396
{ I_ALBUMARTIST, "create album_artist index" },
4397
{ I_COMPOSER, "create composer index" },
4398
{ I_TITLE, "create title index" },
4399
{ I_ALBUM, "create album index" },
4401
{ I_PL_PATH, "create playlist path index" },
4402
{ I_PL_DISABLED, "create playlist state index" },
4242
4404
{ I_FILEPATH, "create file path index" },
4243
4405
{ I_PLITEMID, "create playlist id index" },
4407
{ I_GRP_TYPE_PERSIST, "create groups type/persistentid index" },
4244
4409
{ I_PAIRING, "create pairing guid index" },
4245
{ I_TITLESORT, "create file titlesort index" },
4246
{ I_ARTISTSORT,"create file artistsort index" },
4247
{ I_ALBUMSORT, "create file albumsort index" },
4249
4411
{ TRG_GROUPS_INSERT_FILES, "create trigger update_groups_new_file" },
4250
4412
{ TRG_GROUPS_UPDATE_FILES, "create trigger update_groups_update_file" },
4949
/* Upgrade from schema v12 to v13 */
4951
#define U_V13_DROP_IDX_PATH \
4952
"DROP INDEX idx_path;"
4954
#define U_V13_DROP_IDX_TS \
4955
"DROP INDEX idx_titlesort;"
4957
#define U_V13_DROP_IDX_AS \
4958
"DROP INDEX idx_artistsort;"
4960
#define U_V13_DROP_IDX_BS \
4961
"DROP INDEX idx_albumsort;"
4963
#define U_V13_IDX_RESCAN \
4964
"CREATE INDEX IF NOT EXISTS idx_rescan ON files(path, db_timestamp);"
4966
#define U_V13_IDX_SONGALBUMID \
4967
"CREATE INDEX IF NOT EXISTS idx_sai ON files(songalbumid);"
4969
#define U_V13_IDX_STATEMKINDSAI \
4970
"CREATE INDEX IF NOT EXISTS idx_state_mkind_sai ON files(disabled, media_kind, songalbumid);"
4972
#define U_V13_IDX_ARTIST \
4973
"CREATE INDEX IF NOT EXISTS idx_artist ON files(artist, artist_sort);"
4975
#define U_V13_IDX_ALBUMARTIST \
4976
"CREATE INDEX IF NOT EXISTS idx_albumartist ON files(album_artist, album_artist_sort);"
4978
#define U_V13_IDX_COMPOSER \
4979
"CREATE INDEX IF NOT EXISTS idx_composer ON files(composer, composer_sort);"
4981
#define U_V13_IDX_TITLE \
4982
"CREATE INDEX IF NOT EXISTS idx_title ON files(title, title_sort);"
4984
#define U_V13_IDX_ALBUM \
4985
"CREATE INDEX IF NOT EXISTS idx_album ON files(album, album_sort);"
4987
#define U_V13_IDX_GRP_TYPE_PERSIST \
4988
"CREATE INDEX IF NOT EXISTS idx_grp_type_persist ON groups(type, persistentid);"
4990
#define U_V13_IDX_PL_PATH \
4991
"CREATE INDEX IF NOT EXISTS idx_pl_path ON playlists(path);"
4993
#define U_V13_IDX_PL_DISABLED \
4994
"CREATE INDEX IF NOT EXISTS idx_pl_disabled ON playlists(disabled);"
4997
"UPDATE playlists SET query = 'f.media_kind = 1' where id = 2;"
5000
"UPDATE playlists SET query = 'f.media_kind = 2' where id = 3;"
5003
"UPDATE playlists SET query = 'f.media_kind = 64' where id = 4;"
5005
#define U_V13_SCVER \
5006
"UPDATE admin SET value = '13' WHERE key = 'schema_version';"
5008
static const struct db_init_query db_upgrade_v13_queries[] =
5010
{ U_V13_DROP_IDX_PATH, "drop index path table files" },
5011
{ U_V13_DROP_IDX_TS, "drop index titlesort table files" },
5012
{ U_V13_DROP_IDX_AS, "drop index artistsort table files" },
5013
{ U_V13_DROP_IDX_BS, "drop index albumsort table files" },
5015
{ U_V13_IDX_RESCAN, "create rescan index" },
5016
{ U_V13_IDX_SONGALBUMID, "create songalbumid index" },
5017
{ U_V13_IDX_STATEMKINDSAI, "create state/mkind/sai index" },
5018
{ U_V13_IDX_ARTIST, "create artist index" },
5019
{ U_V13_IDX_ALBUMARTIST, "create album_artist index" },
5020
{ U_V13_IDX_COMPOSER, "create composer index" },
5021
{ U_V13_IDX_TITLE, "create title index" },
5022
{ U_V13_IDX_ALBUM, "create album index" },
5024
{ U_V13_IDX_GRP_TYPE_PERSIST, "create groups type/persistentid index" },
5026
{ U_V13_IDX_PL_PATH, "create playlist path index" },
5027
{ U_V13_IDX_PL_DISABLED, "create playlist state index" },
5029
{ U_V13_PL2, "update default smart playlist 'Music'" },
5030
{ U_V13_PL3, "update default smart playlist 'Movies'" },
5031
{ U_V13_PL4, "update default smart playlist 'TV Shows'" },
5033
{ U_V13_SCVER, "set schema_version to 13" },
4789
5037
db_check_version(void)