From b7c4256df4e287545f69dd05a2b80e6d6305a072 Mon Sep 17 00:00:00 2001 From: ejurgensen Date: Wed, 4 Jan 2017 22:29:47 +0100 Subject: [PATCH] [db] Refactor db_build_query_* to reduce redundancy --- src/db.c | 747 +++++++++++++++++++------------------------------------ 1 file changed, 251 insertions(+), 496 deletions(-) diff --git a/src/db.c b/src/db.c index eddd1b58..fda834ae 100644 --- a/src/db.c +++ b/src/db.c @@ -76,6 +76,12 @@ struct col_type_map { short type; }; +struct query_clause { + char *where; + const char *order; + char *index; +}; + /* This list must be kept in sync with * - the order of the columns in the files table * - the type and name of the fields in struct media_file_info @@ -827,7 +833,7 @@ db_purge_all(void) } static int -db_get_one_int(char *query) +db_get_one_int(const char *query) { sqlite3_stmt *stmt; int ret; @@ -918,461 +924,290 @@ db_transaction_rollback(void) } } - -/* Queries */ -static int -db_build_query_index_clause(char **i, struct query_params *qp) +static void +db_free_query_clause(struct query_clause *qc) { - char *idx; + if (!qc) + return; - *i = NULL; + sqlite3_free(qc->where); + sqlite3_free(qc->index); + free(qc); +} + +static struct query_clause * +db_build_query_clause(struct query_params *qp) +{ + struct query_clause *qc; + + qc = calloc(1, sizeof(struct query_clause)); + if (!qc) + goto error; + + if (qp->filter) + qc->where = sqlite3_mprintf("WHERE f.disabled = 0 AND %s", qp->filter); + else + qc->where = sqlite3_mprintf("WHERE f.disabled = 0"); + + if (qp->sort) + qc->order = sort_clause[qp->sort]; + else + qc->order = ""; switch (qp->idx_type) { case I_FIRST: - idx = sqlite3_mprintf("LIMIT %d", qp->limit); + qc->index = sqlite3_mprintf("LIMIT %d", qp->limit); break; case I_LAST: - idx = sqlite3_mprintf("LIMIT -1 OFFSET %d", qp->results - qp->limit); + qc->index = sqlite3_mprintf("LIMIT -1 OFFSET %d", qp->results - qp->limit); break; case I_SUB: - idx = sqlite3_mprintf("LIMIT %d OFFSET %d", qp->limit, qp->offset); + qc->index = sqlite3_mprintf("LIMIT %d OFFSET %d", qp->limit, qp->offset); break; case I_NONE: - return 0; - - default: - DPRINTF(E_LOG, L_DB, "Unknown index type\n"); - return -1; + qc->index = sqlite3_mprintf(""); + break; } - if (!idx) - { - DPRINTF(E_LOG, L_DB, "Could not build index string; out of memory"); - return -1; - } + if (!qc->where || !qc->index) + goto error; - *i = idx; + return qc; - return 0; + error: + DPRINTF(E_LOG, L_DB, "Error building query clause\n"); + db_free_query_clause(qc); + return NULL; } -static int -db_build_query_items(struct query_params *qp, char **q) +static char * +db_build_query_check(struct query_params *qp, char *count, char *query) { - char *query; - char *count; - char *idx; - const char *sort; - int ret; - - if (qp->filter) - count = sqlite3_mprintf("SELECT COUNT(*) FROM files f WHERE f.disabled = 0 AND %s;", qp->filter); - else - count = sqlite3_mprintf("SELECT COUNT(*) FROM files f WHERE f.disabled = 0;"); - - if (!count) + if (!count || !query) { - DPRINTF(E_LOG, L_DB, "Out of memory for count query string\n"); - - return -1; + DPRINTF(E_LOG, L_DB, "Out of memory for query string\n"); + goto failed; } qp->results = db_get_one_int(count); + if (qp->results < 0) + goto failed; + sqlite3_free(count); - if (qp->results < 0) - return -1; + return query; - /* Get index clause */ - ret = db_build_query_index_clause(&idx, qp); - if (ret < 0) - return -1; - - sort = sort_clause[qp->sort]; - - if (idx && qp->filter) - query = sqlite3_mprintf("SELECT f.* FROM files f WHERE f.disabled = 0 AND %s %s %s;", qp->filter, sort, idx); - else if (idx) - query = sqlite3_mprintf("SELECT f.* FROM files f WHERE f.disabled = 0 %s %s;", sort, idx); - else if (qp->filter) - query = sqlite3_mprintf("SELECT f.* FROM files f WHERE f.disabled = 0 AND %s %s;", qp->filter, sort); - else - query = sqlite3_mprintf("SELECT f.* FROM files f WHERE f.disabled = 0 %s;", sort); - - if (idx) - sqlite3_free(idx); - - if (!query) - { - DPRINTF(E_LOG, L_DB, "Out of memory for query string\n"); - return -1; - } - - *q = query; - - return 0; + failed: + sqlite3_free(count); + sqlite3_free(query); + return NULL; } -static int -db_build_query_pls(struct query_params *qp, char **q) +static char * +db_build_query_items(struct query_params *qp) { - char *query; - char *idx; - const char *sort; - int ret; - - qp->results = db_get_one_int("SELECT COUNT(*) FROM playlists p WHERE p.disabled = 0;"); - if (qp->results < 0) - return -1; - - /* Get index clause */ - ret = db_build_query_index_clause(&idx, qp); - if (ret < 0) - return -1; - - sort = sort_clause[qp->sort]; - - if (idx && qp->filter) - query = sqlite3_mprintf("SELECT f.* FROM playlists f WHERE f.disabled = 0 AND %s %s %s;", qp->filter, sort, idx); - else if (idx) - query = sqlite3_mprintf("SELECT f.* FROM playlists f WHERE f.disabled = 0 %s %s;", sort, idx); - else if (qp->filter) - query = sqlite3_mprintf("SELECT f.* FROM playlists f WHERE f.disabled = 0 AND %s %s;", qp->filter, sort); - else - query = sqlite3_mprintf("SELECT f.* FROM playlists f WHERE f.disabled = 0 %s;", sort); - - if (idx) - sqlite3_free(idx); - - if (!query) - { - DPRINTF(E_LOG, L_DB, "Out of memory for query string\n"); - return -1; - } - - *q = query; - - return 0; -} - -static int -db_build_query_plitems_plain(struct query_params *qp, char **q) -{ - char *query; + struct query_clause *qc; char *count; - char *idx; - int ret; - - if (qp->filter) - count = sqlite3_mprintf("SELECT COUNT(*) FROM files f JOIN playlistitems pi ON f.path = pi.filepath" - " WHERE pi.playlistid = %d AND f.disabled = 0 AND %s;", qp->id, qp->filter); - else - count = sqlite3_mprintf("SELECT COUNT(*) FROM files f JOIN playlistitems pi ON f.path = pi.filepath" - " WHERE pi.playlistid = %d AND f.disabled = 0;", qp->id); - - if (!count) - { - DPRINTF(E_LOG, L_DB, "Out of memory for count query string\n"); - - return -1; - } - - qp->results = db_get_one_int(count); - sqlite3_free(count); - - if (qp->results < 0) - return -1; - - /* Get index clause */ - ret = db_build_query_index_clause(&idx, qp); - if (ret < 0) - return -1; - - if (idx && qp->filter) - query = sqlite3_mprintf("SELECT f.* FROM files f JOIN playlistitems pi ON f.path = pi.filepath" - " WHERE pi.playlistid = %d AND f.disabled = 0 AND %s ORDER BY pi.id ASC %s;", - qp->id, qp->filter, idx); - else if (idx) - query = sqlite3_mprintf("SELECT f.* FROM files f JOIN playlistitems pi ON f.path = pi.filepath" - " WHERE pi.playlistid = %d AND f.disabled = 0 ORDER BY pi.id ASC %s;", - qp->id, idx); - else if (qp->filter) - query = sqlite3_mprintf("SELECT f.* FROM files f JOIN playlistitems pi ON f.path = pi.filepath" - " WHERE pi.playlistid = %d AND f.disabled = 0 AND %s ORDER BY pi.id ASC;", - qp->id, qp->filter); - else - query = sqlite3_mprintf("SELECT f.* FROM files f JOIN playlistitems pi ON f.path = pi.filepath" - " WHERE pi.playlistid = %d AND f.disabled = 0 ORDER BY pi.id ASC;", - qp->id); - - if (idx) - sqlite3_free(idx); - - if (!query) - { - DPRINTF(E_LOG, L_DB, "Out of memory for query string\n"); - return -1; - } - - *q = query; - - return 0; -} - -static int -db_build_query_plitems_smart(struct query_params *qp, char *smartpl_query, char **q) -{ char *query; - char *count; - char *filter; - char *idx; - const char *sort; - int ret; - if (qp->filter) - filter = qp->filter; - else - filter = "1 = 1"; + qc = db_build_query_clause(qp); + if (!qc) + return NULL; - count = sqlite3_mprintf("SELECT COUNT(*) FROM files f WHERE f.disabled = 0 AND %s AND %s;", filter, smartpl_query); - if (!count) - { - DPRINTF(E_LOG, L_DB, "Out of memory for count query string\n"); - return -1; - } + count = sqlite3_mprintf("SELECT COUNT(*) FROM files f %s;", qc->where); + query = sqlite3_mprintf("SELECT f.* FROM files f %s %s %s;", qc->where, qc->order, qc->index); - qp->results = db_get_one_int(count); + db_free_query_clause(qc); - sqlite3_free(count); - - if (qp->results < 0) - return -1; - - /* Get index clause */ - ret = db_build_query_index_clause(&idx, qp); - if (ret < 0) - return -1; - - sort = sort_clause[qp->sort]; - - if (idx) - query = sqlite3_mprintf("SELECT f.* FROM files f WHERE f.disabled = 0 AND %s AND %s %s %s;", smartpl_query, filter, sort, idx); - else - query = sqlite3_mprintf("SELECT f.* FROM files f WHERE f.disabled = 0 AND %s AND %s %s;", smartpl_query, filter, sort); - - if (idx) - sqlite3_free(idx); - - if (!query) - { - DPRINTF(E_LOG, L_DB, "Out of memory for query string\n"); - return -1; - } - - *q = query; - - return 0; + return db_build_query_check(qp, count, query); } -static int -db_build_query_plitems(struct query_params *qp, char **q) +static char * +db_build_query_pls(struct query_params *qp) +{ + 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); + + return db_build_query_check(qp, count, query); +} + +static char * +db_build_query_plitems_plain(struct query_params *qp) +{ + 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); +} + +static char * +db_build_query_plitems_smart(struct query_params *qp, char *smartpl_query) +{ + 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 AND %s;", qc->where, smartpl_query); + query = sqlite3_mprintf("SELECT f.* FROM files f %s AND %s %s %s;", qc->where, smartpl_query, qc->order, qc->index); + + db_free_query_clause(qc); + + return db_build_query_check(qp, count, query); +} + +static char * +db_build_query_plitems(struct query_params *qp) { struct playlist_info *pli; - int ret; + char *query; if (qp->id <= 0) - { - DPRINTF(E_LOG, L_DB, "No playlist id specified in playlist items query\n"); - return -1; - } + { + 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) - return -1; + return NULL; switch (pli->type) { case PL_SPECIAL: case PL_SMART: - ret = db_build_query_plitems_smart(qp, pli->query, q); + query = db_build_query_plitems_smart(qp, pli->query); break; case PL_PLAIN: case PL_FOLDER: - ret = db_build_query_plitems_plain(qp, q); + query = db_build_query_plitems_plain(qp); break; default: DPRINTF(E_LOG, L_DB, "Unknown playlist type %d in playlist items query\n", pli->type); - ret = -1; + query = NULL; break; } free_pli(pli, 0); - return ret; + return query; } -static int -db_build_query_group_albums(struct query_params *qp, char **q) +static char * +db_build_query_group_albums(struct query_params *qp) { - char *query; - char *idx; - const char *sort; - int ret; - - qp->results = db_get_one_int("SELECT COUNT(DISTINCT f.songalbumid) FROM files f WHERE f.disabled = 0;"); - if (qp->results < 0) - return -1; - - /* Get index clause */ - ret = db_build_query_index_clause(&idx, qp); - if (ret < 0) - return -1; - - sort = sort_clause[qp->sort]; - - if (idx && qp->filter) - query = sqlite3_mprintf("SELECT g.id, g.persistentid, f.album, f.album_sort, COUNT(f.id), 1, f.album_artist, f.songartistid, SUM(f.song_length) FROM files f JOIN groups g ON f.songalbumid = g.persistentid WHERE f.disabled = 0 AND %s GROUP BY f.songalbumid %s %s;", qp->filter, sort, idx); - else if (idx) - query = sqlite3_mprintf("SELECT g.id, g.persistentid, f.album, f.album_sort, COUNT(f.id), 1, f.album_artist, f.songartistid, SUM(f.song_length) FROM files f JOIN groups g ON f.songalbumid = g.persistentid WHERE f.disabled = 0 GROUP BY f.songalbumid %s %s;", sort, idx); - else if (qp->filter) - query = sqlite3_mprintf("SELECT g.id, g.persistentid, f.album, f.album_sort, COUNT(f.id), 1, f.album_artist, f.songartistid, SUM(f.song_length) FROM files f JOIN groups g ON f.songalbumid = g.persistentid WHERE f.disabled = 0 AND %s GROUP BY f.songalbumid %s;", qp->filter, sort); - else - query = sqlite3_mprintf("SELECT g.id, g.persistentid, f.album, f.album_sort, COUNT(f.id), 1, f.album_artist, f.songartistid, SUM(f.song_length) FROM files f JOIN groups g ON f.songalbumid = g.persistentid WHERE f.disabled = 0 GROUP BY f.songalbumid %s;", sort); - - if (idx) - sqlite3_free(idx); - - if (!query) - { - DPRINTF(E_LOG, L_DB, "Out of memory for query string\n"); - return -1; - } - - *q = query; - - return 0; -} - -static int -db_build_query_group_artists(struct query_params *qp, char **q) -{ - char *query; - char *idx; - const char *sort; - int ret; - - qp->results = db_get_one_int("SELECT COUNT(DISTINCT f.songartistid) FROM files f WHERE f.disabled = 0;"); - if (qp->results < 0) - return -1; - - /* Get index clause */ - ret = db_build_query_index_clause(&idx, qp); - if (ret < 0) - return -1; - - sort = sort_clause[qp->sort]; - - if (idx && qp->filter) - query = sqlite3_mprintf("SELECT g.id, g.persistentid, f.album_artist, f.album_artist_sort, COUNT(f.id), COUNT(DISTINCT f.songalbumid), f.album_artist, f.songartistid, SUM(f.song_length) FROM files f JOIN groups g ON f.songartistid = g.persistentid WHERE f.disabled = 0 AND %s GROUP BY f.songartistid %s %s;", qp->filter, sort, idx); - else if (idx) - query = sqlite3_mprintf("SELECT g.id, g.persistentid, f.album_artist, f.album_artist_sort, COUNT(f.id), COUNT(DISTINCT f.songalbumid), f.album_artist, f.songartistid, SUM(f.song_length) FROM files f JOIN groups g ON f.songartistid = g.persistentid WHERE f.disabled = 0 GROUP BY f.songartistid %s %s;", sort, idx); - else if (qp->filter) - query = sqlite3_mprintf("SELECT g.id, g.persistentid, f.album_artist, f.album_artist_sort, COUNT(f.id), COUNT(DISTINCT f.songalbumid), f.album_artist, f.songartistid, SUM(f.song_length) FROM files f JOIN groups g ON f.songartistid = g.persistentid WHERE f.disabled = 0 AND %s GROUP BY f.songartistid %s;", qp->filter, sort); - else - query = sqlite3_mprintf("SELECT g.id, g.persistentid, f.album_artist, f.album_artist_sort, COUNT(f.id), COUNT(DISTINCT f.songalbumid), f.album_artist, f.songartistid, SUM(f.song_length) FROM files f JOIN groups g ON f.songartistid = g.persistentid WHERE f.disabled = 0 GROUP BY f.songartistid %s;", sort); - - if (idx) - sqlite3_free(idx); - - if (!query) - { - DPRINTF(E_LOG, L_DB, "Out of memory for query string\n"); - return -1; - } - - *q = query; - - return 0; -} - -static int -db_build_query_group_items(struct query_params *qp, char **q) -{ - char *query; + 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 WHERE f.disabled = 0;"); + query = sqlite3_mprintf("SELECT g.id, g.persistentid, f.album, f.album_sort, COUNT(f.id), 1, 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;", qc->where, 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) +{ + 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), COUNT(DISTINCT f.songalbumid), 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;", qc->where, 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) +{ 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) { case G_ALBUMS: - count = sqlite3_mprintf("SELECT COUNT(*) FROM files f" - " WHERE f.songalbumid = %" PRIi64 " AND f.disabled = 0;", qp->persistentid); + count = sqlite3_mprintf("SELECT COUNT(*) FROM files f %s AND f.songalbumid = %" PRIi64 ";", qc->where, qp->persistentid); + query = sqlite3_mprintf("SELECT f.* FROM files f %s AND f.songalbumid = %" PRIi64 " %s %s;", qc->where, qp->persistentid, qc->order, qc->index); break; case G_ARTISTS: - count = sqlite3_mprintf("SELECT COUNT(*) FROM files f" - " WHERE f.songartistid = %" PRIi64 " AND f.disabled = 0;", qp->persistentid); + count = sqlite3_mprintf("SELECT COUNT(*) FROM files f %s AND f.songartistid = %" PRIi64 ";", qc->where, qp->persistentid); + query = sqlite3_mprintf("SELECT f.* FROM files f %s AND f.songartistid = %" PRIi64 " %s %s;", qc->where, qp->persistentid, qc->order, qc->index); break; default: DPRINTF(E_LOG, L_DB, "Unsupported group type %d for group id %" PRIi64 "\n", gt, qp->persistentid); - return -1; + db_free_query_clause(qc); + return NULL; } - if (!count) - { - DPRINTF(E_LOG, L_DB, "Out of memory for count query string\n"); + db_free_query_clause(qc); - return -1; - } - - qp->results = db_get_one_int(count); - sqlite3_free(count); - - if (qp->results < 0) - return -1; - - switch (gt) - { - case G_ALBUMS: - query = sqlite3_mprintf("SELECT f.* FROM files f" - " WHERE f.songalbumid = %" PRIi64 " AND f.disabled = 0;", qp->persistentid); - break; - - case G_ARTISTS: - query = sqlite3_mprintf("SELECT f.* FROM files f" - " WHERE f.songartistid = %" PRIi64 " AND f.disabled = 0;", qp->persistentid); - break; - - default: - return -1; - } - - if (!query) - { - DPRINTF(E_LOG, L_DB, "Out of memory for query string\n"); - return -1; - } - - *q = query; - - return 0; + return db_build_query_check(qp, count, query); } -static int -db_build_query_group_dirs(struct query_params *qp, char **q) +static char * +db_build_query_group_dirs(struct query_params *qp) { - char *query; - char *count; 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); @@ -1380,147 +1215,67 @@ db_build_query_group_dirs(struct query_params *qp, char **q) { case G_ALBUMS: count = sqlite3_mprintf("SELECT COUNT(DISTINCT(SUBSTR(f.path, 1, LENGTH(f.path) - LENGTH(f.fname) - 1)))" - " FROM files f" - " WHERE f.songalbumid = %" PRIi64 " AND f.disabled = 0;", qp->persistentid); + " FROM files f %s AND f.songalbumid = %" PRIi64 ";", qc->where, qp->persistentid); + query = sqlite3_mprintf("SELECT DISTINCT(SUBSTR(f.path, 1, LENGTH(f.path) - LENGTH(f.fname) - 1))" + " FROM files f %s AND f.songalbumid = %" PRIi64 " %s %s;", qc->where, qp->persistentid, qc->order, qc->index); break; case G_ARTISTS: count = sqlite3_mprintf("SELECT COUNT(DISTINCT(SUBSTR(f.path, 1, LENGTH(f.path) - LENGTH(f.fname) - 1)))" - " FROM files f" - " WHERE f.songartistid = %" PRIi64 " AND f.disabled = 0;", qp->persistentid); + " FROM files f %s AND f.songartistid = %" PRIi64 ";", qc->where, qp->persistentid); + query = sqlite3_mprintf("SELECT DISTINCT(SUBSTR(f.path, 1, LENGTH(f.path) - LENGTH(f.fname) - 1))" + " FROM files f %s AND f.songartistid = %" PRIi64 " %s %s;", qc->where, qp->persistentid, qc->order, qc->index); break; default: DPRINTF(E_LOG, L_DB, "Unsupported group type %d for group id %" PRIi64 "\n", gt, qp->persistentid); - return -1; + db_free_query_clause(qc); + return NULL; } - if (!count) - { - DPRINTF(E_LOG, L_DB, "Out of memory for count query string\n"); + db_free_query_clause(qc); - return -1; - } - - qp->results = db_get_one_int(count); - sqlite3_free(count); - - if (qp->results < 0) - return -1; - - switch (gt) - { - case G_ALBUMS: - query = sqlite3_mprintf("SELECT DISTINCT(SUBSTR(f.path, 1, LENGTH(f.path) - LENGTH(f.fname) - 1))" - " FROM files f" - " WHERE f.songalbumid = %" PRIi64 " AND f.disabled = 0;", qp->persistentid); - break; - - case G_ARTISTS: - query = sqlite3_mprintf("SELECT DISTINCT(SUBSTR(f.path, 1, LENGTH(f.path) - LENGTH(f.fname) - 1))" - " FROM files f" - " WHERE f.songartistid = %" PRIi64 " AND f.disabled = 0;", qp->persistentid); - break; - - default: - return -1; - } - - if (!query) - { - DPRINTF(E_LOG, L_DB, "Out of memory for query string\n"); - return -1; - } - - *q = query; - - return 0; + return db_build_query_check(qp, count, query); } -static int -db_build_query_browse(struct query_params *qp, const char *field, const char *group_field, char **q) +static char * +db_build_query_browse(struct query_params *qp, const char *field, const char *group_field) { - char *query; + struct query_clause *qc; char *count; - char *idx; - const char *sort; - int ret; + char *query; - if (qp->filter) - count = sqlite3_mprintf("SELECT COUNT(DISTINCT f.%s) FROM files f WHERE f.disabled = 0 AND f.%s != '' AND %s;", - field, field, qp->filter); - else - count = sqlite3_mprintf("SELECT COUNT(DISTINCT f.%s) FROM files f WHERE f.disabled = 0 AND f.%s != '';", - field, field); + qc = db_build_query_clause(qp); + if (!qc) + return NULL; - if (!count) - { - DPRINTF(E_LOG, L_DB, "Out of memory for count query string\n"); + count = sqlite3_mprintf("SELECT COUNT(DISTINCT f.%s) FROM files f %s AND f.%s != '';", field, qc->where, field); + query = sqlite3_mprintf("SELECT f.%s, f.%s FROM files f %s AND f.%s != '' GROUP BY f.%s %s %s;", field, group_field, qc->where, field, group_field, qc->order, qc->index); - return -1; - } + db_free_query_clause(qc); - qp->results = db_get_one_int(count); - sqlite3_free(count); - - if (qp->results < 0) - return -1; - - /* Get index clause */ - ret = db_build_query_index_clause(&idx, qp); - if (ret < 0) - return -1; - - sort = sort_clause[qp->sort]; - - if (idx && qp->filter) - query = sqlite3_mprintf("SELECT f.%s, f.%s FROM files f WHERE f.disabled = 0 AND f.%s != ''" - " AND %s GROUP BY f.%s %s %s;", field, group_field, field, qp->filter, group_field, sort, idx); - else if (idx) - query = sqlite3_mprintf("SELECT f.%s, f.%s FROM files f WHERE f.disabled = 0 AND f.%s != ''" - " GROUP BY f.%s %s %s;", field, group_field, field, group_field, sort, idx); - else if (qp->filter) - query = sqlite3_mprintf("SELECT f.%s, f.%s FROM files f WHERE f.disabled = 0 AND f.%s != ''" - " AND %s GROUP BY f.%s %s;", field, group_field, field, qp->filter, group_field, sort); - else - query = sqlite3_mprintf("SELECT f.%s, f.%s FROM files f WHERE f.disabled = 0 AND f.%s != ''" - " GROUP BY f.%s %s", field, group_field, field, group_field, sort); - - if (idx) - sqlite3_free(idx); - - if (!query) - { - DPRINTF(E_LOG, L_DB, "Out of memory for query string\n"); - return -1; - } - - *q = query; - - return 0; + return db_build_query_check(qp, count, query); } -static int -db_build_query_count_items(struct query_params *qp, char **q) +static char * +db_build_query_count_items(struct query_params *qp) { + struct query_clause *qc; char *query; + qc = db_build_query_clause(qp); + if (!qc) + return NULL; + qp->results = 1; - if (qp->filter) - query = sqlite3_mprintf("SELECT COUNT(*), SUM(song_length) FROM files f WHERE f.disabled = 0 AND %s;", qp->filter); - else - query = sqlite3_mprintf("SELECT COUNT(*), SUM(song_length) FROM files f WHERE f.disabled = 0;"); - + query = sqlite3_mprintf("SELECT COUNT(*), SUM(song_length) FROM files f %s;", qc->where); if (!query) - { - DPRINTF(E_LOG, L_DB, "Out of memory for query string\n"); - return -1; - } + DPRINTF(E_LOG, L_DB, "Out of memory for query string\n"); - *q = query; + db_free_query_clause(qc); - return 0; + return query; } int @@ -1534,71 +1289,71 @@ db_query_start(struct query_params *qp) switch (qp->type) { case Q_ITEMS: - ret = db_build_query_items(qp, &query); + query = db_build_query_items(qp); break; case Q_PL: - ret = db_build_query_pls(qp, &query); + query = db_build_query_pls(qp); break; case Q_PLITEMS: - ret = db_build_query_plitems(qp, &query); + query = db_build_query_plitems(qp); break; case Q_GROUP_ALBUMS: - ret = db_build_query_group_albums(qp, &query); + query = db_build_query_group_albums(qp); break; case Q_GROUP_ARTISTS: - ret = db_build_query_group_artists(qp, &query); + query = db_build_query_group_artists(qp); break; case Q_GROUP_ITEMS: - ret = db_build_query_group_items(qp, &query); + query = db_build_query_group_items(qp); break; case Q_GROUP_DIRS: - ret = db_build_query_group_dirs(qp, &query); + query = db_build_query_group_dirs(qp); break; case Q_BROWSE_ALBUMS: - ret = db_build_query_browse(qp, "album", "album_sort", &query); + query = db_build_query_browse(qp, "album", "album_sort"); break; case Q_BROWSE_ARTISTS: - ret = db_build_query_browse(qp, "album_artist", "album_artist_sort", &query); + query = db_build_query_browse(qp, "album_artist", "album_artist_sort"); break; case Q_BROWSE_GENRES: - ret = db_build_query_browse(qp, "genre", "genre", &query); + query = db_build_query_browse(qp, "genre", "genre"); break; case Q_BROWSE_COMPOSERS: - ret = db_build_query_browse(qp, "composer", "composer_sort", &query); + query = db_build_query_browse(qp, "composer", "composer_sort"); break; case Q_BROWSE_YEARS: - ret = db_build_query_browse(qp, "year", "year", &query); + query = db_build_query_browse(qp, "year", "year"); break; case Q_BROWSE_DISCS: - ret = db_build_query_browse(qp, "disc", "disc", &query); + query = db_build_query_browse(qp, "disc", "disc"); break; case Q_BROWSE_TRACKS: - ret = db_build_query_browse(qp, "track", "track", &query); + query = db_build_query_browse(qp, "track", "track"); break; case Q_BROWSE_VPATH: - ret = db_build_query_browse(qp, "virtual_path", "virtual_path", &query); + query = db_build_query_browse(qp, "virtual_path", "virtual_path"); break; case Q_BROWSE_PATH: - ret = db_build_query_browse(qp, "path", "path", &query); + query = db_build_query_browse(qp, "path", "path"); break; case Q_COUNT_ITEMS: - ret = db_build_query_count_items(qp, &query); + query = db_build_query_count_items(qp); break; default: @@ -1606,7 +1361,7 @@ db_query_start(struct query_params *qp) return -1; } - if (ret < 0) + if (!query) return -1; DPRINTF(E_DBG, L_DB, "Starting query '%s'\n", query);