Browse Source

db: Add db_prepare and db_exec_prepared to expose native binding

This makes executing a query/command a two step process, but allows us
to use the native binding and avoid having to build queries as SQL
strings. Two major advantages are that we are no longer vulnerable to
SQL injections and that we do not have to hex-encode binary fields
like private keys, hashes, and routing onions, halving the storage
requirements for those.

Signed-off-by: Christian Decker <decker.christian@gmail.com>
ppa-0.6.1
Christian Decker 7 years ago
committed by Rusty Russell
parent
commit
048680d0f2
  1. 32
      wallet/db.c
  2. 30
      wallet/db.h

32
wallet/db.c

@ -132,6 +132,38 @@ static void db_clear_error(struct db *db)
db->err = tal_free(db->err);
}
sqlite3_stmt *db_prepare_(const char *caller, struct db *db, const char *query)
{
int err;
sqlite3_stmt *stmt;
if (db->in_transaction && db->err)
return NULL;
db_clear_error(db);
err = sqlite3_prepare_v2(db->sql, query, -1, &stmt, NULL);
if (err != SQLITE_OK) {
db->err = tal_fmt(db, "%s: %s: %s", caller, query,
sqlite3_errmsg(db->sql));
}
return stmt;
}
bool db_exec_prepared_(const char *caller, struct db *db, sqlite3_stmt *stmt)
{
if (db->in_transaction && db->err)
return false;
db_clear_error(db);
if (sqlite3_step(stmt) != SQLITE_DONE) {
db->err =
tal_fmt(db, "%s: %s", caller, sqlite3_errmsg(db->sql));
return false;
} else {
return true;
}
}
bool PRINTF_FMT(3, 4)
db_exec(const char *caller, struct db *db, const char *fmt, ...)
{

30
wallet/db.h

@ -80,4 +80,34 @@ s64 db_get_intvar(struct db *db, char *varname, s64 defval);
bool sqlite3_column_hexval(sqlite3_stmt *s, int col, void *dest,
size_t destlen);
/**
* db_prepare -- Prepare a DB query/command
*
* Tiny wrapper around `sqlite3_prepare_v2` that checks and sets
* errors like `db_query` and `db_exec` do. It returns a statement
* `stmt` if the given query/command was successfully compiled into a
* statement, `NULL` otherwise. On failure `db->err` will be set with
* the human readable error.
*
* @db: Database to query/exec
* @query: The SQL statement to compile
*/
#define db_prepare(db,query) db_prepare_(__func__,db,query)
sqlite3_stmt *db_prepare_(const char *caller, struct db *db, const char *query);
/**
* db_exec_prepared -- Execute a prepared statement
*
* After preparing a statement using `db_prepare`, and after binding
* all non-null variables using the `sqlite3_bind_*` functions, it can
* be executed with this function. It is a small, transaction-aware,
* wrapper around `sqlite3_step`, that also sets `db->err` if the
* execution fails.
*
* @db: The database to execute on
* @stmt: The prepared statement to execute
*/
#define db_exec_prepared(db,stmt) db_exec_prepared_(__func__,db,stmt)
bool db_exec_prepared_(const char *caller, struct db *db, sqlite3_stmt *stmt);
#endif /* WALLET_DB_H */

Loading…
Cancel
Save