Should be all the database functions I need
[?]
Jan 14, 2022, 12:48 AM
LLFG625ISXV7P2LUOFUMFIM5V5RJDKWCL47XX43X2CGILVAUQPVQCDependencies
- [2]
AVLXUT3RMake the boxed errors Send - [3]
G5YNDTPHCargo clippy - [4]
LPVC545KGet the scraper part of this program working - [5]
5Y7ZXB53Start picker UI - [6]
AV73DYWQInitial functions for using sqlite in async environment - [7]
RNW6D777Minor tidy - [8]
YCWYAX6KFunctions for scraping names integrated enough to test (they don't work yet) - [9]
KUANIPWFAdd function for adding name to database - [*]
HMOBTVJ4Initialize crate and add expected dependencies
Change contents
- replacement in src/pick.rs at line 7
QueueableCommand,ExecutableCommand, QueueableCommand, - replacement in src/pick.rs at line 11
pub async fn pick(db: AsyncConnection, count: u16) -> DynResult<()> {pub async fn pick(db: &AsyncConnection, count: u16) -> DynResult<()> {let mut stderr = std::io::stderr();stderr.execute(cursor::Hide)?;let (mut input, done) = events();stderr.execute(cursor::Show)?; - edit in src/names_database.rs at line 18
)?;conn.execute("CREATE INDEX IF NOT EXISTS prefs_index ON preferences(better,worse)",)?;conn.execute("CREATE INDEX IF NOT EXISTS prefs_better ON preferences(better)", - edit in src/names_database.rs at line 25
conn.execute("CREATE INDEX IF NOT EXISTS prefs_worse ON preferences(worse)",)?; - replacement in src/names_database.rs at line 31
type DBFunction = Box<dyn for<'a> FnOnce(&'a sqlite::Connection) + Send>;type DBFunction =Box<dyn for<'a> FnOnce(&'a sqlite::Connection) + Send + Sync + 'static>; - edit in src/names_database.rs at line 34
#[derive(Clone)] - replacement in src/names_database.rs at line 55
pub async fn add_name(&self, name: String) -> DynResult<i64> {match selfpub async fn add_name(&self, name: String) -> DynResult<(i64, bool)> {Ok(self - replacement in src/names_database.rs at line 61
stmnt.next().ok();let is_new = stmnt.next().is_ok(); - replacement in src/names_database.rs at line 66
sqlite::State::Row => Ok(stmnt.read::<i64>(0)?),sqlite::State::Row => Ok((stmnt.read::<i64>(0)?, is_new)), - edit in src/names_database.rs at line 73
}}).await??)}pub async fn compare(&self,a: i64,b: i64,) -> DynResult<Option<std::cmp::Ordering>> {if a == b {return Ok(Some(std::cmp::Ordering::Equal));}Ok(self.post(move |conn| -> DynResult<Option<std::cmp::Ordering>> {let mut stmnt = conn.prepare("SELECT better, worse FROM preferences WHERE (better = ? AND worse = ?) OR (better = ? AND worse = ?)")?;stmnt.bind::<i64>(1,a)?;stmnt.bind::<i64>(2,b)?;stmnt.bind::<i64>(3,b)?;stmnt.bind::<i64>(4,a)?;match stmnt.next()? {sqlite::State::Done => Ok(None),sqlite::State::Row => {let better = stmnt.read::<i64>(0)?;let worse = stmnt.read::<i64>(1)?;if better == a && worse == b {Ok(Some(std::cmp::Ordering::Greater))} else if better == b && worse == a {Ok(Some(std::cmp::Ordering::Less))} else {Ok(Some(std::cmp::Ordering::Equal))}}}}).await??)}pub async fn list_names(&self) -> DynResult<Vec<(String, i64)>> {match self.post(|conn| {let mut stmnt =conn.prepare("SELECT name, rowid FROM names")?;let mut rows = Vec::new();while let sqlite::State::Row = stmnt.next()? {rows.push((stmnt.read::<String>(0)?,stmnt.read::<i64>(1)?,)); - edit in src/names_database.rs at line 121
Ok(rows) - replacement in src/names_database.rs at line 126
Ok(Err(e)) => Err(Box::new(e) as crate::DynError),Ok(Err(e)) => Err(e), - edit in src/names_database.rs at line 128
}}async fn insert_preference(&self,better: i64,worse: i64,) -> DynResult<()> {self.insert_one_preference(better, worse).await?;self.make_transitive().await}async fn insert_one_preference(&self,better: i64,worse: i64,) -> DynResult<()> {self.post(move |db| -> DynResult<_> {let mut stmnt = db.prepare("INSERT INTO preferences(better, worse) VALUES(?, ?)",)?;stmnt.bind::<i64>(1, better)?;stmnt.bind::<i64>(2, worse)?;stmnt.next()?;Ok(())}).await?}pub async fn make_transitive(&self) -> DynResult<()> {loop {let todo = self.post(|db| -> DynResult<_> {let mut stmnt = db.prepare("SELECT a.better, b.worseFROM preferences AS aINNER JOIN preferences as b ON a.worse = b.betterWHERE NOT EXISTS (SELECT rowid FROM preferences AS xWHERE x.better = a.betterAND x.worse = b.worse)",)?;let mut rows = Vec::new();while let sqlite::State::Row = stmnt.next()? {rows.push((stmnt.read::<i64>(0)?,stmnt.read::<i64>(1)?,));}Ok(rows)}).await??;if todo.is_empty() {return Ok(());} else {let handles: Vec<_> = todo.into_iter().map(|(better, worse)| {let target = self.clone();tokio::spawn(async move {target.insert_one_preference(better, worse).await})}).collect();for handle in handles {handle.await??;}} - replacement in src/names_database.rs at line 202
F: FnOnce(&sqlite::Connection) -> U + Send + 'static,F: FnOnce(&sqlite::Connection) -> U + Send, - edit in src/names_database.rs at line 209
let h = move |conn: &sqlite::Connection| {sc.send(cb(conn)).unwrap_or(());}; - replacement in src/names_database.rs at line 213
.send(Box::new(move |conn: &sqlite::Connection| {sc.send(cb(conn)).unwrap_or(());.send(unsafe {std::mem::transmute::<_, DBFunction>(Box::new(h)as Box<dyn for<'a> FnOnce(&'a sqlite::Connection) + Send>) - edit in src/names_database.rs at line 217
as Box<dyn for<'a> FnOnce(&'a sqlite::Connection) + Send>) - replacement in src/main.rs at line 47
Self::Pick { count } => {}Self::Pick { count } => {pick::pick(db, *count).await?;}