* Implement and use new sql_get_int_field() function to simplify getting integers from the database.

This commit is contained in:
Justin Maggard 2009-11-02 19:21:38 +00:00
parent 9712e90bdd
commit 58ecfd6380
8 changed files with 144 additions and 148 deletions

View File

@ -124,19 +124,13 @@ int
inotify_create_watches(int fd)
{
FILE * max_watches;
unsigned int num_watches = 0, watch_limit = 8192;
unsigned int num_watches, watch_limit = 8192;
char **result;
int i, rows = 0;
struct media_dir_s * media_path;
if( sql_get_table(db, "SELECT count(*) from DETAILS where SIZE is NULL and PATH is not NULL", &result, &rows, NULL) == SQLITE_OK )
{
if( rows )
{
num_watches = strtoul(result[1], NULL, 10);
}
sqlite3_free_table(result);
}
i = sql_get_int_field(db, "SELECT count(*) from DETAILS where SIZE is NULL and PATH is not NULL");
num_watches = (i < 0) ? 0 : i;
max_watches = fopen("/proc/sys/fs/inotify/max_user_watches", "r");
if( max_watches )
@ -499,7 +493,6 @@ inotify_remove_file(const char * path)
{
char * sql;
char **result;
char **result2;
char * art_cache;
sqlite_int64 detailID = 0;
int i, rows, children, ret = 1;
@ -525,13 +518,21 @@ inotify_remove_file(const char * path)
{
for( i=1; i < rows; i++ )
{
free(sql);
asprintf(&sql, "SELECT count(*) from OBJECTS where PARENT_ID = '%s'", result[i]);
if( sql_get_table(db, sql, &result2, NULL, NULL) == SQLITE_OK )
children = sql_get_int_field(db, "SELECT count(*) from OBJECTS where PARENT_ID = '%s'", result[i]);
if( children < 0 )
continue;
if( children < 2 )
{
children = atoi(result2[1]);
sqlite3_free_table(result2);
if( children < 2 )
free(sql);
asprintf(&sql, "DELETE from DETAILS where ID ="
" (SELECT DETAIL_ID from OBJECTS where OBJECT_ID = '%s')", result[i]);
sql_exec(db, sql);
free(sql);
asprintf(&sql, "DELETE from OBJECTS where OBJECT_ID = '%s'", result[i]);
sql_exec(db, sql);
*rindex(result[i], '$') = '\0';
if( sql_get_int_field("SELECT count(*) from OBJECTS where PARENT_ID = '%s'", result[i]) == 0 )
{
free(sql);
asprintf(&sql, "DELETE from DETAILS where ID ="
@ -540,23 +541,6 @@ inotify_remove_file(const char * path)
free(sql);
asprintf(&sql, "DELETE from OBJECTS where OBJECT_ID = '%s'", result[i]);
sql_exec(db, sql);
free(sql);
*rindex(result[i], '$') = '\0';
asprintf(&sql, "SELECT count(*) from OBJECTS where PARENT_ID = '%s'", result[i]);
if( sql_get_table(db, sql, &result2, NULL, NULL) == SQLITE_OK )
{
if( atoi(result2[1]) == 0 )
{
free(sql);
asprintf(&sql, "DELETE from DETAILS where ID ="
" (SELECT DETAIL_ID from OBJECTS where OBJECT_ID = '%s')", result[i]);
sql_exec(db, sql);
free(sql);
asprintf(&sql, "DELETE from OBJECTS where OBJECT_ID = '%s'", result[i]);
sql_exec(db, sql);
}
sqlite3_free_table(result2);
}
}
}
}

View File

@ -694,55 +694,45 @@ main(int argc, char * * argv)
}
else
{
char **result;
int rows;
sqlite3_busy_timeout(db, 5000);
if( !new_db && (sql_get_table(db, "SELECT UPDATE_ID from SETTINGS", &result, &rows, 0) == SQLITE_OK) )
if( !new_db )
{
if( rows )
{
updateID = atoi(result[1]);
}
sqlite3_free_table(result);
updateID = sql_get_int_field(db, "SELECT UPDATE_ID from SETTINGS");
}
if( sql_get_table(db, "pragma user_version", &result, &rows, 0) == SQLITE_OK )
if( sql_get_int_field(db, "pragma user_version") != DB_VERSION )
{
if( atoi(result[1]) != DB_VERSION )
if( new_db )
{
if( new_db )
{
DPRINTF(E_WARN, L_GENERAL, "Creating new database...\n");
}
else
{
DPRINTF(E_WARN, L_GENERAL, "Database version mismatch; need to recreate...\n");
}
sqlite3_close(db);
unlink(DB_PATH "/files.db");
system("rm -rf " DB_PATH "/art_cache");
sqlite3_open(DB_PATH "/files.db", &db);
sqlite3_busy_timeout(db, 5000);
if( CreateDatabase() != 0 )
{
DPRINTF(E_FATAL, L_GENERAL, "ERROR: Failed to create sqlite database! Exiting...\n");
}
#if USE_FORK
scanning = 1;
sqlite3_close(db);
scanner_pid = fork();
sqlite3_open(DB_PATH "/files.db", &db);
sqlite3_busy_timeout(db, 5000);
if( !scanner_pid ) // child (scanner) process
{
start_scanner();
sqlite3_close(db);
exit(EXIT_SUCCESS);
}
#else
start_scanner();
#endif
DPRINTF(E_WARN, L_GENERAL, "Creating new database...\n");
}
sqlite3_free_table(result);
else
{
DPRINTF(E_WARN, L_GENERAL, "Database version mismatch; need to recreate...\n");
}
sqlite3_close(db);
unlink(DB_PATH "/files.db");
system("rm -rf " DB_PATH "/art_cache");
sqlite3_open(DB_PATH "/files.db", &db);
sqlite3_busy_timeout(db, 5000);
if( CreateDatabase() != 0 )
{
DPRINTF(E_FATAL, L_GENERAL, "ERROR: Failed to create sqlite database! Exiting...\n");
}
#if USE_FORK
scanning = 1;
sqlite3_close(db);
scanner_pid = fork();
sqlite3_open(DB_PATH "/files.db", &db);
sqlite3_busy_timeout(db, 5000);
if( !scanner_pid ) // child (scanner) process
{
start_scanner();
sqlite3_close(db);
exit(EXIT_SUCCESS);
}
#else
start_scanner();
#endif
}
if( sqlite3_threadsafe() && sqlite3_libversion_number() >= 3005001 &&
GETFLAG(INOTIFY_MASK) && pthread_create(&inotify_thread, NULL, start_inotify, NULL) )

View File

@ -429,16 +429,11 @@ insert_directory(const char * name, const char * path, const char * base, const
{
if( strcmp(id_buf, last_found) == 0 )
break;
sql = sqlite3_mprintf("SELECT count(*) from OBJECTS where OBJECT_ID = '%s'", id_buf);
if( (sql_get_table(db, sql, &result, NULL, NULL) == SQLITE_OK) && atoi(result[1]) )
if( sql_get_int_field(db, "SELECT count(*) from OBJECTS where OBJECT_ID = '%s'", id_buf) > 0 )
{
sqlite3_free_table(result);
sqlite3_free(sql);
strcpy(last_found, id_buf);
break;
}
sqlite3_free_table(result);
sqlite3_free(sql);
/* Does not exist. Need to create, and may need to create parents also */
sql = sqlite3_mprintf("SELECT DETAIL_ID from OBJECTS where OBJECT_ID = '%s'", refID);
if( (sql_get_table(db, sql, &result, &rows, NULL) == SQLITE_OK) && rows )
@ -578,7 +573,7 @@ CreateDatabase(void)
"1$14", "1", "Folders",
"2", "0", "Video",
"2$8", "2", "All Video",
"2$15", "2", "Folders",
VIDEO_DIR_ID, "2", "Folders",
"3", "0", "Pictures",
"3$11", "3", "All Pictures",
"3$12", "3", "Date Taken",
@ -646,11 +641,12 @@ CreateDatabase(void)
if( ret != SQLITE_OK )
goto sql_failed;
ret = sql_exec(db, "CREATE TABLE SETTINGS ("
"UPDATE_ID INTEGER PRIMARY KEY DEFAULT 0"
"UPDATE_ID INTEGER PRIMARY KEY DEFAULT 0, "
"FLAGS INTEGER DEFAULT 0"
")");
if( ret != SQLITE_OK )
goto sql_failed;
ret = sql_exec(db, "INSERT into SETTINGS values (0)");
ret = sql_exec(db, "INSERT into SETTINGS values (0, 0)");
if( ret != SQLITE_OK )
goto sql_failed;
for( i=0; containers[i]; i=i+3 )

60
sql.c
View File

@ -16,6 +16,7 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <stdio.h>
#include <unistd.h>
#include "sql.h"
#include "log.h"
@ -53,3 +54,62 @@ sql_get_table(sqlite3 *db, const char *sql, char ***pazResult, int *pnRow, int *
return ret;
}
int
sql_get_int_field(sqlite3 *db, const char *fmt, ...)
{
va_list ap;
int counter, result;
char *sql;
int ret;
sqlite3_stmt *stmt;
va_start(ap, fmt);
sql = sqlite3_vmprintf(fmt, ap);
//DPRINTF(E_DEBUG, L_DB_SQL, "sql: %s\n", sql);
switch (sqlite3_prepare_v2(db, sql, -1, &stmt, NULL))
{
case SQLITE_OK:
break;
default:
DPRINTF(E_ERROR, L_DB_SQL, "prepare failed: %s\n", sqlite3_errmsg(db));
sqlite3_free(sql);
return -1;
}
sqlite3_free(sql);
for (counter = 0;
((result = sqlite3_step(stmt)) == SQLITE_BUSY || result == SQLITE_LOCKED) && counter < 2;
counter++) {
/* While SQLITE_BUSY has a built in timeout,
SQLITE_LOCKED does not, so sleep */
if (result == SQLITE_LOCKED)
sleep(1);
}
switch (result)
{
case SQLITE_DONE:
/* no rows returned */
ret = 0;
break;
case SQLITE_ROW:
if (sqlite3_column_type(stmt, 0) == SQLITE_NULL)
{
ret = 0;
break;
}
ret = sqlite3_column_int(stmt, 0);
break;
default:
DPRINTF(E_WARN, L_DB_SQL, "%s: step failed: %s\n", __func__, sqlite3_errmsg(db));
ret = -1;
break;
}
sqlite3_finalize(stmt);
return ret;
}

3
sql.h
View File

@ -18,4 +18,7 @@ sql_exec(sqlite3 * db, const char * sql);
int
sql_get_table(sqlite3 *db, const char *zSql, char ***pazResult, int *pnRow, int *pnColumn);
int
sql_get_int_field(sqlite3 *db, const char *fmt, ...);
#endif

View File

@ -111,9 +111,7 @@ int callback(void *args, int argc, char **argv, char **azColName)
*bitrate = argv[6], *sampleFrequency = argv[7], *artist = argv[8], *album = argv[9], *genre = argv[10],
*comment = argv[11], *date = argv[12], *resolution = argv[13], *mime = argv[14], *path = argv[15];
char str_buf[4096];
char **result;
int flags = 0;
int ret = 0;
int ret = 0, flags = 0, count;
if( strncmp(class, "item", 4) == 0 )
{
@ -256,19 +254,18 @@ int callback(void *args, int argc, char **argv, char **azColName)
{
/* Determine the number of children */
#ifdef __sparc__ /* Adding filters on large containers can take a long time on slow processors */
sprintf(str_buf, "SELECT count(*) from OBJECTS where PARENT_ID = '%s'", id);
count = sql_get_int_field(db, "SELECT count(*) from OBJECTS where PARENT_ID = '%s'", id);
#else
sprintf(str_buf, "SELECT count(*) from OBJECTS o left join DETAILS d on (d.ID = o.DETAIL_ID) where PARENT_ID = '%s' and "
" (MIME in ('image/jpeg', 'audio/mpeg', 'video/mpeg', 'video/x-tivo-mpeg')"
" or CLASS glob 'container*')", id);
count = sql_get_int_field(db, "SELECT count(*) from OBJECTS o left join DETAILS d on (d.ID = o.DETAIL_ID) where PARENT_ID = '%s' and "
" (MIME in ('image/jpeg', 'audio/mpeg', 'video/mpeg', 'video/x-tivo-mpeg')"
" or CLASS glob 'container*')", id);
#endif
ret = sql_get_table(db, str_buf, &result, NULL, NULL);
ret = sprintf(str_buf, "<Item>"
"<Details>"
"<ContentType>x-container/folder</ContentType>"
"<SourceFormat>x-container/folder</SourceFormat>"
"<Title>%s</Title>"
"<TotalItems>%s</TotalItems>"
"<TotalItems>%d</TotalItems>"
"</Details>"
"<Links>"
"<Content>"
@ -276,8 +273,7 @@ int callback(void *args, int argc, char **argv, char **azColName)
"<ContentType>x-tivo-container/folder</ContentType>"
"</Content>"
"</Links>",
unescape_tag(title), result[1], id);
sqlite3_free_table(result);
unescape_tag(title), count, id);
}
memcpy(passed_args->resp+passed_args->size, &str_buf, ret+1);
passed_args->size += ret;
@ -568,18 +564,11 @@ SendContainer(struct upnphttp * h, const char * objectID, int itemStart, int ite
args.start = itemStart+anchorOffset;
sqlite3Prng.isInit = 0;
asprintf(&sql, "SELECT count(distinct DETAIL_ID) "
"from OBJECTS o left join DETAILS d on (o.DETAIL_ID = d.ID)"
" where %s and (%s)",
which, myfilter);
DPRINTF(E_DEBUG, L_TIVO, "Count SQL: %s\n", sql);
ret = sql_get_table(db, sql, &result, NULL, NULL);
if( ret == SQLITE_OK )
{
totalMatches = atoi(result[1]);
sqlite3_free_table(result);
}
free(sql);
ret = sql_get_int_field(db, "SELECT count(distinct DETAIL_ID) "
"from OBJECTS o left join DETAILS d on (o.DETAIL_ID = d.ID)"
" where %s and (%s)",
which, myfilter);
totalMatches = (ret > 0) ? ret : 0;
sql = sqlite3_mprintf("SELECT o.OBJECT_ID, o.CLASS, o.DETAIL_ID, d.SIZE, d.TITLE,"
" d.DURATION, d.BITRATE, d.SAMPLERATE, d.ARTIST, d.ALBUM,"

View File

@ -21,11 +21,11 @@
#include <sqlite3.h>
#define MINIDLNA_VERSION "1.0.16-pre7"
#define MINIDLNA_VERSION "1.0.16"
#define CLIENT_CACHE_SLOTS 20
#define USE_FORK 1
#define DB_VERSION 3
#define DB_VERSION 4
#if 0 // Add these once the newer ffmpeg libs that can detect WMAPRO are more widely used
"http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_PRO;DLNA.ORG_OP=01;DLNA.ORG_CI=0,"

View File

@ -30,6 +30,7 @@
#include "upnpreplyparse.h"
#include "getifaddr.h"
#include "scanner.h"
#include "utils.h"
#include "sql.h"
#include "log.h"
@ -532,7 +533,6 @@ callback(void *args, int argc, char **argv, char **azColName)
char dlna_buf[96];
char ext[5];
char str_buf[512];
char **result;
int children, ret = 0;
/* Make sure we have at least 4KB left of allocated memory to finish the response. */
@ -777,15 +777,8 @@ callback(void *args, int argc, char **argv, char **azColName)
passed_args->size += ret;
if( passed_args->filter & FILTER_CHILDCOUNT )
{
sprintf(str_buf, "SELECT count(*) from OBJECTS where PARENT_ID = '%s';", id);
ret = sql_get_table(db, str_buf, &result, NULL, NULL);
if( ret == SQLITE_OK ) {
children = atoi(result[1]);
sqlite3_free_table(result);
}
else {
children = 0;
}
ret = sql_get_int_field(db, "SELECT count(*) from OBJECTS where PARENT_ID = '%s';", id);
children = (ret > 0) ? ret : 0;
ret = sprintf(str_buf, "childCount=\"%d\"", children);
memcpy(passed_args->resp+passed_args->size, &str_buf, ret+1);
passed_args->size += ret;
@ -860,10 +853,9 @@ BrowseContentDirectory(struct upnphttp * h, const char * action)
char str_buf[512];
char *zErrMsg = 0;
char *sql, *ptr;
char **result;
int ret;
struct Response args;
int totalMatches = 0;
int totalMatches;
struct NameValueParserData data;
*resp = '\0';
@ -924,7 +916,7 @@ BrowseContentDirectory(struct upnphttp * h, const char * action)
if( strcmp(ObjectId, "16") == 0 )
ObjectId = strdup("3$16");
else if( strcmp(ObjectId, "15") == 0 )
ObjectId = strdup("2$15");
ObjectId = strdup(VIDEO_DIR_ID);
else
ObjectId = strdup(ObjectId);
}
@ -950,12 +942,8 @@ BrowseContentDirectory(struct upnphttp * h, const char * action)
}
else
{
sprintf(str_buf, "SELECT count(*) from OBJECTS where PARENT_ID = '%s'", ObjectId);
ret = sql_get_table(db, str_buf, &result, NULL, NULL);
if( ret == SQLITE_OK ) {
totalMatches = atoi(result[1]);
sqlite3_free_table(result);
}
ret = sql_get_int_field(db, "SELECT count(*) from OBJECTS where PARENT_ID = '%s'", ObjectId);
totalMatches = (ret > 0) ? ret : 0;
#ifdef __sparc__ /* Sorting takes too long on slow processors with very large containers */
ret = 0;
if( totalMatches < 10000 )
@ -984,15 +972,8 @@ BrowseContentDirectory(struct upnphttp * h, const char * action)
/* Does the object even exist? */
if( !totalMatches )
{
ret = 0;
sql = sqlite3_mprintf("SELECT count(*) from OBJECTS where OBJECT_ID = '%q'", ObjectId);
if( sql_get_table(db, sql, &result, NULL, NULL) == SQLITE_OK )
{
ret = atoi(result[1]);
sqlite3_free_table(result);
}
sqlite3_free(sql);
if( !ret )
ret = sql_get_int_field(db, "SELECT count(*) from OBJECTS where OBJECT_ID = '%s'", ObjectId);
if( ret <= 0 )
{
SoapError(h, 701, "No such object error");
goto browse_error;
@ -1184,16 +1165,9 @@ SearchContentDirectory(struct upnphttp * h, const char * action)
/* Does the object even exist? */
if( !totalMatches )
{
ret = 0;
sql = sqlite3_mprintf("SELECT count(*) from OBJECTS where OBJECT_ID = '%q'",
!strcmp(ContainerID, "*")?"0":ContainerID);
if( sql_get_table(db, sql, &result, NULL, NULL) == SQLITE_OK )
{
ret = atoi(result[1]);
sqlite3_free_table(result);
}
sqlite3_free(sql);
if( !ret )
ret = sql_get_int_field(db, "SELECT count(*) from OBJECTS where OBJECT_ID = '%q'",
!strcmp(ContainerID, "*")?"0":ContainerID);
if( ret <= 0 )
{
SoapError(h, 710, "No such container");
goto search_error;