Browse Source

db: Implement basic query capabilities

This is the first step towards being able to extract information from query
rows. Only the most basic types are exposed, the others will be built on top
of these primitives.

Signed-off-by: Christian Decker <decker.christian@gmail.com>
pull/2803/head
Christian Decker 5 years ago
committed by Rusty Russell
parent
commit
d0027b1036
  1. 46
      wallet/db.c
  2. 8
      wallet/db.h
  3. 11
      wallet/db_common.h
  4. 43
      wallet/db_sqlite3.c

46
wallet/db.c

@ -604,6 +604,41 @@ struct db_stmt *db_prepare_v2_(const char *location, struct db *db,
#define db_prepare_v2(db,query) \
db_prepare_v2_(__FILE__ ":" stringify(__LINE__), db, query)
bool db_step(struct db_stmt *stmt)
{
assert(stmt->executed);
return stmt->db->config->step_fn(stmt);
}
u64 db_column_u64(struct db_stmt *stmt, int col)
{
return stmt->db->config->column_u64_fn(stmt, col);
}
int db_column_int(struct db_stmt *stmt, int col)
{
return stmt->db->config->column_int_fn(stmt, col);
}
size_t db_column_bytes(struct db_stmt *stmt, int col)
{
return stmt->db->config->column_bytes_fn(stmt, col);
}
int db_column_is_null(struct db_stmt *stmt, int col)
{
return stmt->db->config->column_is_null_fn(stmt, col);
}
const void *db_column_blob(struct db_stmt *stmt, int col)
{
return stmt->db->config->column_blob_fn(stmt, col);
}
const unsigned char *db_column_text(struct db_stmt *stmt, int col)
{
return stmt->db->config->column_blob_fn(stmt, col);
}
bool db_select_step_(const char *location, struct db *db, struct sqlite3_stmt *stmt)
{
@ -1368,3 +1403,14 @@ bool db_exec_prepared_v2(struct db_stmt *stmt TAKES)
return ret;
}
bool db_query_prepared(struct db_stmt *stmt)
{
/* Make sure we don't accidentally execute a modifying query using a
* read-only path. */
bool ret;
assert(stmt->query->readonly);
ret = stmt->db->config->query_fn(stmt);
stmt->executed = true;
return ret;
}

8
wallet/db.h

@ -249,6 +249,14 @@ void db_bind_blob(struct db_stmt *stmt, int pos, u8 *val, size_t len);
void db_bind_text(struct db_stmt *stmt, int pos, const char *val);
bool db_exec_prepared_v2(struct db_stmt *stmt TAKES);
bool db_step(struct db_stmt *stmt);
u64 db_column_u64(struct db_stmt *stmt, int col);
int db_column_int(struct db_stmt *stmt, int col);
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);
bool db_query_prepared(struct db_stmt *stmt);
struct db_stmt *db_prepare_v2_(const char *location, struct db *db,
const char *query_id);

11
wallet/db_common.h

@ -111,6 +111,17 @@ struct db_config {
* destructor of `struct db_stmt`, before clearing the db_stmt
* itself. */
void (*stmt_free_fn)(struct db_stmt *db_stmt);
/* Column access in a row. Only covers the primitives, others need to
* use these internally to translate (hence the non-allocating
* column_{text,blob}_fn since most other types want in place
* assignment. */
bool (*column_is_null_fn)(struct db_stmt *stmt, int col);
u64 (*column_u64_fn)(struct db_stmt *stmt, int col);
size_t (*column_bytes_fn)(struct db_stmt *stmt, int col);
const void *(*column_blob_fn)(struct db_stmt *stmt, int col);
const unsigned char *(*column_text_fn)(struct db_stmt *stmt, int col);
s64 (*column_int_fn)(struct db_stmt *stmt, int col);
};
/* Provide a way for DB backends to register themselves */

43
wallet/db_sqlite3.c

@ -124,6 +124,42 @@ static bool db_sqlite3_commit_tx(struct db *db)
return true;
}
static bool db_sqlite3_column_is_null(struct db_stmt *stmt, int col)
{
sqlite3_stmt *s = (sqlite3_stmt*)stmt->inner_stmt;
return sqlite3_column_type(s, col) == SQLITE_NULL;
}
static u64 db_sqlite3_column_u64(struct db_stmt *stmt, int col)
{
sqlite3_stmt *s = (sqlite3_stmt*)stmt->inner_stmt;
return sqlite3_column_int64(s, col);
}
static s64 db_sqlite3_column_int(struct db_stmt *stmt, int col)
{
sqlite3_stmt *s = (sqlite3_stmt*)stmt->inner_stmt;
return sqlite3_column_int(s, col);
}
static size_t db_sqlite3_column_bytes(struct db_stmt *stmt, int col)
{
sqlite3_stmt *s = (sqlite3_stmt*)stmt->inner_stmt;
return sqlite3_column_bytes(s, col);
}
static const void *db_sqlite3_column_blob(struct db_stmt *stmt, int col)
{
sqlite3_stmt *s = (sqlite3_stmt*)stmt->inner_stmt;
return sqlite3_column_blob(s, col);
}
static const unsigned char *db_sqlite3_column_text(struct db_stmt *stmt, int col)
{
sqlite3_stmt *s = (sqlite3_stmt*)stmt->inner_stmt;
return sqlite3_column_text(s, col);
}
static void db_sqlite3_stmt_free(struct db_stmt *stmt)
{
if (stmt->inner_stmt)
@ -142,6 +178,13 @@ struct db_config db_sqlite3_config = {
.begin_tx_fn = &db_sqlite3_begin_tx,
.commit_tx_fn = &db_sqlite3_commit_tx,
.stmt_free_fn = &db_sqlite3_stmt_free,
.column_is_null_fn = &db_sqlite3_column_is_null,
.column_u64_fn = &db_sqlite3_column_u64,
.column_int_fn = &db_sqlite3_column_int,
.column_bytes_fn = &db_sqlite3_column_bytes,
.column_blob_fn = &db_sqlite3_column_blob,
.column_text_fn = &db_sqlite3_column_text,
};
AUTODATA(db_backends, &db_sqlite3_config);

Loading…
Cancel
Save