[db/filescanner] Upgrade database to v19.08 and support limit/order by

in smart playlist files
This commit is contained in:
chme 2018-04-13 16:29:06 +02:00 committed by ejurgensen
parent 5189fe2305
commit 6bdcda1524
6 changed files with 92 additions and 15 deletions

View File

@ -178,6 +178,8 @@ static const struct col_type_map pli_cols_map[] =
{ pli_offsetof(virtual_path), DB_TYPE_STRING },
{ pli_offsetof(parent_id), DB_TYPE_INT },
{ pli_offsetof(directory_id), DB_TYPE_INT },
{ pli_offsetof(query_orderby),DB_TYPE_STRING },
{ pli_offsetof(query_limit), DB_TYPE_INT },
/* items is computed on the fly */
};
@ -268,6 +270,8 @@ static const ssize_t dbpli_cols_map[] =
dbpli_offsetof(virtual_path),
dbpli_offsetof(parent_id),
dbpli_offsetof(directory_id),
dbpli_offsetof(query_orderby),
dbpli_offsetof(query_limit),
/* items is computed on the fly */
};
@ -1584,18 +1588,54 @@ db_build_query_plitems_plain(struct query_params *qp)
}
static char *
db_build_query_plitems_smart(struct query_params *qp, char *smartpl_query)
db_build_query_plitems_smart(struct query_params *qp, struct playlist_info *pli)
{
struct query_clause *qc;
char *count;
char *query;
bool free_orderby = false;
if (pli->query_limit > 0)
{
if (qp->idx_type == I_SUB)
{
if (pli->query_limit > qp->offset + qp->limit)
qp->limit = pli->query_limit;
}
else if (qp->idx_type == I_NONE)
{
qp->idx_type = I_SUB;
qp->limit = pli->query_limit;
qp->offset = 0;
}
else
{
DPRINTF(E_WARN, L_DB, "Cannot append limit from smart playlist '%s' to query\n", pli->path);
}
}
if (pli->query_orderby)
{
if (!qp->orderby && qp->sort == S_NONE)
{
qp->orderby = strdup(pli->query_orderby);
free_orderby = true;
}
else
DPRINTF(E_WARN, L_DB, "Cannot append order by from smart playlist '%s' to query\n", pli->path);
}
qc = db_build_query_clause(qp);
if (free_orderby)
{
free(qp->orderby);
qp->orderby = NULL;
}
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);
count = sqlite3_mprintf("SELECT COUNT(*) FROM files f %s AND %s LIMIT %d;", qc->where, pli->query, pli->query_limit);
query = sqlite3_mprintf("SELECT f.* FROM files f %s AND %s %s %s;", qc->where, pli->query, qc->order, qc->index);
db_free_query_clause(qc);
@ -1622,7 +1662,7 @@ db_build_query_plitems(struct query_params *qp)
{
case PL_SPECIAL:
case PL_SMART:
query = db_build_query_plitems_smart(qp, pli->query);
query = db_build_query_plitems_smart(qp, pli);
break;
case PL_PLAIN:
@ -3376,8 +3416,9 @@ int
db_pl_add(struct playlist_info *pli, int *id)
{
#define QDUP_TMPL "SELECT COUNT(*) FROM playlists p WHERE p.title = TRIM(%Q) AND p.path = '%q';"
#define QADD_TMPL "INSERT INTO playlists (title, type, query, db_timestamp, disabled, path, idx, special_id, parent_id, virtual_path, directory_id)" \
" VALUES (TRIM(%Q), %d, '%q', %" PRIi64 ", %d, '%q', %d, %d, %d, '%q', %d);"
#define QADD_TMPL "INSERT INTO playlists (title, type, query, db_timestamp, disabled, path, idx, special_id, " \
" parent_id, virtual_path, directory_id, query_orderby, query_limit)" \
" VALUES (TRIM(%Q), %d, '%q', %" PRIi64 ", %d, '%q', %d, %d, %d, '%q', %d, %Q, %d);"
char *query;
char *errmsg;
int ret;
@ -3403,7 +3444,8 @@ db_pl_add(struct playlist_info *pli, int *id)
/* Add */
query = sqlite3_mprintf(QADD_TMPL,
pli->title, pli->type, pli->query, (int64_t)time(NULL), pli->disabled, STR(pli->path),
pli->index, pli->special_id, pli->parent_id, pli->virtual_path, pli->directory_id);
pli->index, pli->special_id, pli->parent_id, pli->virtual_path, pli->directory_id,
pli->query_orderby, pli->query_limit);
if (!query)
{
@ -3468,14 +3510,16 @@ int
db_pl_update(struct playlist_info *pli)
{
#define Q_TMPL "UPDATE playlists SET title = TRIM(%Q), type = %d, query = '%q', db_timestamp = %" PRIi64 ", disabled = %d, " \
" path = '%q', idx = %d, special_id = %d, parent_id = %d, virtual_path = '%q', directory_id = %d " \
" path = '%q', idx = %d, special_id = %d, parent_id = %d, virtual_path = '%q', directory_id = %d, " \
" query_orderby = %Q, query_limit = %d " \
" WHERE id = %d;"
char *query;
int ret;
query = sqlite3_mprintf(Q_TMPL,
pli->title, pli->type, pli->query, (int64_t)time(NULL), pli->disabled, STR(pli->path),
pli->index, pli->special_id, pli->parent_id, pli->virtual_path, pli->directory_id, pli->id);
pli->index, pli->special_id, pli->parent_id, pli->virtual_path, pli->directory_id,
pli->query_orderby, pli->query_limit, pli->id);
ret = db_query_run(query, 1, 0);

View File

@ -247,6 +247,8 @@ struct playlist_info {
char *virtual_path; /* virtual path of underlying playlist */
uint32_t parent_id; /* Id of parent playlist if the playlist is nested */
uint32_t directory_id; /* Id of directory */
char *query_orderby; /* order by clause if it is a smart playlist */
uint32_t query_limit; /* limit if it is a smart playlist */
};
#define pli_offsetof(field) offsetof(struct playlist_info, field)
@ -266,6 +268,8 @@ struct db_playlist_info {
char *virtual_path;
char *parent_id;
char *directory_id;
char *query_orderby;
char *query_limit;
};
#define dbpli_offsetof(field) offsetof(struct db_playlist_info, field)

View File

@ -109,7 +109,9 @@
" special_id INTEGER DEFAULT 0," \
" virtual_path VARCHAR(4096)," \
" parent_id INTEGER DEFAULT 0," \
" directory_id INTEGER DEFAULT 0" \
" directory_id INTEGER DEFAULT 0," \
" query_orderby VARCHAR(1024)," \
" query_limit INTEGER DEFAULT 0" \
");"
#define T_PLITEMS \

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 19
#define SCHEMA_VERSION_MINOR 07
#define SCHEMA_VERSION_MINOR 8
int
db_init_indices(sqlite3 *hdl);

View File

@ -1634,6 +1634,23 @@ static const struct db_upgrade_query db_upgrade_V1907_queries[] =
};
#define U_V1908_ALTER_PL_ADD_ORDERBY \
"ALTER TABLE playlists ADD COLUMN query_orderby VARCHAR(1024);"
#define U_V1908_ALTER_PL_ADD_LIMIT \
"ALTER TABLE playlists ADD COLUMN query_limit INTEGER DEFAULT 0;"
#define U_V1908_SCVER_MINOR \
"UPDATE admin SET value = '08' WHERE key = 'schema_version_minor';"
static const struct db_upgrade_query db_upgrade_v1908_queries[] =
{
{ U_V1908_ALTER_PL_ADD_ORDERBY, "alter table playlists add column query_orderby" },
{ U_V1908_ALTER_PL_ADD_LIMIT, "alter table playlists add column query_limit" },
{ U_V1908_SCVER_MINOR, "set schema_version_minor to 08" },
};
int
db_upgrade(sqlite3 *hdl, int db_ver)
{
@ -1793,6 +1810,13 @@ db_upgrade(sqlite3 *hdl, int db_ver)
if (ret < 0)
return -1;
/* FALLTHROUGH */
case 1907:
ret = db_generic_upgrade(hdl, db_upgrade_v1908_queries, ARRAY_SIZE(db_upgrade_v1908_queries));
if (ret < 0)
return -1;
break;
default:

View File

@ -80,14 +80,17 @@ scan_smartpl(const char *file, time_t mtime, int dir_id)
return;
}
if (pli->title)
free(pli->title);
free(pli->title);
pli->title = strdup(smartpl.title);
if (pli->query)
free(pli->query);
free(pli->query);
pli->query = strdup(smartpl.query_where);
free(pli->query_orderby);
pli->query_orderby = safe_strdup(smartpl.order_by);
pli->query_limit = smartpl.limit;
free_smartpl(&smartpl, 1);
if (pli->id)