diff --git a/src/artwork.c b/src/artwork.c index fe1267e5..29ff5cf1 100644 --- a/src/artwork.c +++ b/src/artwork.c @@ -1032,7 +1032,7 @@ source_item_ownpl_get(struct artwork_ctx *ctx) mfi_path = ctx->dbmfi->path; format = ART_E_NONE; - while (((ret = db_query_fetch_pl(&qp, &dbpli, 0)) == 0) && (dbpli.id) && (format == ART_E_NONE)) + while (((ret = db_query_fetch_pl(&qp, &dbpli)) == 0) && (dbpli.id) && (format == ART_E_NONE)) { if (!dbpli.path) continue; diff --git a/src/db.c b/src/db.c index cd82cf35..5f2ab1ab 100644 --- a/src/db.c +++ b/src/db.c @@ -67,6 +67,10 @@ // Flags that we will only update column value if we have non-zero value (to avoid zeroing e.g. rating) #define DB_FLAG_NO_ZERO (1 << 1) +// The two last columns of playlist_info are calculated fields, so all playlist retrieval functions must use this query +#define Q_PL_SELECT "SELECT f.*, COUNT(pi.id), SUM(pi.filepath NOT NULL AND pi.filepath LIKE 'http%%')" \ + " FROM playlists f LEFT JOIN playlistitems pi ON (f.id = pi.playlistid)" + enum group_type { G_ALBUMS = 1, G_ARTISTS = 2, @@ -232,7 +236,9 @@ static const struct col_type_map pli_cols_map[] = { "query_order", pli_offsetof(query_order), DB_TYPE_STRING, DB_FIXUP_NO_SANITIZE }, { "query_limit", pli_offsetof(query_limit), DB_TYPE_INT }, - /* items is computed on the fly */ + // Not in the database, but returned via the query's COUNT()/SUM() + { "items", pli_offsetof(items), DB_TYPE_INT }, + { "streams", pli_offsetof(streams), DB_TYPE_INT }, }; /* This list must be kept in sync with @@ -360,7 +366,8 @@ static const ssize_t dbpli_cols_map[] = dbpli_offsetof(query_order), dbpli_offsetof(query_limit), - /* items is computed on the fly */ + dbpli_offsetof(items), + dbpli_offsetof(streams), }; /* This list must be kept in sync with @@ -502,12 +509,6 @@ static __thread struct db_statements db_statements; /* Forward */ -static int -db_pl_count_items(int id, int streams_only); - -static int -db_smartpl_count_items(const char *smartpl_query); - struct playlist_info * db_pl_fetch_byid(int id); @@ -1709,85 +1710,54 @@ db_build_query_check(struct query_params *qp, char *count, char *query) } static char * -db_build_query_items(struct query_params *qp) +db_build_query_items(struct query_params *qp, struct query_clause *qc) { - struct query_clause *qc; char *count; char *query; - qc = db_build_query_clause(qp); - if (!qc) - return NULL; - count = sqlite3_mprintf("SELECT COUNT(*) FROM files f %s;", qc->where); query = sqlite3_mprintf("SELECT f.* FROM files f %s %s %s %s;", qc->where, qc->group, qc->order, qc->index); - db_free_query_clause(qc); - return db_build_query_check(qp, count, query); } static char * -db_build_query_pls(struct query_params *qp) +db_build_query_pls(struct query_params *qp, struct query_clause *qc) { - struct query_clause *qc; char *count; char *query; - qc = db_build_query_clause(qp); - if (!qc) - return NULL; - count = sqlite3_mprintf("SELECT COUNT(*) FROM playlists f %s;", qc->where); - query = sqlite3_mprintf("SELECT f.* FROM playlists f %s %s %s;", qc->where, qc->order, qc->index); - - db_free_query_clause(qc); + query = sqlite3_mprintf(Q_PL_SELECT " %s GROUP BY f.id %s %s;", qc->where, qc->order, qc->index); return db_build_query_check(qp, count, query); } static char * -db_build_query_find_pls(struct query_params *qp) +db_build_query_find_pls(struct query_params *qp, struct query_clause *qc) { - struct query_clause *qc; - char *count; - char *query; - if (!qp->filter) { DPRINTF(E_LOG, L_DB, "Bug! Playlist find called without search criteria\n"); return NULL; } - qc = db_build_query_clause(qp); - if (!qc) - return NULL; - // Use qp->filter because qc->where has a f.disabled which is not a column in playlistitems - count = sqlite3_mprintf("SELECT COUNT(*) FROM playlists f WHERE f.id IN (SELECT playlistid FROM playlistitems WHERE %s);", qp->filter); - query = sqlite3_mprintf("SELECT f.* FROM playlists f WHERE f.id IN (SELECT playlistid FROM playlistitems WHERE %s) %s %s;", qp->filter, qc->order, qc->index); + sqlite3_free(qc->where); + qc->where = sqlite3_mprintf("WHERE f.id IN (SELECT playlistid FROM playlistitems WHERE %s)", qp->filter); - db_free_query_clause(qc); - - return db_build_query_check(qp, count, query); + return db_build_query_pls(qp, qc); } static char * -db_build_query_plitems_plain(struct query_params *qp) +db_build_query_plitems_plain(struct query_params *qp, struct query_clause *qc) { - struct query_clause *qc; char *count; char *query; - qc = db_build_query_clause(qp); - if (!qc) - return NULL; - count = sqlite3_mprintf("SELECT COUNT(*) FROM files f JOIN playlistitems pi ON f.path = pi.filepath %s AND pi.playlistid = %d;", qc->where, qp->id); query = sqlite3_mprintf("SELECT f.* FROM files f JOIN playlistitems pi ON f.path = pi.filepath %s AND pi.playlistid = %d ORDER BY pi.id ASC %s;", qc->where, qp->id, qc->index); - db_free_query_clause(qc); - return db_build_query_check(qp, count, query); } @@ -1847,16 +1817,16 @@ db_build_query_plitems_smart(struct query_params *qp, struct playlist_info *pli) } static char * -db_build_query_plitems(struct query_params *qp) +db_build_query_plitems(struct query_params *qp, struct query_clause *qc) { struct playlist_info *pli; char *query; if (qp->id <= 0) - { - DPRINTF(E_LOG, L_DB, "No playlist id specified in playlist items query\n"); - return NULL; - } + { + DPRINTF(E_LOG, L_DB, "No playlist id specified in playlist items query\n"); + return NULL; + } pli = db_pl_fetch_byid(qp->id); if (!pli) @@ -1871,7 +1841,7 @@ db_build_query_plitems(struct query_params *qp) case PL_PLAIN: case PL_FOLDER: - query = db_build_query_plitems_plain(qp); + query = db_build_query_plitems_plain(qp, qc); break; default: @@ -1886,55 +1856,36 @@ db_build_query_plitems(struct query_params *qp) } static char * -db_build_query_group_albums(struct query_params *qp) +db_build_query_group_albums(struct query_params *qp, struct query_clause *qc) { - struct query_clause *qc; char *count; char *query; - qc = db_build_query_clause(qp); - if (!qc) - return NULL; - count = sqlite3_mprintf("SELECT COUNT(DISTINCT f.songalbumid) FROM files f %s;", qc->where); query = sqlite3_mprintf("SELECT g.id, g.persistentid, f.album, f.album_sort, COUNT(f.id) as track_count, 1 as album_count, f.album_artist, f.songartistid, SUM(f.song_length) FROM files f JOIN groups g ON f.songalbumid = g.persistentid %s GROUP BY f.songalbumid %s %s %s;", qc->where, qc->having, qc->order, qc->index); - db_free_query_clause(qc); - return db_build_query_check(qp, count, query); } static char * -db_build_query_group_artists(struct query_params *qp) +db_build_query_group_artists(struct query_params *qp, struct query_clause *qc) { - struct query_clause *qc; char *count; char *query; - qc = db_build_query_clause(qp); - if (!qc) - return NULL; - count = sqlite3_mprintf("SELECT COUNT(DISTINCT f.songartistid) FROM files f %s;", qc->where); query = sqlite3_mprintf("SELECT g.id, g.persistentid, f.album_artist, f.album_artist_sort, COUNT(f.id) as track_count, COUNT(DISTINCT f.songalbumid) as album_count, f.album_artist, f.songartistid, SUM(f.song_length) FROM files f JOIN groups g ON f.songartistid = g.persistentid %s GROUP BY f.songartistid %s %s %s;", qc->where, qc->having, qc->order, qc->index); - db_free_query_clause(qc); - return db_build_query_check(qp, count, query); } static char * -db_build_query_group_items(struct query_params *qp) +db_build_query_group_items(struct query_params *qp, struct query_clause *qc) { enum group_type gt; - struct query_clause *qc; char *count; char *query; - qc = db_build_query_clause(qp); - if (!qc) - return NULL; - gt = db_group_type_bypersistentid(qp->persistentid); switch (gt) @@ -1951,27 +1902,19 @@ db_build_query_group_items(struct query_params *qp) default: DPRINTF(E_LOG, L_DB, "Unsupported group type %d for group id %" PRIi64 "\n", gt, qp->persistentid); - db_free_query_clause(qc); return NULL; } - db_free_query_clause(qc); - return db_build_query_check(qp, count, query); } static char * -db_build_query_group_dirs(struct query_params *qp) +db_build_query_group_dirs(struct query_params *qp, struct query_clause *qc) { enum group_type gt; - struct query_clause *qc; char *count; char *query; - qc = db_build_query_clause(qp); - if (!qc) - return NULL; - gt = db_group_type_bypersistentid(qp->persistentid); switch (gt) @@ -1992,63 +1935,47 @@ db_build_query_group_dirs(struct query_params *qp) default: DPRINTF(E_LOG, L_DB, "Unsupported group type %d for group id %" PRIi64 "\n", gt, qp->persistentid); - db_free_query_clause(qc); return NULL; } - db_free_query_clause(qc); - return db_build_query_check(qp, count, query); } static char * -db_build_query_browse(struct query_params *qp) +db_build_query_browse(struct query_params *qp, struct query_clause *qc) { - struct query_clause *qc; const char *where; const char *select; char *count; char *query; - qc = db_build_query_clause(qp); - if (!qc) - return NULL; - select = browse_clause[qp->type & ~Q_F_BROWSE].select; where = browse_clause[qp->type & ~Q_F_BROWSE].where; count = sqlite3_mprintf("SELECT COUNT(*) FROM (SELECT %s FROM files f %s AND %s != '' %s);", select, qc->where, where, qc->group); query = sqlite3_mprintf("SELECT %s FROM files f %s AND %s != '' %s %s %s;", select, qc->where, where, qc->group, qc->order, qc->index); - db_free_query_clause(qc); - return db_build_query_check(qp, count, query); } static char * -db_build_query_count_items(struct query_params *qp) +db_build_query_count_items(struct query_params *qp, struct query_clause *qc) { - struct query_clause *qc; char *query; - qc = db_build_query_clause(qp); - if (!qc) - return NULL; - qp->results = 1; query = sqlite3_mprintf("SELECT COUNT(*), SUM(song_length), COUNT(DISTINCT songartistid), COUNT(DISTINCT songalbumid) FROM files f %s;", qc->where); if (!query) DPRINTF(E_LOG, L_DB, "Out of memory for query string\n"); - db_free_query_clause(qc); - return query; } int db_query_start(struct query_params *qp) { + struct query_clause *qc; sqlite3_stmt *stmt; char *query; int ret; @@ -2056,51 +1983,57 @@ db_query_start(struct query_params *qp) qp->stmt = NULL; qp->results = -1; + qc = db_build_query_clause(qp); + if (!qc) + return -1; + switch (qp->type) { case Q_ITEMS: - query = db_build_query_items(qp); + query = db_build_query_items(qp, qc); break; case Q_PL: - query = db_build_query_pls(qp); + query = db_build_query_pls(qp, qc); break; case Q_FIND_PL: - query = db_build_query_find_pls(qp); + query = db_build_query_find_pls(qp, qc); break; case Q_PLITEMS: - query = db_build_query_plitems(qp); + query = db_build_query_plitems(qp, qc); break; case Q_GROUP_ALBUMS: - query = db_build_query_group_albums(qp); + query = db_build_query_group_albums(qp, qc); break; case Q_GROUP_ARTISTS: - query = db_build_query_group_artists(qp); + query = db_build_query_group_artists(qp, qc); break; case Q_GROUP_ITEMS: - query = db_build_query_group_items(qp); + query = db_build_query_group_items(qp, qc); break; case Q_GROUP_DIRS: - query = db_build_query_group_dirs(qp); + query = db_build_query_group_dirs(qp, qc); break; case Q_COUNT_ITEMS: - query = db_build_query_count_items(qp); + query = db_build_query_count_items(qp, qc); break; default: if (qp->type & Q_F_BROWSE) - query = db_build_query_browse(qp); + query = db_build_query_browse(qp, qc); else query = NULL; } + db_free_query_clause(qc); + if (!query) { DPRINTF(E_LOG, L_DB, "Could not create query, unknown type %d\n", qp->type); @@ -2235,14 +2168,13 @@ db_query_fetch_file(struct query_params *qp, struct db_media_file_info *dbmfi) } int -db_query_fetch_pl(struct query_params *qp, struct db_playlist_info *dbpli, int with_itemcount) +db_query_fetch_pl(struct query_params *qp, struct db_playlist_info *dbpli) { int ncols; char **strcol; - int id; + uint32_t nitems; + uint32_t nstreams; int type; - int nitems; - int nstreams; int i; int ret; @@ -2289,46 +2221,14 @@ db_query_fetch_pl(struct query_params *qp, struct db_playlist_info *dbpli, int w *strcol = (char *)sqlite3_column_text(qp->stmt, i); } - if (with_itemcount) + type = sqlite3_column_int(qp->stmt, 2); + if (type == PL_SPECIAL || type == PL_SMART) { - type = sqlite3_column_int(qp->stmt, 2); - - switch (type) - { - case PL_PLAIN: - case PL_FOLDER: - id = sqlite3_column_int(qp->stmt, 0); - nitems = db_pl_count_items(id, 0); - nstreams = db_pl_count_items(id, 1); - break; - - case PL_SPECIAL: - case PL_SMART: - nitems = db_smartpl_count_items(dbpli->query); - nstreams = 0; - break; - - default: - DPRINTF(E_LOG, L_DB, "Unknown playlist type %d while fetching playlist\n", type); - return -1; - } - + db_files_get_count(&nitems, &nstreams, dbpli->query); + snprintf(qp->buf1, sizeof(qp->buf1), "%d", (int)nitems); + snprintf(qp->buf2, sizeof(qp->buf2), "%d", (int)nstreams); dbpli->items = qp->buf1; - ret = snprintf(qp->buf1, sizeof(qp->buf1), "%d", nitems); - if ((ret < 0) || (ret >= sizeof(qp->buf1))) - { - DPRINTF(E_LOG, L_DB, "Could not convert item count, buffer too small\n"); - - strcpy(qp->buf1, "0"); - } dbpli->streams = qp->buf2; - ret = snprintf(qp->buf2, sizeof(qp->buf2), "%d", nstreams); - if ((ret < 0) || (ret >= sizeof(qp->buf2))) - { - DPRINTF(E_LOG, L_DB, "Could not convert stream count, buffer too small\n"); - - strcpy(qp->buf2, "0"); - } } return 0; @@ -2523,9 +2423,62 @@ db_query_fetch_string_sort(struct query_params *qp, char **string, char **sortst /* Files */ int -db_files_get_count(void) +db_files_get_count(uint32_t *nitems, uint32_t *nstreams, const char *filter) { - return db_get_one_int("SELECT COUNT(*) FROM files f WHERE f.disabled = 0;"); + sqlite3_stmt *stmt; + char *query; + int ret; + + if (!filter && !nstreams) + query = sqlite3_mprintf("SELECT COUNT(*) FROM files f WHERE f.disabled = 0;"); + else if (!filter) + query = sqlite3_mprintf("SELECT COUNT(*), SUM(data_kind = %d) FROM files f WHERE f.disabled = 0;", DATA_KIND_HTTP); + else if (!nstreams) + query = sqlite3_mprintf("SELECT COUNT(*) FROM files f WHERE f.disabled = 0 AND %s;", filter); + else + query = sqlite3_mprintf("SELECT COUNT(*), SUM(data_kind = %d) FROM files f WHERE f.disabled = 0 AND %s;", DATA_KIND_HTTP, filter); + + 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 = db_blocking_prepare_v2(query, -1, &stmt, NULL); + sqlite3_free(query); + if (ret != SQLITE_OK) + { + DPRINTF(E_LOG, L_DB, "Could not prepare statement: %s\n", sqlite3_errmsg(hdl)); + return -1; + } + + ret = db_blocking_step(stmt); + if (ret != SQLITE_ROW) + { + if (ret == SQLITE_DONE) + DPRINTF(E_INFO, L_DB, "No matching row found for query: %s\n", query); + else + DPRINTF(E_LOG, L_DB, "Could not step: %s (%s)\n", sqlite3_errmsg(hdl), query); + + sqlite3_finalize(stmt); + return -1; + } + + if (nitems) + *nitems = sqlite3_column_int(stmt, 0); + if (nstreams) + *nstreams = sqlite3_column_int(stmt, 1); + +#ifdef DB_PROFILE + while (db_blocking_step(stmt) == SQLITE_ROW) + ; /* EMPTY */ +#endif + + sqlite3_finalize(stmt); + + return 0; } void @@ -3232,64 +3185,16 @@ db_file_update_directoryid(const char *path, int dir_id) /* Playlists */ int -db_pl_get_count(void) +db_pl_get_count(uint32_t *nitems) { - return db_get_one_int("SELECT COUNT(*) FROM playlists p WHERE p.disabled = 0;"); -} + int ret = db_get_one_int("SELECT COUNT(*) FROM playlists p WHERE p.disabled = 0;"); -static int -db_pl_count_items(int id, int streams_only) -{ -#define Q_TMPL "SELECT COUNT(*) FROM playlistitems pi JOIN files f" \ - " ON pi.filepath = f.path WHERE f.disabled = 0 AND pi.playlistid = %d;" -#define Q_TMPL_STREAMS "SELECT COUNT(*) FROM playlistitems pi JOIN files f" \ - " ON pi.filepath = f.path WHERE f.disabled = 0 AND f.data_kind = 1 AND pi.playlistid = %d;" - char *query; - int ret; + if (ret < 0) + return -1; - if (!streams_only) - query = sqlite3_mprintf(Q_TMPL, id); - else - query = sqlite3_mprintf(Q_TMPL_STREAMS, id); + *nitems = (uint32_t)ret; - if (!query) - { - DPRINTF(E_LOG, L_DB, "Out of memory for query string\n"); - return 0; - } - - ret = db_get_one_int(query); - - sqlite3_free(query); - - return ret; - -#undef Q_TMPL_STREAMS -#undef Q_TMPL -} - -static int -db_smartpl_count_items(const char *smartpl_query) -{ -#define Q_TMPL "SELECT COUNT(*) FROM files f WHERE f.disabled = 0 AND %s;" - char *query; - int ret; - - query = sqlite3_mprintf(Q_TMPL, smartpl_query); - - if (!query) - { - DPRINTF(E_LOG, L_DB, "Out of memory for query string\n"); - return 0; - } - - ret = db_get_one_int(query); - - sqlite3_free(query); - - return ret; - -#undef Q_TMPL + return 0; } void @@ -3459,25 +3364,8 @@ db_pl_fetch_byquery(const char *query) return NULL; } - switch (pli->type) - { - case PL_PLAIN: - case PL_FOLDER: - pli->items = db_pl_count_items(pli->id, 0); - pli->streams = db_pl_count_items(pli->id, 1); - break; - - case PL_SPECIAL: - case PL_SMART: - pli->items = db_smartpl_count_items(pli->query); - break; - - default: - DPRINTF(E_LOG, L_DB, "Unknown playlist type %d while fetching playlist\n", pli->type); - - free_pli(pli, 0); - return NULL; - } + if (pli->type == PL_SPECIAL || pli->type == PL_SMART) + db_files_get_count(&pli->items, &pli->streams, pli->query); return pli; } @@ -3485,11 +3373,10 @@ db_pl_fetch_byquery(const char *query) struct playlist_info * db_pl_fetch_bypath(const char *path) { -#define Q_TMPL "SELECT p.* FROM playlists p WHERE p.path = '%q';" struct playlist_info *pli; char *query; - query = sqlite3_mprintf(Q_TMPL, path); + query = sqlite3_mprintf(Q_PL_SELECT " WHERE f.path = '%q' GROUP BY f.id;", path); if (!query) { DPRINTF(E_LOG, L_DB, "Out of memory for query string\n"); @@ -3502,18 +3389,15 @@ db_pl_fetch_bypath(const char *path) sqlite3_free(query); return pli; - -#undef Q_TMPL } struct playlist_info * db_pl_fetch_byvirtualpath(const char *virtual_path) { -#define Q_TMPL "SELECT p.* FROM playlists p WHERE p.virtual_path = '%q';" struct playlist_info *pli; char *query; - query = sqlite3_mprintf(Q_TMPL, virtual_path); + query = sqlite3_mprintf(Q_PL_SELECT " WHERE f.virtual_path = '%q' GROUP BY f.id;", virtual_path); if (!query) { DPRINTF(E_LOG, L_DB, "Out of memory for query string\n"); @@ -3526,18 +3410,15 @@ db_pl_fetch_byvirtualpath(const char *virtual_path) sqlite3_free(query); return pli; - -#undef Q_TMPL } struct playlist_info * db_pl_fetch_byid(int id) { -#define Q_TMPL "SELECT p.* FROM playlists p WHERE p.id = %d;" struct playlist_info *pli; char *query; - query = sqlite3_mprintf(Q_TMPL, id); + query = sqlite3_mprintf(Q_PL_SELECT " WHERE f.id = %d GROUP BY f.id;", id); if (!query) { DPRINTF(E_LOG, L_DB, "Out of memory for query string\n"); @@ -3550,18 +3431,15 @@ db_pl_fetch_byid(int id) sqlite3_free(query); return pli; - -#undef Q_TMPL } struct playlist_info * db_pl_fetch_bytitlepath(const char *title, const char *path) { -#define Q_TMPL "SELECT p.* FROM playlists p WHERE p.title = '%q' AND p.path = '%q';" struct playlist_info *pli; char *query; - query = sqlite3_mprintf(Q_TMPL, title, path); + query = sqlite3_mprintf(Q_PL_SELECT " WHERE f.title = '%q' AND f.path = '%q' GROUP BY f.id;", title, path); if (!query) { DPRINTF(E_LOG, L_DB, "Out of memory for query string\n"); @@ -3574,15 +3452,13 @@ db_pl_fetch_bytitlepath(const char *title, const char *path) sqlite3_free(query); return pli; - -#undef Q_TMPL } int db_pl_add(struct playlist_info *pli, int *id) { #define QDUP_TMPL "SELECT COUNT(*) FROM playlists p WHERE p.title = TRIM(%Q) AND p.path = '%q';" -#define QADD_TMPL "INSERT INTO playlists (title, type, query, db_timestamp, disabled, path, idx, special_id, " \ +#define QADD_TMPL "INSERT INTO playlists (title, type, query, db_timestamp, disabled, path, idx, special_id," \ " parent_id, virtual_path, directory_id, query_order, query_limit)" \ " VALUES (TRIM(%Q), %d, '%q', %" PRIi64 ", %d, '%q', %d, %d, %d, '%q', %d, %Q, %d);" char *query; @@ -3677,9 +3553,9 @@ db_pl_add_item_byid(int plid, int fileid) int db_pl_update(struct playlist_info *pli) { -#define Q_TMPL "UPDATE playlists SET title = TRIM(%Q), type = %d, query = '%q', db_timestamp = %" PRIi64 ", disabled = %d, " \ - " path = '%q', idx = %d, special_id = %d, parent_id = %d, virtual_path = '%q', directory_id = %d, " \ - " query_order = %Q, query_limit = %d " \ +#define Q_TMPL "UPDATE playlists SET title = TRIM(%Q), type = %d, query = '%q', db_timestamp = %" PRIi64 ", disabled = %d," \ + " path = '%q', idx = %d, special_id = %d, parent_id = %d, virtual_path = '%q', directory_id = %d," \ + " query_order = %Q, query_limit = %d" \ " WHERE id = %d;" char *query; int ret; @@ -4229,7 +4105,8 @@ db_directory_ping_bymatch(char *virtual_path) void db_directory_disable_bymatch(char *path, enum strip_type strip, uint32_t cookie) { -#define Q_TMPL "UPDATE directories SET virtual_path = substr(virtual_path, %d), disabled = %" PRIi64 " WHERE virtual_path = '/file:%q' OR virtual_path LIKE '/file:%q/%%';" +#define Q_TMPL "UPDATE directories SET virtual_path = substr(virtual_path, %d)," \ + " disabled = %" PRIi64 " WHERE virtual_path = '/file:%q' OR virtual_path LIKE '/file:%q/%%';" char *query; int64_t disabled; int vpath_striplen; @@ -4247,7 +4124,8 @@ db_directory_disable_bymatch(char *path, enum strip_type strip, uint32_t cookie) int db_directory_enable_bycookie(uint32_t cookie, char *path) { -#define Q_TMPL "UPDATE directories SET virtual_path = ('/file:%q' || virtual_path), disabled = 0 WHERE disabled = %" PRIi64 ";" +#define Q_TMPL "UPDATE directories SET virtual_path = ('/file:%q' || virtual_path)," \ + " disabled = 0 WHERE disabled = %" PRIi64 ";" char *query; int ret; @@ -4895,14 +4773,14 @@ db_queue_add_by_queryafteritemid(struct query_params *qp, uint32_t item_id) int db_queue_add_start(struct db_queue_add_info *queue_add_info, int pos) { - int queue_count; - int ret = 0; + uint32_t queue_count; + int ret; memset(queue_add_info, 0, sizeof(struct db_queue_add_info)); queue_add_info->queue_version = queue_transaction_begin(); - queue_count = db_queue_get_count(); - if (queue_count < 0) + ret = db_queue_get_count(&queue_count); + if (ret < 0) { ret = -1; queue_transaction_end(ret, queue_add_info->queue_version); @@ -4988,7 +4866,7 @@ db_queue_add_by_query(struct query_params *qp, char reshuffle, uint32_t item_id, struct db_media_file_info dbmfi; char *query; int queue_version; - int queue_count; + uint32_t queue_count; int pos; int ret; @@ -4999,8 +4877,8 @@ db_queue_add_by_query(struct query_params *qp, char reshuffle, uint32_t item_id, queue_version = queue_transaction_begin(); - queue_count = db_queue_get_count(); - if (queue_count < 0) + ret = db_queue_get_count(&queue_count); + if (ret < 0) { ret = -1; goto end_transaction; @@ -6001,7 +5879,7 @@ queue_reshuffle(uint32_t item_id, int queue_version) { char *query; int pos; - int count; + uint32_t count; struct db_queue_item queue_item; int *shuffle_pos; int len; @@ -6015,27 +5893,25 @@ queue_reshuffle(uint32_t item_id, int queue_version) query = sqlite3_mprintf("UPDATE queue SET shuffle_pos = pos, queue_version = %d;", queue_version); ret = db_query_run(query, 1, 0); if (ret < 0) - { - return -1; - } + return -1; pos = 0; if (item_id > 0) { pos = db_queue_get_pos(item_id, 0); if (pos < 0) - { - return -1; - } + return -1; pos++; // Do not reshuffle the base item } - count = db_queue_get_count(); + ret = db_queue_get_count(&count); + if (ret < 0) + return -1; len = count - pos; - DPRINTF(E_DBG, L_DB, "Reshuffle %d items off %d total items, starting from pos %d\n", len, count, pos); + DPRINTF(E_DBG, L_DB, "Reshuffle %d items off %" PRIu32 " total items, starting from pos %d\n", len, count, pos); shuffle_pos = malloc(len * sizeof(int)); for (i = 0; i < len; i++) @@ -6073,9 +5949,7 @@ queue_reshuffle(uint32_t item_id, int queue_version) sqlite3_free(qp.filter); if (ret < 0) - { - return -1; - } + return -1; return 0; } @@ -6119,9 +5993,16 @@ db_queue_inc_version() } int -db_queue_get_count() +db_queue_get_count(uint32_t *nitems) { - return db_get_one_int("SELECT COUNT(*) FROM queue;"); + int ret = db_get_one_int("SELECT COUNT(*) FROM queue;"); + + if (ret < 0) + return -1; + + *nitems = (uint32_t)ret; + + return 0; } @@ -7141,8 +7022,8 @@ db_check_version(void) int db_init(void) { - int files; - int pls; + uint32_t files; + uint32_t pls; int ret; if (ARRAY_SIZE(dbmfi_cols_map) != ARRAY_SIZE(mfi_cols_map)) @@ -7214,13 +7095,14 @@ db_init(void) db_set_cfg_names(); - files = db_files_get_count(); - pls = db_pl_get_count(); + CHECK_ERR(L_DB, db_files_get_count(&files, NULL, NULL)); + CHECK_ERR(L_DB, db_pl_get_count(&pls)); + db_admin_setint64(DB_ADMIN_START_TIME, (int64_t) time(NULL)); db_perthread_deinit(); - DPRINTF(E_LOG, L_DB, "Database OK with %d active files and %d active playlists\n", files, pls); + DPRINTF(E_LOG, L_DB, "Database OK with %" PRIu32 " active files and %" PRIu32 " active playlists\n", files, pls); rng_init(&shuffle_rng); diff --git a/src/db.h b/src/db.h index 83eeadc2..a761b057 100644 --- a/src/db.h +++ b/src/db.h @@ -238,8 +238,6 @@ struct playlist_info { uint32_t id; /* integer id (miid) */ char *title; /* playlist name as displayed in iTunes (minm) */ enum pl_type type; /* see PL_ types */ - uint32_t items; /* number of items (mimc) */ - uint32_t streams; /* number of internet streams */ char *query; /* where clause if type 1 (MSPS) */ uint32_t db_timestamp; /* time last updated */ uint32_t disabled; @@ -251,6 +249,8 @@ struct playlist_info { uint32_t directory_id; /* Id of directory */ char *query_order; /* order by clause if it is a smart playlist */ int32_t query_limit; /* limit if it is a smart playlist */ + uint32_t items; /* number of items (mimc) */ + uint32_t streams; /* number of internet streams */ }; #define pli_offsetof(field) offsetof(struct playlist_info, field) @@ -259,8 +259,6 @@ struct db_playlist_info { char *id; char *title; char *type; - char *items; - char *streams; char *query; char *db_timestamp; char *disabled; @@ -272,6 +270,8 @@ struct db_playlist_info { char *directory_id; char *query_order; char *query_limit; + char *items; + char *streams; }; #define dbpli_offsetof(field) offsetof(struct db_playlist_info, field) @@ -545,7 +545,7 @@ int db_query_fetch_file(struct query_params *qp, struct db_media_file_info *dbmfi); int -db_query_fetch_pl(struct query_params *qp, struct db_playlist_info *dbpli, int with_itemcount); +db_query_fetch_pl(struct query_params *qp, struct db_playlist_info *dbpli); int db_query_fetch_group(struct query_params *qp, struct db_group_info *dbgri); @@ -561,7 +561,7 @@ db_query_fetch_string_sort(struct query_params *qp, char **string, char **sortst /* Files */ int -db_files_get_count(void); +db_files_get_count(uint32_t *nitems, uint32_t *nstreams, const char *filter); void db_file_inc_playcount(int id); @@ -637,7 +637,7 @@ db_filecount_get(struct filecount_info *fci, struct query_params *qp); /* Playlists */ int -db_pl_get_count(void); +db_pl_get_count(uint32_t *nitems); void db_pl_ping(int id); @@ -863,7 +863,7 @@ int db_queue_inc_version(void); int -db_queue_get_count(); +db_queue_get_count(uint32_t *nitems); int db_queue_get_pos(uint32_t item_id, char shuffle); diff --git a/src/httpd_daap.c b/src/httpd_daap.c index 6cf7546e..af25454e 100644 --- a/src/httpd_daap.c +++ b/src/httpd_daap.c @@ -1095,7 +1095,7 @@ daap_reply_dblist(struct httpd_request *hreq) char *name; char *name_radio; size_t len; - int count; + uint32_t count = 0; name = cfg_getstr(cfg_getsec(cfg, "library"), "name"); name_radio = cfg_getstr(cfg_getsec(cfg, "library"), "name_radio"); @@ -1111,10 +1111,10 @@ daap_reply_dblist(struct httpd_request *hreq) dmap_add_int(item, "mdbk", 1); dmap_add_int(item, "aeCs", 1); dmap_add_string(item, "minm", name); - count = db_files_get_count(); - dmap_add_int(item, "mimc", count); - count = db_pl_get_count(); // TODO Don't count empty smart playlists, because they get excluded in aply - dmap_add_int(item, "mctc", count); + db_files_get_count(&count, NULL, NULL); + dmap_add_int(item, "mimc", (int)count); + db_pl_get_count(&count); // TODO Don't count empty smart playlists, because they get excluded in aply + dmap_add_int(item, "mctc", (int)count); // dmap_add_int(content, "aeMk", 0x405); // com.apple.itunes.extended-media-kind (OR of all in library) dmap_add_int(item, "meds", 3); @@ -1132,8 +1132,8 @@ daap_reply_dblist(struct httpd_request *hreq) dmap_add_int(item, "mdbk", 0x64); dmap_add_int(item, "aeCs", 0); dmap_add_string(item, "minm", name_radio); - count = db_pl_get_count(); // TODO This counts too much, should only include stream playlists - dmap_add_int(item, "mimc", count); + db_pl_get_count(&count); // TODO This counts too much, should only include stream playlists + dmap_add_int(item, "mimc", (int)count); dmap_add_int(item, "mctc", 0); dmap_add_int(item, "aeMk", 1); // com.apple.itunes.extended-media-kind (OR of all in library) dmap_add_int(item, "meds", 3); @@ -1465,7 +1465,7 @@ daap_reply_playlists(struct httpd_request *hreq) } npls = 0; - while (((ret = db_query_fetch_pl(&qp, &dbpli, 1)) == 0) && (dbpli.id)) + while (((ret = db_query_fetch_pl(&qp, &dbpli)) == 0) && (dbpli.id)) { plid = 1; if (safe_atoi32(dbpli.id, &plid) != 0) diff --git a/src/httpd_jsonapi.c b/src/httpd_jsonapi.c index 5a530e0e..ad77e490 100644 --- a/src/httpd_jsonapi.c +++ b/src/httpd_jsonapi.c @@ -487,7 +487,7 @@ fetch_playlists(struct query_params *query_params, json_object *items, int *tota if (ret < 0) goto error; - while (((ret = db_query_fetch_pl(query_params, &dbpli, 0)) == 0) && (dbpli.id)) + while (((ret = db_query_fetch_pl(query_params, &dbpli)) == 0) && (dbpli.id)) { item = playlist_to_json(&dbpli); if (!item) @@ -527,7 +527,7 @@ fetch_playlist(const char *playlist_id) if (ret < 0) goto error; - if (((ret = db_query_fetch_pl(&query_params, &dbpli, 0)) == 0) && (dbpli.id)) + if (((ret = db_query_fetch_pl(&query_params, &dbpli)) == 0) && (dbpli.id)) { playlist = playlist_to_json(&dbpli); } @@ -2096,9 +2096,9 @@ jsonapi_reply_queue(struct httpd_request *hreq) struct query_params query_params; const char *param; uint32_t item_id; + uint32_t count; int start_pos, end_pos; int version; - int count; char etag[21]; struct player_status status; struct db_queue_item queue_item; @@ -2108,7 +2108,7 @@ jsonapi_reply_queue(struct httpd_request *hreq) int ret = 0; version = db_admin_getint(DB_ADMIN_QUEUE_VERSION); - count = db_queue_get_count(); + db_queue_get_count(&count); snprintf(etag, sizeof(etag), "%d", version); if (httpd_request_etag_matches(hreq->req, etag)) @@ -2118,7 +2118,7 @@ jsonapi_reply_queue(struct httpd_request *hreq) reply = json_object_new_object(); json_object_object_add(reply, "version", json_object_new_int(version)); - json_object_object_add(reply, "count", json_object_new_int(count)); + json_object_object_add(reply, "count", json_object_new_int((int)count)); items = json_object_new_array(); json_object_object_add(reply, "items", items); diff --git a/src/httpd_rsp.c b/src/httpd_rsp.c index f0e6d7db..fb16fd32 100644 --- a/src/httpd_rsp.c +++ b/src/httpd_rsp.c @@ -316,9 +316,9 @@ rsp_reply_info(struct httpd_request *hreq) mxml_node_t *node; cfg_t *lib; char *library; - int songcount; + uint32_t songcount; - songcount = db_files_get_count(); + db_files_get_count(&songcount, NULL, NULL); lib = cfg_getsec(cfg, "library"); library = cfg_getstr(lib, "name"); @@ -347,7 +347,7 @@ rsp_reply_info(struct httpd_request *hreq) /* Info block */ node = mxmlNewElement(info, "count"); - mxmlNewTextf(node, 0, "%d", songcount); + mxmlNewTextf(node, 0, "%d", (int)songcount); node = mxmlNewElement(info, "rsp-version"); mxmlNewText(node, 0, RSP_VERSION); @@ -377,7 +377,7 @@ rsp_reply_db(struct httpd_request *hreq) int i; int ret; - memset(&qp, 0, sizeof(struct db_playlist_info)); + memset(&qp, 0, sizeof(struct query_params)); qp.type = Q_PL; qp.idx_type = I_NONE; @@ -414,7 +414,7 @@ rsp_reply_db(struct httpd_request *hreq) mxmlNewTextf(node, 0, "%d", qp.results); /* Playlists block (all playlists) */ - while (((ret = db_query_fetch_pl(&qp, &dbpli, 1)) == 0) && (dbpli.id)) + while (((ret = db_query_fetch_pl(&qp, &dbpli)) == 0) && (dbpli.id)) { /* Playlist block (one playlist) */ pl = mxmlNewElement(pls, "playlist"); diff --git a/src/mpd.c b/src/mpd.c index 5ac07544..4b783a07 100644 --- a/src/mpd.c +++ b/src/mpd.c @@ -958,7 +958,7 @@ static int mpd_command_status(struct evbuffer *evbuf, int argc, char **argv, char **errmsg, struct mpd_client_ctx *ctx) { struct player_status status; - int queue_length; + uint32_t queue_length = 0; int queue_version; char *state; uint32_t itemid = 0; @@ -982,7 +982,7 @@ mpd_command_status(struct evbuffer *evbuf, int argc, char **argv, char **errmsg, } queue_version = db_admin_getint(DB_ADMIN_QUEUE_VERSION); - queue_length = db_queue_get_count(); + db_queue_get_count(&queue_length); evbuffer_add_printf(evbuf, "volume: %d\n" @@ -2413,7 +2413,7 @@ mpd_command_listplaylists(struct evbuffer *evbuf, int argc, char **argv, char ** return ACK_ERROR_UNKNOWN; } - while (((ret = db_query_fetch_pl(&qp, &dbpli, 0)) == 0) && (dbpli.id)) + while (((ret = db_query_fetch_pl(&qp, &dbpli)) == 0) && (dbpli.id)) { if (safe_atou32(dbpli.db_timestamp, &time_modified) != 0) { @@ -2830,7 +2830,7 @@ mpd_add_directory(struct evbuffer *evbuf, int directory_id, int listall, int lis *errmsg = safe_asprintf("Could not start query"); return ACK_ERROR_UNKNOWN; } - while (((ret = db_query_fetch_pl(&qp, &dbpli, 0)) == 0) && (dbpli.id)) + while (((ret = db_query_fetch_pl(&qp, &dbpli)) == 0) && (dbpli.id)) { if (safe_atou32(dbpli.db_timestamp, &time_modified) != 0) {