SQL schema 24 - local settings, cleanup

This commit is contained in:
Mike Dilger 2023-02-18 17:22:59 +13:00
parent e998222abd
commit 3fe4c8b620
29 changed files with 119 additions and 82 deletions

View File

@ -22,9 +22,6 @@ pub use contact::DbContact;
mod person_relay;
pub use person_relay::{DbPersonRelay, Direction};
mod setting;
pub use setting::DbSetting;
use crate::error::Error;
use crate::globals::GLOBALS;
use rusqlite::Connection;
@ -72,14 +69,31 @@ fn check_and_upgrade() -> Result<(), Error> {
let maybe_db = GLOBALS.db.blocking_lock();
let db = maybe_db.as_ref().unwrap();
// Load the current version
match db.query_row(
"SELECT value FROM settings WHERE key=?",
["version"],
"SELECT schema_version FROM local_settings LIMIT 1",
[],
|row| row.get::<usize, usize>(0),
) {
Ok(version) => upgrade(db, version),
Err(e) => {
if let rusqlite::Error::SqliteFailure(_, Some(ref s)) = e {
if s.contains("no such table") {
return old_check_and_upgrade(db);
}
}
Err(e.into())
}
}
}
fn old_check_and_upgrade(db: &Connection) -> Result<(), Error> {
match db.query_row(
"SELECT value FROM settings WHERE key='version'",
[],
|row| row.get::<usize, String>(0),
) {
Ok(v) => {
let version = v.parse::<u16>().unwrap();
let version = v.parse::<usize>().unwrap();
if version < 2 {
GLOBALS.first_run.store(true, Ordering::Relaxed);
}
@ -93,58 +107,32 @@ fn check_and_upgrade() -> Result<(), Error> {
}
}
macro_rules! apply_sql {
($db:ident, $version:ident, $thisversion:expr, $file:expr) => {{
if $version < $thisversion {
tracing::info!("Upgrading database to version {}", $thisversion);
$db.execute_batch(include_str!($file))?;
$db.execute(
&format!(
"UPDATE settings SET value='{}' WHERE key='version'",
$thisversion
),
(),
)?;
$version = $thisversion;
}
}};
}
fn upgrade(db: &Connection, mut version: u16) -> Result<(), Error> {
let current_version = 23;
if version > current_version {
fn upgrade(db: &Connection, mut version: usize) -> Result<(), Error> {
if version > UPGRADE_SQL.len() {
panic!(
"Database version {} is newer than this binary which expects version {}.",
version, current_version
version,
UPGRADE_SQL.len()
);
}
// note to developers: we cannot make this into a loop because include_str! included
// by apply_sql! requires a static string, not a dynamically formatted one.
apply_sql!(db, version, 1, "schema1.sql");
apply_sql!(db, version, 2, "schema2.sql");
apply_sql!(db, version, 3, "schema3.sql");
apply_sql!(db, version, 4, "schema4.sql");
apply_sql!(db, version, 5, "schema5.sql");
apply_sql!(db, version, 6, "schema6.sql");
apply_sql!(db, version, 7, "schema7.sql");
apply_sql!(db, version, 8, "schema8.sql");
apply_sql!(db, version, 9, "schema9.sql");
apply_sql!(db, version, 10, "schema10.sql");
apply_sql!(db, version, 11, "schema11.sql");
apply_sql!(db, version, 12, "schema12.sql");
apply_sql!(db, version, 13, "schema13.sql");
apply_sql!(db, version, 14, "schema14.sql");
apply_sql!(db, version, 15, "schema15.sql");
apply_sql!(db, version, 16, "schema16.sql");
apply_sql!(db, version, 17, "schema17.sql");
apply_sql!(db, version, 18, "schema18.sql");
apply_sql!(db, version, 19, "schema19.sql");
apply_sql!(db, version, 20, "schema20.sql");
apply_sql!(db, version, 21, "schema21.sql");
apply_sql!(db, version, 22, "schema22.sql");
apply_sql!(db, version, 23, "schema23.sql");
while version < UPGRADE_SQL.len() {
tracing::info!("Upgrading database to version {}", version + 1);
db.execute_batch(UPGRADE_SQL[version + 1 - 1])?;
version += 1;
if version < 24 {
// 24 is when we switched to local_settings
db.execute(
"UPDATE settings SET value=? WHERE key='version'",
(version,),
)?;
} else {
db.execute("UPDATE local_settings SET schema_version=?", (version,))?;
}
}
tracing::info!("Database is at version {}", version);
Ok(())
}
@ -152,7 +140,7 @@ pub async fn prune() -> Result<(), Error> {
task::spawn_blocking(move || {
let maybe_db = GLOBALS.db.blocking_lock();
let db = maybe_db.as_ref().unwrap();
db.execute_batch(include_str!("prune.sql"))?;
db.execute_batch(include_str!("sql/prune.sql"))?;
Ok::<(), Error>(())
})
.await??;
@ -161,3 +149,30 @@ pub async fn prune() -> Result<(), Error> {
Ok(())
}
const UPGRADE_SQL: [&str; 24] = [
include_str!("sql/schema1.sql"),
include_str!("sql/schema2.sql"),
include_str!("sql/schema3.sql"),
include_str!("sql/schema4.sql"),
include_str!("sql/schema5.sql"),
include_str!("sql/schema6.sql"),
include_str!("sql/schema7.sql"),
include_str!("sql/schema8.sql"),
include_str!("sql/schema9.sql"),
include_str!("sql/schema10.sql"),
include_str!("sql/schema11.sql"),
include_str!("sql/schema12.sql"),
include_str!("sql/schema13.sql"),
include_str!("sql/schema14.sql"),
include_str!("sql/schema15.sql"),
include_str!("sql/schema16.sql"),
include_str!("sql/schema17.sql"),
include_str!("sql/schema18.sql"),
include_str!("sql/schema19.sql"),
include_str!("sql/schema20.sql"),
include_str!("sql/schema21.sql"),
include_str!("sql/schema22.sql"),
include_str!("sql/schema23.sql"),
include_str!("sql/schema24.sql"),
];

View File

@ -1,7 +0,0 @@
use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize)]
pub struct DbSetting {
pub key: String,
pub value: String,
}

26
src/db/sql/schema24.sql Normal file
View File

@ -0,0 +1,26 @@
-- unused setting
DELETE FROM settings WHERE key='autofollow';
DELETE FROM settings WHERE key='thread_view_ancestors';
DELETE FROM settings WHERE key='thread_view_replies';
DELETE FROM settings WHERE key='view_posts_referred_to';
DELETE FROM settings WHERE key='view_posts_referring_to';
DELETE FROM settings WHERE key='view_threaded';
-- unused table
DROP TABLE contact;
-- missing data
ALTER TABLE person ADD COLUMN petname TEXT DEFAULT NULL;
-- move local settings
CREATE TABLE local_settings (
schema_version INTEGER DEFAULT 0,
encrypted_private_key TEXT DEFAULT NULL
);
INSERT INTO local_settings (schema_version, encrypted_private_key)
SELECT a.value, b.value FROM settings a INNER JOIN settings b
ON a.key='version' AND b.key='encrypted_private_key';
DELETE FROM settings WHERE key='version';
DELETE FROM settings WHERE key='encrypted_private_key';

View File

@ -1,6 +1,6 @@
use crate::error::Error;
use crate::globals::GLOBALS;
use nostr_types::{EncryptedPrivateKey, PublicKey};
use nostr_types::PublicKey;
use rusqlite::params;
use serde::{Deserialize, Serialize};
@ -31,7 +31,6 @@ pub struct Settings {
pub num_relays_per_person: u8,
pub max_relays: u8,
pub public_key: Option<PublicKey>,
pub encrypted_private_key: Option<EncryptedPrivateKey>,
pub max_fps: u32,
pub feed_recompute_interval_ms: u32,
pub pow: u8,
@ -56,7 +55,6 @@ impl Default for Settings {
num_relays_per_person: DEFAULT_NUM_RELAYS_PER_PERSON,
max_relays: DEFAULT_MAX_RELAYS,
public_key: None,
encrypted_private_key: None,
max_fps: DEFAULT_MAX_FPS,
feed_recompute_interval_ms: DEFAULT_FEED_RECOMPUTE_INTERVAL_MS,
pow: DEFAULT_POW,
@ -104,9 +102,6 @@ impl Settings {
"max_relays" => {
settings.max_relays = row.1.parse::<u8>().unwrap_or(DEFAULT_MAX_RELAYS)
}
"encrypted_private_key" => {
settings.encrypted_private_key = Some(EncryptedPrivateKey(row.1))
}
"public_key" => {
settings.public_key = match PublicKey::try_from_hex_string(&row.1) {
Ok(pk) => Some(pk),
@ -202,6 +197,9 @@ impl Settings {
bool_to_numstr(self.direct_replies_only),
])?;
// Settings which are Options should not even exist when None. We don't accept null valued
// settings.
// Save override dpi
if let Some(ref dpi) = self.override_dpi {
let mut stmt =
@ -213,18 +211,6 @@ impl Settings {
stmt.execute(())?;
}
// Save private key identity
if let Some(ref epk) = self.encrypted_private_key {
let mut stmt = db.prepare(
"REPLACE INTO SETTINGS (key, value) VALUES ('encrypted_private_key', ?)",
)?;
stmt.execute((&epk.0,))?;
} else {
// Otherwise delete any such setting
let mut stmt = db.prepare("DELETE FROM settings WHERE key='encrypted_private_key'")?;
stmt.execute(())?;
}
// Save public key
if let Some(ref pk) = self.public_key {
let mut stmt =

View File

@ -18,15 +18,32 @@ impl Signer {
let settings = GLOBALS.settings.read().await;
*self.public.write() = settings.public_key;
*self.encrypted.write() = settings.encrypted_private_key.clone();
*self.private.write() = None;
let maybe_db = GLOBALS.db.lock().await;
let db = maybe_db.as_ref().unwrap();
if let Ok(epk) = db.query_row(
"SELECT encrypted_private_key FROM local_settings LIMIT 1",
[],
|row| row.get::<usize, String>(0),
) {
*self.encrypted.write() = Some(EncryptedPrivateKey(epk));
}
}
pub async fn save_through_settings(&self) -> Result<(), Error> {
let mut settings = GLOBALS.settings.write().await;
settings.public_key = *self.public.read();
settings.encrypted_private_key = self.encrypted.read().clone();
settings.save().await
settings.save().await?;
let epk = self.encrypted.read().clone();
let maybe_db = GLOBALS.db.lock().await;
let db = maybe_db.as_ref().unwrap();
db.execute(
"UPDATE local_settings SET encrypted_private_key=?",
(epk.map(|e| e.0),),
)?;
Ok(())
}
pub fn set_public_key(&self, pk: PublicKey) {