cleanups in dbs-sqlite, fixes for paths with single quotes in them
This commit is contained in:
parent
adc26c90b4
commit
6565596321
257
src/dbs-sqlite.c
257
src/dbs-sqlite.c
|
@ -49,6 +49,9 @@ static int db_sqlite_reload=0;
|
|||
int db_sqlite_get_size(DBQUERYINFO *pinfo, char **valarray);
|
||||
int db_sqlite_build_dmap(DBQUERYINFO *pinfo, char **valarray, char *presult, int len);
|
||||
void db_sqlite_build_mp3file(char **valarray, MP3FILE *pmp3);
|
||||
int db_sqlite_exec(int fatal, char *fmt, ...);
|
||||
int db_sqlite_get_table(int fatal, char ***resarray, int *rows, int *cols, char *fmt, ...);
|
||||
int db_sqlite_free_table(char **resarray);
|
||||
|
||||
#define STR(a) (a) ? (a) : ""
|
||||
#define MAYBEFREE(a) { if((a)) free((a)); };
|
||||
|
@ -71,6 +74,90 @@ int db_sqlite_unlock(void) {
|
|||
return pthread_mutex_unlock(&db_sqlite_mutex);
|
||||
}
|
||||
|
||||
/**
|
||||
* exec a simple statement
|
||||
*
|
||||
* \param fatal whether failure of this to execute is fatal or not
|
||||
*/
|
||||
int db_sqlite_exec(int fatal, char *fmt, ...) {
|
||||
va_list ap;
|
||||
char *query;
|
||||
int err;
|
||||
char *perr;
|
||||
int loglevel;
|
||||
|
||||
|
||||
va_start(ap,fmt);
|
||||
query=sqlite_vmprintf(fmt,ap);
|
||||
va_end(ap);
|
||||
|
||||
DPRINTF(E_DBG,L_DB,"Executing: %s\n",query);
|
||||
|
||||
db_sqlite_lock();
|
||||
err=sqlite_exec(db_sqlite_songs,query,NULL,NULL,&perr);
|
||||
if(err == SQLITE_OK)
|
||||
sqlite_freemem(query);
|
||||
db_sqlite_unlock();
|
||||
|
||||
if(err != SQLITE_OK) {
|
||||
loglevel=E_FATAL;
|
||||
if(!fatal)
|
||||
loglevel=E_LOG;
|
||||
|
||||
DPRINTF(loglevel,L_DB,"Query: %s Error: %s\n",query,perr);
|
||||
db_sqlite_lock();
|
||||
sqlite_freemem(query);
|
||||
db_sqlite_unlock();
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* get a sqlite table
|
||||
*
|
||||
*/
|
||||
int db_sqlite_get_table(int fatal, char ***resarray, int *rows, int *cols, char *fmt, ...) {
|
||||
va_list ap;
|
||||
char *query;
|
||||
int err;
|
||||
char *perr;
|
||||
int loglevel;
|
||||
|
||||
va_start(ap,fmt);
|
||||
query=sqlite_vmprintf(fmt,ap);
|
||||
va_end(ap);
|
||||
|
||||
DPRINTF(E_DBG,L_DB,"Executing: %s\n",query);
|
||||
|
||||
db_sqlite_lock();
|
||||
err=sqlite_get_table(db_sqlite_songs,query,resarray,rows,cols,&perr);
|
||||
if(err == SQLITE_OK)
|
||||
sqlite_freemem(query);
|
||||
db_sqlite_unlock();
|
||||
|
||||
if(err != SQLITE_OK) {
|
||||
loglevel=E_FATAL;
|
||||
if(!fatal)
|
||||
loglevel=E_LOG;
|
||||
|
||||
DPRINTF(loglevel,L_DB,"Query: %s, Error: %s\n",query,perr);
|
||||
db_sqlite_lock();
|
||||
sqlite_freemem(query);
|
||||
db_sqlite_unlock();
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int db_sqlite_free_table(char **resarray) {
|
||||
db_sqlite_lock();
|
||||
sqlite_free_table(resarray);
|
||||
db_sqlite_unlock();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* open sqlite database
|
||||
|
@ -96,8 +183,6 @@ int db_sqlite_open(char *parameters) {
|
|||
* \param reload whether or not to do a full reload on the db
|
||||
*/
|
||||
int db_sqlite_init(int reload) {
|
||||
int err;
|
||||
char *perr;
|
||||
int items;
|
||||
|
||||
items=db_sqlite_get_count(countSongs);
|
||||
|
@ -106,15 +191,9 @@ int db_sqlite_init(int reload) {
|
|||
DPRINTF(E_LOG,L_DB,"Full reload...\n");
|
||||
/* this may or may not fail, depending if the index is already in place */
|
||||
db_sqlite_reload=1;
|
||||
db_sqlite_lock();
|
||||
sqlite_exec(db_sqlite_songs,"DROP INDEX idx_path",NULL,NULL,&perr);
|
||||
err=sqlite_exec(db_sqlite_songs,"DELETE FROM songs",NULL,NULL,&perr);
|
||||
db_sqlite_unlock();
|
||||
if(err != SQLITE_OK) {
|
||||
DPRINTF(E_FATAL,L_DB,"Cannot reaload tables: %s\n",perr);
|
||||
db_sqlite_exec(0,"DROP INDEX idx_path");
|
||||
db_sqlite_exec(1,"DELETE FROM songs");
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -134,23 +213,17 @@ int db_sqlite_deinit(void) {
|
|||
* start a background scan
|
||||
*/
|
||||
int db_sqlite_start_scan(void) {
|
||||
char *perr;
|
||||
|
||||
db_sqlite_lock();
|
||||
|
||||
if(db_sqlite_reload) {
|
||||
sqlite_exec(db_sqlite_songs,"PRAGMA synchronous = OFF;",NULL,NULL,&perr);
|
||||
sqlite_exec(db_sqlite_songs,"BEGIN TRANSACTION;",NULL,NULL,&perr);
|
||||
db_sqlite_exec(0,"PRAGMA synchronous = OFF");
|
||||
db_sqlite_exec(0,"BEGIN TRANSACTION");
|
||||
} else {
|
||||
/* if not a full reload, we'll be doing update checks */
|
||||
sqlite_exec(db_sqlite_songs,"DROP TABLE updated",NULL,NULL,&perr);
|
||||
sqlite_exec(db_sqlite_songs,"CREATE TEMP TABLE updated (id int)",NULL,NULL,&perr);
|
||||
db_sqlite_exec(0,"DROP TABLE updated");
|
||||
db_sqlite_exec(1,"CREATE TEMP TABLE updated (id int)");
|
||||
}
|
||||
|
||||
db_sqlite_unlock();
|
||||
|
||||
db_sqlite_in_scan=1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -158,31 +231,15 @@ int db_sqlite_start_scan(void) {
|
|||
* stop a db scan
|
||||
*/
|
||||
int db_sqlite_end_scan(void) {
|
||||
char *perr;
|
||||
int err=0;
|
||||
|
||||
db_sqlite_lock();
|
||||
if(db_sqlite_reload) {
|
||||
err=sqlite_exec(db_sqlite_songs,"COMMIT TRANSACTION;",NULL,NULL,&perr);
|
||||
if(err != SQLITE_OK) {
|
||||
DPRINTF(E_FATAL,L_DB,"Could not commit insert transactions\n");
|
||||
}
|
||||
DPRINTF(E_LOG,L_DB,"Creating path index...\n");
|
||||
sqlite_exec(db_sqlite_songs,"CREATE INDEX idx_path ON songs(path)",NULL,NULL,&perr);
|
||||
sqlite_exec(db_sqlite_songs,"PRAGMA synchronous=NORMAL;",NULL,NULL,&perr);
|
||||
db_sqlite_exec(1,"COMMIT TRANSACTION");
|
||||
db_sqlite_exec(1,"CREATE INDEX idx_path ON songs(path)");
|
||||
db_sqlite_exec(1,"PRAGMA synchronous=NORMAL");
|
||||
} else {
|
||||
err=sqlite_exec(db_sqlite_songs,
|
||||
"DELETE FROM songs WHERE id NOT IN (SELECT id FROM updated)",
|
||||
NULL,NULL,&perr);
|
||||
if(err == SQLITE_OK) {
|
||||
err |= sqlite_exec(db_sqlite_songs,"DROP TABLE updated",NULL,NULL,&perr);
|
||||
db_sqlite_exec(1,"DELETE FROM songs WHERE id NOT IN (SELECT id FROM updated)");
|
||||
db_sqlite_exec(1,"DROP TABLE updated");
|
||||
}
|
||||
}
|
||||
|
||||
db_sqlite_unlock();
|
||||
|
||||
if(err != SQLITE_OK)
|
||||
DPRINTF(E_FATAL,L_DB,"db_sqlite_end_scan: %s\n",perr);
|
||||
|
||||
db_sqlite_reload=0;
|
||||
db_sqlite_in_scan=0;
|
||||
|
@ -197,11 +254,9 @@ int db_sqlite_end_scan(void) {
|
|||
*/
|
||||
int db_sqlite_add(MP3FILE *pmp3) {
|
||||
int err;
|
||||
char *perr;
|
||||
|
||||
DPRINTF(E_SPAM,L_DB,"Entering db_sqlite_add\n");
|
||||
|
||||
|
||||
if(!pmp3->time_added)
|
||||
pmp3->time_added = (int)time(NULL);
|
||||
|
||||
|
@ -212,8 +267,7 @@ int db_sqlite_add(MP3FILE *pmp3) {
|
|||
pmp3->play_count=0;
|
||||
pmp3->time_played=0;
|
||||
|
||||
db_sqlite_lock();
|
||||
err=sqlite_exec_printf(db_sqlite_songs,"INSERT INTO songs VALUES"
|
||||
err=db_sqlite_exec(0,"INSERT INTO songs VALUES "
|
||||
"(NULL," // id
|
||||
"'%q'," // path
|
||||
"'%q'," // fname
|
||||
|
@ -251,8 +305,6 @@ int db_sqlite_add(MP3FILE *pmp3) {
|
|||
"%d," // disabled
|
||||
"%d," // sample_count
|
||||
"0)", // force_update
|
||||
NULL,NULL,
|
||||
&perr,
|
||||
STR(pmp3->path),
|
||||
STR(pmp3->fname),
|
||||
STR(pmp3->title),
|
||||
|
@ -286,7 +338,6 @@ int db_sqlite_add(MP3FILE *pmp3) {
|
|||
pmp3->time_played,
|
||||
pmp3->db_timestamp,
|
||||
pmp3->disabled);
|
||||
db_sqlite_unlock();
|
||||
|
||||
if(err == SQLITE_CONSTRAINT) {
|
||||
/* probably because the path already exists... */
|
||||
|
@ -295,17 +346,10 @@ int db_sqlite_add(MP3FILE *pmp3) {
|
|||
}
|
||||
|
||||
if(err != SQLITE_OK)
|
||||
DPRINTF(E_FATAL,L_DB,"Error inserting file %s in database: %s\n",
|
||||
pmp3->fname,perr);
|
||||
DPRINTF(E_FATAL,L_DB,"Error inserting file %s in database\n",pmp3->fname);
|
||||
|
||||
if((db_sqlite_in_scan)&&(!db_sqlite_reload)) {
|
||||
db_sqlite_lock();
|
||||
err=sqlite_exec(db_sqlite_songs,"INSERT INTO updated VALUES (last_insert_rowid())",
|
||||
NULL,NULL,&perr);
|
||||
if(err != SQLITE_OK)
|
||||
DPRINTF(E_LOG,L_DB,"Error inserting into update table: %s\n",perr);
|
||||
|
||||
db_sqlite_unlock();
|
||||
db_sqlite_exec(1,"INSERT INTO updated VALUES (last_insert_rowid())");
|
||||
}
|
||||
|
||||
DPRINTF(E_SPAM,L_DB,"Exiting db_sqlite_add\n");
|
||||
|
@ -319,15 +363,13 @@ int db_sqlite_add(MP3FILE *pmp3) {
|
|||
*/
|
||||
int db_sqlite_update(MP3FILE *pmp3) {
|
||||
int err;
|
||||
char *perr;
|
||||
|
||||
if(!pmp3->time_modified)
|
||||
pmp3->time_modified = (int)time(NULL);
|
||||
|
||||
pmp3->db_timestamp = (int)time(NULL);
|
||||
|
||||
db_sqlite_lock();
|
||||
err=sqlite_exec_printf(db_sqlite_songs,"UPDATE songs SET "
|
||||
err=db_sqlite_exec(1,"UPDATE songs SET "
|
||||
"title='%q'," // title
|
||||
"artist='%q'," // artist
|
||||
"album='%q'," // album
|
||||
|
@ -355,8 +397,6 @@ int db_sqlite_update(MP3FILE *pmp3) {
|
|||
"rating=%d," // rating
|
||||
"sample_count=%d,"
|
||||
" WHERE path='%q'",
|
||||
NULL,NULL,
|
||||
&perr,
|
||||
STR(pmp3->title),
|
||||
STR(pmp3->artist),
|
||||
STR(pmp3->album),
|
||||
|
@ -384,20 +424,10 @@ int db_sqlite_update(MP3FILE *pmp3) {
|
|||
pmp3->rating,
|
||||
pmp3->sample_count,
|
||||
pmp3->path);
|
||||
db_sqlite_unlock();
|
||||
if(err != SQLITE_OK)
|
||||
DPRINTF(E_FATAL,L_DB,"Error updating file %s in database: %s\n",
|
||||
pmp3->fname,perr);
|
||||
|
||||
if((db_sqlite_in_scan) && (!db_sqlite_reload)) {
|
||||
db_sqlite_lock();
|
||||
err=sqlite_exec_printf(db_sqlite_songs,
|
||||
"INSERT INTO updated (id) select id from songs where path='%q')",
|
||||
NULL,NULL,&perr,pmp3->path);
|
||||
if(err != SQLITE_OK)
|
||||
DPRINTF(E_LOG,L_DB,"Error inserting into update table: %s\n",perr);
|
||||
|
||||
db_sqlite_unlock();
|
||||
db_sqlite_exec(1,"INSERT INTO updated (id) select id from songs where path='%q')",
|
||||
pmp3->path);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -408,40 +438,25 @@ int db_sqlite_update(MP3FILE *pmp3) {
|
|||
* Update the playlist item counts
|
||||
*/
|
||||
int db_sqlite_update_playlists(void) {
|
||||
int err;
|
||||
char *perr;
|
||||
char **resarray;
|
||||
int rows, cols, index;
|
||||
char query[1204];
|
||||
|
||||
db_sqlite_lock();
|
||||
err=sqlite_get_table(db_sqlite_songs,"select * from playlists",&resarray,&rows,&cols,&perr);
|
||||
if(err != SQLITE_OK) {
|
||||
DPRINTF(E_FATAL,L_DB,"Cannot select from playlists: %s\n",perr);
|
||||
}
|
||||
db_sqlite_unlock();
|
||||
db_sqlite_get_table(1,&resarray, &rows, &cols, "SELECT * FROM playlists");
|
||||
|
||||
for(index=1;index <= rows; index ++) {
|
||||
DPRINTF(E_DBG,L_DB,"Updating playlist counts for %s\n",resarray[cols * index + 1]);
|
||||
if(atoi(resarray[cols * index + 2])) { // is a smart playlist
|
||||
snprintf(query,sizeof(query),"UPDATE playlists SET items=(SELECT COUNT(*) "
|
||||
db_sqlite_exec(1,"UPDATE playlsits SET items=(SELECT COUNT(*) "
|
||||
"FROM songs WHERE %s) WHERE id=%s",resarray[cols * index + 4],
|
||||
resarray[cols * index]);
|
||||
} else {
|
||||
snprintf(query,sizeof(query),"UPDATE playlists SET items=(SELECT COUNT(*) "
|
||||
db_sqlite_exec(1,"UPDATE playlists SET items=(SELECT COUNT(*) "
|
||||
"FROM playlistitems WHERE id=%s) WHERE id=%s",
|
||||
resarray[cols * index], resarray[cols * index]);
|
||||
}
|
||||
|
||||
db_sqlite_lock();
|
||||
sqlite_exec(db_sqlite_songs,query,NULL,NULL,&perr);
|
||||
db_sqlite_unlock();
|
||||
}
|
||||
|
||||
|
||||
db_sqlite_lock();
|
||||
sqlite_free_table(resarray);
|
||||
db_sqlite_unlock();
|
||||
db_sqlite_free_table(resarray);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -988,15 +1003,11 @@ void db_sqlite_build_mp3file(char **valarray, MP3FILE *pmp3) {
|
|||
* \param id id to fetch
|
||||
*/
|
||||
MP3FILE *db_sqlite_fetch_item(int id) {
|
||||
int err,rows,cols;
|
||||
char *perr;
|
||||
int rows,cols;
|
||||
char **resarray;
|
||||
MP3FILE *pmp3=NULL;
|
||||
|
||||
db_sqlite_lock();
|
||||
err=sqlite_get_table_printf(db_sqlite_songs,"SELECT * FROM songs WHERE id=%d",
|
||||
&resarray, &rows, &cols, &perr, id);
|
||||
db_sqlite_unlock();
|
||||
db_sqlite_get_table(0,&resarray,&rows,&cols,"SELECT * FROM songs WHERE id=%d",id);
|
||||
|
||||
if(rows != 0) {
|
||||
pmp3=(MP3FILE*)malloc(sizeof(MP3FILE));
|
||||
|
@ -1006,13 +1017,11 @@ MP3FILE *db_sqlite_fetch_item(int id) {
|
|||
db_sqlite_build_mp3file((char **)&resarray[cols],pmp3);
|
||||
}
|
||||
|
||||
db_sqlite_lock();
|
||||
sqlite_free_table(resarray);
|
||||
if((db_sqlite_in_scan) && (!db_sqlite_reload)) {
|
||||
sqlite_exec_printf(db_sqlite_songs,"insert into updated values (%d)",
|
||||
NULL,NULL,&perr,id);
|
||||
db_sqlite_free_table(resarray);
|
||||
|
||||
if ((rows) && (db_sqlite_in_scan) && (!db_sqlite_reload)) {
|
||||
db_sqlite_exec(1,"INSERT INTO updated VALUES (%d)",id);
|
||||
}
|
||||
db_sqlite_unlock();
|
||||
|
||||
return pmp3;
|
||||
}
|
||||
|
@ -1022,21 +1031,12 @@ MP3FILE *db_sqlite_fetch_item(int id) {
|
|||
*
|
||||
* \param path path of the file to retreive
|
||||
*/
|
||||
extern MP3FILE *db_sqlite_fetch_path(char *path) {
|
||||
int err,rows,cols;
|
||||
char *perr;
|
||||
MP3FILE *db_sqlite_fetch_path(char *path) {
|
||||
int rows,cols;
|
||||
char **resarray;
|
||||
MP3FILE *pmp3=NULL;
|
||||
|
||||
/* here's a bit of a hack */
|
||||
if(db_sqlite_reload) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
db_sqlite_lock();
|
||||
err=sqlite_get_table_printf(db_sqlite_songs,"SELECT * FROM songs WHERE path=%q",
|
||||
&resarray, &rows, &cols, &perr, path);
|
||||
db_sqlite_unlock();
|
||||
db_sqlite_get_table(0,&resarray,&rows,&cols,"SELECT * FROM songs WHERE path='%q'",path);
|
||||
|
||||
if(rows != 0) {
|
||||
pmp3=(MP3FILE*)malloc(sizeof(MP3FILE));
|
||||
|
@ -1046,13 +1046,11 @@ extern MP3FILE *db_sqlite_fetch_path(char *path) {
|
|||
db_sqlite_build_mp3file((char **)&resarray[cols],pmp3);
|
||||
}
|
||||
|
||||
db_sqlite_lock();
|
||||
sqlite_free_table(resarray);
|
||||
if((db_sqlite_in_scan)&&(!db_sqlite_reload)) {
|
||||
sqlite_exec_printf(db_sqlite_songs,"INSERT INTO updated VALUES (%d)",
|
||||
NULL,NULL,&perr,pmp3->id);
|
||||
db_sqlite_free_table(resarray);
|
||||
|
||||
if ((rows) && (db_sqlite_in_scan) && (!db_sqlite_reload)) {
|
||||
db_sqlite_exec(1,"INSERT INTO updated VALUES (%d)",pmp3->id);
|
||||
}
|
||||
db_sqlite_unlock();
|
||||
|
||||
return pmp3;
|
||||
}
|
||||
|
@ -1092,8 +1090,7 @@ void db_sqlite_dispose_item(MP3FILE *pmp3) {
|
|||
*/
|
||||
extern int db_sqlite_get_count(CountType_t type) {
|
||||
char *table;
|
||||
int err, rows, cols;
|
||||
char *perr;
|
||||
int rows, cols;
|
||||
char **resarray;
|
||||
int retval=0;
|
||||
|
||||
|
@ -1108,18 +1105,12 @@ extern int db_sqlite_get_count(CountType_t type) {
|
|||
break;
|
||||
}
|
||||
|
||||
db_sqlite_lock();
|
||||
err=sqlite_get_table_printf(db_sqlite_songs,"SELECT COUNT(*) FROM %q",
|
||||
&resarray, &rows, &cols, &perr, table);
|
||||
db_sqlite_unlock();
|
||||
db_sqlite_get_table(0,&resarray, &rows, &cols,"SELECT COUNT(*) FROM %q", table);
|
||||
|
||||
if(rows != 0) {
|
||||
retval=atoi(resarray[cols]);
|
||||
}
|
||||
|
||||
db_sqlite_lock();
|
||||
sqlite_free_table(resarray);
|
||||
db_sqlite_unlock();
|
||||
|
||||
db_sqlite_free_table(resarray);
|
||||
return retval;
|
||||
}
|
||||
|
|
|
@ -50,8 +50,6 @@ static query_node_t *match_string(const query_field_t* field,
|
|||
|
||||
char *query_unescape(const char* query);
|
||||
|
||||
static char *query_lookup_name(char *name);
|
||||
|
||||
|
||||
static query_field_t song_fields[] = {
|
||||
{ qft_string, "dmap.itemname", "title" },
|
||||
|
|
Loading…
Reference in New Issue