Store playlist items paths instead of resolving to file ids

This allows for more dynamic playlists now that files can move
around while we're running.
This commit is contained in:
Julien BLACHE 2009-06-11 20:27:31 +02:00
parent 3b7ff30c1b
commit 0a8c171187
3 changed files with 22 additions and 115 deletions

118
src/db.c
View File

@ -312,12 +312,11 @@ db_purge_cruft(time_t ref)
char *errmsg; char *errmsg;
int i; int i;
int ret; int ret;
char *queries[4] = { NULL, NULL, NULL, NULL }; char *queries[3] = { NULL, NULL, NULL };
char *queries_tmpl[4] = char *queries_tmpl[3] =
{ {
"DELETE FROM playlistitems WHERE playlistid IN (SELECT id FROM playlists WHERE id <> 1 AND db_timestamp < %" PRIi64 ");", "DELETE FROM playlistitems WHERE playlistid IN (SELECT id FROM playlists WHERE id <> 1 AND db_timestamp < %" PRIi64 ");",
"DELETE FROM playlists WHERE id <> 1 AND db_timestamp < %" PRIi64 ";", "DELETE FROM playlists WHERE id <> 1 AND db_timestamp < %" PRIi64 ";",
"DELETE FROM playlistitems WHERE songid IN (SELECT id FROM songs WHERE db_timestamp < %" PRIi64 ");",
"DELETE FROM songs WHERE db_timestamp < %" PRIi64 ";" "DELETE FROM songs WHERE db_timestamp < %" PRIi64 ";"
}; };
@ -539,10 +538,10 @@ db_build_query_plitems(struct query_params *qp, char **q)
else else
{ {
if (qp->filter) if (qp->filter)
count = sqlite3_mprintf("SELECT COUNT(*) FROM songs JOIN playlistitems ON songs.id = playlistitems.songid" count = sqlite3_mprintf("SELECT COUNT(*) FROM songs JOIN playlistitems ON songs.path = playlistitems.filepath"
" WHERE playlistitems.playlistid = %d AND songs.disabled = 0 AND %s;", qp->pl_id, qp->filter); " WHERE playlistitems.playlistid = %d AND songs.disabled = 0 AND %s;", qp->pl_id, qp->filter);
else else
count = sqlite3_mprintf("SELECT COUNT(*) FROM songs JOIN playlistitems ON songs.id = playlistitems.songid" count = sqlite3_mprintf("SELECT COUNT(*) FROM songs JOIN playlistitems ON songs.path = playlistitems.filepath"
" WHERE playlistitems.playlistid = %d AND songs.disabled = 0;", qp->pl_id); " WHERE playlistitems.playlistid = %d AND songs.disabled = 0;", qp->pl_id);
} }
@ -565,19 +564,19 @@ db_build_query_plitems(struct query_params *qp, char **q)
return -1; return -1;
if (idx && qp->filter) if (idx && qp->filter)
query = sqlite3_mprintf("SELECT songs.* FROM songs JOIN playlistitems ON songs.id = playlistitems.songid" query = sqlite3_mprintf("SELECT songs.* FROM songs JOIN playlistitems ON songs.path = playlistitems.filepath"
" WHERE playlistitems.playlistid = %d AND songs.disabled = 0 AND %s ORDER BY playlistitems.id ASC %s;", " WHERE playlistitems.playlistid = %d AND songs.disabled = 0 AND %s ORDER BY playlistitems.id ASC %s;",
qp->pl_id, qp->filter, idx); qp->pl_id, qp->filter, idx);
else if (idx) else if (idx)
query = sqlite3_mprintf("SELECT songs.* FROM songs JOIN playlistitems ON songs.id = playlistitems.songid" query = sqlite3_mprintf("SELECT songs.* FROM songs JOIN playlistitems ON songs.path = playlistitems.filepath"
" WHERE playlistitems.playlistid = %d AND songs.disabled = 0 ORDER BY playlistitems.id ASC %s;", " WHERE playlistitems.playlistid = %d AND songs.disabled = 0 ORDER BY playlistitems.id ASC %s;",
qp->pl_id, idx); qp->pl_id, idx);
else if (qp->filter) else if (qp->filter)
query = sqlite3_mprintf("SELECT songs.* FROM songs JOIN playlistitems ON songs.id = playlistitems.songid" query = sqlite3_mprintf("SELECT songs.* FROM songs JOIN playlistitems ON songs.path = playlistitems.filepath"
" WHERE playlistitems.playlistid = %d AND songs.disabled = 0 AND %s ORDER BY playlistitems.id ASC;", " WHERE playlistitems.playlistid = %d AND songs.disabled = 0 AND %s ORDER BY playlistitems.id ASC;",
qp->pl_id, qp->filter); qp->pl_id, qp->filter);
else else
query = sqlite3_mprintf("SELECT songs.* FROM songs JOIN playlistitems ON songs.id = playlistitems.songid" query = sqlite3_mprintf("SELECT songs.* FROM songs JOIN playlistitems ON songs.path = playlistitems.filepath"
" WHERE playlistitems.playlistid = %d AND songs.disabled = 0 ORDER BY playlistitems.id ASC;", " WHERE playlistitems.playlistid = %d AND songs.disabled = 0 ORDER BY playlistitems.id ASC;",
qp->pl_id); qp->pl_id);
@ -1432,7 +1431,7 @@ static int
db_pl_count_items(int id) db_pl_count_items(int id)
{ {
#define Q_TMPL "SELECT COUNT(*) FROM playlistitems JOIN songs" \ #define Q_TMPL "SELECT COUNT(*) FROM playlistitems JOIN songs" \
" ON playlistitems.songid = songs.id WHERE songs.disabled = 0 AND playlistitems.playlistid = %d;" " ON playlistitems.filepath = songs.path WHERE songs.disabled = 0 AND playlistitems.playlistid = %d;"
char *query; char *query;
int ret; int ret;
@ -1730,91 +1729,14 @@ db_pl_add(char *title, char *path, int *id)
} }
int int
db_pl_add_item(int plid, int mfid) db_pl_add_item(int plid, char *path)
{ {
#define QPL_TMPL "SELECT title FROM playlists WHERE id = %d;" #define Q_TMPL "INSERT INTO playlistitems (playlistid, filepath) VALUES (%d, '%q');"
#define QMF_TMPL "SELECT fname FROM songs WHERE id = %d;"
#define QADD_TMPL "INSERT INTO playlistitems (playlistid, songid) VALUES (%d, %d);"
char *query; char *query;
char *str;
char *errmsg; char *errmsg;
sqlite3_stmt *stmt;
int ret; int ret;
/* Check playlist */ query = sqlite3_mprintf(Q_TMPL, plid, path);
query = sqlite3_mprintf(QPL_TMPL, plid);
if (!query)
{
DPRINTF(E_LOG, L_DB, "Out of memory for query string\n");
return -1;
}
DPRINTF(E_DBG, L_DB, "Running query '%s'\n", query);
ret = sqlite3_prepare_v2(hdl, query, -1, &stmt, NULL);
if (ret != SQLITE_OK)
{
DPRINTF(E_LOG, L_DB, "Could not prepare statement: %s\n", sqlite3_errmsg(hdl));
sqlite3_free(query);
return -1;
}
ret = sqlite3_step(stmt);
if (ret != SQLITE_ROW)
{
DPRINTF(E_LOG, L_DB, "Playlist id %d not found\n", plid);
sqlite3_finalize(stmt);
sqlite3_free(query);
return -1;
}
str = (char *)sqlite3_column_text(stmt, 0);
DPRINTF(E_DBG, L_DB, "Found playlist id %d ('%s')\n", plid, str);
sqlite3_finalize(stmt);
sqlite3_free(query);
/* Check media file */
query = sqlite3_mprintf(QMF_TMPL, mfid);
if (!query)
{
DPRINTF(E_LOG, L_DB, "Out of memory for query string\n");
return -1;
}
DPRINTF(E_DBG, L_DB, "Running query '%s'\n", query);
ret = sqlite3_prepare_v2(hdl, query, -1, &stmt, NULL);
if (ret != SQLITE_OK)
{
DPRINTF(E_LOG, L_DB, "Could not prepare statement: %s\n", sqlite3_errmsg(hdl));
sqlite3_free(query);
return -1;
}
ret = sqlite3_step(stmt);
if (ret != SQLITE_ROW)
{
DPRINTF(E_LOG, L_DB, "Media file id %d not found\n", mfid);
sqlite3_finalize(stmt);
sqlite3_free(query);
return -1;
}
str = (char *)sqlite3_column_text(stmt, 0);
DPRINTF(E_DBG, L_DB, "Found media file id %d (%s)\n", mfid, str);
sqlite3_finalize(stmt);
sqlite3_free(query);
/* Add */
query = sqlite3_mprintf(QADD_TMPL, plid, mfid);
if (!query) if (!query)
{ {
DPRINTF(E_LOG, L_DB, "Out of memory for query string\n"); DPRINTF(E_LOG, L_DB, "Out of memory for query string\n");
@ -1836,13 +1758,9 @@ db_pl_add_item(int plid, int mfid)
sqlite3_free(query); sqlite3_free(query);
DPRINTF(E_DBG, L_DB, "Added media file id %d to playlist id %d\n", mfid, plid);
return 0; return 0;
#undef QPL_TMPL #undef Q_TMPL
#undef QMF_TMPL
#undef QADD_TMPL
} }
void void
@ -2609,7 +2527,7 @@ db_perthread_deinit(void)
"CREATE TABLE IF NOT EXISTS playlistitems (" \ "CREATE TABLE IF NOT EXISTS playlistitems (" \
" id INTEGER PRIMARY KEY NOT NULL," \ " id INTEGER PRIMARY KEY NOT NULL," \
" playlistid INTEGER NOT NULL," \ " playlistid INTEGER NOT NULL," \
" songid INTEGER NOT NULL" \ " filepath VARCHAR(4096) NOT NULL" \
");" ");"
#define T_INOTIFY \ #define T_INOTIFY \
@ -2627,11 +2545,11 @@ db_perthread_deinit(void)
#define I_PATH \ #define I_PATH \
"CREATE INDEX IF NOT EXISTS idx_path ON songs(path, idx);" "CREATE INDEX IF NOT EXISTS idx_path ON songs(path, idx);"
#define I_FILEID \ #define I_FILEPATH \
"CREATE INDEX IF NOT EXISTS idx_fileid ON playlistitems(songid ASC);" "CREATE INDEX IF NOT EXISTS idx_filepath ON playlistitems(filepath ASC);"
#define I_PLITEMID \ #define I_PLITEMID \
"CREATE INDEX IF NOT EXISTS idx_playlistid ON playlistitems(playlistid, songid);" "CREATE INDEX IF NOT EXISTS idx_playlistid ON playlistitems(playlistid, filepath);"
#define SCHEMA_VERSION 1 #define SCHEMA_VERSION 1
@ -2652,7 +2570,7 @@ static struct db_init_query db_init_queries[] =
{ T_INOTIFY, "create table inotify" }, { T_INOTIFY, "create table inotify" },
{ I_PATH, "create file path index" }, { I_PATH, "create file path index" },
{ I_FILEID, "create file id index" }, { I_FILEPATH, "create file path index" },
{ I_PLITEMID, "create playlist id index" }, { I_PLITEMID, "create playlist id index" },
}; };

