Issue #69: refactor all Rhizome SQL queries to use binding

Remove all uses of sprintf(3) and its ilk to form SQL query commands.
Use the new sqlite_bind() and sqlite_prepare_bind() functions instead.
This commit is contained in:
Andrew Bettison 2013-10-03 15:15:30 +09:30
parent 41c862ea30
commit 7e3a552011
8 changed files with 269 additions and 190 deletions

View File

@ -140,7 +140,7 @@ int rhizome_bundle_import_files(rhizome_manifest *m, const char *manifest_path,
/* Do we already have this manifest or newer? */
int64_t dbVersion = -1;
const char *id=rhizome_manifest_get(m, "id", NULL, 0);
if (sqlite_exec_int64(&dbVersion, "SELECT version FROM MANIFESTS WHERE id='%s';", id) == -1)
if (sqlite_exec_int64(&dbVersion, "SELECT version FROM MANIFESTS WHERE id = ?;", TEXT_TOUPPER, id, END) == -1)
return WHY("Select failure");
if (dbVersion>=m->version)
@ -266,10 +266,9 @@ int rhizome_add_manifest(rhizome_manifest *m_in,int ttl)
/* no manifest ID */
return WHY("Manifest does not have an ID");
str_toupper_inplace(id);
/* Discard the new manifest unless it is newer than the most recent known version with the same ID */
int64_t storedversion = -1;
switch (sqlite_exec_int64(&storedversion, "SELECT version from manifests where id='%s';", id)) {
switch (sqlite_exec_int64(&storedversion, "SELECT version FROM MANIFESTS WHERE id = ?;", TEXT_TOUPPER, id, END)) {
case -1:
return WHY("Select failed");
case 0:

View File

@ -296,32 +296,36 @@ int is_debug_rhizome_ads();
enum sqlbind_type {
END = 0xbabecafe,
NUL = 0xbeef, // int index
INT, // int index, int value
INT64, // int index, int64_t value
STATIC_TEXT, // int index, const char *text,
STATIC_TEXT_LEN, // int index, const char *text, int bytes
STATIC_BLOB, // int index, const void *blob, int bytes
SID_T, // int index, const sid_t *sidp
BUNDLE_ID_T, // int index, const unsigned char bid_binary[RHIZOME_BUNDLE_ID_BYTES]
FILEHASH_T, // int index, const unsigned char hash_binary[RHIZOME_FILEHASH_BYTES]
TOHEX, // int index, const unsigned char *binary, unsigned bytes
TEXT_TOUPPER, // int index, const char *text,
TEXT_LEN_TOUPPER, // int index, const char *text, unsigned bytes
NUL = 0xbeef, // (no arg)
INT, // int value
INT_TOSTR, // int value
UINT_TOSTR, // unsigned value
INT64, // int64_t value
INT64_TOSTR, // int64_t value
UINT64_TOSTR, // uint64_t value
STATIC_TEXT, // const char *text,
STATIC_TEXT_LEN, // const char *text, int bytes
STATIC_BLOB, // const void *blob, int bytes
ZEROBLOB, // int bytes
SID_T, // const sid_t *sidp
BUNDLE_ID_T, // const unsigned char bid_binary[RHIZOME_BUNDLE_ID_BYTES]
FILEHASH_T, // const unsigned char hash_binary[RHIZOME_FILEHASH_BYTES]
TOHEX, // const unsigned char *binary, unsigned bytes
TEXT_TOUPPER, // const char *text,
TEXT_LEN_TOUPPER, // const char *text, unsigned bytes
INDEX = 0xfade0000, // INDEX|INT, int index, ...
NAMED = 0xdead0000 // NAMED|INT, const char *label, ...
};
sqlite3_stmt *_sqlite_prepare_bind_loglevel(struct __sourceloc, int log_level, sqlite_retry_state *retry, const char *sqltext, ...);
sqlite3_stmt *_sqlite_prepare(struct __sourceloc, int log_level, sqlite_retry_state *retry, const char *sqltext);
int _sqlite_bind(struct __sourceloc __whence, int log_level, sqlite_retry_state *retry, sqlite3_stmt *statement, ...);
int _sqlite_vbind(struct __sourceloc __whence, int log_level, sqlite_retry_state *retry, sqlite3_stmt *statement, va_list ap);
sqlite3_stmt *_sqlite_prepare_bind(struct __sourceloc, int log_level, sqlite_retry_state *retry, const char *sqltext, ...);
int _sqlite_retry(struct __sourceloc, sqlite_retry_state *retry, const char *action);
void _sqlite_retry_done(struct __sourceloc, sqlite_retry_state *retry, const char *action);
int _sqlite_step_retry(struct __sourceloc, int log_level, sqlite_retry_state *retry, sqlite3_stmt *statement);
int _sqlite_exec_void(struct __sourceloc, const char *sqltext, ...);
int _sqlite_exec_void_loglevel(struct __sourceloc, int log_level, const char *sqltext, ...);
int _sqlite_exec_void_retry(struct __sourceloc, sqlite_retry_state *retry, const char *sqltext, ...);
int _sqlite_exec_void_retry_loglevel(struct __sourceloc, int log_level, sqlite_retry_state *retry, const char *sqltext, ...);
int _sqlite_step(struct __sourceloc, int log_level, sqlite_retry_state *retry, sqlite3_stmt *statement);
int _sqlite_exec_void(struct __sourceloc, int log_level, const char *sqltext, ...);
int _sqlite_exec_void_retry(struct __sourceloc, int log_level, sqlite_retry_state *retry, const char *sqltext, ...);
int _sqlite_exec_int64(struct __sourceloc, int64_t *result, const char *sqltext, ...);
int _sqlite_exec_int64_retry(struct __sourceloc, sqlite_retry_state *retry, int64_t *result, const char *sqltext, ...);
int _sqlite_exec_strbuf(struct __sourceloc, strbuf sb, const char *sqltext, ...);
@ -332,18 +336,20 @@ int _sqlite_vexec_strbuf_retry(struct __sourceloc, sqlite_retry_state *retry, st
// they serve a very useful purpose, so don't remove them! They ensure that
// programmers do not forget the bind args, of which there must be at least
// one, even if it is only 'END' to make no bindings at all.
#define sqlite_prepare(rs,sql) _sqlite_prepare_bind_loglevel(__WHENCE__, LOG_LEVEL_ERROR, (rs), (sql), END)
#define sqlite_prepare_loglevel(ll,rs,sql) _sqlite_prepare_bind_loglevel(__WHENCE__, (ll), (rs), (sql), END)
#define sqlite_prepare_bind(rs,sql,arg,...) _sqlite_prepare_bind_loglevel(__WHENCE__, LOG_LEVEL_ERROR, (rs), (sql), arg, ##__VA_ARGS__)
#define sqlite_prepare_bind_loglevel(ll,rs,sql,arg,...) _sqlite_prepare_bind_loglevel(__WHENCE__, (ll), (rs), (sql), arg, ##__VA_ARGS__)
#define sqlite_prepare(rs,sql) _sqlite_prepare(__WHENCE__, LOG_LEVEL_ERROR, (rs), (sql))
#define sqlite_prepare_loglevel(ll,rs,sql) _sqlite_prepare(__WHENCE__, (ll), (rs), (sql))
#define sqlite_prepare_bind(rs,sql,arg,...) _sqlite_prepare_bind(__WHENCE__, LOG_LEVEL_ERROR, (rs), (sql), arg, ##__VA_ARGS__)
#define sqlite_prepare_bind_loglevel(ll,rs,sql,arg,...) _sqlite_prepare_bind(__WHENCE__, (ll), (rs), (sql), arg, ##__VA_ARGS__)
#define sqlite_bind(rs,stmt,arg,...) _sqlite_bind(__WHENCE__, LOG_LEVEL_ERROR, (rs), (stmt), arg, ##__VA_ARGS__)
#define sqlite_bind_loglevel(ll,rs,stmt,arg,...) _sqlite_bind(__WHENCE__, (ll), (rs), (stmt), arg, ##__VA_ARGS__)
#define sqlite_retry(rs,action) _sqlite_retry(__WHENCE__, (rs), (action))
#define sqlite_retry_done(rs,action) _sqlite_retry_done(__WHENCE__, (rs), (action))
#define sqlite_step(stmt) _sqlite_step_retry(__WHENCE__, LOG_LEVEL_ERROR, NULL, (stmt))
#define sqlite_step_retry(rs,stmt) _sqlite_step_retry(__WHENCE__, LOG_LEVEL_ERROR, (rs), (stmt))
#define sqlite_exec_void(sql,arg,...) _sqlite_exec_void(__WHENCE__, (sql), ##__VA_ARGS__)
#define sqlite_exec_void_loglevel(ll,sql,arg,...) _sqlite_exec_void_loglevel(__WHENCE__, (ll), (sql), arg, ##__VA_ARGS__)
#define sqlite_exec_void_retry(rs,sql,arg,...) _sqlite_exec_void_retry(__WHENCE__, (rs), (sql), arg, ##__VA_ARGS__)
#define sqlite_exec_void_retry_loglevel(ll,rs,sql,arg,...) _sqlite_exec_void_retry_loglevel(__WHENCE__, (ll), (rs), (sql), arg, ##__VA_ARGS__)
#define sqlite_step(stmt) _sqlite_step(__WHENCE__, LOG_LEVEL_ERROR, NULL, (stmt))
#define sqlite_step_retry(rs,stmt) _sqlite_step(__WHENCE__, LOG_LEVEL_ERROR, (rs), (stmt))
#define sqlite_exec_void(sql,arg,...) _sqlite_exec_void(__WHENCE__, LOG_LEVEL_ERROR, (sql), arg, ##__VA_ARGS__)
#define sqlite_exec_void_loglevel(ll,sql,arg,...) _sqlite_exec_void(__WHENCE__, (ll), (sql), arg, ##__VA_ARGS__)
#define sqlite_exec_void_retry(rs,sql,arg,...) _sqlite_exec_void_retry(__WHENCE__, LOG_LEVEL_ERROR, (rs), (sql), arg, ##__VA_ARGS__)
#define sqlite_exec_void_retry_loglevel(ll,rs,sql,arg,...) _sqlite_exec_void_retry(__WHENCE__, (ll), (rs), (sql), arg, ##__VA_ARGS__)
#define sqlite_exec_int64(res,sql,arg,...) _sqlite_exec_int64(__WHENCE__, (res), (sql), arg, ##__VA_ARGS__)
#define sqlite_exec_int64_retry(rs,res,sql,arg,...) _sqlite_exec_int64_retry(__WHENCE__, (rs), (res), (sql), arg, ##__VA_ARGS__)
#define sqlite_exec_strbuf(sb,sql,arg,...) _sqlite_exec_strbuf(__WHENCE__, (sb), (sql), arg, ##__VA_ARGS__)

View File

@ -373,10 +373,9 @@ int rhizome_find_bundle_author(rhizome_manifest *m)
DEBUGF("found bundle author sid=%s", alloca_tohex_sid(m->author));
// if this bundle is already in the database, update the author.
if (m->inserttime){
if (m->inserttime) {
const char *id = rhizome_manifest_get(m, "id", NULL, 0);
if (sqlite_exec_void("UPDATE MANIFESTS SET author='%s' WHERE id='%s';", alloca_tohex_sid(m->author), id) == -1)
WARN("Error updating MANIFESTS author column");
sqlite_exec_void_loglevel(LOG_LEVEL_WARN, "UPDATE MANIFESTS SET author = ? WHERE id = ?;", SID_T, (sid_t*)m->author, TEXT_TOUPPER, id, END);
}
}

View File

@ -178,7 +178,7 @@ void verify_bundles(){
* that has write permission on the bundle, ie, possesses the Rhizome secret key that generated the
* BID, and hence can derive the Bundle Secret from the bundle's BK field:
* - The MANIFESTS table 'author' column is set to the author SID when a bundle is created
* locally bu a non-secret identity, so no verification need ever be performed for one's own
* locally by a non-secret identity, so no verification need be performed for one's own
* bundles while they remain in the Rhizome store.
* - When a bundle is imported, the 'author' column is set to NULL to indicate that no
* verification has passed yet. This includes one's own bundles that have been purged from
@ -411,22 +411,23 @@ void _sqlite_retry_done(struct __sourceloc __whence, sqlite_retry_state *retry,
retry->start = -1;
}
/* Prepare an SQL command from a simple string. Returns -1 if an error occurs (logged as an error),
* otherwise zero with the prepared statement in *statement.
/* Prepare an SQL command from a simple string. Returns NULL if an error occurs (logged as an
* error), otherwise returns a pointer to the prepared SQLite statement.
*
* IMPORTANT! Do not form statement strings using sprintf(3) or strbuf_sprintf() or similar
* methods, because those are susceptible to SQL injection attacks. Instead, use bound parameters
* and bind them using the sqlite_bind() function below.
* and bind them using the _sqlite_bind() function below.
*
* ALSO! Do not add sprintf(3)-like functionality to this method. It used to take sprintf(3)-style
* varargs and these were deliberately removed. It is vital to discourage bad practice, and adding
* sprintf(3)-style args to this function would be a step in the wrong direction.
* IMPORTANT! Do not add sprintf(3)-like functionality to this method. It used to take
* sprintf(3)-style varargs and these were deliberately removed. It is vital to discourage bad
* practice, and adding sprintf(3)-style args to this function would be a step in the wrong
* direction.
*
* See GitHub issue #69.
*
* @author Andrew Bettison <andrew@servalproject.com>
*/
sqlite3_stmt *_sqlite_prepare_loglevel(struct __sourceloc __whence, int log_level, sqlite_retry_state *retry, const char *sqltext)
sqlite3_stmt *_sqlite_prepare(struct __sourceloc __whence, int log_level, sqlite_retry_state *retry, const char *sqltext)
{
IN();
sqlite3_stmt *statement = NULL;
@ -450,14 +451,23 @@ sqlite3_stmt *_sqlite_prepare_loglevel(struct __sourceloc __whence, int log_leve
}
}
/* Bind some parameters to a prepared SQL statement. Returns -1 if an error occurs (logged as an
* error), otherwise zero with the prepared statement in *statement.
*
* Developed as part of GitHub issue #69.
*
* @author Andrew Bettison <andrew@servalproject.com>
*/
int _sqlite_vbind(struct __sourceloc __whence, int log_level, sqlite_retry_state *retry, sqlite3_stmt *statement, va_list ap)
{
const int index_limit = 50; // for safety checks
const int index_limit = sqlite3_limit(rhizome_db, SQLITE_LIMIT_VARIABLE_NUMBER, -1);
enum sqlbind_type typ;
int index_counter = 0;
strbuf ext = NULL;
do {
typ = va_arg(ap, int);
int index;
const char *name = NULL;
if ((typ & 0xffff0000) == INDEX) {
typ &= 0xffff;
index = va_arg(ap, int);
@ -465,16 +475,29 @@ int _sqlite_vbind(struct __sourceloc __whence, int log_level, sqlite_retry_state
LOGF(log_level, "illegal index %d: %s", index, sqlite3_sql(statement));
return -1;
}
if (config.debug.rhizome)
strbuf_sprintf((ext = strbuf_alloca(25)), "|INDEX index=%d", index);
} else if ((typ & 0xffff0000) == NAMED) {
typ &= 0xffff;
const char *name = va_arg(ap, const char *);
name = va_arg(ap, const char *);
index = sqlite3_bind_parameter_index(statement, name);
if (index == 0) {
LOGF(log_level, "no parameter %s in query: %s", alloca_str_toprint(name), sqlite3_sql(statement));
return -1;
}
} else
if (config.debug.rhizome) {
ext = strbuf_alloca(20 + toprint_str_len(name, "\"\""));
strbuf_puts(ext, "|NAMED name=");
strbuf_toprint_quoted(ext, "\"\"", name);
}
} else {
index = ++index_counter;
if (config.debug.rhizome)
ext = strbuf_alloca(1);
}
#define BIND_DEBUG(TYP,FUNC,ARGFMT,...) \
if (config.debug.rhizome) \
DEBUGF("%s%s %s(%d," ARGFMT ") %s", #TYP, strbuf_str(ext), #FUNC, index, ##__VA_ARGS__, sqlite3_sql(statement))
#define BIND_RETRY(FUNC, ...) \
do { \
switch (FUNC(statement, index, ##__VA_ARGS__)) { \
@ -492,68 +515,115 @@ int _sqlite_vbind(struct __sourceloc __whence, int log_level, sqlite_retry_state
break; \
} while (1)
switch (typ) {
case END: break;
case END:
break;
case NUL:
BIND_DEBUG(NUL, sqlite3_bind_null, "");
BIND_RETRY(sqlite3_bind_null);
break;
case INT: {
int value = va_arg(ap, int);
BIND_DEBUG(INT, sqlite3_bind_int, "%d", value);
BIND_RETRY(sqlite3_bind_int, value);
}
break;
case INT_TOSTR: {
int value = va_arg(ap, int);
char str[25];
sprintf(str, "%d", value);
BIND_DEBUG(INT_TOSTR, sqlite3_bind_text, "%s,-1,SQLITE_TRANSIENT", alloca_str_toprint(str));
BIND_RETRY(sqlite3_bind_text, str, -1, SQLITE_TRANSIENT);
}
break;
case UINT_TOSTR: {
unsigned value = va_arg(ap, unsigned);
char str[25];
sprintf(str, "%u", value);
BIND_DEBUG(UINT_TOSTR, sqlite3_bind_text, "%s,-1,SQLITE_TRANSIENT", alloca_str_toprint(str));
BIND_RETRY(sqlite3_bind_text, str, -1, SQLITE_TRANSIENT);
}
break;
case INT64: {
int64_t value = va_arg(ap, int64_t);
BIND_DEBUG(INT64, sqlite3_bind_int64, "%"PRId64, value);
BIND_RETRY(sqlite3_bind_int64, value);
}
break;
case INT64_TOSTR: {
int64_t value = va_arg(ap, int64_t);
char str[35];
sprintf(str, "%"PRId64, value);
BIND_DEBUG(INT64_TOSTR, sqlite3_bind_text, "%s,-1,SQLITE_TRANSIENT", alloca_str_toprint(str));
BIND_RETRY(sqlite3_bind_text, str, -1, SQLITE_TRANSIENT);
}
break;
case UINT64_TOSTR: {
uint64_t value = va_arg(ap, uint64_t);
char str[35];
sprintf(str, "%"PRIu64, value);
BIND_DEBUG(UINT64_TOSTR, sqlite3_bind_text, "%s,-1,SQLITE_TRANSIENT", alloca_str_toprint(str));
BIND_RETRY(sqlite3_bind_text, str, -1, SQLITE_TRANSIENT);
}
break;
case STATIC_TEXT: {
const char *text = va_arg(ap, const char *);
BIND_DEBUG(STATIC_TEXT, sqlite3_bind_text, "%s,-1,SQLITE_STATIC", alloca_str_toprint(text));
BIND_RETRY(sqlite3_bind_text, text, -1, SQLITE_STATIC);
}
break;
case STATIC_TEXT_LEN: {
const char *text = va_arg(ap, const char *);
int bytes = va_arg(ap, int);
BIND_DEBUG(STATIC_TEXT_LEN, sqlite3_bind_text, "%s,%d,SQLITE_STATIC", alloca_str_toprint(text), bytes);
BIND_RETRY(sqlite3_bind_text, text, bytes, SQLITE_STATIC);
}
break;
case STATIC_BLOB: {
const void *blob = va_arg(ap, const void *);
int bytes = va_arg(ap, int);
BIND_DEBUG(STATIC_BLOB, sqlite3_bind_blob, "%s,%d,SQLITE_STATIC", alloca_toprint(20, blob, bytes), bytes);
BIND_RETRY(sqlite3_bind_blob, blob, bytes, SQLITE_STATIC);
};
break;
case ZEROBLOB: {
int bytes = va_arg(ap, int);
BIND_DEBUG(ZEROBLOB, sqlite3_bind_zeroblob, "%d,SQLITE_STATIC", bytes);
BIND_RETRY(sqlite3_bind_zeroblob, bytes);
};
break;
case SID_T: {
const sid_t *sidp = va_arg(ap, const sid_t *);
const char *sid_hex = alloca_tohex_sid_t(*sidp);
BIND_DEBUG(SID_T, sqlite3_bind_text, "%s,%d,SQLITE_TRANSIENT", sid_hex, SID_STRLEN);
BIND_RETRY(sqlite3_bind_text, sid_hex, SID_STRLEN, SQLITE_TRANSIENT);
}
break;
case BUNDLE_ID_T: {
const char *bid_hex = alloca_tohex(va_arg(ap, const unsigned char *), RHIZOME_MANIFEST_ID_BYTES);
BIND_DEBUG(BUNDLE_ID_T, sqlite3_bind_text, "%s,%d,SQLITE_TRANSIENT", bid_hex, RHIZOME_MANIFEST_ID_STRLEN);
BIND_RETRY(sqlite3_bind_text, bid_hex, RHIZOME_MANIFEST_ID_STRLEN, SQLITE_TRANSIENT);
}
break;
case FILEHASH_T: {
const char *hash_hex = alloca_tohex(va_arg(ap, const unsigned char *), RHIZOME_FILEHASH_BYTES);
BIND_DEBUG(FILEHASH_T, sqlite3_bind_text, "%s,%d,SQLITE_TRANSIENT", hash_hex, RHIZOME_FILEHASH_STRLEN);
BIND_RETRY(sqlite3_bind_text, hash_hex, RHIZOME_FILEHASH_STRLEN, SQLITE_TRANSIENT);
}
break;
case TOHEX: {
const unsigned char *binary = va_arg(ap, const unsigned char *);
unsigned bytes = va_arg(ap, unsigned);
char hex[bytes * 2];
tohex(hex, binary, bytes);
const char *hex = alloca_tohex(binary, bytes);
BIND_DEBUG(TOHEX, sqlite3_bind_text, "%s,%d,SQLITE_TRANSIENT", hex, bytes * 2);
BIND_RETRY(sqlite3_bind_text, hex, bytes * 2, SQLITE_TRANSIENT);
}
break;
case TEXT_TOUPPER: {
const char *text = va_arg(ap, const char *);
unsigned bytes = strlen(text);
char upper[bytes];
unsigned i;
for (i = 0; i != bytes; ++i)
upper[i] = toupper(text[i]);
char upper[bytes + 1];
str_toupper_inplace(strcpy(upper, text));
BIND_DEBUG(TEXT_TOUPPER, sqlite3_bind_text, "%s,%d,SQLITE_TRANSIENT", alloca_toprint(-1, upper, bytes), bytes);
BIND_RETRY(sqlite3_bind_text, upper, bytes, SQLITE_TRANSIENT);
}
break;
@ -564,11 +634,13 @@ int _sqlite_vbind(struct __sourceloc __whence, int log_level, sqlite_retry_state
unsigned i;
for (i = 0; i != bytes; ++i)
upper[i] = toupper(text[i]);
BIND_DEBUG(TEXT_LEN_TOUPPER, sqlite3_bind_text, "%s,%d,SQLITE_TRANSIENT", alloca_toprint(-1, upper, bytes), bytes);
BIND_RETRY(sqlite3_bind_text, upper, bytes, SQLITE_TRANSIENT);
}
break;
#undef BIND_RETRY
default:
FATALF("unsupported bind code %d", typ);
FATALF("unsupported bind code, index=%d typ=0x%08x: %s", index, typ, sqlite3_sql(statement));
}
} while (typ != END);
return 0;
@ -583,7 +655,28 @@ int _sqlite_bind(struct __sourceloc __whence, int log_level, sqlite_retry_state
return ret;
}
int _sqlite_step_retry(struct __sourceloc __whence, int log_level, sqlite_retry_state *retry, sqlite3_stmt *statement)
/* Prepare an SQL statement and bind some parameters. Returns a pointer to the SQLite statement if
* successful or NULL if an error occurs (which is logged at the given log level).
*
* @author Andrew Bettison <andrew@servalproject.com>
*/
sqlite3_stmt *_sqlite_prepare_bind(struct __sourceloc __whence, int log_level, sqlite_retry_state *retry, const char *sqltext, ...)
{
sqlite3_stmt *statement = _sqlite_prepare(__whence, log_level, retry, sqltext);
if (statement != NULL) {
va_list ap;
va_start(ap, sqltext);
int ret = _sqlite_vbind(__whence, log_level, retry, statement, ap);
va_end(ap);
if (ret == -1) {
sqlite3_finalize(statement);
statement = NULL;
}
}
return statement;
}
int _sqlite_step(struct __sourceloc __whence, int log_level, sqlite_retry_state *retry, sqlite3_stmt *statement)
{
IN();
int ret = -1;
@ -633,13 +726,13 @@ int _sqlite_step_retry(struct __sourceloc __whence, int log_level, sqlite_retry_
*
* @author Andrew Bettison <andrew@servalproject.com>
*/
static int _sqlite_exec_prepared(struct __sourceloc __whence, int log_level, sqlite_retry_state *retry, sqlite3_stmt *statement)
static int _sqlite_exec(struct __sourceloc __whence, int log_level, sqlite_retry_state *retry, sqlite3_stmt *statement)
{
if (!statement)
return -1;
int rowcount = 0;
int stepcode;
while ((stepcode = _sqlite_step_retry(__whence, log_level, retry, statement)) == SQLITE_ROW)
while ((stepcode = _sqlite_step(__whence, log_level, retry, statement)) == SQLITE_ROW)
++rowcount;
sqlite3_finalize(statement);
if (sqlite_trace_func())
@ -654,12 +747,12 @@ static int _sqlite_exec_prepared(struct __sourceloc __whence, int log_level, sql
*/
static int _sqlite_vexec_void(struct __sourceloc __whence, int log_level, sqlite_retry_state *retry, const char *sqltext, va_list ap)
{
sqlite3_stmt *statement = _sqlite_prepare_loglevel(__whence, log_level, retry, sqltext);
sqlite3_stmt *statement = _sqlite_prepare(__whence, log_level, retry, sqltext);
if (!statement)
return -1;
if (_sqlite_vbind(__whence, log_level, retry, statement, ap) == -1)
return -1;
int rowcount = _sqlite_exec_prepared(__whence, log_level, retry, statement);
int rowcount = _sqlite_exec(__whence, log_level, retry, statement);
if (rowcount == -1)
return -1;
if (rowcount)
@ -673,21 +766,7 @@ static int _sqlite_vexec_void(struct __sourceloc __whence, int log_level, sqlite
*
* @author Andrew Bettison <andrew@servalproject.com>
*/
int _sqlite_exec_void(struct __sourceloc __whence, const char *sqltext, ...)
{
va_list ap;
va_start(ap, sqltext);
sqlite_retry_state retry = SQLITE_RETRY_STATE_DEFAULT;
int ret = _sqlite_vexec_void(__whence, LOG_LEVEL_ERROR, &retry, sqltext, ap);
va_end(ap);
return ret;
}
/* Same as sqlite_exec_void(), but logs any error at the given level instead of ERROR.
*
* @author Andrew Bettison <andrew@servalproject.com>
*/
int _sqlite_exec_void_loglevel(struct __sourceloc __whence, int log_level, const char *sqltext, ...)
int _sqlite_exec_void(struct __sourceloc __whence, int log_level, const char *sqltext, ...)
{
va_list ap;
va_start(ap, sqltext);
@ -704,20 +783,7 @@ int _sqlite_exec_void_loglevel(struct __sourceloc __whence, int log_level, const
*
* @author Andrew Bettison <andrew@servalproject.com>
*/
int _sqlite_exec_void_retry(struct __sourceloc __whence, sqlite_retry_state *retry, const char *sqltext, ...)
{
va_list ap;
va_start(ap, sqltext);
int ret = _sqlite_vexec_void(__whence, LOG_LEVEL_ERROR, retry, sqltext, ap);
va_end(ap);
return ret;
}
/* Same as sqlite_exec_void_retry(), but logs any error at the given level instead of ERROR.
*
* @author Andrew Bettison <andrew@servalproject.com>
*/
int _sqlite_exec_void_retry_loglevel(struct __sourceloc __whence, int log_level, sqlite_retry_state *retry, const char *sqltext, ...)
int _sqlite_exec_void_retry(struct __sourceloc __whence, int log_level, sqlite_retry_state *retry, const char *sqltext, ...)
{
va_list ap;
va_start(ap, sqltext);
@ -728,7 +794,7 @@ int _sqlite_exec_void_retry_loglevel(struct __sourceloc __whence, int log_level,
static int _sqlite_vexec_int64(struct __sourceloc __whence, sqlite_retry_state *retry, int64_t *result, const char *sqltext, va_list ap)
{
sqlite3_stmt *statement = _sqlite_prepare_loglevel(__whence, LOG_LEVEL_ERROR, retry, sqltext);
sqlite3_stmt *statement = _sqlite_prepare(__whence, LOG_LEVEL_ERROR, retry, sqltext);
if (!statement)
return -1;
if (_sqlite_vbind(__whence, LOG_LEVEL_ERROR, retry, statement, ap) == -1)
@ -736,7 +802,7 @@ static int _sqlite_vexec_int64(struct __sourceloc __whence, sqlite_retry_state *
int ret = 0;
int rowcount = 0;
int stepcode;
while ((stepcode = _sqlite_step_retry(__whence, LOG_LEVEL_ERROR, retry, statement)) == SQLITE_ROW) {
while ((stepcode = _sqlite_step(__whence, LOG_LEVEL_ERROR, retry, statement)) == SQLITE_ROW) {
int columncount = sqlite3_column_count(statement);
if (columncount != 1)
ret = WHYF("incorrect column count %d (should be 1): %s", columncount, sqlite3_sql(statement));
@ -818,7 +884,7 @@ int _sqlite_exec_strbuf_retry(struct __sourceloc __whence, sqlite_retry_state *r
int _sqlite_vexec_strbuf_retry(struct __sourceloc __whence, sqlite_retry_state *retry, strbuf sb, const char *sqltext, va_list ap)
{
sqlite3_stmt *statement = _sqlite_prepare_loglevel(__whence, LOG_LEVEL_ERROR, retry, sqltext);
sqlite3_stmt *statement = _sqlite_prepare(__whence, LOG_LEVEL_ERROR, retry, sqltext);
if (!statement)
return -1;
if (_sqlite_vbind(__whence, LOG_LEVEL_ERROR, retry, statement, ap) == -1)
@ -826,7 +892,7 @@ int _sqlite_vexec_strbuf_retry(struct __sourceloc __whence, sqlite_retry_state *
int ret = 0;
int rowcount = 0;
int stepcode;
while ((stepcode = _sqlite_step_retry(__whence, LOG_LEVEL_ERROR, retry, statement)) == SQLITE_ROW) {
while ((stepcode = _sqlite_step(__whence, LOG_LEVEL_ERROR, retry, statement)) == SQLITE_ROW) {
int columncount = sqlite3_column_count(statement);
if (columncount != 1)
ret - WHYF("incorrect column count %d (should be 1): %s", columncount, sqlite3_sql(statement));
@ -856,8 +922,8 @@ int rhizome_database_filehash_from_id(const char *id, uint64_t version, char has
{
IN();
strbuf hash_sb = strbuf_local(hash, SHA512_DIGEST_STRING_LENGTH);
RETURN(sqlite_exec_strbuf(hash_sb, "SELECT filehash FROM MANIFESTS WHERE manifests.version=%lld AND manifests.id='%s';",
version,id));
RETURN(sqlite_exec_strbuf(hash_sb, "SELECT filehash FROM MANIFESTS WHERE manifests.version = ? AND manifests.id = ?;",
INT64, version, TEXT_TOUPPER, id, END));
OUT();
}
@ -1589,7 +1655,7 @@ static int rhizome_delete_manifest_retry(sqlite_retry_state *retry, const char *
if (!statement)
return -1;
sqlite3_bind_text(statement, 1, manifestid, -1, SQLITE_STATIC);
if (_sqlite_exec_prepared(__WHENCE__, LOG_LEVEL_ERROR, retry, statement) == -1)
if (_sqlite_exec(__WHENCE__, LOG_LEVEL_ERROR, retry, statement) == -1)
return -1;
return sqlite3_changes(rhizome_db) ? 0 : 1;
}
@ -1605,7 +1671,7 @@ static int rhizome_delete_file_retry(sqlite_retry_state *retry, const char *file
ret = -1;
else {
sqlite3_bind_text(statement, 1, fileid, -1, SQLITE_STATIC);
if (_sqlite_exec_prepared(__WHENCE__, LOG_LEVEL_ERROR, retry, statement) == -1)
if (_sqlite_exec(__WHENCE__, LOG_LEVEL_ERROR, retry, statement) == -1)
ret = -1;
}
statement = sqlite_prepare(retry, "DELETE FROM fileblobs WHERE id = ?");
@ -1613,7 +1679,7 @@ static int rhizome_delete_file_retry(sqlite_retry_state *retry, const char *file
ret = -1;
else {
sqlite3_bind_text(statement, 1, fileid, -1, SQLITE_STATIC);
if (_sqlite_exec_prepared(__WHENCE__, LOG_LEVEL_ERROR, retry, statement) == -1)
if (_sqlite_exec(__WHENCE__, LOG_LEVEL_ERROR, retry, statement) == -1)
ret = -1;
}
return ret == -1 ? -1 : sqlite3_changes(rhizome_db) ? 0 : 1;
@ -1622,7 +1688,7 @@ static int rhizome_delete_file_retry(sqlite_retry_state *retry, const char *file
static int rhizome_delete_payload_retry(sqlite_retry_state *retry, const char *manifestid)
{
strbuf fh = strbuf_alloca(RHIZOME_FILEHASH_STRLEN + 1);
int rows = sqlite_exec_strbuf_retry(retry, fh, "SELECT filehash FROM manifests WHERE id = '%s'", manifestid);
int rows = sqlite_exec_strbuf_retry(retry, fh, "SELECT filehash FROM manifests WHERE id = ?", TEXT_TOUPPER, manifestid, END);
if (rows == -1)
return -1;
if (rows && rhizome_delete_file_retry(retry, strbuf_str(fh)) == -1)

View File

@ -421,14 +421,13 @@ rhizome_manifest *rhizome_direct_get_manifest(unsigned char *bid_prefix,int pref
bcopy(bid_prefix,low,prefix_length);
bcopy(bid_prefix,high,prefix_length);
char query[1024];
snprintf(query,1024,"SELECT MANIFEST,ROWID FROM MANIFESTS WHERE ID>='%s' AND ID<='%s'",
alloca_tohex(low,RHIZOME_MANIFEST_ID_BYTES),
alloca_tohex(high,RHIZOME_MANIFEST_ID_BYTES));
sqlite_retry_state retry = SQLITE_RETRY_STATE_DEFAULT;
sqlite3_stmt *statement = sqlite_prepare(&retry, query);
sqlite3_blob *blob=NULL;
sqlite3_stmt *statement = sqlite_prepare_bind(&retry,
"SELECT manifest, rowid FROM MANIFESTS WHERE id >= ? AND id <= ?",
BUNDLE_ID_T, low,
BUNDLE_ID_T, high,
END);
sqlite3_blob *blob=NULL;
if (sqlite_step_retry(&retry, statement) == SQLITE_ROW)
{
int ret;
@ -751,23 +750,20 @@ int rhizome_direct_get_bars(const unsigned char bid_low[RHIZOME_MANIFEST_ID_BYTE
int bars_requested)
{
sqlite_retry_state retry = SQLITE_RETRY_STATE_DEFAULT;
char query[1024];
snprintf(query,1024,
"SELECT BAR,ROWID,ID,FILESIZE FROM MANIFESTS"
" WHERE"
" FILESIZE BETWEEN %" PRId64 " AND %" PRId64
" AND ID>='%s' AND ID<='%s'"
// The following formulation doesn't remove the weird returning of
// bundles with out of range filesize values
// " WHERE ID>='%s' AND ID<='%s' AND FILESIZE > %lld AND FILESIZE < %lld"
" ORDER BY BAR LIMIT %d;",
size_low, size_high,
alloca_tohex(bid_low,RHIZOME_MANIFEST_ID_BYTES),
alloca_tohex(bid_max,RHIZOME_MANIFEST_ID_BYTES),
bars_requested);
sqlite3_stmt *statement=sqlite_prepare(&retry, query);
sqlite3_stmt *statement = sqlite_prepare_bind(&retry,
"SELECT bar, rowid, id, filesize FROM MANIFESTS"
" WHERE filesize BETWEEN ? AND ? AND id >= ? AND id <= ?"
" ORDER BY bar LIMIT ?;",
INT64, size_low,
INT64, size_high,
BUNDLE_ID_T, bid_low,
BUNDLE_ID_T, bid_high,
INT, bars_requested,
// The following formulation doesn't remove the weird returning of
// bundles with out of range filesize values
// " WHERE id >= ? AND id <= ? AND filesize > ? AND filesize < ?"
END);
sqlite3_blob *blob=NULL;
int bars_written=0;
@ -784,8 +780,7 @@ int rhizome_direct_get_bars(const unsigned char bid_low[RHIZOME_MANIFEST_ID_BYTE
int ret;
int64_t filesize = sqlite3_column_int64(statement, 3);
if (filesize<size_low||filesize>size_high) {
DEBUGF("WEIRDNESS ALERT: filesize=%"PRId64", but query was: %s",
filesize,query);
DEBUGF("WEIRDNESS ALERT: filesize=%"PRId64", but query was: %s", filesize, sqlite3_sql(statement));
break;
}
int64_t rowid = sqlite3_column_int64(statement, 1);

View File

@ -857,11 +857,10 @@ int rhizome_suggest_queue_manifest_import(rhizome_manifest *m, const struct sock
RETURN(0);
}
const char *bid = alloca_tohex_bid(m->cryptoSignPublic);
int priority=100; /* normal priority */
if (config.debug.rhizome_rx)
DEBUGF("Considering import bid=%s version=%"PRId64" size=%"PRId64" priority=%d:", bid, m->version, m->fileLength, priority);
DEBUGF("Considering import bid=%s version=%"PRId64" size=%"PRId64" priority=%d:", alloca_tohex_bid(m->cryptoSignPublic), m->version, m->fileLength, priority);
if (!rhizome_is_manifest_interesting(m)) {
if (config.debug.rhizome_rx)
@ -872,7 +871,7 @@ int rhizome_suggest_queue_manifest_import(rhizome_manifest *m, const struct sock
if (config.debug.rhizome_rx) {
int64_t stored_version;
if (sqlite_exec_int64(&stored_version, "select version from manifests where id='%s'", bid) > 0)
if (sqlite_exec_int64(&stored_version, "SELECT version FROM MANIFESTS WHERE id = ?", BUNDLE_ID_T, m->cryptoSignPublic, END) > 0)
DEBUGF(" is new (have version %"PRId64")", stored_version);
}

View File

@ -134,38 +134,43 @@ uint64_t rhizome_bar_bidprefix_ll(unsigned char *bar)
return bidprefix;
}
static int append_bars(struct overlay_buffer *e, sqlite_retry_state *retry, const char *sql, int64_t *last_rowid){
int count=0;
sqlite3_stmt *statement=sqlite_prepare(retry, sql, *last_rowid);
static int append_bars(struct overlay_buffer *e, sqlite_retry_state *retry, const char *sql, int64_t *last_rowid)
{
sqlite3_stmt *statement = sqlite_prepare(retry, sql);
if (statement == NULL)
return -1;
int params = sqlite3_bind_parameter_count(statement);
switch (params) {
case 0: break;
case 1:
if (sqlite_bind(retry, statement, INT64, *last_rowid, END) == -1)
return -1;
break;
default:
return WHYF("query has invalid number of parameters (%d): %s", params, sqlite3_sql(statement));
}
int count = 0;
while(sqlite_step_retry(retry, statement) == SQLITE_ROW) {
count++;
if (sqlite3_column_type(statement, 0)!=SQLITE_BLOB)
continue;
const void *data = sqlite3_column_blob(statement, 0);
int blob_bytes = sqlite3_column_bytes(statement, 0);
int64_t rowid = sqlite3_column_int64(statement, 1);
if (blob_bytes!=RHIZOME_BAR_BYTES) {
if (config.debug.rhizome_ads)
DEBUG("Found a BAR that is the wrong size - ignoring");
continue;
}
if (ob_append_bytes(e, (unsigned char *)data, blob_bytes)){
// out of room
count--;
break;
}
*last_rowid=rowid;
}
if (statement)
sqlite3_finalize(statement);
return count;
}
@ -191,7 +196,7 @@ void overlay_rhizome_advertise(struct sched_ent *alarm){
goto end;
/* Get number of bundles available */
if (sqlite_exec_int64_retry(&retry, &bundles_available, "SELECT COUNT(BAR) FROM MANIFESTS;") != 1){
if (sqlite_exec_int64_retry(&retry, &bundles_available, "SELECT COUNT(BAR) FROM MANIFESTS;", END) != 1){
WHY("Could not count BARs for advertisement");
goto end;
}
@ -221,7 +226,7 @@ void overlay_rhizome_advertise(struct sched_ent *alarm){
bundle_last_rowid=rowid;
count = append_bars(frame->payload, &retry,
"SELECT BAR,ROWID FROM MANIFESTS WHERE ROWID < %lld ORDER BY ROWID DESC LIMIT 17",
"SELECT BAR,ROWID FROM MANIFESTS WHERE ROWID < ? ORDER BY ROWID DESC LIMIT 17",
&bundle_last_rowid);
if (count<17)
bundle_last_rowid=INT64_MAX;

View File

@ -8,12 +8,13 @@
int rhizome_exists(const char *fileHash)
{
int64_t gotfile = 0;
if (sqlite_exec_int64(&gotfile, "SELECT COUNT(*) FROM FILES WHERE ID='%s' and datavalid=1;", fileHash) != 1)
if (sqlite_exec_int64(&gotfile, "SELECT COUNT(*) FROM FILES WHERE id = ? and datavalid = 1;", TEXT_TOUPPER, fileHash, END) != 1)
return 0;
return gotfile;
}
int rhizome_open_write(struct rhizome_write *write, char *expectedFileHash, int64_t file_length, int priority){
int rhizome_open_write(struct rhizome_write *write, char *expectedFileHash, int64_t file_length, int priority)
{
write->blob_fd=-1;
if (expectedFileHash){
@ -24,15 +25,16 @@ int rhizome_open_write(struct rhizome_write *write, char *expectedFileHash, int6
}else{
write->id_known=0;
}
time_ms_t now = gettime_ms();
static uint64_t last_id=0;
write->temp_id = gettime_ms();
if (write->temp_id<last_id)
write->temp_id=last_id+1;
last_id=write->temp_id;
write->temp_id = now;
if (write->temp_id < last_id)
write->temp_id = last_id + 1;
last_id = write->temp_id;
sqlite_retry_state retry = SQLITE_RETRY_STATE_DEFAULT;
if (sqlite_exec_void_retry(&retry, "BEGIN TRANSACTION;") == -1)
if (sqlite_exec_void_retry(&retry, "BEGIN TRANSACTION;", END) == -1)
return WHY("Failed to begin transaction");
/*
@ -45,10 +47,15 @@ int rhizome_open_write(struct rhizome_write *write, char *expectedFileHash, int6
*/
sqlite3_stmt *statement = NULL;
int ret=sqlite_exec_void_retry(&retry,
"INSERT OR REPLACE INTO FILES(id,length,highestpriority,datavalid,inserttime) "
"VALUES('%"PRId64"',%"PRId64",%d,0,%"PRId64");",
write->temp_id, file_length, priority, gettime_ms());
int ret = sqlite_exec_void_retry(
&retry,
"INSERT OR REPLACE INTO FILES(id,length,highestpriority,datavalid,inserttime) VALUES(?,?,?,0,?);",
UINT64_TOSTR, write->temp_id,
INT64, file_length,
INT, priority,
INT64, now,
END
);
if (ret==-1)
goto insert_row_fail;
@ -61,8 +68,7 @@ int rhizome_open_write(struct rhizome_write *write, char *expectedFileHash, int6
}
if (config.debug.externalblobs)
DEBUGF("Attempting to put blob for %"PRId64" in %s",
write->temp_id,blob_path);
DEBUGF("Attempting to put blob for id='%"PRId64"' in %s", write->temp_id, blob_path);
write->blob_fd=open(blob_path, O_CREAT | O_TRUNC | O_WRONLY, 0664);
if (write->blob_fd<0)
@ -72,45 +78,39 @@ int rhizome_open_write(struct rhizome_write *write, char *expectedFileHash, int6
DEBUGF("Writing to new blob file %s (fd=%d)", blob_path, write->blob_fd);
}else{
statement = sqlite_prepare(&retry,"INSERT OR REPLACE INTO FILEBLOBS(id,data) VALUES('%"PRId64"',?)",write->temp_id);
if (!statement) {
WHYF("Failed to insert into fileblobs: %s", sqlite3_errmsg(rhizome_db));
statement = sqlite_prepare_bind(
&retry,
"INSERT OR REPLACE INTO FILEBLOBS(id,data) VALUES(?,?)",
UINT64_TOSTR, write->temp_id,
ZEROBLOB, (int)file_length,
END);
if (statement == NULL)
goto insert_row_fail;
}
/* Bind appropriate sized zero-filled blob to data field */
if (sqlite3_bind_zeroblob(statement, 1, file_length) != SQLITE_OK) {
WHYF("sqlite3_bind_zeroblob() failed: %s: %s", sqlite3_errmsg(rhizome_db), sqlite3_sql(statement));
goto insert_row_fail;
}
/* Do actual insert, and abort if it fails */
int rowcount = 0;
int stepcode;
while ((stepcode = _sqlite_step_retry(__WHENCE__, LOG_LEVEL_ERROR, &retry, statement)) == SQLITE_ROW)
while ((stepcode = sqlite_step_retry(&retry, statement)) == SQLITE_ROW)
++rowcount;
if (rowcount)
WARNF("void query unexpectedly returned %d row%s", rowcount, rowcount == 1 ? "" : "s");
if (!sqlite_code_ok(stepcode)){
insert_row_fail:
WHYF("Failed to insert row for fileid=%"PRId64, write->temp_id);
WHYF("Failed to insert row for id='%"PRId64"'", write->temp_id);
if (statement) sqlite3_finalize(statement);
sqlite_exec_void_retry(&retry, "ROLLBACK;");
sqlite_exec_void_retry(&retry, "ROLLBACK;", END);
return -1;
}
sqlite3_finalize(statement);
statement=NULL;
/* Get rowid for inserted row, so that we can modify the blob */
write->blob_rowid = sqlite3_last_insert_rowid(rhizome_db);
if (config.debug.rhizome_rx)
DEBUGF("Got rowid %"PRId64" for %"PRId64, write->blob_rowid, write->temp_id);
DEBUGF("Got rowid=%"PRId64" for id='%"PRId64"'", write->blob_rowid, write->temp_id);
}
if (sqlite_exec_void_retry(&retry, "COMMIT;") == -1){
if (sqlite_exec_void_retry(&retry, "COMMIT;", END) == -1){
if (write->blob_fd>=0){
if (config.debug.externalblobs)
DEBUGF("Cancel write to fd %d", write->blob_fd);
@ -167,7 +167,7 @@ static int write_get_lock(struct rhizome_write *write_state){
sqlite_retry_state retry = SQLITE_RETRY_STATE_DEFAULT;
// use an explicit transaction so we can delay I/O failures until COMMIT so they can be retried.
if (sqlite_exec_void_retry(&retry, "BEGIN TRANSACTION;") == -1)
if (sqlite_exec_void_retry(&retry, "BEGIN TRANSACTION;", END) == -1)
return -1;
while(1){
@ -243,7 +243,7 @@ static int write_release_lock(struct rhizome_write *write_state){
sqlite3_errmsg(rhizome_db));
sqlite_retry_state retry = SQLITE_RETRY_STATE_DEFAULT;
if (sqlite_exec_void_retry(&retry, "COMMIT;") == -1)
if (sqlite_exec_void_retry(&retry, "COMMIT;", END) == -1)
ret=-1;
}
write_state->sql_blob=NULL;
@ -477,21 +477,27 @@ int rhizome_finish_write(struct rhizome_write *write)
rhizome_remove_file_datainvalid(&retry, write->id);
if (rhizome_exists(write->id)) {
// we've already got that payload, delete the new copy
sqlite_exec_void_retry_loglevel(LOG_LEVEL_WARN, &retry,"DELETE FROM FILEBLOBS WHERE id='%"PRId64"';", write->temp_id);
sqlite_exec_void_retry_loglevel(LOG_LEVEL_WARN, &retry,"DELETE FROM FILES WHERE id='%"PRId64"';", write->temp_id);
sqlite_exec_void_retry_loglevel(LOG_LEVEL_WARN, &retry, "DELETE FROM FILEBLOBS WHERE id = ?;", UINT64_TOSTR, write->temp_id, END);
sqlite_exec_void_retry_loglevel(LOG_LEVEL_WARN, &retry, "DELETE FROM FILES WHERE id = ?;", UINT64_TOSTR, write->temp_id, END);
if (config.debug.rhizome)
DEBUGF("File id='%s' already present, removed id='%"PRId64"'", write->id, write->temp_id);
} else {
if (sqlite_exec_void_retry(&retry, "BEGIN TRANSACTION;") == -1)
if (sqlite_exec_void_retry(&retry, "BEGIN TRANSACTION;", END) == -1)
goto dbfailure;
// delete any half finished records
sqlite_exec_void_retry_loglevel(LOG_LEVEL_WARN, &retry,"DELETE FROM FILEBLOBS WHERE id='%s';",hash_out);
sqlite_exec_void_retry_loglevel(LOG_LEVEL_WARN, &retry,"DELETE FROM FILES WHERE id='%s';",hash_out);
sqlite_exec_void_retry_loglevel(LOG_LEVEL_WARN, &retry, "DELETE FROM FILEBLOBS WHERE id = ?;", STATIC_TEXT, write->id, END);
sqlite_exec_void_retry_loglevel(LOG_LEVEL_WARN, &retry, "DELETE FROM FILES WHERE id = ?;", STATIC_TEXT, write->id, END);
if (sqlite_exec_void_retry(&retry,
"UPDATE FILES SET id='%s', inserttime=%lld, datavalid=1 WHERE id='%"PRId64"'",
hash_out, gettime_ms(), write->temp_id) == -1)
if (sqlite_exec_void_retry(
&retry,
"UPDATE FILES SET id = ?, inserttime = ?, datavalid = 1 WHERE id = ?",
STATIC_TEXT, write->id,
INT64, gettime_ms(),
UINT64_TOSTR, write->temp_id,
END
) == -1
)
goto dbfailure;
if (fd>=0){
@ -501,7 +507,7 @@ int rhizome_finish_write(struct rhizome_write *write)
WHYF("Failed to generate file path");
goto dbfailure;
}
if (!FORM_RHIZOME_DATASTORE_PATH(dest_path, hash_out)){
if (!FORM_RHIZOME_DATASTORE_PATH(dest_path, write->id)){
WHYF("Failed to generate file path");
goto dbfailure;
}
@ -512,13 +518,17 @@ int rhizome_finish_write(struct rhizome_write *write)
}
}else{
if (sqlite_exec_void_retry(&retry,
"UPDATE FILEBLOBS SET id='%s' WHERE rowid=%lld",
hash_out, write->blob_rowid) == -1){
goto dbfailure;
}
if (sqlite_exec_void_retry(
&retry,
"UPDATE FILEBLOBS SET id = ? WHERE rowid = ?",
STATIC_TEXT, write->id,
INT64, write->blob_rowid,
END
) == -1
)
goto dbfailure;
}
if (sqlite_exec_void_retry(&retry, "COMMIT;") == -1)
if (sqlite_exec_void_retry(&retry, "COMMIT;", END) == -1)
goto dbfailure;
if (config.debug.rhizome)
DEBUGF("Stored file %s", write->id);
@ -527,7 +537,7 @@ int rhizome_finish_write(struct rhizome_write *write)
return 0;
dbfailure:
sqlite_exec_void_retry(&retry, "ROLLBACK;");
sqlite_exec_void_retry(&retry, "ROLLBACK;", END);
failure:
rhizome_fail_write(write);
return -1;
@ -687,9 +697,9 @@ int rhizome_open_read(struct rhizome_read *read, const char *fileid)
if (sqlite_exec_int64(&read->blob_rowid,
"SELECT FILEBLOBS.rowid "
"FROM FILEBLOBS, FILES "
"WHERE FILEBLOBS.id = FILES.id "
"AND FILES.id = '%s' "
"AND FILES.datavalid != 0", read->id) == -1)
"WHERE FILEBLOBS.id = FILES.id"
" AND FILES.id = ?"
" AND FILES.datavalid != 0", STATIC_TEXT, read->id, END) == -1)
return -1;
if (read->blob_rowid != -1) {
read->length = -1; // discover the length on opening the db BLOB