db: Check execution when accessing the result of a statement

This was already done in `db_step` but `db_count_changes` and
`db_last_insert_id` also rely on the statement being executed. Furthermore we
now check that the statement was executed before freeing it, so it can't
happen that we dispose of a statement we meant to execute but forgot.

The combination of these could be used to replace the pending_statement
tracking based on lists, since we now make sure to execute all statements and
we use the memleak checker to make sure we don't keep a statement in memory.

Signed-off-by: Christian Decker <decker.christian@gmail.com>
This commit is contained in:
Christian Decker
2019-09-12 12:18:59 +02:00
committed by Rusty Russell
parent 1f935cbd85
commit 416af636f0

View File

@@ -483,6 +483,9 @@ static void db_assert_no_outstanding_statements(struct db *db)
static void db_stmt_free(struct db_stmt *stmt) static void db_stmt_free(struct db_stmt *stmt)
{ {
if (!stmt->executed)
fatal("Freeing an un-executed statement from %s: %s",
stmt->location, stmt->query->query);
if (stmt->inner_stmt) if (stmt->inner_stmt)
stmt->db->config->stmt_free_fn(stmt); stmt->db->config->stmt_free_fn(stmt);
assert(stmt->inner_stmt == NULL); assert(stmt->inner_stmt == NULL);
@@ -575,12 +578,14 @@ const unsigned char *db_column_text(struct db_stmt *stmt, int col)
size_t db_count_changes(struct db_stmt *stmt) size_t db_count_changes(struct db_stmt *stmt)
{ {
assert(stmt->executed);
return stmt->db->config->count_changes_fn(stmt); return stmt->db->config->count_changes_fn(stmt);
} }
u64 db_last_insert_id_v2(struct db_stmt *stmt TAKES) u64 db_last_insert_id_v2(struct db_stmt *stmt TAKES)
{ {
u64 id; u64 id;
assert(stmt->executed);
id = stmt->db->config->last_insert_id_fn(stmt); id = stmt->db->config->last_insert_id_fn(stmt);
if (taken(stmt)) if (taken(stmt))