From 2d1c35b8556c383c0e76074a1e0436816d7492b9 Mon Sep 17 00:00:00 2001 From: Julien BLACHE Date: Thu, 11 Jun 2009 18:28:01 +0200 Subject: [PATCH] Count playlist items on the fly --- src/db.c | 158 ++++++++++++++++++------------------------ src/db.h | 7 +- src/filescanner.c | 4 -- src/filescanner_m3u.c | 2 - 4 files changed, 68 insertions(+), 103 deletions(-) diff --git a/src/db.c b/src/db.c index 37152275..d8b7e7d3 100644 --- a/src/db.c +++ b/src/db.c @@ -116,12 +116,13 @@ static struct col_type_map pli_cols_map[] = { pli_offsetof(id), DB_TYPE_INT }, { pli_offsetof(title), DB_TYPE_STRING }, { pli_offsetof(type), DB_TYPE_INT }, - { pli_offsetof(items), DB_TYPE_INT }, { pli_offsetof(query), DB_TYPE_STRING }, { pli_offsetof(db_timestamp), DB_TYPE_INT }, { pli_offsetof(disabled), DB_TYPE_INT }, { pli_offsetof(path), DB_TYPE_STRING }, { pli_offsetof(index), DB_TYPE_INT }, + + /* items is computed on the fly */ }; #define dbmfi_offsetof(field) offsetof(struct db_media_file_info, field) @@ -187,12 +188,13 @@ static ssize_t dbpli_cols_map[] = dbpli_offsetof(id), dbpli_offsetof(title), dbpli_offsetof(type), - dbpli_offsetof(items), dbpli_offsetof(query), dbpli_offsetof(db_timestamp), dbpli_offsetof(disabled), dbpli_offsetof(path), dbpli_offsetof(index), + + /* items is computed on the fly */ }; #define wi_offsetof(field) offsetof(struct watch_info, field) @@ -212,6 +214,11 @@ static struct col_type_map wi_cols_map[] = static __thread sqlite3 *hdl; +/* Forward */ +static int +db_pl_count_items(int id); + + char * db_escape_string(const char *str) { @@ -776,6 +783,7 @@ db_query_fetch_pl(struct query_params *qp, struct db_playlist_info *dbpli) { int ncols; char **strcol; + int id; int i; int ret; @@ -821,6 +829,19 @@ db_query_fetch_pl(struct query_params *qp, struct db_playlist_info *dbpli) *strcol = (char *)sqlite3_column_text(qp->stmt, i); } + id = sqlite3_column_int(qp->stmt, 0); + + i = db_pl_count_items(id); + + dbpli->items = qp->buf; + ret = snprintf(qp->buf, sizeof(qp->buf), "%d", i); + if ((ret < 0) || (ret >= sizeof(qp->buf))) + { + DPRINTF(E_LOG, L_DB, "Could not convert items, buffer too small\n"); + + strcpy(qp->buf, "0"); + } + return 0; } @@ -1463,6 +1484,44 @@ db_pl_get_count(int *count) return 0; } +static int +db_pl_count_items(int id) +{ +#define Q_TMPL "SELECT COUNT(*) FROM playlistitems JOIN songs" \ + " ON playlistitems.songid = songs.id WHERE songs.disabled = 0 AND playlistitems.playlistid = %d;" + char *query; + int nsongs; + int ret; + + if (id == 1) + { + ret = db_files_get_count(&nsongs); + if (ret < 0) + { + DPRINTF(E_LOG, L_DB, "Could not get file count\n"); + return 0; + } + + return nsongs; + } + + query = sqlite3_mprintf(Q_TMPL, id); + + if (!query) + { + DPRINTF(E_LOG, L_DB, "Out of memory for query string\n"); + return 0; + } + + ret = db_get_count(query); + + sqlite3_free(query); + + return ret; + +#undef Q_TMPL +} + void db_pl_ping(int id) { @@ -1649,6 +1708,8 @@ db_pl_fetch_byquery(char *query) pli->items = i; } + else + pli->items = db_pl_count_items(pli->id); return pli; } @@ -1681,8 +1742,8 @@ int db_pl_add(char *title, char *path, int *id) { #define QDUP_TMPL "SELECT COUNT(*) FROM playlists WHERE title = '%q' OR path = '%q';" -#define QADD_TMPL "INSERT INTO playlists (title, type, items, query, db_timestamp, disabled, path, idx)" \ - " VALUES ('%q', 0, 0, NULL, %" PRIi64 ", 0, '%q', 0);" +#define QADD_TMPL "INSERT INTO playlists (title, type, query, db_timestamp, disabled, path, idx)" \ + " VALUES ('%q', 0, NULL, %" PRIi64 ", 0, '%q', 0);" char *query; char *errmsg; sqlite3_stmt *stmt; @@ -1911,90 +1972,6 @@ db_pl_clear_items(int id) #undef Q_TMPL } -void -db_pl_update(int id) -{ -#define QPL1_TMPL "UPDATE playlists SET items = %d WHERE id = 1;" -#define Q_TMPL "UPDATE playlists SET items = (SELECT COUNT(*) FROM playlistitems JOIN songs" \ - " ON playlistitems.songid = songs.id WHERE songs.disabled = 0 AND playlistitems.playlistid = %d) WHERE id = %d;" - char *query; - char *errmsg; - int nsongs; - int ret; - - if (id == 1) - { - ret = db_files_get_count(&nsongs); - if (ret < 0) - { - DPRINTF(E_LOG, L_DB, "Could not get file count\n"); - return; - } - - query = sqlite3_mprintf(QPL1_TMPL, nsongs); - } - else - query = sqlite3_mprintf(Q_TMPL, id, id); - - if (!query) - { - DPRINTF(E_LOG, L_DB, "Out of memory for query string\n"); - return; - } - - DPRINTF(E_DBG, L_DB, "Running query '%s'\n", query); - - errmsg = NULL; - ret = sqlite3_exec(hdl, query, NULL, NULL, &errmsg); - if (ret != SQLITE_OK) - { - DPRINTF(E_LOG, L_DB, "Query error: %s\n", errmsg); - - sqlite3_free(errmsg); - sqlite3_free(query); - return; - } - - sqlite3_free(query); - -#undef QPL1_TMPL -#undef Q_TMPL -} - -void -db_pl_update_all(void) -{ - char *query = "SELECT id FROM playlists;"; - sqlite3_stmt *stmt; - int plid; - int ret; - - DPRINTF(E_DBG, L_DB, "Running query '%s'\n", query); - - ret = sqlite3_prepare_v2(hdl, query, strlen(query) + 1, &stmt, NULL); - if (ret != SQLITE_OK) - { - DPRINTF(E_LOG, L_DB, "Could not prepare statement: %s\n", sqlite3_errmsg(hdl)); - return; - } - - while ((ret = sqlite3_step(stmt)) == SQLITE_ROW) - { - plid = sqlite3_column_int(stmt, 0); - db_pl_update(plid); - } - - if (ret != SQLITE_DONE) - { - DPRINTF(E_LOG, L_DB, "Could not step: %s\n", sqlite3_errmsg(hdl)); - - sqlite3_finalize(stmt); - return; - } - - sqlite3_finalize(stmt); -} - void db_pl_delete(int id) { @@ -2720,7 +2697,6 @@ db_perthread_deinit(void) " id INTEGER PRIMARY KEY NOT NULL," \ " title VARCHAR(255) NOT NULL," \ " type INTEGER NOT NULL," \ - " items INTEGER NOT NULL," \ " query VARCHAR(1024)," \ " db_timestamp INTEGER NOT NULL," \ " disabled INTEGER DEFAULT 0," \ @@ -2744,8 +2720,8 @@ db_perthread_deinit(void) ");" #define Q_PL1 \ - "INSERT INTO playlists (id, title, type, items, query, db_timestamp, path, idx)" \ - " VALUES(1, 'Library', 1, 0, '1', 0, '', 0);" + "INSERT INTO playlists (id, title, type, query, db_timestamp, path, idx)" \ + " VALUES(1, 'Library', 1, '1', 0, '', 0);" #define I_PATH \ "CREATE INDEX IF NOT EXISTS idx_path ON songs(path, idx);" diff --git a/src/db.h b/src/db.h index 12d83850..600fdb5d 100644 --- a/src/db.h +++ b/src/db.h @@ -43,6 +43,7 @@ struct query_params { /* Private query context, keep out */ sqlite3_stmt *stmt; + char buf[32]; }; struct media_file_info { @@ -272,12 +273,6 @@ db_pl_add(char *title, char *path, int *id); int db_pl_add_item(int plid, int mfid); -void -db_pl_update(int id); - -void -db_pl_update_all(void); - void db_pl_delete(int id); diff --git a/src/filescanner.c b/src/filescanner.c index 5986de7b..10f00bef 100644 --- a/src/filescanner.c +++ b/src/filescanner.c @@ -600,8 +600,6 @@ bulk_scan(void) } } - db_pl_update_all(); - if (playlists) process_deferred_playlists(); @@ -642,8 +640,6 @@ filescanner(void *arg) if (!scan_exit) { - db_pl_update_all(); - /* Enable inotify */ event_add(&inoev, NULL); diff --git a/src/filescanner_m3u.c b/src/filescanner_m3u.c index c2029674..18b97488 100644 --- a/src/filescanner_m3u.c +++ b/src/filescanner_m3u.c @@ -220,7 +220,5 @@ scan_m3u_playlist(char *file) fclose(fp); - db_pl_update(pl_id); - DPRINTF(E_INFO, L_SCAN, "Done processing playlist\n"); }