View File

@ -269,7 +269,7 @@ int
db_pl_add(char *title, char *path, int *id); db_pl_add(char *title, char *path, int *id);
int int
db_pl_add_item(int plid, int mfid); db_pl_add_item(int plid, char *path);
void void
db_pl_clear_items(int id); db_pl_clear_items(int id);

View File

@ -52,7 +52,6 @@ scan_m3u_playlist(char *file)
char *ptr; char *ptr;
size_t len; size_t len;
int pl_id; int pl_id;
int mf_id;
int ret; int ret;
DPRINTF(E_INFO, L_SCAN, "Processing static playlist: %s\n", file); DPRINTF(E_INFO, L_SCAN, "Processing static playlist: %s\n", file);
@ -190,21 +189,11 @@ scan_m3u_playlist(char *file)
continue; continue;
} }
DPRINTF(E_DBG, L_SCAN, "Checking %s\n", filename); ret = db_pl_add_item(pl_id, filename);
ret = db_file_id_bypath(filename, &mf_id);
if (ret < 0)
{
DPRINTF(E_WARN, L_SCAN, "Playlist entry '%s' not found\n", entry);
free(filename);
continue;
}
DPRINTF(E_DBG, L_SCAN, "Resolved %s to %d\n", filename, mf_id);
ret = db_pl_add_item(pl_id, mf_id);
if (ret < 0) if (ret < 0)
DPRINTF(E_WARN, L_SCAN, "Could not add %s to playlist\n", filename); DPRINTF(E_WARN, L_SCAN, "Could not add %s to playlist\n", filename);
free(filename);
} }
if (!feof(fp)) if (!feof(fp))