mirror of
https://github.com/owntone/owntone-server.git
synced 2025-07-28 09:50:13 -04:00
[db] Consolidate setting struct fields from database queries
This commit is contained in:
parent
689d1ce3dd
commit
1fa1d9091b
277
src/db.c
277
src/db.c
@ -56,10 +56,6 @@
|
|||||||
// Inotify cookies are uint32_t
|
// Inotify cookies are uint32_t
|
||||||
#define INOTIFY_FAKE_COOKIE ((int64_t)1 << 32)
|
#define INOTIFY_FAKE_COOKIE ((int64_t)1 << 32)
|
||||||
|
|
||||||
#define DB_TYPE_INT 1
|
|
||||||
#define DB_TYPE_INT64 2
|
|
||||||
#define DB_TYPE_STRING 3
|
|
||||||
|
|
||||||
// Flags that the field will not be bound to prepared statements, which is relevant if the field has no
|
// Flags that the field will not be bound to prepared statements, which is relevant if the field has no
|
||||||
// matching column, or if the the column value is set automatically by the db, e.g. by a trigger
|
// matching column, or if the the column value is set automatically by the db, e.g. by a trigger
|
||||||
#define DB_FLAG_NO_BIND (1 << 0)
|
#define DB_FLAG_NO_BIND (1 << 0)
|
||||||
@ -75,6 +71,12 @@ enum group_type {
|
|||||||
G_ARTISTS = 2,
|
G_ARTISTS = 2,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum field_type {
|
||||||
|
DB_TYPE_INT,
|
||||||
|
DB_TYPE_INT64,
|
||||||
|
DB_TYPE_STRING,
|
||||||
|
};
|
||||||
|
|
||||||
enum fixup_type {
|
enum fixup_type {
|
||||||
DB_FIXUP_STANDARD = 0,
|
DB_FIXUP_STANDARD = 0,
|
||||||
DB_FIXUP_NO_SANITIZE,
|
DB_FIXUP_NO_SANITIZE,
|
||||||
@ -120,7 +122,7 @@ struct db_statements
|
|||||||
struct col_type_map {
|
struct col_type_map {
|
||||||
char *name;
|
char *name;
|
||||||
ssize_t offset;
|
ssize_t offset;
|
||||||
short type;
|
enum field_type type;
|
||||||
enum fixup_type fixup;
|
enum fixup_type fixup;
|
||||||
short flag;
|
short flag;
|
||||||
};
|
};
|
||||||
@ -800,38 +802,92 @@ free_queue_item(struct db_queue_item *qi, int content_only)
|
|||||||
// because src is not a struct, caller wants to strdup the string so
|
// because src is not a struct, caller wants to strdup the string so
|
||||||
// must_strdup is true
|
// must_strdup is true
|
||||||
static inline void
|
static inline void
|
||||||
struct_set(void *dst_struct, ssize_t dst_offset, int dst_type, const void *src_struct, ssize_t src_offset, bool must_strdup, bool parse_integers)
|
struct_field_set_str(void *dst, const void *src, bool must_strdup)
|
||||||
|
{
|
||||||
|
char *srcstr;
|
||||||
|
char **dstptr;
|
||||||
|
|
||||||
|
srcstr = *(char **)(src);
|
||||||
|
dstptr = (char **)(dst);
|
||||||
|
*dstptr = must_strdup ? safe_strdup(srcstr) : srcstr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
struct_field_set_uint32(void *dst, const void *src, bool parse_integers)
|
||||||
{
|
{
|
||||||
char *srcstr;
|
char *srcstr;
|
||||||
uint32_t srcu32val;
|
uint32_t srcu32val;
|
||||||
int64_t srci64val;
|
|
||||||
char **dstptr;
|
|
||||||
|
|
||||||
srcstr = *(char **)(src_struct + src_offset);
|
if (parse_integers)
|
||||||
|
{
|
||||||
|
srcstr = *(char **)(src);
|
||||||
|
safe_atou32(srcstr, &srcu32val);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
srcu32val = *(uint32_t *)(src);
|
||||||
|
|
||||||
|
memcpy(dst, &srcu32val, sizeof(srcu32val));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
struct_field_set_int64(void *dst, const void *src, bool parse_integers)
|
||||||
|
{
|
||||||
|
char *srcstr;
|
||||||
|
int64_t srci64val;
|
||||||
|
|
||||||
|
if (parse_integers)
|
||||||
|
{
|
||||||
|
srcstr = *(char **)(src);
|
||||||
|
safe_atoi64(srcstr, &srci64val);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
srci64val = *(int64_t *)(src);
|
||||||
|
|
||||||
|
memcpy(dst, &srci64val, sizeof(srci64val));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
struct_field_from_field(void *dst_struct, ssize_t dst_offset, enum field_type dst_type, const void *src_struct, ssize_t src_offset, bool must_strdup, bool parse_integers)
|
||||||
|
{
|
||||||
|
switch (dst_type)
|
||||||
|
{
|
||||||
|
case DB_TYPE_STRING:
|
||||||
|
struct_field_set_str(dst_struct + dst_offset, src_struct + src_offset, must_strdup);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DB_TYPE_INT:
|
||||||
|
struct_field_set_uint32(dst_struct + dst_offset, src_struct + src_offset, parse_integers);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DB_TYPE_INT64:
|
||||||
|
struct_field_set_int64(dst_struct + dst_offset, src_struct + src_offset, parse_integers);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
struct_field_from_statement(void *dst_struct, ssize_t dst_offset, enum field_type dst_type, sqlite3_stmt *stmt, int col, bool must_strdup, bool parse_integers)
|
||||||
|
{
|
||||||
|
const char *str;
|
||||||
|
uint32_t u32;
|
||||||
|
int64_t i64;
|
||||||
|
|
||||||
switch (dst_type)
|
switch (dst_type)
|
||||||
{
|
{
|
||||||
case DB_TYPE_STRING:
|
case DB_TYPE_STRING:
|
||||||
dstptr = (char **)(dst_struct + dst_offset);
|
str = (const char *)sqlite3_column_text(stmt, col);
|
||||||
*dstptr = must_strdup ? safe_strdup(srcstr) : srcstr;
|
struct_field_set_str(dst_struct + dst_offset, &str, must_strdup);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DB_TYPE_INT:
|
case DB_TYPE_INT:
|
||||||
if (parse_integers)
|
u32 = (uint32_t)sqlite3_column_int64(stmt, col); // _int64() because _int() wouldn't be enough for uint32
|
||||||
safe_atou32(srcstr, &srcu32val);
|
// TODO add a check that we aren't truncating int64 !=0 to uint32 == 0?
|
||||||
else
|
struct_field_set_uint32(dst_struct + dst_offset, &u32, parse_integers);
|
||||||
srcu32val = *(uint32_t *)(src_struct + src_offset);
|
|
||||||
|
|
||||||
memcpy(dst_struct + dst_offset, &srcu32val, sizeof(srcu32val));
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DB_TYPE_INT64:
|
case DB_TYPE_INT64:
|
||||||
if (parse_integers)
|
i64 = sqlite3_column_int64(stmt, col);
|
||||||
safe_atoi64(srcstr, &srci64val);
|
struct_field_set_int64(dst_struct + dst_offset, &i64, parse_integers);
|
||||||
else
|
|
||||||
srci64val = *(int64_t *)(src_struct + src_offset);
|
|
||||||
|
|
||||||
memcpy(dst_struct + dst_offset, &srci64val, sizeof(srci64val));
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3011,11 +3067,6 @@ db_file_fetch_byquery(char *query)
|
|||||||
struct media_file_info *mfi;
|
struct media_file_info *mfi;
|
||||||
sqlite3_stmt *stmt;
|
sqlite3_stmt *stmt;
|
||||||
int ncols;
|
int ncols;
|
||||||
char *cval;
|
|
||||||
uint32_t *ival;
|
|
||||||
uint64_t *i64val;
|
|
||||||
char **strval;
|
|
||||||
uint64_t disabled;
|
|
||||||
int i;
|
int i;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
@ -3068,41 +3119,7 @@ db_file_fetch_byquery(char *query)
|
|||||||
|
|
||||||
for (i = 0; i < ARRAY_SIZE(mfi_cols_map); i++)
|
for (i = 0; i < ARRAY_SIZE(mfi_cols_map); i++)
|
||||||
{
|
{
|
||||||
switch (mfi_cols_map[i].type)
|
struct_field_from_statement(mfi, mfi_cols_map[i].offset, mfi_cols_map[i].type, stmt, i, true, false);
|
||||||
{
|
|
||||||
case DB_TYPE_INT:
|
|
||||||
ival = (uint32_t *) ((char *)mfi + mfi_cols_map[i].offset);
|
|
||||||
|
|
||||||
if (mfi_cols_map[i].offset == mfi_offsetof(disabled))
|
|
||||||
{
|
|
||||||
disabled = sqlite3_column_int64(stmt, i);
|
|
||||||
*ival = (disabled != 0);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
*ival = sqlite3_column_int(stmt, i);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DB_TYPE_INT64:
|
|
||||||
i64val = (uint64_t *) ((char *)mfi + mfi_cols_map[i].offset);
|
|
||||||
|
|
||||||
*i64val = sqlite3_column_int64(stmt, i);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DB_TYPE_STRING:
|
|
||||||
strval = (char **) ((char *)mfi + mfi_cols_map[i].offset);
|
|
||||||
|
|
||||||
cval = (char *)sqlite3_column_text(stmt, i);
|
|
||||||
if (cval)
|
|
||||||
*strval = strdup(cval);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
DPRINTF(E_LOG, L_DB, "BUG: Unknown type %d in mfi column map\n", mfi_cols_map[i].type);
|
|
||||||
|
|
||||||
free_mfi(mfi, 0);
|
|
||||||
sqlite3_finalize(stmt);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DB_PROFILE
|
#ifdef DB_PROFILE
|
||||||
@ -3464,10 +3481,6 @@ db_pl_fetch_byquery(const char *query)
|
|||||||
struct playlist_info *pli;
|
struct playlist_info *pli;
|
||||||
sqlite3_stmt *stmt;
|
sqlite3_stmt *stmt;
|
||||||
int ncols;
|
int ncols;
|
||||||
char *cval;
|
|
||||||
uint32_t *ival;
|
|
||||||
char **strval;
|
|
||||||
uint64_t disabled;
|
|
||||||
int i;
|
int i;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
@ -3518,35 +3531,7 @@ db_pl_fetch_byquery(const char *query)
|
|||||||
|
|
||||||
for (i = 0; i < ARRAY_SIZE(pli_cols_map); i++)
|
for (i = 0; i < ARRAY_SIZE(pli_cols_map); i++)
|
||||||
{
|
{
|
||||||
switch (pli_cols_map[i].type)
|
struct_field_from_statement(pli, pli_cols_map[i].offset, pli_cols_map[i].type, stmt, i, true, false);
|
||||||
{
|
|
||||||
case DB_TYPE_INT:
|
|
||||||
ival = (uint32_t *) ((char *)pli + pli_cols_map[i].offset);
|
|
||||||
|
|
||||||
if (pli_cols_map[i].offset == pli_offsetof(disabled))
|
|
||||||
{
|
|
||||||
disabled = sqlite3_column_int64(stmt, i);
|
|
||||||
*ival = (disabled != 0);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
*ival = sqlite3_column_int(stmt, i);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DB_TYPE_STRING:
|
|
||||||
strval = (char **) ((char *)pli + pli_cols_map[i].offset);
|
|
||||||
|
|
||||||
cval = (char *)sqlite3_column_text(stmt, i);
|
|
||||||
if (cval)
|
|
||||||
*strval = strdup(cval);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
DPRINTF(E_LOG, L_DB, "BUG: Unknown type %d in pli column map\n", pli_cols_map[i].type);
|
|
||||||
|
|
||||||
sqlite3_finalize(stmt);
|
|
||||||
free_pli(pli, 0);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = db_blocking_step(stmt);
|
ret = db_blocking_step(stmt);
|
||||||
@ -4556,10 +4541,6 @@ admin_get(void *value, const char *key, short type)
|
|||||||
#define Q_TMPL "SELECT value FROM admin a WHERE a.key = '%q';"
|
#define Q_TMPL "SELECT value FROM admin a WHERE a.key = '%q';"
|
||||||
char *query;
|
char *query;
|
||||||
sqlite3_stmt *stmt;
|
sqlite3_stmt *stmt;
|
||||||
char *cval;
|
|
||||||
int32_t *ival;
|
|
||||||
int64_t *i64val;
|
|
||||||
char **strval;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
CHECK_NULL(L_DB, query = sqlite3_mprintf(Q_TMPL, key));
|
CHECK_NULL(L_DB, query = sqlite3_mprintf(Q_TMPL, key));
|
||||||
@ -4588,35 +4569,7 @@ admin_get(void *value, const char *key, short type)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (type)
|
struct_field_from_statement(value, 0, type, stmt, 0, true, false);
|
||||||
{
|
|
||||||
case DB_TYPE_INT:
|
|
||||||
ival = (int32_t *) value;
|
|
||||||
|
|
||||||
*ival = sqlite3_column_int(stmt, 0);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DB_TYPE_INT64:
|
|
||||||
i64val = (int64_t *) value;
|
|
||||||
|
|
||||||
*i64val = sqlite3_column_int64(stmt, 0);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DB_TYPE_STRING:
|
|
||||||
strval = (char **) value;
|
|
||||||
|
|
||||||
cval = (char *)sqlite3_column_text(stmt, 0);
|
|
||||||
if (cval)
|
|
||||||
*strval = strdup(cval);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
DPRINTF(E_LOG, L_DB, "BUG: Unknown type %d in admin_set\n", type);
|
|
||||||
|
|
||||||
sqlite3_finalize(stmt);
|
|
||||||
sqlite3_free(query);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef DB_PROFILE
|
#ifdef DB_PROFILE
|
||||||
while (db_blocking_step(stmt) == SQLITE_ROW)
|
while (db_blocking_step(stmt) == SQLITE_ROW)
|
||||||
@ -4879,7 +4832,7 @@ db_queue_item_from_mfi(struct db_queue_item *qi, struct media_file_info *mfi)
|
|||||||
if (qi_mfi_map[i].mfi_offset < 0)
|
if (qi_mfi_map[i].mfi_offset < 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
struct_set(qi, qi_cols_map[i].offset, qi_cols_map[i].type, mfi, qi_mfi_map[i].mfi_offset, true, false);
|
struct_field_from_field(qi, qi_cols_map[i].offset, qi_cols_map[i].type, mfi, qi_mfi_map[i].mfi_offset, true, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!qi->file_id)
|
if (!qi->file_id)
|
||||||
@ -4898,7 +4851,7 @@ db_queue_item_from_dbmfi(struct db_queue_item *qi, struct db_media_file_info *db
|
|||||||
if (qi_mfi_map[i].dbmfi_offset < 0)
|
if (qi_mfi_map[i].dbmfi_offset < 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
struct_set(qi, qi_cols_map[i].offset, qi_cols_map[i].type, dbmfi, qi_mfi_map[i].dbmfi_offset, false, true);
|
struct_field_from_field(qi, qi_cols_map[i].offset, qi_cols_map[i].type, dbmfi, qi_mfi_map[i].dbmfi_offset, false, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!qi->file_id)
|
if (!qi->file_id)
|
||||||
@ -5257,10 +5210,6 @@ strdup_if(char *str, int cond)
|
|||||||
static int
|
static int
|
||||||
queue_enum_fetch(struct query_params *qp, struct db_queue_item *qi, int must_strdup)
|
queue_enum_fetch(struct query_params *qp, struct db_queue_item *qi, int must_strdup)
|
||||||
{
|
{
|
||||||
const void *srcptr;
|
|
||||||
const char *str;
|
|
||||||
int32_t i32;
|
|
||||||
int64_t i64;
|
|
||||||
int ret;
|
int ret;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
@ -5286,29 +5235,7 @@ queue_enum_fetch(struct query_params *qp, struct db_queue_item *qi, int must_str
|
|||||||
|
|
||||||
for (i = 0; i < ARRAY_SIZE(qi_cols_map); i++)
|
for (i = 0; i < ARRAY_SIZE(qi_cols_map); i++)
|
||||||
{
|
{
|
||||||
switch (qi_cols_map[i].type)
|
struct_field_from_statement(qi, qi_cols_map[i].offset, qi_cols_map[i].type, qp->stmt, i, must_strdup, false);
|
||||||
{
|
|
||||||
case DB_TYPE_STRING:
|
|
||||||
str = (const char *)sqlite3_column_text(qp->stmt, i);
|
|
||||||
srcptr = &str;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DB_TYPE_INT:
|
|
||||||
i32 = sqlite3_column_int(qp->stmt, i);
|
|
||||||
srcptr = &i32;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DB_TYPE_INT64:
|
|
||||||
i64 = sqlite3_column_int64(qp->stmt, i);
|
|
||||||
srcptr = &i64;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
DPRINTF(E_LOG, L_DB, "BUG! Unknown data type (%d) in queue_enum_fetch()\n", qi_cols_map[i].type);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct_set(qi, qi_cols_map[i].offset, qi_cols_map[i].type, srcptr, 0, must_strdup, false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -6274,9 +6201,6 @@ static int
|
|||||||
db_watch_get_byquery(struct watch_info *wi, char *query)
|
db_watch_get_byquery(struct watch_info *wi, char *query)
|
||||||
{
|
{
|
||||||
sqlite3_stmt *stmt;
|
sqlite3_stmt *stmt;
|
||||||
char **strval;
|
|
||||||
char *cval;
|
|
||||||
uint32_t *ival;
|
|
||||||
int64_t cookie;
|
int64_t cookie;
|
||||||
int ncols;
|
int ncols;
|
||||||
int i;
|
int i;
|
||||||
@ -6314,33 +6238,12 @@ db_watch_get_byquery(struct watch_info *wi, char *query)
|
|||||||
|
|
||||||
for (i = 0; i < ARRAY_SIZE(wi_cols_map); i++)
|
for (i = 0; i < ARRAY_SIZE(wi_cols_map); i++)
|
||||||
{
|
{
|
||||||
switch (wi_cols_map[i].type)
|
struct_field_from_statement(wi, wi_cols_map[i].offset, wi_cols_map[i].type, stmt, i, true, false);
|
||||||
|
|
||||||
|
if (wi_cols_map[i].offset == wi_offsetof(cookie))
|
||||||
{
|
{
|
||||||
case DB_TYPE_INT:
|
cookie = sqlite3_column_int64(stmt, i);
|
||||||
ival = (uint32_t *) ((char *)wi + wi_cols_map[i].offset);
|
wi->cookie = (cookie == INOTIFY_FAKE_COOKIE) ? 0 : cookie;
|
||||||
|
|
||||||
if (wi_cols_map[i].offset == wi_offsetof(cookie))
|
|
||||||
{
|
|
||||||
cookie = sqlite3_column_int64(stmt, i);
|
|
||||||
*ival = (cookie == INOTIFY_FAKE_COOKIE) ? 0 : cookie;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
*ival = sqlite3_column_int(stmt, i);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DB_TYPE_STRING:
|
|
||||||
strval = (char **) ((char *)wi + wi_cols_map[i].offset);
|
|
||||||
|
|
||||||
cval = (char *)sqlite3_column_text(stmt, i);
|
|
||||||
if (cval)
|
|
||||||
*strval = strdup(cval);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
DPRINTF(E_LOG, L_DB, "BUG: Unknown type %d in wi column map\n", wi_cols_map[i].type);
|
|
||||||
sqlite3_finalize(stmt);
|
|
||||||
sqlite3_free(query);
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user