diff --git a/wallet/db.c b/wallet/db.c index 179fa743a..21a498e45 100644 --- a/wallet/db.c +++ b/wallet/db.c @@ -1,7 +1,6 @@ #include "db.h" #include -#include #include #include #include @@ -470,29 +469,6 @@ static void db_assert_no_outstanding_statements(struct db *db) } #endif -void db_stmt_done(sqlite3_stmt *stmt) -{ - sqlite3_finalize(stmt); -} - -sqlite3_stmt *db_select_prepare_(const char *location, struct db *db, const char *query) -{ - int err; - sqlite3_stmt *stmt; - - /* 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, query, -1, &stmt, NULL); - - if (err != SQLITE_OK) - db_fatal("%s: %s: %s", location, query, sqlite3_errmsg(db->sql)); - - return stmt; -} - static void db_stmt_free(struct db_stmt *stmt) { if (stmt->inner_stmt) @@ -601,53 +577,6 @@ u64 db_last_insert_id_v2(struct db_stmt *stmt TAKES) return id; } -bool db_select_step_(const char *location, struct db *db, struct sqlite3_stmt *stmt) -{ - int ret; - - ret = sqlite3_step(stmt); - if (ret == SQLITE_ROW) - return true; - if (ret != SQLITE_DONE) - db_fatal("%s: %s", location, sqlite3_errmsg(db->sql)); - db_stmt_done(stmt); - return false; -} -sqlite3_stmt *db_prepare_(const char *location, struct db *db, const char *query) -{ - int err; - sqlite3_stmt *stmt; - - assert(db->in_transaction); - - err = sqlite3_prepare_v2(db->sql, query, -1, &stmt, NULL); - - if (err != SQLITE_OK) - db_fatal("%s: %s: %s", location, query, sqlite3_errmsg(db->sql)); - - return stmt; -} - -void db_exec_prepared_(const char *caller, struct db *db, sqlite3_stmt *stmt) -{ - assert(db->in_transaction); - - if (sqlite3_step(stmt) != SQLITE_DONE) - db_fatal("%s: %s", caller, sqlite3_errmsg(db->sql)); - - db_stmt_done(stmt); -} - -sqlite3_stmt *db_select_(const char *location, struct db *db, const char *query) -{ - sqlite3_stmt *stmt; - - assert(db->in_transaction); - - stmt = db_select_prepare(db, query); - return stmt; -} - static void destroy_db(struct db *db) { db_assert_no_outstanding_statements(db); @@ -679,16 +608,6 @@ bool db_in_transaction(struct db *db) return db->in_transaction; } -u64 db_last_insert_id(struct db *db) -{ - return sqlite3_last_insert_rowid(db->sql); -} - -size_t db_changes(struct db *db) -{ - return sqlite3_changes(db->sql); -} - void db_begin_transaction_(struct db *db, const char *location) { bool ok; @@ -728,12 +647,6 @@ static void setup_open_db(struct db *db) db_report_changes(db, NULL, 0); } -void db_close(struct db *db) -{ - if (db->config->teardown_fn) - db->config->teardown_fn(db); -} - /** * db_open - Open or create a sqlite3 database */ @@ -906,332 +819,6 @@ void db_set_intvar(struct db *db, char *varname, s64 val) tal_free(v); } -void *sqlite3_column_arr_(const tal_t *ctx, sqlite3_stmt *stmt, int col, - size_t bytes, const char *label, const char *caller) -{ - size_t sourcelen = sqlite3_column_bytes(stmt, col); - void *p; - - if (sqlite3_column_type(stmt, col) == SQLITE_NULL) - return NULL; - - if (sourcelen % bytes != 0) - db_fatal("%s: column size %zu not a multiple of %s (%zu)", - caller, sourcelen, label, bytes); - - p = tal_arr_label(ctx, char, sourcelen, label); - memcpy(p, sqlite3_column_blob(stmt, col), sourcelen); - return p; -} - -bool sqlite3_bind_short_channel_id(sqlite3_stmt *stmt, int col, - const struct short_channel_id *id) -{ - char *ser = short_channel_id_to_str(id, id); - int err = sqlite3_bind_blob(stmt, col, ser, strlen(ser), SQLITE_TRANSIENT); - tal_free(ser); - return err == SQLITE_OK; -} - -bool sqlite3_column_short_channel_id(sqlite3_stmt *stmt, int col, - struct short_channel_id *dest) -{ - const char *source = sqlite3_column_blob(stmt, col); - size_t sourcelen = sqlite3_column_bytes(stmt, col); - return short_channel_id_from_str(source, sourcelen, dest, true); -} -bool sqlite3_bind_short_channel_id_array(sqlite3_stmt *stmt, int col, - const struct short_channel_id *id) -{ - u8 *ser; - size_t num; - size_t i; - - /* Handle nulls early. */ - if (!id) { - int err = sqlite3_bind_null(stmt, col); - return err == SQLITE_OK; - } - - ser = tal_arr(NULL, u8, 0); - num = tal_count(id); - - for (i = 0; i < num; ++i) - towire_short_channel_id(&ser, &id[i]); - - int err = sqlite3_bind_blob(stmt, col, ser, tal_count(ser), SQLITE_TRANSIENT); - - tal_free(ser); - return err == SQLITE_OK; -} -struct short_channel_id * -sqlite3_column_short_channel_id_array(const tal_t *ctx, - sqlite3_stmt *stmt, int col) -{ - const u8 *ser; - size_t len; - struct short_channel_id *ret; - - /* Handle nulls early. */ - if (sqlite3_column_type(stmt, col) == SQLITE_NULL) - return NULL; - - ser = sqlite3_column_blob(stmt, col); - len = sqlite3_column_bytes(stmt, col); - ret = tal_arr(ctx, struct short_channel_id, 0); - - while (len != 0) { - struct short_channel_id scid; - fromwire_short_channel_id(&ser, &len, &scid); - tal_arr_expand(&ret, scid); - } - - return ret; -} - -bool sqlite3_bind_tx(sqlite3_stmt *stmt, int col, const struct bitcoin_tx *tx) -{ - u8 *ser = linearize_tx(NULL, tx); - int err = sqlite3_bind_blob(stmt, col, ser, tal_count(ser), SQLITE_TRANSIENT); - tal_free(ser); - return err == SQLITE_OK; -} - -struct bitcoin_tx *sqlite3_column_tx(const tal_t *ctx, sqlite3_stmt *stmt, - int col) -{ - const u8 *src = sqlite3_column_blob(stmt, col); - size_t len = sqlite3_column_bytes(stmt, col); - return pull_bitcoin_tx(ctx, &src, &len); -} -bool sqlite3_bind_signature(sqlite3_stmt *stmt, int col, - const secp256k1_ecdsa_signature *sig) -{ - bool ok; - u8 buf[64]; - ok = secp256k1_ecdsa_signature_serialize_compact(secp256k1_ctx, buf, - sig) == 1; - int err = sqlite3_bind_blob(stmt, col, buf, sizeof(buf), SQLITE_TRANSIENT); - return ok && err == SQLITE_OK; -} - -bool sqlite3_column_signature(sqlite3_stmt *stmt, int col, - secp256k1_ecdsa_signature *sig) -{ - assert(sqlite3_column_bytes(stmt, col) == 64); - return secp256k1_ecdsa_signature_parse_compact( - secp256k1_ctx, sig, sqlite3_column_blob(stmt, col)) == 1; -} - -bool sqlite3_column_pubkey(sqlite3_stmt *stmt, int col, struct pubkey *dest) -{ - assert(sqlite3_column_bytes(stmt, col) == PUBKEY_CMPR_LEN); - return pubkey_from_der(sqlite3_column_blob(stmt, col), PUBKEY_CMPR_LEN, dest); -} - -bool sqlite3_bind_pubkey(sqlite3_stmt *stmt, int col, const struct pubkey *pk) -{ - u8 der[PUBKEY_CMPR_LEN]; - pubkey_to_der(der, pk); - int err = sqlite3_bind_blob(stmt, col, der, sizeof(der), SQLITE_TRANSIENT); - return err == SQLITE_OK; -} - -bool sqlite3_column_node_id(sqlite3_stmt *stmt, int col, struct node_id *dest) -{ - assert(sqlite3_column_bytes(stmt, col) == sizeof(dest->k)); - memcpy(dest->k, sqlite3_column_blob(stmt, col), sizeof(dest->k)); - return node_id_valid(dest); -} - -bool sqlite3_bind_node_id(sqlite3_stmt *stmt, int col, const struct node_id *id) -{ - assert(node_id_valid(id)); - int err = sqlite3_bind_blob(stmt, col, id->k, sizeof(id->k), SQLITE_TRANSIENT); - return err == SQLITE_OK; -} - -bool sqlite3_bind_pubkey_array(sqlite3_stmt *stmt, int col, - const struct pubkey *pks) -{ - size_t n; - size_t i; - u8 *ders; - - if (!pks) { - int err = sqlite3_bind_null(stmt, col); - return err == SQLITE_OK; - } - - n = tal_count(pks); - ders = tal_arr(NULL, u8, n * PUBKEY_CMPR_LEN); - - for (i = 0; i < n; ++i) - pubkey_to_der(&ders[i * PUBKEY_CMPR_LEN], &pks[i]); - int err = sqlite3_bind_blob(stmt, col, ders, tal_count(ders), SQLITE_TRANSIENT); - - tal_free(ders); - return err == SQLITE_OK; -} -struct pubkey *sqlite3_column_pubkey_array(const tal_t *ctx, - sqlite3_stmt *stmt, int col) -{ - size_t i; - size_t n; - struct pubkey *ret; - const u8 *ders; - - if (sqlite3_column_type(stmt, col) == SQLITE_NULL) - return NULL; - - n = sqlite3_column_bytes(stmt, col) / PUBKEY_CMPR_LEN; - assert(n * PUBKEY_CMPR_LEN == (size_t)sqlite3_column_bytes(stmt, col)); - ret = tal_arr(ctx, struct pubkey, n); - ders = sqlite3_column_blob(stmt, col); - - for (i = 0; i < n; ++i) { - if (!pubkey_from_der(&ders[i * PUBKEY_CMPR_LEN], PUBKEY_CMPR_LEN, &ret[i])) - return tal_free(ret); - } - - return ret; -} - -bool sqlite3_bind_node_id_array(sqlite3_stmt *stmt, int col, - const struct node_id *ids) -{ - size_t n; - u8 *arr; - - if (!ids) { - int err = sqlite3_bind_null(stmt, col); - return err == SQLITE_OK; - } - - /* Copy into contiguous array: ARM will add padding to struct node_id! */ - n = tal_count(ids); - arr = tal_arr(NULL, u8, n * sizeof(ids[0].k)); - for (size_t i = 0; i < n; ++i) { - assert(node_id_valid(&ids[i])); - memcpy(arr + sizeof(ids[i].k) * i, - ids[i].k, - sizeof(ids[i].k)); - } - int err = sqlite3_bind_blob(stmt, col, arr, tal_count(arr), SQLITE_TRANSIENT); - - tal_free(arr); - return err == SQLITE_OK; -} - -struct node_id *sqlite3_column_node_id_array(const tal_t *ctx, - sqlite3_stmt *stmt, int col) -{ - size_t n; - struct node_id *ret; - const u8 *arr; - - if (sqlite3_column_type(stmt, col) == SQLITE_NULL) - return NULL; - - n = sqlite3_column_bytes(stmt, col) / sizeof(ret->k); - assert(n * sizeof(ret->k) == (size_t)sqlite3_column_bytes(stmt, col)); - ret = tal_arr(ctx, struct node_id, n); - arr = sqlite3_column_blob(stmt, col); - - for (size_t i = 0; i < n; i++) { - memcpy(ret[i].k, arr + i * sizeof(ret[i].k), sizeof(ret[i].k)); - if (!node_id_valid(&ret[i])) - return tal_free(ret); - } - - return ret; -} - -bool sqlite3_column_preimage(sqlite3_stmt *stmt, int col, struct preimage *dest) -{ - assert(sqlite3_column_bytes(stmt, col) == sizeof(struct preimage)); - return memcpy(dest, sqlite3_column_blob(stmt, col), sizeof(struct preimage)); -} - -bool sqlite3_bind_preimage(sqlite3_stmt *stmt, int col, const struct preimage *p) -{ - int err = sqlite3_bind_blob(stmt, col, p, sizeof(struct preimage), SQLITE_TRANSIENT); - return err == SQLITE_OK; -} - -bool sqlite3_column_sha256(sqlite3_stmt *stmt, int col, struct sha256 *dest) -{ - assert(sqlite3_column_bytes(stmt, col) == sizeof(struct sha256)); - return memcpy(dest, sqlite3_column_blob(stmt, col), sizeof(struct sha256)); -} - -bool sqlite3_bind_sha256(sqlite3_stmt *stmt, int col, const struct sha256 *p) -{ - int err = sqlite3_bind_blob(stmt, col, p, sizeof(struct sha256), SQLITE_TRANSIENT); - return err == SQLITE_OK; -} - -bool sqlite3_column_sha256_double(sqlite3_stmt *stmt, int col, struct sha256_double *dest) -{ - assert(sqlite3_column_bytes(stmt, col) == sizeof(struct sha256_double)); - return memcpy(dest, sqlite3_column_blob(stmt, col), sizeof(struct sha256_double)); -} - -struct secret *sqlite3_column_secrets(const tal_t *ctx, - sqlite3_stmt *stmt, int col) -{ - return sqlite3_column_arr(ctx, stmt, col, struct secret); -} - -bool sqlite3_bind_sha256_double(sqlite3_stmt *stmt, int col, const struct sha256_double *p) -{ - int err = sqlite3_bind_blob(stmt, col, p, sizeof(struct sha256_double), SQLITE_TRANSIENT); - return err == SQLITE_OK; -} - -struct json_escape *sqlite3_column_json_escape(const tal_t *ctx, - sqlite3_stmt *stmt, int col) -{ - return json_escape_string_(ctx, - sqlite3_column_blob(stmt, col), - sqlite3_column_bytes(stmt, col)); -} - -bool sqlite3_bind_json_escape(sqlite3_stmt *stmt, int col, - const struct json_escape *esc) -{ - int err = sqlite3_bind_text(stmt, col, esc->s, strlen(esc->s), SQLITE_TRANSIENT); - return err == SQLITE_OK; -} - -struct amount_msat sqlite3_column_amount_msat(sqlite3_stmt *stmt, int col) -{ - struct amount_msat msat; - - msat.millisatoshis = sqlite3_column_int64(stmt, col); /* Raw: low level function */ - return msat; -} - -struct amount_sat sqlite3_column_amount_sat(sqlite3_stmt *stmt, int col) -{ - struct amount_sat sat; - - sat.satoshis = sqlite3_column_int64(stmt, col); /* Raw: low level function */ - return sat; -} - -void sqlite3_bind_amount_msat(sqlite3_stmt *stmt, int col, - struct amount_msat msat) -{ - sqlite3_bind_int64(stmt, col, msat.millisatoshis); /* Raw: low level function */ -} - -void sqlite3_bind_amount_sat(sqlite3_stmt *stmt, int col, - struct amount_sat sat) -{ - sqlite3_bind_int64(stmt, col, sat.satoshis); /* Raw: low level function */ -} - /* Will apply the current config fee settings to all channels */ void migrate_pr2342_feerate_per_channel(struct lightningd *ld, struct db *db) { @@ -1245,22 +832,6 @@ void migrate_pr2342_feerate_per_channel(struct lightningd *ld, struct db *db) tal_free(stmt); } -void sqlite3_bind_timeabs(sqlite3_stmt *stmt, int col, struct timeabs t) -{ - u64 timestamp = t.ts.tv_nsec + (((u64) t.ts.tv_sec) * ((u64) NSEC_IN_SEC)); - sqlite3_bind_int64(stmt, col, timestamp); -} - -struct timeabs sqlite3_column_timeabs(sqlite3_stmt *stmt, int col) -{ - struct timeabs t; - u64 timestamp = sqlite3_column_int64(stmt, col); - t.ts.tv_sec = timestamp / NSEC_IN_SEC; - t.ts.tv_nsec = timestamp % NSEC_IN_SEC; - return t; - -} - void db_bind_null(struct db_stmt *stmt, int pos) { assert(pos < tal_count(stmt->bindings)); diff --git a/wallet/db.h b/wallet/db.h index 8ef764a5c..2444c1772 100644 --- a/wallet/db.h +++ b/wallet/db.h @@ -7,12 +7,12 @@ #include #include #include +#include #include #include #include #include #include -#include #include struct lightningd; @@ -57,15 +57,6 @@ struct db; */ struct db *db_setup(const tal_t *ctx, struct lightningd *ld, struct log *log); -/** - * db_select - Prepare and execute a SELECT, and return the result - * - * A simpler version of db_select_prepare. - */ -sqlite3_stmt *db_select_(const char *location, struct db *db, const char *query); -#define db_select(db, query) \ - db_select_(__FILE__ ":" stringify(__LINE__), db, query) - /** * db_begin_transaction - Begin a transaction * @@ -77,14 +68,6 @@ void db_begin_transaction_(struct db *db, const char *location); bool db_in_transaction(struct db *db); -// FIXME(cdecker) Need to maybe add a pointer to the db_stmt we are referring to -// FIXME(cdecker) Comment -u64 db_last_insert_id(struct db *db); - -// FIXME(cdecker) Need to maybe add a pointer to the db_stmt we are referring to -// FIXME(cdecker) Comment -size_t db_changes(struct db *db); - /** * db_commit_transaction - Commit a running transaction * @@ -109,136 +92,6 @@ void db_set_intvar(struct db *db, char *varname, s64 val); */ s64 db_get_intvar(struct db *db, char *varname, s64 defval); -/** - * db_select_prepare -- Prepare a DB select statement (read-only!) - * - * Tiny wrapper around `sqlite3_prepare_v2` that checks and sets - * errors like `db_query` and `db_exec` do. It calls fatal if - * the stmt is not valid. - * - * Call db_select_step() until it returns false (which will also consume - * the stmt). - * - * @db: Database to query/exec - * @query: The SELECT SQL statement to compile - */ -#define db_select_prepare(db, query) \ - db_select_prepare_(__FILE__ ":" stringify(__LINE__), db, query) -sqlite3_stmt *db_select_prepare_(const char *location, - struct db *db, const char *query); - -/** - * db_select_step -- iterate through db results. - * - * Returns false and frees stmt if we've reached end, otherwise - * it means sqlite3_step has returned SQLITE_ROW. - */ -#define db_select_step(db, stmt) \ - db_select_step_(__FILE__ ":" stringify(__LINE__), db, stmt) -bool db_select_step_(const char *location, - struct db *db, struct sqlite3_stmt *stmt); - -/** - * 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_(__FILE__ ":" stringify(__LINE__), db, query) -sqlite3_stmt *db_prepare_(const char *location, 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 calls fatal() if the execution - * fails. This will take ownership of `stmt` and will free - * it before returning. - * - * @db: The database to execute on - * @stmt: The prepared statement to execute - */ -#define db_exec_prepared(db,stmt) db_exec_prepared_(__func__,db,stmt) -void db_exec_prepared_(const char *caller, struct db *db, sqlite3_stmt *stmt); - -/* Wrapper around sqlite3_finalize(), for tracking statements. */ -void db_stmt_done(sqlite3_stmt *stmt); - -#define sqlite3_column_arr(ctx, stmt, col, type) \ - ((type *)sqlite3_column_arr_((ctx), (stmt), (col), \ - sizeof(type), TAL_LABEL(type, "[]"), \ - __func__)) -void *sqlite3_column_arr_(const tal_t *ctx, sqlite3_stmt *stmt, int col, - size_t bytes, const char *label, const char *caller); - -bool sqlite3_bind_short_channel_id(sqlite3_stmt *stmt, int col, - const struct short_channel_id *id); -WARN_UNUSED_RESULT bool sqlite3_column_short_channel_id(sqlite3_stmt *stmt, int col, - struct short_channel_id *dest); -bool sqlite3_bind_short_channel_id_array(sqlite3_stmt *stmt, int col, - const struct short_channel_id *id); -struct short_channel_id * -sqlite3_column_short_channel_id_array(const tal_t *ctx, - sqlite3_stmt *stmt, int col); -bool sqlite3_bind_tx(sqlite3_stmt *stmt, int col, const struct bitcoin_tx *tx); -struct bitcoin_tx *sqlite3_column_tx(const tal_t *ctx, sqlite3_stmt *stmt, - int col); -bool sqlite3_bind_signature(sqlite3_stmt *stmt, int col, const secp256k1_ecdsa_signature *sig); -bool sqlite3_column_signature(sqlite3_stmt *stmt, int col, secp256k1_ecdsa_signature *sig); - -bool sqlite3_column_pubkey(sqlite3_stmt *stmt, int col, struct pubkey *dest); -bool sqlite3_bind_pubkey(sqlite3_stmt *stmt, int col, const struct pubkey *pk); - -bool sqlite3_column_node_id(sqlite3_stmt *stmt, int col, struct node_id *dest); -bool sqlite3_bind_node_id(sqlite3_stmt *stmt, int col, const struct node_id *id); - -bool sqlite3_bind_pubkey_array(sqlite3_stmt *stmt, int col, - const struct pubkey *pks); -struct pubkey *sqlite3_column_pubkey_array(const tal_t *ctx, - sqlite3_stmt *stmt, int col); - -bool sqlite3_bind_node_id_array(sqlite3_stmt *stmt, int col, - const struct node_id *ids); -struct node_id *sqlite3_column_node_id_array(const tal_t *ctx, - sqlite3_stmt *stmt, int col); - -bool sqlite3_column_preimage(sqlite3_stmt *stmt, int col, struct preimage *dest); -bool sqlite3_bind_preimage(sqlite3_stmt *stmt, int col, const struct preimage *p); - -bool sqlite3_column_sha256(sqlite3_stmt *stmt, int col, struct sha256 *dest); -bool sqlite3_bind_sha256(sqlite3_stmt *stmt, int col, const struct sha256 *p); - -bool sqlite3_column_sha256_double(sqlite3_stmt *stmt, int col, struct sha256_double *dest); -bool sqlite3_bind_sha256_double(sqlite3_stmt *stmt, int col, const struct sha256_double *p); -struct secret *sqlite3_column_secrets(const tal_t *ctx, - sqlite3_stmt *stmt, int col); - -struct json_escape *sqlite3_column_json_escape(const tal_t *ctx, - sqlite3_stmt *stmt, int col); -bool sqlite3_bind_json_escape(sqlite3_stmt *stmt, int col, - const struct json_escape *esc); - -struct amount_msat sqlite3_column_amount_msat(sqlite3_stmt *stmt, int col); -struct amount_sat sqlite3_column_amount_sat(sqlite3_stmt *stmt, int col); -void sqlite3_bind_amount_msat(sqlite3_stmt *stmt, int col, - struct amount_msat msat); -void sqlite3_bind_amount_sat(sqlite3_stmt *stmt, int col, - struct amount_sat sat); - -/* Helpers to read and write absolute times from and to the database. */ -void sqlite3_bind_timeabs(sqlite3_stmt *stmt, int col, struct timeabs t); -struct timeabs sqlite3_column_timeabs(sqlite3_stmt *stmt, int col); - - void db_bind_null(struct db_stmt *stmt, int pos); void db_bind_int(struct db_stmt *stmt, int pos, int val); void db_bind_u64(struct db_stmt *stmt, int pos, u64 val); @@ -306,14 +159,63 @@ struct bitcoin_tx *db_column_tx(const tal_t *ctx, struct db_stmt *stmt, int col) void *db_column_arr_(const tal_t *ctx, struct db_stmt *stmt, int col, size_t bytes, const char *label, const char *caller); -void db_close(struct db *db); +/** + * db_exec_prepared -- Execute a prepared statement + * + * After preparing a statement using `db_prepare`, and after binding all + * non-null variables using the `db_bind_*` functions, it can be executed with + * this function. It is a small, transaction-aware, wrapper around `db_step`, + * that calls fatal() if the execution fails. This may take ownership of + * `stmt` if annotated with `take()`and will free it before returning. + * + * If you'd like to issue a query and access the rows returned by the query + * please use `db_query_prepared` instead, since this function will not expose + * returned results, and the `stmt` can only be used for calls to + * `db_count_changes` and `db_last_insert_id` after executing. + * + * @stmt: The prepared statement to execute + */ bool db_exec_prepared_v2(struct db_stmt *stmt TAKES); + +/** + * db_query_prepared -- Execute a prepared query + * + * After preparing a query using `db_prepare`, and after binding all non-null + * variables using the `db_bind_*` functions, it can be executed with this + * function. This function must be called before calling `db_step` or any of + * the `db_column_*` column access functions. + * + * If you are not executing a read-only statement, please use + * `db_exec_prepared` instead. + * + * @stmt: The prepared statement to execute + */ bool db_query_prepared(struct db_stmt *stmt); size_t db_count_changes(struct db_stmt *stmt); u64 db_last_insert_id_v2(struct db_stmt *stmt); + +/** + * db_prepare -- Prepare a DB query/command + * + * Create an instance of `struct db_stmt` that encapsulates a SQL query or command. + * + * @query MUST be wrapped in a `SQL()` macro call, since that allows the + * extraction and translation of the query into the target SQL dialect. + * + * It does not execute the query and does not check its validity, but + * allocates the placeholders detected in the query. The placeholders in the + * `stmt` can then be bound using the `db_bind_*` functions, and executed + * using `db_exec_prepared` for write-only statements and `db_query_prepared` + * for read-only statements. + * + * @db: Database to query/exec + * @query: The SQL statement to compile + */ struct db_stmt *db_prepare_v2_(const char *location, struct db *db, const char *query_id); -#define db_prepare_v2(db,query) \ + +/* TODO(cdecker) Remove the v2 suffix after finishing the migration */ +#define db_prepare_v2(db,query) \ db_prepare_v2_(__FILE__ ":" stringify(__LINE__), db, query) #endif /* LIGHTNING_WALLET_DB_H */