From 6b26ce57643c769017ffde63b994b9434d4e66ea Mon Sep 17 00:00:00 2001 From: Christian Decker Date: Tue, 10 Sep 2019 15:45:53 +0200 Subject: [PATCH] db: Split the vars table to have type-specific columns This was weird right from the start, so we just split the table into integers and blobs, so each column has a well-defined format. It is also required for postgres not to cry about explicit casts in the `paramTypes` array. Signed-off-by: Christian Decker --- tests/test_closing.py | 2 +- wallet/db.c | 18 ++++++++++-------- wallet/wallet.c | 4 ++-- 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/tests/test_closing.py b/tests/test_closing.py index 9b1e2ae7b..13dbbbd19 100644 --- a/tests/test_closing.py +++ b/tests/test_closing.py @@ -1550,7 +1550,7 @@ def test_option_upfront_shutdown_script(node_factory, bitcoind): wait_for(lambda: [c['state'] for c in only_one(l2.rpc.listpeers()['peers'])['channels']] == ['ONCHAIN', 'ONCHAIN']) # Figure out what address it will try to use. - keyidx = int(l1.db_query("SELECT val FROM vars WHERE name='bip32_max_index';")[0]['val']) + keyidx = int(l1.db_query("SELECT intval FROM vars WHERE name='bip32_max_index';")[0]['intval']) # Expect 1 for change address, 1 for the channel final address, # which are discarded as the 'scratch' tx that the fundchannel diff --git a/wallet/db.c b/wallet/db.c index fafd79c1d..fc8c03901 100644 --- a/wallet/db.c +++ b/wallet/db.c @@ -459,6 +459,10 @@ static struct migration dbmigrations[] = { /* option_static_remotekey is nailed at creation time. */ {SQL("ALTER TABLE channels ADD COLUMN option_static_remotekey" " DEFAULT FALSE;"), NULL }, + {SQL("ALTER TABLE vars ADD COLUMN intval INTEGER"), NULL}, + {SQL("ALTER TABLE vars ADD COLUMN blobval BLOB"), NULL}, + {SQL("UPDATE vars SET intval = CAST(val AS INTEGER) WHERE name IN (\"bip32_max_index\", \"last_processed_block\", \"next_pay_index\")"), NULL}, + {SQL("UPDATE vars SET blobval = CAST(val AS BLOB) WHERE name = 'genesis_hash'"), NULL}, }; /* Leak tracking. */ @@ -798,13 +802,13 @@ s64 db_get_intvar(struct db *db, char *varname, s64 defval) { s64 res = defval; struct db_stmt *stmt = db_prepare_v2( - db, SQL("SELECT val FROM vars WHERE name= ? LIMIT 1")); + db, SQL("SELECT intval FROM vars WHERE name= ? LIMIT 1")); db_bind_text(stmt, 0, varname); if (!db_query_prepared(stmt)) goto done; if (db_step(stmt)) - res = atol((const char*)db_column_text(stmt, 0)); + res = db_column_int(stmt, 0); done: tal_free(stmt); @@ -813,10 +817,9 @@ done: void db_set_intvar(struct db *db, char *varname, s64 val) { - char *v = tal_fmt(NULL, "%"PRIi64, val); size_t changes; - struct db_stmt *stmt = db_prepare_v2(db, SQL("UPDATE vars SET val=? WHERE name=?;")); - db_bind_text(stmt, 0, v); + struct db_stmt *stmt = db_prepare_v2(db, SQL("UPDATE vars SET intval=? WHERE name=?;")); + db_bind_int(stmt, 0, val); db_bind_text(stmt, 1, varname); if (!db_exec_prepared_v2(stmt)) db_fatal("Error executing update: %s", stmt->error); @@ -824,14 +827,13 @@ void db_set_intvar(struct db *db, char *varname, s64 val) tal_free(stmt); if (changes == 0) { - stmt = db_prepare_v2(db, SQL("INSERT INTO vars (name, val) VALUES (?, ?);")); + stmt = db_prepare_v2(db, SQL("INSERT INTO vars (name, intval) VALUES (?, ?);")); db_bind_text(stmt, 0, varname); - db_bind_text(stmt, 1, v); + db_bind_int(stmt, 1, val); if (!db_exec_prepared_v2(stmt)) db_fatal("Error executing insert: %s", stmt->error); tal_free(stmt); } - tal_free(v); } /* Will apply the current config fee settings to all channels */ diff --git a/wallet/wallet.c b/wallet/wallet.c index 9d3e11b80..abded008c 100644 --- a/wallet/wallet.c +++ b/wallet/wallet.c @@ -2483,7 +2483,7 @@ bool wallet_network_check(struct wallet *w, { struct bitcoin_blkid chainhash; struct db_stmt *stmt = db_prepare_v2( - w->db, SQL("SELECT val FROM vars WHERE name='genesis_hash'")); + w->db, SQL("SELECT blobval FROM vars WHERE name='genesis_hash'")); db_query_prepared(stmt); if (db_step(stmt)) { @@ -2507,7 +2507,7 @@ bool wallet_network_check(struct wallet *w, tal_free(stmt); /* Still a pristine wallet, claim it for the chain * that we are running */ - stmt = db_prepare_v2(w->db, SQL("INSERT INTO vars (name, val) " + stmt = db_prepare_v2(w->db, SQL("INSERT INTO vars (name, blobval) " "VALUES ('genesis_hash', ?);")); db_bind_sha256d(stmt, 0, &chainparams->genesis_blockhash.shad); db_exec_prepared_v2(take(stmt));