Browse Source

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>
pull/2803/head
Christian Decker 6 years ago
committed by Rusty Russell
parent
commit
dffd3d79bc
  1. 123
      wallet/db.c
  2. 33
      wallet/db.h

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

@ -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…
Cancel
Save