mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-03-01 17:47:30 +01:00
db: Add type-safe column access functions
These are based on top of the basic column access functions, and act as a small type-safe wrapper, that also does a bit of validation. Signed-off-by: Christian Decker <decker.christian@gmail.com>
This commit is contained in:
parent
a4e5371732
commit
dffd3d79bc
2 changed files with 153 additions and 3 deletions
123
wallet/db.c
123
wallet/db.c
|
@ -1486,6 +1486,110 @@ void db_column_preimage(struct db_stmt *stmt, int col,
|
|||
memcpy(preimage, raw, size);
|
||||
}
|
||||
|
||||
void db_column_node_id(struct db_stmt *stmt, int col, struct node_id *dest)
|
||||
{
|
||||
assert(db_column_bytes(stmt, col) == sizeof(dest->k));
|
||||
memcpy(dest->k, db_column_blob(stmt, col), sizeof(dest->k));
|
||||
assert(node_id_valid(dest));
|
||||
}
|
||||
|
||||
struct node_id *db_column_node_id_arr(const tal_t *ctx, struct db_stmt *stmt,
|
||||
int col)
|
||||
{
|
||||
struct node_id *ret;
|
||||
size_t n = db_column_bytes(stmt, col) / sizeof(ret->k);
|
||||
const u8 *arr = db_column_blob(stmt, col);
|
||||
assert(n * sizeof(ret->k) == (size_t)db_column_bytes(stmt, col));
|
||||
ret = tal_arr(ctx, struct node_id, n);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
void db_column_pubkey(struct db_stmt *stmt, int pos, struct pubkey *dest)
|
||||
{
|
||||
bool ok;
|
||||
assert(db_column_bytes(stmt, pos) == PUBKEY_CMPR_LEN);
|
||||
ok = pubkey_from_der(db_column_blob(stmt, pos), PUBKEY_CMPR_LEN, dest);
|
||||
assert(ok);
|
||||
}
|
||||
|
||||
bool db_column_short_channel_id(struct db_stmt *stmt, int col,
|
||||
struct short_channel_id *dest)
|
||||
{
|
||||
const char *source = db_column_blob(stmt, col);
|
||||
size_t sourcelen = db_column_bytes(stmt, col);
|
||||
return short_channel_id_from_str(source, sourcelen, dest, true);
|
||||
}
|
||||
|
||||
struct short_channel_id *
|
||||
db_column_short_channel_id_arr(const tal_t *ctx, struct db_stmt *stmt, int col)
|
||||
{
|
||||
const u8 *ser;
|
||||
size_t len;
|
||||
struct short_channel_id *ret;
|
||||
|
||||
ser = db_column_blob(stmt, col);
|
||||
len = db_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 db_column_signature(struct db_stmt *stmt, int col,
|
||||
secp256k1_ecdsa_signature *sig)
|
||||
{
|
||||
assert(db_column_bytes(stmt, col) == 64);
|
||||
return secp256k1_ecdsa_signature_parse_compact(
|
||||
secp256k1_ctx, sig, db_column_blob(stmt, col)) == 1;
|
||||
}
|
||||
|
||||
struct timeabs db_column_timeabs(struct db_stmt *stmt, int col)
|
||||
{
|
||||
struct timeabs t;
|
||||
u64 timestamp = db_column_u64(stmt, col);
|
||||
t.ts.tv_sec = timestamp / NSEC_IN_SEC;
|
||||
t.ts.tv_nsec = timestamp % NSEC_IN_SEC;
|
||||
return t;
|
||||
|
||||
}
|
||||
|
||||
struct bitcoin_tx *db_column_tx(const tal_t *ctx, struct db_stmt *stmt, int col)
|
||||
{
|
||||
const u8 *src = db_column_blob(stmt, col);
|
||||
size_t len = db_column_bytes(stmt, col);
|
||||
return pull_bitcoin_tx(ctx, &src, &len);
|
||||
}
|
||||
|
||||
void *db_column_arr_(const tal_t *ctx, struct db_stmt *stmt, int col,
|
||||
size_t bytes, const char *label, const char *caller)
|
||||
{
|
||||
size_t sourcelen = db_column_bytes(stmt, col);
|
||||
void *p;
|
||||
|
||||
if (db_column_is_null(stmt, col))
|
||||
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, db_column_blob(stmt, col), sourcelen);
|
||||
return p;
|
||||
}
|
||||
|
||||
void db_column_amount_msat(struct db_stmt *stmt, int col,
|
||||
struct amount_msat *msat)
|
||||
{
|
||||
|
@ -1523,6 +1627,25 @@ void db_column_sha256d(struct db_stmt *stmt, int col,
|
|||
memcpy(shad, raw, size);
|
||||
}
|
||||
|
||||
void db_column_secret(struct db_stmt *stmt, int col, struct secret *s)
|
||||
{
|
||||
const u8 *raw;
|
||||
assert(db_column_bytes(stmt, col) == sizeof(struct secret));
|
||||
raw = db_column_blob(stmt, col);
|
||||
memcpy(s, raw, sizeof(struct secret));
|
||||
}
|
||||
|
||||
struct secret *db_column_secret_arr(const tal_t *ctx, struct db_stmt *stmt,
|
||||
int col)
|
||||
{
|
||||
return db_column_arr(ctx, stmt, col, struct secret);
|
||||
}
|
||||
|
||||
void db_column_txid(struct db_stmt *stmt, int pos, struct bitcoin_txid *t)
|
||||
{
|
||||
db_column_sha256d(stmt, pos, &t->shad);
|
||||
}
|
||||
|
||||
bool db_exec_prepared_v2(struct db_stmt *stmt TAKES)
|
||||
{
|
||||
const char *expanded_sql;
|
||||
|
|
33
wallet/db.h
33
wallet/db.h
|
@ -242,8 +242,6 @@ void sqlite3_bind_timeabs(sqlite3_stmt *stmt, int col, struct timeabs t);
|
|||
struct timeabs sqlite3_column_timeabs(sqlite3_stmt *stmt, int col);
|
||||
|
||||
|
||||
void db_close(struct db *db);
|
||||
|
||||
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);
|
||||
|
@ -281,11 +279,40 @@ size_t db_column_bytes(struct db_stmt *stmt, int col);
|
|||
int db_column_is_null(struct db_stmt *stmt, int col);
|
||||
const void* db_column_blob(struct db_stmt *stmt, int col);
|
||||
const unsigned char *db_column_text(struct db_stmt *stmt, int col);
|
||||
void db_column_preimage(struct db_stmt *stmt, int col, struct preimage *preimage);
|
||||
void db_column_amount_msat(struct db_stmt *stmt, int col, struct amount_msat *msat);
|
||||
void db_column_amount_sat(struct db_stmt *stmt, int col, struct amount_sat *sat);
|
||||
struct json_escape *db_column_json_escape(const tal_t *ctx, struct db_stmt *stmt, int col);
|
||||
void db_column_sha256(struct db_stmt *stmt, int col, struct sha256 *sha);
|
||||
void db_column_sha256d(struct db_stmt *stmt, int col, struct sha256_double *shad);
|
||||
void db_column_secret(struct db_stmt *stmt, int col, struct secret *s);
|
||||
struct secret *db_column_secret_arr(const tal_t *ctx, struct db_stmt *stmt,
|
||||
int col);
|
||||
void db_column_txid(struct db_stmt *stmt, int pos, struct bitcoin_txid *t);
|
||||
void db_column_node_id(struct db_stmt *stmt, int pos, struct node_id *ni);
|
||||
struct node_id *db_column_node_id_arr(const tal_t *ctx, struct db_stmt *stmt,
|
||||
int col);
|
||||
void db_column_pubkey(struct db_stmt *stmt, int pos, struct pubkey *p);
|
||||
bool db_column_short_channel_id(struct db_stmt *stmt, int col,
|
||||
struct short_channel_id *dest);
|
||||
struct short_channel_id *
|
||||
db_column_short_channel_id_arr(const tal_t *ctx, struct db_stmt *stmt, int col);
|
||||
bool db_column_signature(struct db_stmt *stmt, int col,
|
||||
secp256k1_ecdsa_signature *sig);
|
||||
struct timeabs db_column_timeabs(struct db_stmt *stmt, int col);
|
||||
struct bitcoin_tx *db_column_tx(const tal_t *ctx, struct db_stmt *stmt, int col);
|
||||
|
||||
#define db_column_arr(ctx, stmt, col, type) \
|
||||
((type *)db_column_arr_((ctx), (stmt), (col), \
|
||||
sizeof(type), TAL_LABEL(type, "[]"), \
|
||||
__func__))
|
||||
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);
|
||||
bool db_exec_prepared_v2(struct db_stmt *stmt TAKES);
|
||||
bool db_query_prepared(struct db_stmt *stmt);
|
||||
size_t db_count_changes(struct db_stmt *stmt);
|
||||
|
||||
struct db_stmt *db_prepare_v2_(const char *location, struct db *db,
|
||||
const char *query_id);
|
||||
#define db_prepare_v2(db,query) \
|
||||
|
|
Loading…
Add table
Reference in a new issue