Skip to content

Commit

Permalink
wallet: Change db_select_prepare to check for select instead
Browse files Browse the repository at this point in the history
`db_select_prepare` was prepending the "SELECT" part in an attempt to limit
its use to read-only statements. This is leads to the queries in the code not
actually being well-formed, which we'll need in a later commit, and was also
resulting in extra allocations. This switches the behavior to just enforce a
"SELECT" prefix being present which allows us to have well-formed queries in
the code again and avoids the extra allocation.

Signed-off-by: Christian Decker <[email protected]>
  • Loading branch information
cdecker authored and rustyrussell committed Sep 5, 2019
1 parent f08fd9e commit 57f9124
Show file tree
Hide file tree
Showing 3 changed files with 138 additions and 122 deletions.
9 changes: 5 additions & 4 deletions wallet/db.c
Original file line number Diff line number Diff line change
Expand Up @@ -479,17 +479,18 @@ sqlite3_stmt *db_select_prepare_(const char *location, struct db *db, const char
{
int err;
sqlite3_stmt *stmt;
const char *full_query = tal_fmt(db, "SELECT %s", query);

/* Since these queries will be treated as read-only they need to start
* with "SELECT" and have no side-effects. */
assert(strncmp(query, "SELECT", 6) == 0);
assert(db->in_transaction);

err = sqlite3_prepare_v2(db->sql, full_query, -1, &stmt, NULL);
err = sqlite3_prepare_v2(db->sql, query, -1, &stmt, NULL);

if (err != SQLITE_OK)
db_fatal("%s: %s: %s", location, full_query, sqlite3_errmsg(db->sql));
db_fatal("%s: %s: %s", location, query, sqlite3_errmsg(db->sql));

dev_statement_start(stmt, location);
tal_free(full_query);
return stmt;
}

Expand Down
16 changes: 9 additions & 7 deletions wallet/invoices.c
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ static void trigger_expiration(struct invoices *invoices)
/* Acquire all expired invoices and save them in a list */
list_head_init(&idlist);
stmt = db_select_prepare(invoices->db,
"id"
"SELECT id"
" FROM invoices"
" WHERE state = ?"
" AND expiry_time <= ?;");
Expand Down Expand Up @@ -218,7 +218,7 @@ static void install_expiration_timer(struct invoices *invoices)

/* Find unpaid invoice with nearest expiry time */
stmt = db_select_prepare(invoices->db,
"MIN(expiry_time)"
"SELECT MIN(expiry_time)"
" FROM invoices"
" WHERE state = ?;");
sqlite3_bind_int(stmt, 1, UNPAID);
Expand Down Expand Up @@ -330,7 +330,7 @@ bool invoices_find_by_label(struct invoices *invoices,
sqlite3_stmt *stmt;

stmt = db_select_prepare(invoices->db,
"id"
"SELECT id"
" FROM invoices"
" WHERE label = ?;");
sqlite3_bind_json_escape(stmt, 1, label);
Expand All @@ -349,7 +349,7 @@ bool invoices_find_by_rhash(struct invoices *invoices,
sqlite3_stmt *stmt;

stmt = db_select_prepare(invoices->db,
"id"
"SELECT id"
" FROM invoices"
" WHERE payment_hash = ?;");
sqlite3_bind_blob(stmt, 1, rhash, sizeof(*rhash), SQLITE_TRANSIENT);
Expand All @@ -368,7 +368,7 @@ bool invoices_find_unpaid(struct invoices *invoices,
sqlite3_stmt *stmt;

stmt = db_select_prepare(invoices->db,
" id"
"SELECT id"
" FROM invoices"
" WHERE payment_hash = ?"
" AND state = ?;");
Expand Down Expand Up @@ -421,6 +421,7 @@ bool invoices_iterate(struct invoices *invoices,

if (!it->p) {
stmt = db_select_prepare(invoices->db,
"SELECT"
" state"
", payment_key"
", payment_hash"
Expand Down Expand Up @@ -470,7 +471,7 @@ static enum invoice_status invoice_get_status(struct invoices *invoices, struct
bool res;

stmt = db_select_prepare(invoices->db,
"state FROM invoices WHERE id = ?;");
"SELECT state FROM invoices WHERE id = ?;");
sqlite3_bind_int64(stmt, 1, invoice.id);
res = db_select_step(invoices->db, stmt);
assert(res);
Expand Down Expand Up @@ -552,7 +553,7 @@ void invoices_waitany(const tal_t *ctx,

/* Look for an already-paid invoice. */
stmt = db_select_prepare(invoices->db,
"id"
"SELECT id"
" FROM invoices"
" WHERE pay_index NOT NULL"
" AND pay_index > ?"
Expand Down Expand Up @@ -602,6 +603,7 @@ const struct invoice_details *invoices_get_details(const tal_t *ctx,
struct invoice_details *details;

stmt = db_select_prepare(invoices->db,
"SELECT"
" state"
", payment_key"
", payment_hash"
Expand Down
Loading

0 comments on commit 57f9124

Please sign in to comment.