Revert "Merge branch 'db' of git://github.com/chme/forked-daapd into chme-db"

This reverts commit b8d5e32160, reversing
changes made to 5a02f926e3.
This commit is contained in:
ejurgensen 2015-01-08 22:40:47 +01:00
parent b8d5e32160
commit ad48ccb804
5 changed files with 159 additions and 499 deletions

View File

@ -69,7 +69,11 @@ expr returns [ pANTLR3_STRING result, int valid ]
@init { $result = NULL; $valid = 1; } @init { $result = NULL; $valid = 1; }
: ^(OPAND a = expr b = expr) : ^(OPAND a = expr b = expr)
{ {
if ($a.valid && $b.valid) if (!$a.valid || !$b.valid)
{
$valid = 0;
}
else
{ {
$result = $a.result->factory->newRaw($a.result->factory); $result = $a.result->factory->newRaw($a.result->factory);
$result->append8($result, "("); $result->append8($result, "(");
@ -78,24 +82,14 @@ expr returns [ pANTLR3_STRING result, int valid ]
$result->appendS($result, $b.result); $result->appendS($result, $b.result);
$result->append8($result, ")"); $result->append8($result, ")");
} }
else if ($a.valid)
{
$result = $a.result->factory->newRaw($a.result->factory);
$result->appendS($result, $a.result);
}
else if ($b.valid)
{
$result = $b.result->factory->newRaw($b.result->factory);
$result->appendS($result, $b.result);
}
else
{
$valid = 0;
}
} }
| ^(OPOR a = expr b = expr) | ^(OPOR a = expr b = expr)
{ {
if ($a.valid && $b.valid) if (!$a.valid || !$b.valid)
{
$valid = 0;
}
else
{ {
$result = $a.result->factory->newRaw($a.result->factory); $result = $a.result->factory->newRaw($a.result->factory);
$result->append8($result, "("); $result->append8($result, "(");
@ -104,20 +98,6 @@ expr returns [ pANTLR3_STRING result, int valid ]
$result->appendS($result, $b.result); $result->appendS($result, $b.result);
$result->append8($result, ")"); $result->append8($result, ")");
} }
else if ($a.valid)
{
$result = $a.result->factory->newRaw($a.result->factory);
$result->appendS($result, $a.result);
}
else if ($b.valid)
{
$result = $b.result->factory->newRaw($b.result->factory);
$result->appendS($result, $b.result);
}
else
{
$valid = 0;
}
} }
| STR | STR
{ {
@ -214,22 +194,13 @@ expr returns [ pANTLR3_STRING result, int valid ]
goto STR_result_valid_0; /* ABORT */ goto STR_result_valid_0; /* ABORT */
} }
/* No need to exclude empty artist and album, as forked-daapd makes sure there always exists an artist/album. */
if (neg_op && op == ':'
&& (strcmp((char *)field, "daap.songalbumartist") == 0
|| strcmp((char *)field, "daap.songartist") == 0
|| strcmp((char *)field, "daap.songalbum") == 0))
{
DPRINTF(E_DBG, L_DAAP, "Ignoring clause '\%s\%s\%c'\n", field, (neg_op) ? "!" : "", op);
$valid = 0;
goto STR_result_valid_0;
}
/* Need to check against NULL too */ /* Need to check against NULL too */
if (op == ':') if (op == ':')
$result->append8($result, "("); $result->append8($result, "(");
} }
$result->append8($result, dqfm->db_col);
/* Int field: check integer conversion */ /* Int field: check integer conversion */
if (dqfm->as_int) if (dqfm->as_int)
{ {
@ -254,16 +225,6 @@ expr returns [ pANTLR3_STRING result, int valid ]
} }
*end = '\0'; /* Cut out potential garbage - we're being kind */ *end = '\0'; /* Cut out potential garbage - we're being kind */
/* forked-daapd only has media_kind = 1 for music - so remove media_kind = 32 to imporve select query performance. */
if (llval == 32
&& (strcmp((char *)field, "com.apple.itunes.mediakind") == 0
|| strcmp((char *)field, "com.apple.itunes.extended-media-kind") == 0))
{
DPRINTF(E_DBG, L_DAAP, "Ignoring clause '\%s\%s\%c\%s'\n", field, (neg_op) ? "!" : "", op, val);
$valid = 0;
goto STR_result_valid_0;
}
} }
/* String field: escape string, check for '*' */ /* String field: escape string, check for '*' */
else else
@ -297,8 +258,6 @@ expr returns [ pANTLR3_STRING result, int valid ]
val[strlen((char *)val) - 1] = '\%'; val[strlen((char *)val) - 1] = '\%';
} }
} }
$result->append8($result, dqfm->db_col);
switch(op) switch(op)
{ {

View File

@ -1303,12 +1303,20 @@ artwork_get_item(int id, int max_w, int max_h, struct evbuffer *evbuf)
int int
artwork_get_group(int id, int max_w, int max_h, struct evbuffer *evbuf) artwork_get_group(int id, int max_w, int max_h, struct evbuffer *evbuf)
{ {
int64_t persistentid;
int format; int format;
DPRINTF(E_DBG, L_ART, "Artwork request for group %d\n", id); DPRINTF(E_DBG, L_ART, "Artwork request for group %d\n", id);
/* Get the persistent id for the given group id */
if (db_group_persistentid_byid(id, &persistentid) < 0)
{
DPRINTF(E_LOG, L_ART, "Error fetching persistent id for group id %d\n", id);
return -1;
}
/* Load artwork image for the persistent id */ /* Load artwork image for the persistent id */
format = artwork_get_group_persistentid(id, max_w, max_h, evbuf); format = artwork_get_group_persistentid(persistentid, max_w, max_h, evbuf);
if (format <= 0) if (format <= 0)
{ {
DPRINTF(E_DBG, L_ART, "No artwork found for group %d\n", id); DPRINTF(E_DBG, L_ART, "No artwork found for group %d\n", id);

561
src/db.c
View File

@ -742,14 +742,12 @@ db_purge_cruft(time_t ref)
char *errmsg; char *errmsg;
int i; int i;
int ret; int ret;
char *queries[5] = { NULL, NULL, NULL, NULL, NULL }; char *queries[3] = { NULL, NULL, NULL };
char *queries_tmpl[5] = char *queries_tmpl[3] =
{ {
"DELETE FROM playlistitems WHERE playlistid IN (SELECT id FROM playlists p WHERE p.type <> 1 AND p.db_timestamp < %" PRIi64 ");", "DELETE FROM playlistitems WHERE playlistid IN (SELECT id FROM playlists p WHERE p.type <> 1 AND p.db_timestamp < %" PRIi64 ");",
"DELETE FROM playlists WHERE type <> 1 AND db_timestamp < %" PRIi64 ";", "DELETE FROM playlists WHERE type <> 1 AND db_timestamp < %" PRIi64 ";",
"DELETE FROM files WHERE db_timestamp < %" PRIi64 ";", "DELETE FROM files WHERE db_timestamp < %" PRIi64 ";"
"DELETE FROM groups WHERE type = 1 AND id NOT IN (SELECT songalbumid FROM files);",
"DELETE FROM groups WHERE type = 2 AND id NOT IN (SELECT songartistid FROM files);"
}; };
if (sizeof(queries) != sizeof(queries_tmpl)) if (sizeof(queries) != sizeof(queries_tmpl))
@ -760,11 +758,7 @@ db_purge_cruft(time_t ref)
for (i = 0; i < (sizeof(queries_tmpl) / sizeof(queries_tmpl[0])); i++) for (i = 0; i < (sizeof(queries_tmpl) / sizeof(queries_tmpl[0])); i++)
{ {
if (i < 3) queries[i] = sqlite3_mprintf(queries_tmpl[i], (int64_t)ref);
queries[i] = sqlite3_mprintf(queries_tmpl[i], (int64_t)ref);
else
queries[i] = sqlite3_mprintf(queries_tmpl[i]);
if (!queries[i]) if (!queries[i])
{ {
DPRINTF(E_LOG, L_DB, "Out of memory for query string\n"); DPRINTF(E_LOG, L_DB, "Out of memory for query string\n");
@ -1203,13 +1197,13 @@ db_build_query_group_albums(struct query_params *qp, char **q)
sort = sort_clause[qp->sort]; sort = sort_clause[qp->sort];
if (idx && qp->filter) if (idx && qp->filter)
query = sqlite3_mprintf("SELECT f.songalbumid, f.songalbumid, f.album, f.album_sort, COUNT(f.id), 1, f.album_artist, f.songartistid FROM files f WHERE f.disabled = 0 AND %s GROUP BY f.songalbumid %s %s;", qp->filter, sort, idx); query = sqlite3_mprintf("SELECT g.id, g.persistentid, f.album, f.album_sort, COUNT(f.id), 1, f.album_artist, f.songartistid FROM files f, groups g WHERE f.songalbumid = g.persistentid AND g.type = %d AND f.disabled = 0 AND %s GROUP BY f.album, g.name %s %s;", G_ALBUMS, qp->filter, sort, idx);
else if (idx) else if (idx)
query = sqlite3_mprintf("SELECT f.songalbumid, f.songalbumid, f.album, f.album_sort, COUNT(f.id), 1, f.album_artist, f.songartistid FROM files f WHERE f.disabled = 0 GROUP BY f.songalbumid %s %s;", sort, idx); query = sqlite3_mprintf("SELECT g.id, g.persistentid, f.album, f.album_sort, COUNT(f.id), 1, f.album_artist, f.songartistid FROM files f, groups g WHERE f.songalbumid = g.persistentid AND g.type = %d AND f.disabled = 0 GROUP BY f.album, g.name %s %s;", G_ALBUMS, sort, idx);
else if (qp->filter) else if (qp->filter)
query = sqlite3_mprintf("SELECT f.songalbumid, f.songalbumid, f.album, f.album_sort, COUNT(f.id), 1, f.album_artist, f.songartistid FROM files f WHERE f.disabled = 0 AND %s GROUP BY f.songalbumid %s;", qp->filter, sort); query = sqlite3_mprintf("SELECT g.id, g.persistentid, f.album, f.album_sort, COUNT(f.id), 1, f.album_artist, f.songartistid FROM files f, groups g WHERE f.songalbumid = g.persistentid AND g.type = %d AND f.disabled = 0 AND %s GROUP BY f.album, g.name %s;", G_ALBUMS, qp->filter, sort);
else else
query = sqlite3_mprintf("SELECT f.songalbumid, f.songalbumid, f.album, f.album_sort, COUNT(f.id), 1, f.album_artist, f.songartistid FROM files f WHERE f.disabled = 0 GROUP BY f.songalbumid %s;", sort); query = sqlite3_mprintf("SELECT g.id, g.persistentid, f.album, f.album_sort, COUNT(f.id), 1, f.album_artist, f.songartistid FROM files f, groups g WHERE f.songalbumid = g.persistentid AND g.type = %d AND f.disabled = 0 GROUP BY f.album, g.name %s;", G_ALBUMS, sort);
if (!query) if (!query)
{ {
@ -1242,13 +1236,13 @@ db_build_query_group_artists(struct query_params *qp, char **q)
sort = sort_clause[qp->sort]; sort = sort_clause[qp->sort];
if (idx && qp->filter) if (idx && qp->filter)
query = sqlite3_mprintf("SELECT f.songartistid, f.songartistid, f.album_artist, f.album_artist_sort, COUNT(f.id), COUNT(DISTINCT f.songalbumid), f.album_artist, f.songartistid FROM files f WHERE f.disabled = 0 AND %s GROUP BY f.songartistid %s %s;", qp->filter, sort, 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 FROM files f, groups g WHERE f.songartistid = g.persistentid AND g.type = %d AND f.disabled = 0 AND %s GROUP BY f.album_artist, g.name %s %s;", G_ARTISTS, qp->filter, sort, idx);
else if (idx) else if (idx)
query = sqlite3_mprintf("SELECT f.songartistid, f.songartistid, f.album_artist, f.album_artist_sort, COUNT(f.id), COUNT(DISTINCT f.songalbumid), f.album_artist, f.songartistid FROM files f WHERE f.disabled = 0 GROUP BY f.songartistid %s %s;", sort, 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 FROM files f, groups g WHERE f.songartistid = g.persistentid AND g.type = %d AND f.disabled = 0 GROUP BY f.album_artist, g.name %s %s;", G_ARTISTS, sort, idx);
else if (qp->filter) else if (qp->filter)
query = sqlite3_mprintf("SELECT f.songartistid, f.songartistid, f.album_artist, f.album_artist_sort, COUNT(f.id), COUNT(DISTINCT f.songalbumid), f.album_artist, f.songartistid FROM files f WHERE f.disabled = 0 AND %s GROUP BY f.songartistid %s;", qp->filter, sort); 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 FROM files f, groups g WHERE f.songartistid = g.persistentid AND g.type = %d AND f.disabled = 0 AND %s GROUP BY f.album_artist, g.name %s;", G_ARTISTS, qp->filter, sort);
else else
query = sqlite3_mprintf("SELECT f.songartistid, f.songartistid, f.album_artist, f.album_artist_sort, COUNT(f.id), COUNT(DISTINCT f.songalbumid), f.album_artist, f.songartistid FROM files f WHERE f.disabled = 0 GROUP BY f.songartistid %s;", sort); 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 FROM files f, groups g WHERE f.songartistid = g.persistentid AND g.type = %d AND f.disabled = 0 GROUP BY f.album_artist, g.name %s;", G_ARTISTS, sort);
if (!query) if (!query)
{ {
@ -1450,17 +1444,17 @@ db_build_query_browse(struct query_params *qp, char *field, char *sort_field, ch
} }
if (idx && qp->filter) if (idx && qp->filter)
query = sqlite3_mprintf("SELECT f.%s, f.%s FROM files f WHERE f.disabled = 0 AND f.%s != ''" query = sqlite3_mprintf("SELECT DISTINCT f.%s, f.%s FROM files f WHERE f.disabled = 0 AND f.%s != ''"
" AND %s GROUP BY f.%s %s %s;", field, sort_field, field, qp->filter, field, sort, idx); " AND %s %s %s;", field, sort_field, field, qp->filter, sort, idx);
else if (idx) else if (idx)
query = sqlite3_mprintf("SELECT f.%s, f.%s FROM files f WHERE f.disabled = 0 AND f.%s != ''" query = sqlite3_mprintf("SELECT DISTINCT f.%s, f.%s FROM files f WHERE f.disabled = 0 AND f.%s != ''"
" GROUP BY f.%s %s %s;", field, sort_field, field, field, sort, idx); " %s %s;", field, sort_field, field, sort, idx);
else if (qp->filter) else if (qp->filter)
query = sqlite3_mprintf("SELECT f.%s, f.%s FROM files f WHERE f.disabled = 0 AND f.%s != ''" query = sqlite3_mprintf("SELECT DISTINCT f.%s, f.%s FROM files f WHERE f.disabled = 0 AND f.%s != ''"
" AND %s GROUP BY f.%s %s;", field, sort_field, field, qp->filter, field, sort); " AND %s %s;", field, sort_field, field, qp->filter, sort);
else else
query = sqlite3_mprintf("SELECT f.%s, f.%s FROM files f WHERE f.disabled = 0 AND f.%s != '' GROUP BY f.%s %s", query = sqlite3_mprintf("SELECT DISTINCT f.%s, f.%s FROM files f WHERE f.disabled = 0 AND f.%s != '' %s",
field, sort_field, field, field, sort); field, sort_field, field, sort);
free(sort); free(sort);
@ -2365,101 +2359,6 @@ db_file_fetch_byid(int id)
#undef Q_TMPL #undef Q_TMPL
} }
static int
db_group_get_id(enum group_type type, const char *artist, const char *album, uint32_t *id)
{
#define Q_TMPL "SELECT id FROM groups WHERE type = %d AND name = LOWER(TRIM(%Q)) || '==' || LOWER(TRIM(%Q));"
sqlite3_stmt *stmt;
char *query;
int ret;
// Select artist and album from groups
query = sqlite3_mprintf(Q_TMPL, type, artist, (album ? album : ""));
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, strlen(query) + 1, &stmt, NULL);
if (ret != SQLITE_OK)
{
DPRINTF(E_LOG, L_DB, "Could not prepare statement: %s\n", sqlite3_errmsg(hdl));
sqlite3_free(query);
return -1;
}
ret = db_blocking_step(stmt);
if (ret == SQLITE_DONE)
{
DPRINTF(E_DBG, L_DB, "No results\n");
sqlite3_finalize(stmt);
sqlite3_free(query);
*id = 0;
return 0;
}
else if (ret == SQLITE_ROW)
{
*id = sqlite3_column_int(stmt, 0);
sqlite3_finalize(stmt);
sqlite3_free(query);
return 0;
}
DPRINTF(E_LOG, L_DB, "Could not step: %s\n", sqlite3_errmsg(hdl));
sqlite3_finalize(stmt);
sqlite3_free(query);
return -1;
#undef Q_TMPL
}
static int
db_group_add(enum group_type type, const char *artist, const char *album, uint32_t *id)
{
#define Q_TMPL "INSERT OR REPLACE INTO groups (type, name) VALUES (%d, LOWER(TRIM(%Q)) || '==' || LOWER(TRIM(%Q)));"
char *query;
char *errmsg;
int ret;
// Select artist and album from groups
query = sqlite3_mprintf(Q_TMPL, type, artist, (album ? album : ""));
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_exec(query, &errmsg);
if (ret != SQLITE_OK)
{
DPRINTF(E_LOG, L_DB, "Error '%s' while runnning '%s'\n", errmsg, query);
sqlite3_free(errmsg);
sqlite3_free(query);
*id = 0;
return -1;
}
sqlite3_free(errmsg);
sqlite3_free(query);
*id = sqlite3_last_insert_rowid(hdl);
return 0;
#undef Q_TMPL
}
int int
db_file_add(struct media_file_info *mfi) db_file_add(struct media_file_info *mfi)
{ {
@ -2478,13 +2377,11 @@ db_file_add(struct media_file_info *mfi)
" %Q, %" PRIi64 ", %" PRIi64 ", %" PRIi64 ", %" PRIi64 ", %d, %" PRIi64 "," \ " %Q, %" PRIi64 ", %" PRIi64 ", %" PRIi64 ", %" PRIi64 ", %d, %" PRIi64 "," \
" %Q, %d, %d, %d, %d, TRIM(%Q)," \ " %Q, %d, %d, %d, %d, TRIM(%Q)," \
" %d, TRIM(%Q), TRIM(%Q), TRIM(%Q), %d, %d," \ " %d, TRIM(%Q), TRIM(%Q), TRIM(%Q), %d, %d," \
" %" PRIi64 ", %" PRIi64 ", " \ " daap_songalbumid(LOWER(TRIM(%Q)), ''), daap_songalbumid(LOWER(TRIM(%Q)), LOWER(TRIM(%Q))), " \
" TRIM(%Q), TRIM(%Q), TRIM(%Q), TRIM(%Q), TRIM(%Q));" " TRIM(%Q), TRIM(%Q), TRIM(%Q), TRIM(%Q), TRIM(%Q));"
char *query; char *query;
char *errmsg; char *errmsg;
uint32_t albumid;
uint32_t artistid;
int ret; int ret;
@ -2494,43 +2391,6 @@ db_file_add(struct media_file_info *mfi)
return -1; return -1;
} }
// Select artist and album from groups
ret = db_group_get_id(G_ALBUMS, mfi->album_artist, mfi->album, &albumid);
if (ret < 0)
{
DPRINTF(E_LOG, L_DB, "Could not get albumid for artist '%s' album '%s'\n", mfi->album_artist, mfi->album);
return -1;
}
if (albumid == 0)
{
ret = db_group_add(G_ALBUMS, mfi->album_artist, mfi->album, &albumid);
if (ret < 0)
{
DPRINTF(E_LOG, L_DB, "Could not add artist '%s' album '%s'\n", mfi->album_artist, mfi->album);
return -1;
}
}
ret = db_group_get_id(G_ARTISTS, mfi->album_artist, NULL, &artistid);
if (ret < 0)
{
DPRINTF(E_LOG, L_DB, "Could not get artistid for artist '%s'\n", mfi->album_artist);
return -1;
}
if (artistid == 0)
{
ret = db_group_add(G_ARTISTS, mfi->album_artist, NULL, &artistid);
if (ret < 0)
{
DPRINTF(E_LOG, L_DB, "Could not add artist '%s'\n", mfi->album_artist);
return -1;
}
}
mfi->songalbumid = albumid;
mfi->songartistid = artistid;
mfi->db_timestamp = (uint64_t)time(NULL); mfi->db_timestamp = (uint64_t)time(NULL);
mfi->time_added = mfi->db_timestamp; mfi->time_added = mfi->db_timestamp;
@ -2550,8 +2410,7 @@ db_file_add(struct media_file_info *mfi)
mfi->contentrating, mfi->bits_per_sample, mfi->album_artist, mfi->contentrating, mfi->bits_per_sample, mfi->album_artist,
mfi->media_kind, mfi->tv_series_name, mfi->tv_episode_num_str, mfi->media_kind, mfi->tv_series_name, mfi->tv_episode_num_str,
mfi->tv_network_name, mfi->tv_episode_sort, mfi->tv_season_num, mfi->tv_network_name, mfi->tv_episode_sort, mfi->tv_season_num,
mfi->songartistid, mfi->songalbumid, mfi->album_artist, mfi->album_artist, mfi->album, mfi->title_sort, mfi->artist_sort, mfi->album_sort,
mfi->title_sort, mfi->artist_sort, mfi->album_sort,
mfi->composer_sort, mfi->album_artist_sort); mfi->composer_sort, mfi->album_artist_sort);
if (!query) if (!query)
@ -2595,15 +2454,11 @@ db_file_update(struct media_file_info *mfi)
" bits_per_sample = %d, album_artist = TRIM(%Q)," \ " bits_per_sample = %d, album_artist = TRIM(%Q)," \
" media_kind = %d, tv_series_name = TRIM(%Q), tv_episode_num_str = TRIM(%Q)," \ " media_kind = %d, tv_series_name = TRIM(%Q), tv_episode_num_str = TRIM(%Q)," \
" tv_network_name = TRIM(%Q), tv_episode_sort = %d, tv_season_num = %d," \ " tv_network_name = TRIM(%Q), tv_episode_sort = %d, tv_season_num = %d," \
" songartistid = %" PRIi64 ", songalbumid = %" PRIi64 "," \ " songartistid = daap_songalbumid(LOWER(TRIM(%Q)), ''), songalbumid = daap_songalbumid(LOWER(TRIM(%Q)), LOWER(TRIM(%Q)))," \
" title_sort = TRIM(%Q), artist_sort = TRIM(%Q), album_sort = TRIM(%Q), composer_sort = TRIM(%Q), album_artist_sort = TRIM(%Q)" \ " title_sort = TRIM(%Q), artist_sort = TRIM(%Q), album_sort = TRIM(%Q), composer_sort = TRIM(%Q), album_artist_sort = TRIM(%Q)" \
" WHERE id = %d;" " WHERE id = %d;"
// struct media_file_info *oldmfi;
char *query; char *query;
char *errmsg; char *errmsg;
uint32_t albumid;
uint32_t artistid;
int ret; int ret;
if (mfi->id == 0) if (mfi->id == 0)
@ -2612,55 +2467,6 @@ db_file_update(struct media_file_info *mfi)
return -1; return -1;
} }
/*
oldmfi = db_file_fetch_byid(mfi->id);
if (!oldmfi)
{
DPRINTF(E_WARN, L_DB, "File with id '%d' does not exist\n", mfi->id);
return -1;
}
free_mfi(oldmfi, 0);
*/
ret = db_group_get_id(G_ALBUMS, mfi->album_artist, mfi->album, &albumid);
if (ret < 0)
{
DPRINTF(E_LOG, L_DB, "Could not get albumid for artist '%s' album '%s'\n", mfi->album_artist, mfi->album);
return -1;
}
if (albumid == 0)
{
ret = db_group_add(G_ALBUMS, mfi->album_artist, mfi->album, &albumid);
if (ret < 0)
{
DPRINTF(E_LOG, L_DB, "Could not add artist '%s' album '%s'\n", mfi->album_artist, mfi->album);
return -1;
}
}
ret = db_group_get_id(G_ARTISTS, mfi->album_artist, NULL, &artistid);
if (ret < 0)
{
DPRINTF(E_LOG, L_DB, "Could not get artistid for artist '%s'\n", mfi->album_artist);
return -1;
}
if (artistid == 0)
{
ret = db_group_add(G_ARTISTS, mfi->album_artist, NULL, &artistid);
if (ret < 0)
{
DPRINTF(E_LOG, L_DB, "Could not add artist '%s'\n", mfi->album_artist);
return -1;
}
}
mfi->songalbumid = albumid;
mfi->songartistid = artistid;
mfi->db_timestamp = (uint64_t)time(NULL); mfi->db_timestamp = (uint64_t)time(NULL);
if (mfi->time_modified == 0) if (mfi->time_modified == 0)
@ -2678,7 +2484,7 @@ db_file_update(struct media_file_info *mfi)
mfi->bits_per_sample, mfi->album_artist, mfi->bits_per_sample, mfi->album_artist,
mfi->media_kind, mfi->tv_series_name, mfi->tv_episode_num_str, mfi->media_kind, mfi->tv_series_name, mfi->tv_episode_num_str,
mfi->tv_network_name, mfi->tv_episode_sort, mfi->tv_season_num, mfi->tv_network_name, mfi->tv_episode_sort, mfi->tv_season_num,
mfi->songartistid, mfi->songalbumid, mfi->album_artist, mfi->album_artist, mfi->album,
mfi->title_sort, mfi->artist_sort, mfi->album_sort, mfi->title_sort, mfi->artist_sort, mfi->album_sort,
mfi->composer_sort, mfi->album_artist_sort, mfi->composer_sort, mfi->album_artist_sort,
mfi->id); mfi->id);
@ -3303,11 +3109,16 @@ db_pl_enable_bycookie(uint32_t cookie, char *path)
/* Groups */ /* Groups */
int
db_groups_clear(void)
{
return db_query_run("DELETE FROM groups;", 0, 1);
}
static enum group_type static enum group_type
db_group_type_bypersistentid(int64_t persistentid) db_group_type_bypersistentid(int64_t persistentid)
{ {
#define Q_TMPL "SELECT g.type FROM groups g WHERE g.id = %" PRIi64 ";" #define Q_TMPL "SELECT g.type FROM groups g WHERE g.persistentid = %" PRIi64 ";"
char *query; char *query;
sqlite3_stmt *stmt; sqlite3_stmt *stmt;
int ret; int ret;
@ -3359,6 +3170,61 @@ db_group_type_bypersistentid(int64_t persistentid)
#undef Q_TMPL #undef Q_TMPL
} }
int
db_group_persistentid_byid(int id, int64_t *persistentid)
{
#define Q_TMPL "SELECT g.persistentid FROM groups g WHERE g.id = %d;"
char *query;
sqlite3_stmt *stmt;
int ret;
query = sqlite3_mprintf(Q_TMPL, id);
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);
if (ret != SQLITE_OK)
{
DPRINTF(E_LOG, L_DB, "Could not prepare statement: %s\n", sqlite3_errmsg(hdl));
sqlite3_free(query);
return -1;
}
ret = db_blocking_step(stmt);
if (ret != SQLITE_ROW)
{
if (ret == SQLITE_DONE)
DPRINTF(E_DBG, L_DB, "No results\n");
else
DPRINTF(E_LOG, L_DB, "Could not step: %s\n", sqlite3_errmsg(hdl));
sqlite3_finalize(stmt);
sqlite3_free(query);
return -1;
}
*persistentid = sqlite3_column_int64(stmt, 0);
#ifdef DB_PROFILE
while (db_blocking_step(stmt) == SQLITE_ROW)
; /* EMPTY */
#endif
sqlite3_finalize(stmt);
sqlite3_free(query);
return 0;
#undef Q_TMPL
}
/* Remotes */ /* Remotes */
static int static int
@ -4437,7 +4303,8 @@ db_perthread_deinit(void)
" id INTEGER PRIMARY KEY NOT NULL," \ " id INTEGER PRIMARY KEY NOT NULL," \
" type INTEGER NOT NULL," \ " type INTEGER NOT NULL," \
" name VARCHAR(1024) NOT NULL COLLATE DAAP," \ " name VARCHAR(1024) NOT NULL COLLATE DAAP," \
"CONSTRAINT groups_type_unique_name UNIQUE (type, name)" \ " persistentid INTEGER NOT NULL," \
"CONSTRAINT groups_type_unique_persistentid UNIQUE (type, persistentid)" \
");" ");"
#define T_PAIRINGS \ #define T_PAIRINGS \
@ -4468,7 +4335,7 @@ db_perthread_deinit(void)
"CREATE INDEX IF NOT EXISTS idx_sari ON files(songartistid);" "CREATE INDEX IF NOT EXISTS idx_sari ON files(songartistid);"
#define I_SONGALBUMID \ #define I_SONGALBUMID \
"CREATE INDEX IF NOT EXISTS idx_sali ON files(songalbumid, disabled, media_kind, album_sort, disc, track);" "CREATE INDEX IF NOT EXISTS idx_sali ON files(songalbumid);"
#define I_STATEMKINDSARI \ #define I_STATEMKINDSARI \
"CREATE INDEX IF NOT EXISTS idx_state_mkind_sari ON files(disabled, media_kind, songartistid);" "CREATE INDEX IF NOT EXISTS idx_state_mkind_sari ON files(disabled, media_kind, songartistid);"
@ -4483,13 +4350,10 @@ db_perthread_deinit(void)
"CREATE INDEX IF NOT EXISTS idx_albumartist ON files(album_artist, album_artist_sort);" "CREATE INDEX IF NOT EXISTS idx_albumartist ON files(album_artist, album_artist_sort);"
#define I_COMPOSER \ #define I_COMPOSER \
"CREATE INDEX IF NOT EXISTS idx_composer ON files(disabled, media_kind, composer, data_kind);" "CREATE INDEX IF NOT EXISTS idx_composer ON files(composer, composer_sort);"
#define I_GENRE \
"CREATE INDEX IF NOT EXISTS idx_genre ON files(disabled, media_kind, genre, data_kind);"
#define I_TITLE \ #define I_TITLE \
"CREATE INDEX IF NOT EXISTS idx_title ON files(disabled, media_kind, title_sort, data_kind);" "CREATE INDEX IF NOT EXISTS idx_title ON files(title, title_sort);"
#define I_ALBUM \ #define I_ALBUM \
"CREATE INDEX IF NOT EXISTS idx_album ON files(album, album_sort);" "CREATE INDEX IF NOT EXISTS idx_album ON files(album, album_sort);"
@ -4506,13 +4370,27 @@ db_perthread_deinit(void)
#define I_PLITEMID \ #define I_PLITEMID \
"CREATE INDEX IF NOT EXISTS idx_playlistid ON playlistitems(playlistid, filepath);" "CREATE INDEX IF NOT EXISTS idx_playlistid ON playlistitems(playlistid, filepath);"
#define I_GRP_TYPE_NAME \ #define I_GRP_TYPE_PERSIST \
"CREATE INDEX IF NOT EXISTS idx_grp_type_name ON groups(type, name);" "CREATE INDEX IF NOT EXISTS idx_grp_type_persist ON groups(type, persistentid);"
#define I_PAIRING \ #define I_PAIRING \
"CREATE INDEX IF NOT EXISTS idx_pairingguid ON pairings(guid);" "CREATE INDEX IF NOT EXISTS idx_pairingguid ON pairings(guid);"
#define TRG_GROUPS_INSERT_FILES \
"CREATE TRIGGER update_groups_new_file AFTER INSERT ON files FOR EACH ROW" \
" BEGIN" \
" INSERT OR IGNORE INTO groups (type, name, persistentid) VALUES (1, NEW.album, NEW.songalbumid);" \
" INSERT OR IGNORE INTO groups (type, name, persistentid) VALUES (2, NEW.album_artist, NEW.songartistid);" \
" END;"
#define TRG_GROUPS_UPDATE_FILES \
"CREATE TRIGGER update_groups_update_file AFTER UPDATE OF songalbumid ON files FOR EACH ROW" \
" BEGIN" \
" INSERT OR IGNORE INTO groups (type, name, persistentid) VALUES (1, NEW.album, NEW.songalbumid);" \
" INSERT OR IGNORE INTO groups (type, name, persistentid) VALUES (2, NEW.album_artist, NEW.songartistid);" \
" END;"
#define Q_PL1 \ #define Q_PL1 \
"INSERT INTO playlists (id, title, type, query, db_timestamp, path, idx, special_id)" \ "INSERT INTO playlists (id, title, type, query, db_timestamp, path, idx, special_id)" \
" VALUES(1, 'Library', 1, '1 = 1', 0, '', 0, 0);" " VALUES(1, 'Library', 1, '1 = 1', 0, '', 0, 0);"
@ -4543,9 +4421,9 @@ db_perthread_deinit(void)
" VALUES(8, 'Purchased', 0, 'media_kind = 1024', 0, '', 0, 8);" " VALUES(8, 'Purchased', 0, 'media_kind = 1024', 0, '', 0, 8);"
*/ */
#define SCHEMA_VERSION 16 #define SCHEMA_VERSION 15
#define Q_SCVER \ #define Q_SCVER \
"INSERT INTO admin (key, value) VALUES ('schema_version', '16');" "INSERT INTO admin (key, value) VALUES ('schema_version', '15');"
struct db_init_query { struct db_init_query {
char *query; char *query;
@ -4569,12 +4447,11 @@ static const struct db_init_query db_init_queries[] =
{ I_STATEMKINDSARI, "create state/mkind/sari index" }, { I_STATEMKINDSARI, "create state/mkind/sari index" },
{ I_STATEMKINDSALI, "create state/mkind/sali index" }, { I_STATEMKINDSALI, "create state/mkind/sali index" },
{ I_ARTIST, "create artist index" }, { I_ARTIST, "create artist index" },
{ I_ALBUMARTIST, "create album_artist index" }, { I_ALBUMARTIST, "create album_artist index" },
{ I_COMPOSER, "create composer index" }, { I_COMPOSER, "create composer index" },
{ I_GENRE, "create genre index" }, { I_TITLE, "create title index" },
{ I_TITLE, "create title index" }, { I_ALBUM, "create album index" },
{ I_ALBUM, "create album index" },
{ I_PL_PATH, "create playlist path index" }, { I_PL_PATH, "create playlist path index" },
{ I_PL_DISABLED, "create playlist state index" }, { I_PL_DISABLED, "create playlist state index" },
@ -4582,10 +4459,13 @@ static const struct db_init_query db_init_queries[] =
{ I_FILEPATH, "create file path index" }, { I_FILEPATH, "create file path index" },
{ I_PLITEMID, "create playlist id index" }, { I_PLITEMID, "create playlist id index" },
{ I_GRP_TYPE_NAME, "create groups type/name index" }, { I_GRP_TYPE_PERSIST, "create groups type/persistentid index" },
{ I_PAIRING, "create pairing guid index" }, { I_PAIRING, "create pairing guid index" },
{ TRG_GROUPS_INSERT_FILES, "create trigger update_groups_new_file" },
{ TRG_GROUPS_UPDATE_FILES, "create trigger update_groups_update_file" },
{ Q_PL1, "create default playlist" }, { Q_PL1, "create default playlist" },
{ Q_PL2, "create default smart playlist 'Music'" }, { Q_PL2, "create default smart playlist 'Music'" },
{ Q_PL3, "create default smart playlist 'Movies'" }, { Q_PL3, "create default smart playlist 'Movies'" },
@ -5588,190 +5468,6 @@ db_upgrade_v15(void)
#undef Q_DUMP #undef Q_DUMP
} }
/* Upgrade from schema v15 to v16 */
#define U_V16_DROP_IDX \
"DROP INDEX idx_grp_type_persist;"
#define U_V16_DROP_TRG_NEW \
"DROP TRIGGER update_groups_new_file;"
#define U_V16_DROP_TRG_UPDATE \
"DROP TRIGGER update_groups_update_file;"
#define U_V16_DROP_TBL_GROUPS \
"DROP TABLE groups;"
#define U_V16_CREATE_TBL_GROUPS \
"CREATE TABLE IF NOT EXISTS groups (" \
" id INTEGER PRIMARY KEY NOT NULL," \
" type INTEGER NOT NULL," \
" name VARCHAR(1024) NOT NULL COLLATE DAAP," \
"CONSTRAINT groups_type_unique_name UNIQUE (type, name)" \
");"
#define U_V16_CREATE_IDX \
"CREATE INDEX IF NOT EXISTS idx_grp_type_name ON groups(type, name);"
#define U_V16_DROP_IDX_TITLE \
"DROP INDEX idx_title;"
#define U_V16_CREATE_IDX_TITLE \
"CREATE INDEX IF NOT EXISTS idx_title ON files(disabled, media_kind, title_sort, data_kind);"
#define U_V16_DROP_IDX_SONGALBUMID \
"DROP INDEX idx_sali;"
#define U_V16_CREATE_IDX_SONGALBUMID \
"CREATE INDEX IF NOT EXISTS idx_sali ON files(songalbumid, disabled, media_kind, album_sort, disc, track);"
#define U_V16_CREATE_IDX_GENRE \
"CREATE INDEX IF NOT EXISTS idx_genre ON files(disabled, media_kind, genre, data_kind);"
#define U_V16_DROP_IDX_COMPOSER \
"DROP INDEX idx_composer;"
#define U_V16_CREATE_IDX_COMPOSER \
"CREATE INDEX IF NOT EXISTS idx_composer ON files(disabled, media_kind, composer, data_kind);"
#define U_V16_SCVER \
"UPDATE admin SET value = '16' WHERE key = 'schema_version';"
static const struct db_init_query db_upgrade_v16_queries[] =
{
{ U_V16_DROP_IDX, "drop index type/persistentid" },
{ U_V16_DROP_TRG_NEW, "drop trigger new files" },
{ U_V16_DROP_TRG_UPDATE, "drop trigger update files" },
{ U_V16_DROP_TBL_GROUPS, "drop table groups" },
{ U_V16_CREATE_TBL_GROUPS, "create table groups" },
{ U_V16_CREATE_IDX, "create index type/name" },
{ U_V16_DROP_IDX_TITLE, "drop index title on files" },
{ U_V16_CREATE_IDX_TITLE, "create index title on files" },
{ U_V16_DROP_IDX_SONGALBUMID, "drop index songalbumid on files" },
{ U_V16_CREATE_IDX_SONGALBUMID, "create index songalbumid on files" },
{ U_V16_CREATE_IDX_GENRE, "create index genre on files" },
{ U_V16_DROP_IDX_COMPOSER, "drop index composer on files" },
{ U_V16_CREATE_IDX_COMPOSER, "create index composer on files" },
{ U_V16_SCVER, "set schema_version to 16" },
};
static int
db_upgrade_v16_persistentid(enum group_type type, char *artist, char *album)
{
sqlite3_stmt *stmt;
char *query;
char *errmsg;
int id;
int ret;
id = 0;
query = sqlite3_mprintf("SELECT id FROM groups WHERE type = %d AND name = LOWER(TRIM(%Q)) || '==' || LOWER(TRIM(%Q));", type, (artist ? artist : ""), (album ? album : ""));
ret = sqlite3_prepare_v2(hdl, query, -1, &stmt, NULL);
if (ret != SQLITE_OK)
{
DPRINTF(E_LOG, L_DB, "Could not prepare statement: %s\n", sqlite3_errmsg(hdl));
return -1;
}
ret = sqlite3_step(stmt);
if (ret == SQLITE_ROW)
{
id = sqlite3_column_int(stmt, 0);
}
else
{
if (ret != SQLITE_DONE)
{
DPRINTF(E_LOG, L_DB, "Could not step: %s\n", sqlite3_errmsg(hdl));
}
id = 0;
}
sqlite3_finalize(stmt);
sqlite3_free(query);
if (id > 0)
return id;
query = sqlite3_mprintf("INSERT INTO groups (type, name) VALUES (%d, LOWER(TRIM(%Q)) || '==' || LOWER(TRIM(%Q)));", type, (artist ? artist : ""), (album ? album : ""));
ret = sqlite3_exec(hdl, query, NULL, NULL, &errmsg);
if (ret == SQLITE_OK)
{
id = sqlite3_last_insert_rowid(hdl);
}
else
{
DPRINTF(E_LOG, L_DB, "Error adding group: %s\n", errmsg);
return -1;
}
sqlite3_free(query);
sqlite3_free(errmsg);
return id;
}
static int
db_upgrade_v16(void)
{
sqlite3_stmt *stmt;
char *query;
char *uquery;
char *errmsg;
char *artist;
char *album;
int id;
int artistid;
int albumid;
int ret;
query = "SELECT id, album_artist, album FROM files;";
DPRINTF(E_DBG, L_DB, "Running query '%s'\n", query);
ret = sqlite3_prepare_v2(hdl, query, -1, &stmt, NULL);
if (ret != SQLITE_OK)
{
DPRINTF(E_LOG, L_DB, "Could not prepare statement: %s\n", sqlite3_errmsg(hdl));
return -1;
}
while ((ret = sqlite3_step(stmt)) == SQLITE_ROW)
{
id = sqlite3_column_int(stmt, 0);
artist = (char *)sqlite3_column_text(stmt, 1);
album = (char *)sqlite3_column_text(stmt, 2);
artistid = db_upgrade_v16_persistentid(G_ARTISTS, artist, NULL);
albumid = db_upgrade_v16_persistentid(G_ALBUMS, artist, album);
if (artistid <= 0)
{
}
if (albumid <= 0)
{
}
uquery = sqlite3_mprintf("UPDATE files SET songartistid = %d, songalbumid = %d WHERE id = %d;", artistid, albumid, id);
ret = sqlite3_exec(hdl, uquery, NULL, NULL, &errmsg);
if (ret != SQLITE_OK)
{
DPRINTF(E_LOG, L_DB, "Error updating files: %s\n", errmsg);
}
sqlite3_free(uquery);
sqlite3_free(errmsg);
}
sqlite3_finalize(stmt);
return 0;
}
static int static int
db_check_version(void) db_check_version(void)
{ {
@ -5814,14 +5510,6 @@ db_check_version(void)
{ {
DPRINTF(E_LOG, L_DB, "Database schema outdated, schema upgrade needed v%d -> v%d\n", cur_ver, SCHEMA_VERSION); DPRINTF(E_LOG, L_DB, "Database schema outdated, schema upgrade needed v%d -> v%d\n", cur_ver, SCHEMA_VERSION);
ret = sqlite3_exec(hdl, "BEGIN TRANSACTION;", NULL, NULL, &errmsg);
if (ret != SQLITE_OK)
{
DPRINTF(E_LOG, L_DB, "Error starting transaction: %s\n", errmsg);
sqlite3_free(errmsg);
return -1;
}
switch (cur_ver) switch (cur_ver)
{ {
case 10: case 10:
@ -5873,15 +5561,6 @@ db_check_version(void)
if (ret < 0) if (ret < 0)
return -1; return -1;
case 15:
ret = db_generic_upgrade(db_upgrade_v16_queries, sizeof(db_upgrade_v16_queries) / sizeof(db_upgrade_v16_queries[0]));
if (ret < 0)
return -1;
ret = db_upgrade_v16();
if (ret < 0)
return -1;
break; break;
default: default:
@ -5889,14 +5568,6 @@ db_check_version(void)
return -1; return -1;
} }
ret = sqlite3_exec(hdl, "END TRANSACTION;", NULL, NULL, &errmsg);
if (ret != SQLITE_OK)
{
DPRINTF(E_LOG, L_DB, "Error ending transaction: %s\n", errmsg);
sqlite3_free(errmsg);
return -1;
}
/* What about some housekeeping work, eh? */ /* What about some housekeeping work, eh? */
DPRINTF(E_INFO, L_DB, "Now vacuuming database, this may take some time...\n"); DPRINTF(E_INFO, L_DB, "Now vacuuming database, this may take some time...\n");

View File

@ -458,6 +458,13 @@ db_pl_disable_bymatch(char *path, char *strip, uint32_t cookie);
int int
db_pl_enable_bycookie(uint32_t cookie, char *path); db_pl_enable_bycookie(uint32_t cookie, char *path);
/* Groups */
int
db_groups_clear(void);
int
db_group_persistentid_byid(int id, int64_t *persistentid);
/* Remotes */ /* Remotes */
int int
db_pairing_add(struct pairing_info *pi); db_pairing_add(struct pairing_info *pi);

View File

@ -1125,6 +1125,21 @@ filescanner(void *arg)
pthread_exit(NULL); pthread_exit(NULL);
} }
ret = db_groups_clear();
if (ret < 0)
{
DPRINTF(E_LOG, L_SCAN, "Error: could not clear old groups from DB\n");
pthread_exit(NULL);
}
/* Recompute all songartistids and songalbumids, in case the SQLite DB got transferred
* to a different host; the hash is not portable.
* It will also rebuild the groups we just cleared.
*/
db_files_update_songartistid();
db_files_update_songalbumid();
if (cfg_getbool(cfg_getsec(cfg, "library"), "filescan_disable")) if (cfg_getbool(cfg_getsec(cfg, "library"), "filescan_disable"))
bulk_scan(F_SCAN_BULK | F_SCAN_FAST); bulk_scan(F_SCAN_BULK | F_SCAN_FAST);
else else