[db] Refactor db_build_query_* to reduce redundancy

This commit is contained in:
ejurgensen 2017-01-04 22:29:47 +01:00
parent ce998fb38a
commit b7c4256df4

747
src/db.c
View File

@ -76,6 +76,12 @@ struct col_type_map {
short type; short type;
}; };
struct query_clause {
char *where;
const char *order;
char *index;
};
/* This list must be kept in sync with /* This list must be kept in sync with
* - the order of the columns in the files table * - the order of the columns in the files table
* - the type and name of the fields in struct media_file_info * - the type and name of the fields in struct media_file_info
@ -827,7 +833,7 @@ db_purge_all(void)
} }
static int static int
db_get_one_int(char *query) db_get_one_int(const char *query)
{ {
sqlite3_stmt *stmt; sqlite3_stmt *stmt;
int ret; int ret;
@ -918,461 +924,290 @@ db_transaction_rollback(void)
} }
} }
static void
/* Queries */ db_free_query_clause(struct query_clause *qc)
static int
db_build_query_index_clause(char **i, struct query_params *qp)
{ {
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) switch (qp->idx_type)
{ {
case I_FIRST: case I_FIRST:
idx = sqlite3_mprintf("LIMIT %d", qp->limit); qc->index = sqlite3_mprintf("LIMIT %d", qp->limit);
break; break;
case I_LAST: 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; break;
case I_SUB: 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; break;
case I_NONE: case I_NONE:
return 0; qc->index = sqlite3_mprintf("");
break;
default:
DPRINTF(E_LOG, L_DB, "Unknown index type\n");
return -1;
} }
if (!idx) if (!qc->where || !qc->index)
{ goto error;
DPRINTF(E_LOG, L_DB, "Could not build index string; out of memory");
return -1;
}
*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 static char *
db_build_query_items(struct query_params *qp, char **q) db_build_query_check(struct query_params *qp, char *count, char *query)
{ {
char *query; if (!count || !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)
{ {
DPRINTF(E_LOG, L_DB, "Out of memory for count query string\n"); DPRINTF(E_LOG, L_DB, "Out of memory for query string\n");
goto failed;
return -1;
} }
qp->results = db_get_one_int(count); qp->results = db_get_one_int(count);
if (qp->results < 0)
goto failed;
sqlite3_free(count); sqlite3_free(count);
if (qp->results < 0) return query;
return -1;
/* Get index clause */ failed:
ret = db_build_query_index_clause(&idx, qp); sqlite3_free(count);
if (ret < 0) sqlite3_free(query);
return -1; return NULL;
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;
} }
static int static char *
db_build_query_pls(struct query_params *qp, char **q) db_build_query_items(struct query_params *qp)
{ {
char *query; struct query_clause *qc;
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;
char *count; 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 *query;
char *count;
char *filter;
char *idx;
const char *sort;
int ret;
if (qp->filter) qc = db_build_query_clause(qp);
filter = qp->filter; if (!qc)
else return NULL;
filter = "1 = 1";
count = sqlite3_mprintf("SELECT COUNT(*) FROM files f WHERE f.disabled = 0 AND %s AND %s;", filter, smartpl_query); count = sqlite3_mprintf("SELECT COUNT(*) FROM files f %s;", qc->where);
if (!count) query = sqlite3_mprintf("SELECT f.* FROM files f %s %s %s;", qc->where, qc->order, qc->index);
{
DPRINTF(E_LOG, L_DB, "Out of memory for count query string\n");
return -1;
}
qp->results = db_get_one_int(count); db_free_query_clause(qc);
sqlite3_free(count); return db_build_query_check(qp, count, query);
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;
} }
static int static char *
db_build_query_plitems(struct query_params *qp, char **q) 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; struct playlist_info *pli;
int ret; char *query;
if (qp->id <= 0) if (qp->id <= 0)
{ {
DPRINTF(E_LOG, L_DB, "No playlist id specified in playlist items query\n"); DPRINTF(E_LOG, L_DB, "No playlist id specified in playlist items query\n");
return -1; return NULL;
} }
pli = db_pl_fetch_byid(qp->id); pli = db_pl_fetch_byid(qp->id);
if (!pli) if (!pli)
return -1; return NULL;
switch (pli->type) switch (pli->type)
{ {
case PL_SPECIAL: case PL_SPECIAL:
case PL_SMART: case PL_SMART:
ret = db_build_query_plitems_smart(qp, pli->query, q); query = db_build_query_plitems_smart(qp, pli->query);
break; break;
case PL_PLAIN: case PL_PLAIN:
case PL_FOLDER: case PL_FOLDER:
ret = db_build_query_plitems_plain(qp, q); query = db_build_query_plitems_plain(qp);
break; break;
default: default:
DPRINTF(E_LOG, L_DB, "Unknown playlist type %d in playlist items query\n", pli->type); DPRINTF(E_LOG, L_DB, "Unknown playlist type %d in playlist items query\n", pli->type);
ret = -1; query = NULL;
break; break;
} }
free_pli(pli, 0); free_pli(pli, 0);
return ret; return query;
} }
static int static char *
db_build_query_group_albums(struct query_params *qp, char **q) db_build_query_group_albums(struct query_params *qp)
{ {
char *query; struct query_clause *qc;
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;
char *count; 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; 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); gt = db_group_type_bypersistentid(qp->persistentid);
switch (gt) switch (gt)
{ {
case G_ALBUMS: case G_ALBUMS:
count = sqlite3_mprintf("SELECT COUNT(*) FROM files f" count = sqlite3_mprintf("SELECT COUNT(*) FROM files f %s AND f.songalbumid = %" PRIi64 ";", qc->where, qp->persistentid);
" WHERE f.songalbumid = %" PRIi64 " AND f.disabled = 0;", 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; break;
case G_ARTISTS: case G_ARTISTS:
count = sqlite3_mprintf("SELECT COUNT(*) FROM files f" count = sqlite3_mprintf("SELECT COUNT(*) FROM files f %s AND f.songartistid = %" PRIi64 ";", qc->where, qp->persistentid);
" WHERE f.songartistid = %" PRIi64 " AND f.disabled = 0;", 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; break;
default: default:
DPRINTF(E_LOG, L_DB, "Unsupported group type %d for group id %" PRIi64 "\n", gt, qp->persistentid); 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) db_free_query_clause(qc);
{
DPRINTF(E_LOG, L_DB, "Out of memory for count query string\n");
return -1; return db_build_query_check(qp, count, query);
}
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;
} }
static int static char *
db_build_query_group_dirs(struct query_params *qp, char **q) db_build_query_group_dirs(struct query_params *qp)
{ {
char *query;
char *count;
enum group_type gt; 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); 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: case G_ALBUMS:
count = sqlite3_mprintf("SELECT COUNT(DISTINCT(SUBSTR(f.path, 1, LENGTH(f.path) - LENGTH(f.fname) - 1)))" count = sqlite3_mprintf("SELECT COUNT(DISTINCT(SUBSTR(f.path, 1, LENGTH(f.path) - LENGTH(f.fname) - 1)))"
" FROM files f" " FROM files f %s AND f.songalbumid = %" PRIi64 ";", qc->where, qp->persistentid);
" WHERE f.songalbumid = %" PRIi64 " AND f.disabled = 0;", 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; break;
case G_ARTISTS: case G_ARTISTS:
count = sqlite3_mprintf("SELECT COUNT(DISTINCT(SUBSTR(f.path, 1, LENGTH(f.path) - LENGTH(f.fname) - 1)))" count = sqlite3_mprintf("SELECT COUNT(DISTINCT(SUBSTR(f.path, 1, LENGTH(f.path) - LENGTH(f.fname) - 1)))"
" FROM files f" " FROM files f %s AND f.songartistid = %" PRIi64 ";", qc->where, qp->persistentid);
" WHERE f.songartistid = %" PRIi64 " AND f.disabled = 0;", 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; break;
default: default:
DPRINTF(E_LOG, L_DB, "Unsupported group type %d for group id %" PRIi64 "\n", gt, qp->persistentid); 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) db_free_query_clause(qc);
{
DPRINTF(E_LOG, L_DB, "Out of memory for count query string\n");
return -1; return db_build_query_check(qp, count, query);
}
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;
} }
static int static char *
db_build_query_browse(struct query_params *qp, const char *field, const char *group_field, char **q) db_build_query_browse(struct query_params *qp, const char *field, const char *group_field)
{ {
char *query; struct query_clause *qc;
char *count; char *count;
char *idx; char *query;
const char *sort;
int ret;
if (qp->filter) qc = db_build_query_clause(qp);
count = sqlite3_mprintf("SELECT COUNT(DISTINCT f.%s) FROM files f WHERE f.disabled = 0 AND f.%s != '' AND %s;", if (!qc)
field, field, qp->filter); return NULL;
else
count = sqlite3_mprintf("SELECT COUNT(DISTINCT f.%s) FROM files f WHERE f.disabled = 0 AND f.%s != '';",
field, field);
if (!count) 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);
DPRINTF(E_LOG, L_DB, "Out of memory for count query string\n");
return -1; db_free_query_clause(qc);
}
qp->results = db_get_one_int(count); return db_build_query_check(qp, count, query);
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;
} }
static int static char *
db_build_query_count_items(struct query_params *qp, char **q) db_build_query_count_items(struct query_params *qp)
{ {
struct query_clause *qc;
char *query; char *query;
qc = db_build_query_clause(qp);
if (!qc)
return NULL;
qp->results = 1; qp->results = 1;
if (qp->filter) query = sqlite3_mprintf("SELECT COUNT(*), SUM(song_length) FROM files f %s;", qc->where);
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;");
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");
return -1;
}
*q = query; db_free_query_clause(qc);
return 0; return query;
} }
int int
@ -1534,71 +1289,71 @@ db_query_start(struct query_params *qp)
switch (qp->type) switch (qp->type)
{ {
case Q_ITEMS: case Q_ITEMS:
ret = db_build_query_items(qp, &query); query = db_build_query_items(qp);
break; break;
case Q_PL: case Q_PL:
ret = db_build_query_pls(qp, &query); query = db_build_query_pls(qp);
break; break;
case Q_PLITEMS: case Q_PLITEMS:
ret = db_build_query_plitems(qp, &query); query = db_build_query_plitems(qp);
break; break;
case Q_GROUP_ALBUMS: case Q_GROUP_ALBUMS:
ret = db_build_query_group_albums(qp, &query); query = db_build_query_group_albums(qp);
break; break;
case Q_GROUP_ARTISTS: case Q_GROUP_ARTISTS:
ret = db_build_query_group_artists(qp, &query); query = db_build_query_group_artists(qp);
break; break;
case Q_GROUP_ITEMS: case Q_GROUP_ITEMS:
ret = db_build_query_group_items(qp, &query); query = db_build_query_group_items(qp);
break; break;
case Q_GROUP_DIRS: case Q_GROUP_DIRS:
ret = db_build_query_group_dirs(qp, &query); query = db_build_query_group_dirs(qp);
break; break;
case Q_BROWSE_ALBUMS: case Q_BROWSE_ALBUMS:
ret = db_build_query_browse(qp, "album", "album_sort", &query); query = db_build_query_browse(qp, "album", "album_sort");
break; break;
case Q_BROWSE_ARTISTS: 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; break;
case Q_BROWSE_GENRES: case Q_BROWSE_GENRES:
ret = db_build_query_browse(qp, "genre", "genre", &query); query = db_build_query_browse(qp, "genre", "genre");
break; break;
case Q_BROWSE_COMPOSERS: case Q_BROWSE_COMPOSERS:
ret = db_build_query_browse(qp, "composer", "composer_sort", &query); query = db_build_query_browse(qp, "composer", "composer_sort");
break; break;
case Q_BROWSE_YEARS: case Q_BROWSE_YEARS:
ret = db_build_query_browse(qp, "year", "year", &query); query = db_build_query_browse(qp, "year", "year");
break; break;
case Q_BROWSE_DISCS: case Q_BROWSE_DISCS:
ret = db_build_query_browse(qp, "disc", "disc", &query); query = db_build_query_browse(qp, "disc", "disc");
break; break;
case Q_BROWSE_TRACKS: case Q_BROWSE_TRACKS:
ret = db_build_query_browse(qp, "track", "track", &query); query = db_build_query_browse(qp, "track", "track");
break; break;
case Q_BROWSE_VPATH: 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; break;
case Q_BROWSE_PATH: case Q_BROWSE_PATH:
ret = db_build_query_browse(qp, "path", "path", &query); query = db_build_query_browse(qp, "path", "path");
break; break;
case Q_COUNT_ITEMS: case Q_COUNT_ITEMS:
ret = db_build_query_count_items(qp, &query); query = db_build_query_count_items(qp);
break; break;
default: default:
@ -1606,7 +1361,7 @@ db_query_start(struct query_params *qp)
return -1; return -1;
} }
if (ret < 0) if (!query)
return -1; return -1;
DPRINTF(E_DBG, L_DB, "Starting query '%s'\n", query); DPRINTF(E_DBG, L_DB, "Starting query '%s'\n", query);