[db] Move calculation of artist/album id's from sqlite to code

The purpose of this is to support library backends making their own
calculation of these id's, which is relevant if they have more information
available than just album_artist and album.

This also removes a bunch of sqlite extension code plus some triggers, which
in itself is probably an improvement.
This commit is contained in:
ejurgensen
2019-05-12 23:28:38 +02:00
parent c8650a0450
commit b3bfb0a5f6
7 changed files with 58 additions and 209 deletions

View File

@@ -92,6 +92,8 @@ enum fixup_type {
DB_FIXUP_COMPOSER_SORT,
DB_FIXUP_TIME_ADDED,
DB_FIXUP_TIME_MODIFIED,
DB_FIXUP_SONGARTISTID,
DB_FIXUP_SONGALBUMID,
};
struct db_unlock {
@@ -200,8 +202,8 @@ static const struct col_type_map mfi_cols_map[] =
{ "tv_network_name", mfi_offsetof(tv_network_name), DB_TYPE_STRING },
{ "tv_episode_sort", mfi_offsetof(tv_episode_sort), DB_TYPE_INT },
{ "tv_season_num", mfi_offsetof(tv_season_num), DB_TYPE_INT },
{ "songartistid", mfi_offsetof(songartistid), DB_TYPE_INT64, DB_FIXUP_STANDARD, DB_FLAG_AUTO },
{ "songalbumid", mfi_offsetof(songalbumid), DB_TYPE_INT64, DB_FIXUP_STANDARD, DB_FLAG_AUTO },
{ "songartistid", mfi_offsetof(songartistid), DB_TYPE_INT64, DB_FIXUP_SONGARTISTID },
{ "songalbumid", mfi_offsetof(songalbumid), DB_TYPE_INT64, DB_FIXUP_SONGALBUMID },
{ "title_sort", mfi_offsetof(title_sort), DB_TYPE_STRING, DB_FIXUP_TITLE_SORT },
{ "artist_sort", mfi_offsetof(artist_sort), DB_TYPE_STRING, DB_FIXUP_ARTIST_SORT },
{ "album_sort", mfi_offsetof(album_sort), DB_TYPE_STRING, DB_FIXUP_ALBUM_SORT },
@@ -726,7 +728,7 @@ sort_tag_create(char **sort_tag, const char *src_tag)
if (*sort_tag)
{
DPRINTF(E_DBG, L_LIB, "Existing sort tag will be normalized: %s\n", *sort_tag);
DPRINTF(E_DBG, L_DB, "Existing sort tag will be normalized: %s\n", *sort_tag);
o_ptr = u8_normalize(UNINORM_NFD, (uint8_t *)*sort_tag, strlen(*sort_tag) + 1, NULL, &len);
free(*sort_tag);
*sort_tag = (char *)o_ptr;
@@ -841,7 +843,6 @@ fixup_sanitize(char **tag, enum fixup_type fixup, struct fixup_ctx *ctx)
*tag = ret;
}
}
}
static void
@@ -851,6 +852,16 @@ fixup_defaults(char **tag, enum fixup_type fixup, struct fixup_ctx *ctx)
switch(fixup)
{
case DB_FIXUP_SONGARTISTID:
if (ctx->mfi && ctx->mfi->songartistid == 0)
ctx->mfi->songartistid = two_str_hash(ctx->mfi->album_artist, NULL);
break;
case DB_FIXUP_SONGALBUMID:
if (ctx->mfi && ctx->mfi->songalbumid == 0)
ctx->mfi->songalbumid = two_str_hash(ctx->mfi->album_artist, ctx->mfi->album);
break;
case DB_FIXUP_TITLE:
if (*tag)
break;

View File

@@ -400,22 +400,6 @@ static const struct db_init_query db_init_index_queries[] =
/* Triggers must be prefixed with trg_ for db_drop_triggers() to id them */
#define TRG_FILES_INSERT_SONGIDS \
"CREATE TRIGGER trg_files_insert_songids AFTER INSERT ON files FOR EACH ROW" \
" BEGIN" \
" UPDATE files SET songartistid = daap_songalbumid(LOWER(NEW.album_artist), ''), " \
" songalbumid = daap_songalbumid(LOWER(NEW.album_artist), LOWER(NEW.album))" \
" WHERE id = NEW.id;" \
" END;"
#define TRG_FILES_UPDATE_SONGIDS \
"CREATE TRIGGER trg_files_update_songids AFTER UPDATE OF album_artist, album ON files FOR EACH ROW" \
" BEGIN" \
" UPDATE files SET songartistid = daap_songalbumid(LOWER(NEW.album_artist), ''), " \
" songalbumid = daap_songalbumid(LOWER(NEW.album_artist), LOWER(NEW.album))" \
" WHERE id = NEW.id;" \
" END;"
#define TRG_GROUPS_UPDATE \
"CREATE TRIGGER trg_groups_update AFTER UPDATE OF songartistid, songalbumid ON files FOR EACH ROW" \
" WHEN (NEW.songartistid != 0 AND NEW.songalbumid != 0)" \
@@ -426,8 +410,6 @@ static const struct db_init_query db_init_index_queries[] =
static const struct db_init_query db_init_trigger_queries[] =
{
{ TRG_FILES_INSERT_SONGIDS, "create trigger trg_files_insert_songids" },
{ TRG_FILES_UPDATE_SONGIDS, "create trigger trg_files_update_songids" },
{ TRG_GROUPS_UPDATE, "create trigger trg_groups_update" },
};

View File

@@ -26,7 +26,7 @@
* is a major upgrade. In other words minor version upgrades permit downgrading
* forked-daapd after the database was upgraded. */
#define SCHEMA_VERSION_MAJOR 20
#define SCHEMA_VERSION_MINOR 01
#define SCHEMA_VERSION_MINOR 02
int
db_init_indices(sqlite3 *hdl);

View File

@@ -983,6 +983,15 @@ static const struct db_upgrade_query db_upgrade_v2001_queries[] =
{ U_V2001_SCVER_MINOR, "set schema_version_minor to 01" },
};
#define U_V2002_SCVER_MINOR \
"UPDATE admin SET value = '02' WHERE key = 'schema_version_minor';"
// This upgrade removes some triggers (will be done automatically by db_drop...)
static const struct db_upgrade_query db_upgrade_v2002_queries[] =
{
{ U_V2002_SCVER_MINOR, "set schema_version_minor to 02" },
};
int
db_upgrade(sqlite3 *hdl, int db_ver)
@@ -1124,6 +1133,13 @@ db_upgrade(sqlite3 *hdl, int db_ver)
if (ret < 0)
return -1;
/* FALLTHROUGH */
case 2001:
ret = db_generic_upgrade(hdl, db_upgrade_v2002_queries, ARRAY_SIZE(db_upgrade_v2002_queries));
if (ret < 0)
return -1;
break;
default:

View File

@@ -747,6 +747,29 @@ djb_hash(const void *data, size_t len)
return hash;
}
int64_t
two_str_hash(const char *a, const char *b)
{
char hashbuf[2048];
int64_t hash;
int i;
int ret;
ret = snprintf(hashbuf, sizeof(hashbuf), "%s==%s", (a) ? a : "", (b) ? b : "");
if (ret < 0 || ret == sizeof(hashbuf))
{
DPRINTF(E_LOG, L_MISC, "Buffer too large to calculate hash: '%s==%s'\n", a, b);
return 999999; // Stand-in hash...
}
for (i = 0; hashbuf[i]; i++)
hashbuf[i] = tolower(hashbuf[i]);
// Limit hash length to 63 bits, due to signed type in sqlite
hash = murmur_hash64(hashbuf, strlen(hashbuf), 0) >> 1;
return hash;
}
static unsigned char b64_decode_table[256];

View File

@@ -130,6 +130,9 @@ swap_pointers(char **a, char **b);
uint32_t
djb_hash(const void *data, size_t len);
int64_t
two_str_hash(const char *a, const char *b);
char *
b64_decode(const char *b64);