mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-02-22 14:42:40 +01:00
db: keep track of changes.
For the moment we just dump them to stderr, but later this will go to a hook. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
parent
e1e26ca69d
commit
f0200027b8
2 changed files with 54 additions and 3 deletions
56
wallet/db.c
56
wallet/db.c
|
@ -493,6 +493,8 @@ void db_exec_prepared_(const char *caller, struct db *db, sqlite3_stmt *stmt)
|
||||||
if (sqlite3_step(stmt) != SQLITE_DONE)
|
if (sqlite3_step(stmt) != SQLITE_DONE)
|
||||||
db_fatal("%s: %s", caller, sqlite3_errmsg(db->sql));
|
db_fatal("%s: %s", caller, sqlite3_errmsg(db->sql));
|
||||||
|
|
||||||
|
tal_arr_expand(&db->changes,
|
||||||
|
tal_strdup(db->changes, sqlite3_expanded_sql(stmt)));
|
||||||
db_stmt_done(stmt);
|
db_stmt_done(stmt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -508,6 +510,7 @@ static void db_do_exec(const char *caller, struct db *db, const char *cmd)
|
||||||
/* Only reached in testing */
|
/* Only reached in testing */
|
||||||
sqlite3_free(errmsg);
|
sqlite3_free(errmsg);
|
||||||
}
|
}
|
||||||
|
tal_arr_expand(&db->changes, tal_strdup(db->changes, cmd));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void PRINTF_FMT(3, 4)
|
static void PRINTF_FMT(3, 4)
|
||||||
|
@ -568,23 +571,68 @@ static void destroy_db(struct db *db)
|
||||||
sqlite3_close(db->sql);
|
sqlite3_close(db->sql);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* We expect min changes (ie. BEGIN TRANSACTION): report if more.
|
||||||
|
* Optionally add "final" at the end (ie. COMMIT). */
|
||||||
|
static void db_report_changes(struct db *db, const char *final, size_t min)
|
||||||
|
{
|
||||||
|
assert(db->changes);
|
||||||
|
assert(tal_count(db->changes) >= min);
|
||||||
|
|
||||||
|
if (tal_count(db->changes) > min) {
|
||||||
|
fprintf(stderr, "Committing db changes:\n");
|
||||||
|
for (size_t i = 0; i < tal_count(db->changes); i++)
|
||||||
|
fprintf(stderr, " %zu: %s\n", i, db->changes[i]);
|
||||||
|
if (final)
|
||||||
|
fprintf(stderr, " %s\n", final);
|
||||||
|
}
|
||||||
|
db->changes = tal_free(db->changes);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void db_prepare_for_changes(struct db *db)
|
||||||
|
{
|
||||||
|
assert(!db->changes);
|
||||||
|
db->changes = tal_arr(db, const char *, 0);
|
||||||
|
}
|
||||||
|
|
||||||
void db_begin_transaction_(struct db *db, const char *location)
|
void db_begin_transaction_(struct db *db, const char *location)
|
||||||
{
|
{
|
||||||
if (db->in_transaction)
|
if (db->in_transaction)
|
||||||
db_fatal("Already in transaction from %s", db->in_transaction);
|
db_fatal("Already in transaction from %s", db->in_transaction);
|
||||||
|
|
||||||
|
db_prepare_for_changes(db);
|
||||||
db_do_exec(location, db, "BEGIN TRANSACTION;");
|
db_do_exec(location, db, "BEGIN TRANSACTION;");
|
||||||
db->in_transaction = location;
|
db->in_transaction = location;
|
||||||
}
|
}
|
||||||
|
|
||||||
void db_commit_transaction(struct db *db)
|
void db_commit_transaction(struct db *db)
|
||||||
{
|
{
|
||||||
|
int err;
|
||||||
|
char *errmsg;
|
||||||
|
const char *cmd = "COMMIT;";
|
||||||
|
|
||||||
assert(db->in_transaction);
|
assert(db->in_transaction);
|
||||||
db_assert_no_outstanding_statements();
|
db_assert_no_outstanding_statements();
|
||||||
db_exec(__func__, db, "COMMIT;");
|
|
||||||
|
/* We expect at least the BEGIN TRANSACTION */
|
||||||
|
db_report_changes(db, cmd, 1);
|
||||||
|
|
||||||
|
err = sqlite3_exec(db->sql, cmd, NULL, NULL, &errmsg);
|
||||||
|
if (err != SQLITE_OK)
|
||||||
|
db_fatal("%s:%s:%s:%s", __func__, sqlite3_errstr(err), cmd, errmsg);
|
||||||
|
|
||||||
db->in_transaction = NULL;
|
db->in_transaction = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void enable_foreign_keys(struct db *db)
|
||||||
|
{
|
||||||
|
/* This must be outside a transaction, so catch it */
|
||||||
|
assert(!db->in_transaction);
|
||||||
|
|
||||||
|
db_prepare_for_changes(db);
|
||||||
|
db_do_exec(__func__, db, "PRAGMA foreign_keys = ON;");
|
||||||
|
db_report_changes(db, NULL, 0);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* db_open - Open or create a sqlite3 database
|
* db_open - Open or create a sqlite3 database
|
||||||
*/
|
*/
|
||||||
|
@ -607,7 +655,9 @@ static struct db *db_open(const tal_t *ctx, char *filename)
|
||||||
db->sql = sql;
|
db->sql = sql;
|
||||||
tal_add_destructor(db, destroy_db);
|
tal_add_destructor(db, destroy_db);
|
||||||
db->in_transaction = NULL;
|
db->in_transaction = NULL;
|
||||||
db_do_exec(__func__, db, "PRAGMA foreign_keys = ON;");
|
db->changes = NULL;
|
||||||
|
|
||||||
|
enable_foreign_keys(db);
|
||||||
|
|
||||||
return db;
|
return db;
|
||||||
}
|
}
|
||||||
|
@ -707,7 +757,7 @@ void db_reopen_after_fork(struct db *db)
|
||||||
db_fatal("failed to re-open database %s: %s", db->filename,
|
db_fatal("failed to re-open database %s: %s", db->filename,
|
||||||
sqlite3_errstr(err));
|
sqlite3_errstr(err));
|
||||||
}
|
}
|
||||||
db_do_exec(__func__, db, "PRAGMA foreign_keys = ON;");
|
enable_foreign_keys(db);
|
||||||
}
|
}
|
||||||
|
|
||||||
s64 db_get_intvar(struct db *db, char *varname, s64 defval)
|
s64 db_get_intvar(struct db *db, char *varname, s64 defval)
|
||||||
|
|
|
@ -20,6 +20,7 @@ struct db {
|
||||||
char *filename;
|
char *filename;
|
||||||
const char *in_transaction;
|
const char *in_transaction;
|
||||||
sqlite3 *sql;
|
sqlite3 *sql;
|
||||||
|
const char **changes;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Add table
Reference in a new issue