mirror of
https://github.com/YGGverse/Yoda.git
synced 2026-03-31 16:45:27 +00:00
use r2d2 pool, update rusqlite version
This commit is contained in:
parent
c3f63dfbdc
commit
33369e31ea
17 changed files with 171 additions and 197 deletions
|
|
@ -22,7 +22,7 @@ features = ["gnome_46"]
|
|||
|
||||
[dependencies.sqlite]
|
||||
package = "rusqlite"
|
||||
version = "0.32.1"
|
||||
version = "0.34.0"
|
||||
|
||||
[dependencies.sourceview]
|
||||
package = "sourceview5"
|
||||
|
|
@ -38,6 +38,8 @@ itertools = "0.14.0"
|
|||
libspelling = "0.3.0"
|
||||
openssl = "0.10.70"
|
||||
plurify = "0.2.0"
|
||||
r2d2 = "0.8.10"
|
||||
r2d2_sqlite = "0.27.0"
|
||||
syntect = "5.2.0"
|
||||
|
||||
# development
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ impl App {
|
|||
let profile = profile.clone();
|
||||
move |this| {
|
||||
// Init readable connection
|
||||
match profile.database.connection.read() {
|
||||
match profile.database.pool.get() {
|
||||
Ok(connection) => {
|
||||
// Create transaction
|
||||
match connection.unchecked_transaction() {
|
||||
|
|
@ -77,7 +77,7 @@ impl App {
|
|||
let profile = profile.clone();
|
||||
move |_| {
|
||||
match profile.save() {
|
||||
Ok(_) => match profile.database.connection.write() {
|
||||
Ok(_) => match profile.database.pool.get() {
|
||||
Ok(mut connection) => {
|
||||
// Create transaction
|
||||
match connection.transaction() {
|
||||
|
|
@ -266,7 +266,7 @@ impl App {
|
|||
pub fn run(&self) -> Result<ExitCode> {
|
||||
// Begin database migration @TODO
|
||||
{
|
||||
let mut connection = self.profile.database.connection.write().unwrap();
|
||||
let mut connection = self.profile.database.pool.get()?;
|
||||
let transaction = connection.transaction()?;
|
||||
migrate(&transaction)?;
|
||||
transaction.commit()?;
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ impl Save {
|
|||
button.set_sensitive(false);
|
||||
|
||||
// Create PEM file based on option ID selected
|
||||
match Certificate::new(profile.clone(), profile_identity_id) {
|
||||
match Certificate::build(profile.clone(), profile_identity_id) {
|
||||
Ok(certificate) => {
|
||||
// Init file filters related with PEM extension
|
||||
let filters = ListStore::new::<FileFilter>();
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
mod error;
|
||||
pub use error::Error;
|
||||
use anyhow::{bail, Result};
|
||||
|
||||
use crate::profile::Profile;
|
||||
use gtk::{gio::TlsCertificate, prelude::TlsCertificateExt};
|
||||
|
|
@ -15,19 +14,17 @@ impl Certificate {
|
|||
// Constructors
|
||||
|
||||
/// Create new `Self`
|
||||
pub fn new(profile: Rc<Profile>, profile_identity_id: i64) -> Result<Self, Error> {
|
||||
match profile.identity.database.record(profile_identity_id) {
|
||||
Ok(record) => match record {
|
||||
Some(identity) => match TlsCertificate::from_pem(&identity.pem) {
|
||||
Ok(certificate) => Ok(Self {
|
||||
data: identity.pem,
|
||||
name: certificate.subject_name().unwrap().replace("CN=", ""),
|
||||
}),
|
||||
Err(e) => Err(Error::TlsCertificate(e)),
|
||||
},
|
||||
None => Err(Error::NotFound(profile_identity_id)),
|
||||
},
|
||||
Err(e) => Err(Error::Database(e)),
|
||||
pub fn build(profile: Rc<Profile>, profile_identity_id: i64) -> Result<Self> {
|
||||
let record = profile.identity.database.record(profile_identity_id)?;
|
||||
match record {
|
||||
Some(identity) => Ok(Self {
|
||||
name: TlsCertificate::from_pem(&identity.pem)?
|
||||
.subject_name()
|
||||
.unwrap_or_default()
|
||||
.replace("CN=", ""),
|
||||
data: identity.pem,
|
||||
}),
|
||||
None => bail!("Identity not found!"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,25 +0,0 @@
|
|||
use gtk::glib;
|
||||
use std::fmt::{Display, Formatter, Result};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Error {
|
||||
Database(sqlite::Error),
|
||||
NotFound(i64),
|
||||
TlsCertificate(glib::Error),
|
||||
}
|
||||
|
||||
impl Display for Error {
|
||||
fn fmt(&self, f: &mut Formatter) -> Result {
|
||||
match self {
|
||||
Self::Database(e) => {
|
||||
write!(f, "Database error: {e}")
|
||||
}
|
||||
Self::NotFound(profile_identity_id) => {
|
||||
write!(f, "Record for `{profile_identity_id}` not found")
|
||||
}
|
||||
Self::TlsCertificate(e) => {
|
||||
write!(f, "TLS certificate error: {e}")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -4,16 +4,17 @@ mod history;
|
|||
mod identity;
|
||||
mod search;
|
||||
|
||||
use anyhow::Result;
|
||||
use bookmark::Bookmark;
|
||||
use database::Database;
|
||||
use gtk::glib::{user_config_dir, DateTime};
|
||||
use history::History;
|
||||
use identity::Identity;
|
||||
use r2d2::Pool;
|
||||
use r2d2_sqlite::SqliteConnectionManager;
|
||||
use search::Search;
|
||||
|
||||
use anyhow::Result;
|
||||
use gtk::glib::{user_config_dir, DateTime};
|
||||
use sqlite::{Connection, Transaction};
|
||||
use std::{fs::create_dir_all, path::PathBuf, rc::Rc, sync::RwLock};
|
||||
use sqlite::Transaction;
|
||||
use std::{fs::create_dir_all, path::PathBuf};
|
||||
|
||||
const VENDOR: &str = "YGGverse";
|
||||
const APP_ID: &str = "Yoda";
|
||||
|
|
@ -53,23 +54,24 @@ impl Profile {
|
|||
database_path.push(DB_NAME);
|
||||
|
||||
// Init database connection
|
||||
let connection = Rc::new(RwLock::new(Connection::open(database_path.as_path())?));
|
||||
let database_pool =
|
||||
Pool::new(SqliteConnectionManager::file(database_path.as_path())).unwrap();
|
||||
|
||||
// Init profile components
|
||||
{
|
||||
// Init writable connection
|
||||
let mut connection = connection.write().unwrap(); // @TODO handle
|
||||
let mut connection = database_pool.get()?;
|
||||
|
||||
// Init new transaction
|
||||
let transaction = connection.transaction()?;
|
||||
let tx = connection.transaction()?;
|
||||
|
||||
// Begin migration
|
||||
migrate(&transaction)?;
|
||||
transaction.commit()?;
|
||||
migrate(&tx)?;
|
||||
tx.commit()?;
|
||||
} // unlock database
|
||||
|
||||
// Init model
|
||||
let database = Database::build(&connection);
|
||||
let database = Database::build(&database_pool);
|
||||
|
||||
// Get active profile or create new one
|
||||
let profile_id = match database.active()? {
|
||||
|
|
@ -78,10 +80,10 @@ impl Profile {
|
|||
};
|
||||
|
||||
// Init components
|
||||
let bookmark = Bookmark::build(&connection, profile_id)?;
|
||||
let history = History::build(&connection, profile_id)?;
|
||||
let search = Search::build(&connection, profile_id)?;
|
||||
let identity = Identity::build(&connection, profile_id)?;
|
||||
let bookmark = Bookmark::build(&database_pool, profile_id)?;
|
||||
let history = History::build(&database_pool, profile_id)?;
|
||||
let search = Search::build(&database_pool, profile_id)?;
|
||||
let identity = Identity::build(&database_pool, profile_id)?;
|
||||
|
||||
// Result
|
||||
Ok(Self {
|
||||
|
|
|
|||
|
|
@ -7,11 +7,10 @@ use database::Database;
|
|||
use gtk::glib::DateTime;
|
||||
use item::Item;
|
||||
use memory::Memory;
|
||||
use sqlite::{Connection, Transaction};
|
||||
use std::{
|
||||
rc::Rc,
|
||||
sync::{Arc, RwLock},
|
||||
};
|
||||
use r2d2::Pool;
|
||||
use r2d2_sqlite::SqliteConnectionManager;
|
||||
use sqlite::Transaction;
|
||||
use std::sync::{Arc, RwLock};
|
||||
|
||||
pub struct Bookmark {
|
||||
database: Database, // permanent storage
|
||||
|
|
@ -22,9 +21,9 @@ impl Bookmark {
|
|||
// Constructors
|
||||
|
||||
/// Create new `Self`
|
||||
pub fn build(connection: &Rc<RwLock<Connection>>, profile_id: i64) -> Result<Self> {
|
||||
pub fn build(database_pool: &Pool<SqliteConnectionManager>, profile_id: i64) -> Result<Self> {
|
||||
// Init children components
|
||||
let database = Database::new(connection, profile_id);
|
||||
let database = Database::new(database_pool, profile_id);
|
||||
let memory = Arc::new(RwLock::new(Memory::new()));
|
||||
|
||||
// Build initial index
|
||||
|
|
|
|||
|
|
@ -1,11 +1,12 @@
|
|||
use super::Item;
|
||||
use anyhow::Result;
|
||||
use gtk::glib::DateTime;
|
||||
use sqlite::{Connection, Transaction};
|
||||
use std::{rc::Rc, sync::RwLock};
|
||||
use r2d2::Pool;
|
||||
use r2d2_sqlite::SqliteConnectionManager;
|
||||
use sqlite::Transaction;
|
||||
|
||||
pub struct Database {
|
||||
connection: Rc<RwLock<Connection>>,
|
||||
pool: Pool<SqliteConnectionManager>,
|
||||
profile_id: i64,
|
||||
}
|
||||
|
||||
|
|
@ -13,9 +14,9 @@ impl Database {
|
|||
// Constructors
|
||||
|
||||
/// Create new `Self`
|
||||
pub fn new(connection: &Rc<RwLock<Connection>>, profile_id: i64) -> Self {
|
||||
pub fn new(pool: &Pool<SqliteConnectionManager>, profile_id: i64) -> Self {
|
||||
Self {
|
||||
connection: connection.clone(),
|
||||
pool: pool.clone(),
|
||||
profile_id,
|
||||
}
|
||||
}
|
||||
|
|
@ -24,9 +25,12 @@ impl Database {
|
|||
|
||||
/// Get bookmark records from database with optional filter by `request`
|
||||
pub fn records(&self, request: Option<&str>, title: Option<&str>) -> Result<Vec<Item>> {
|
||||
let readable = self.connection.read().unwrap(); // @TODO
|
||||
let tx = readable.unchecked_transaction()?;
|
||||
select(&tx, self.profile_id, request, title)
|
||||
select(
|
||||
&self.pool.get()?.unchecked_transaction()?,
|
||||
self.profile_id,
|
||||
request,
|
||||
title,
|
||||
)
|
||||
}
|
||||
|
||||
// Setters
|
||||
|
|
@ -34,8 +38,8 @@ impl Database {
|
|||
/// Create new bookmark record in database
|
||||
/// * return last insert ID on success
|
||||
pub fn add(&self, time: DateTime, request: &str, title: Option<&str>) -> Result<i64> {
|
||||
let mut writable = self.connection.write().unwrap(); // @TODO
|
||||
let tx = writable.transaction()?;
|
||||
let mut connection = self.pool.get()?;
|
||||
let tx = connection.transaction()?;
|
||||
let id = insert(&tx, self.profile_id, time, request, title)?;
|
||||
tx.commit()?;
|
||||
Ok(id)
|
||||
|
|
@ -43,8 +47,8 @@ impl Database {
|
|||
|
||||
/// Delete bookmark record from database
|
||||
pub fn delete(&self, id: i64) -> Result<usize> {
|
||||
let mut writable = self.connection.write().unwrap(); // @TODO
|
||||
let tx = writable.transaction()?;
|
||||
let mut connection = self.pool.get()?;
|
||||
let tx = connection.transaction()?;
|
||||
let usize = delete(&tx, id)?;
|
||||
tx.commit()?;
|
||||
Ok(usize)
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
use anyhow::Result;
|
||||
use gtk::glib::DateTime;
|
||||
use sqlite::{Connection, Transaction};
|
||||
use std::{rc::Rc, sync::RwLock};
|
||||
use r2d2::Pool;
|
||||
use r2d2_sqlite::SqliteConnectionManager;
|
||||
use sqlite::Transaction;
|
||||
|
||||
pub struct Table {
|
||||
pub id: i64,
|
||||
|
|
@ -11,26 +12,22 @@ pub struct Table {
|
|||
}
|
||||
|
||||
pub struct Database {
|
||||
pub connection: Rc<RwLock<Connection>>,
|
||||
pub pool: Pool<SqliteConnectionManager>,
|
||||
}
|
||||
|
||||
impl Database {
|
||||
// Constructors
|
||||
|
||||
/// Create new `Self`
|
||||
pub fn build(connection: &Rc<RwLock<Connection>>) -> Self {
|
||||
Self {
|
||||
connection: connection.clone(),
|
||||
}
|
||||
pub fn build(pool: &Pool<SqliteConnectionManager>) -> Self {
|
||||
Self { pool: pool.clone() }
|
||||
}
|
||||
|
||||
// Getters
|
||||
|
||||
/// Get all records
|
||||
pub fn records(&self) -> Result<Vec<Table>> {
|
||||
let readable = self.connection.read().unwrap();
|
||||
let tx = readable.unchecked_transaction()?;
|
||||
select(&tx)
|
||||
select(&self.pool.get()?.unchecked_transaction()?)
|
||||
}
|
||||
|
||||
/// Get active profile record if exist
|
||||
|
|
@ -43,8 +40,8 @@ impl Database {
|
|||
|
||||
/// Create new record in `Self` database connected
|
||||
pub fn add(&self, is_active: bool, time: DateTime, name: Option<String>) -> Result<i64> {
|
||||
let mut writable = self.connection.write().unwrap();
|
||||
let tx = writable.transaction()?;
|
||||
let mut connection = self.pool.get()?;
|
||||
let tx = connection.transaction()?;
|
||||
if is_active {
|
||||
for record in select(&tx)? {
|
||||
update(&tx, record.id, false, record.time, record.name)?;
|
||||
|
|
|
|||
|
|
@ -7,11 +7,10 @@ use database::Database;
|
|||
use gtk::glib::GString;
|
||||
use item::{Event, Item};
|
||||
use memory::Memory;
|
||||
use sqlite::{Connection, Transaction};
|
||||
use std::{
|
||||
rc::Rc,
|
||||
sync::{Arc, RwLock},
|
||||
};
|
||||
use r2d2::Pool;
|
||||
use r2d2_sqlite::SqliteConnectionManager;
|
||||
use sqlite::Transaction;
|
||||
use std::sync::{Arc, RwLock};
|
||||
|
||||
pub struct History {
|
||||
database: Database, // permanent storage
|
||||
|
|
@ -22,9 +21,9 @@ impl History {
|
|||
// Constructors
|
||||
|
||||
/// Create new `Self`
|
||||
pub fn build(connection: &Rc<RwLock<Connection>>, profile_id: i64) -> Result<Self> {
|
||||
pub fn build(database_pool: &Pool<SqliteConnectionManager>, profile_id: i64) -> Result<Self> {
|
||||
// Init children components
|
||||
let database = Database::build(connection, profile_id);
|
||||
let database = Database::build(database_pool, profile_id);
|
||||
let memory = Arc::new(RwLock::new(Memory::new()));
|
||||
|
||||
for item in database.records(None, None)? {
|
||||
|
|
|
|||
|
|
@ -1,11 +1,12 @@
|
|||
use super::{item::Event, Item};
|
||||
use anyhow::Result;
|
||||
use gtk::glib::DateTime;
|
||||
use sqlite::{Connection, Transaction};
|
||||
use std::{rc::Rc, sync::RwLock};
|
||||
use r2d2::Pool;
|
||||
use r2d2_sqlite::SqliteConnectionManager;
|
||||
use sqlite::Transaction;
|
||||
|
||||
pub struct Database {
|
||||
connection: Rc<RwLock<Connection>>,
|
||||
pool: Pool<SqliteConnectionManager>,
|
||||
profile_id: i64,
|
||||
}
|
||||
|
||||
|
|
@ -13,9 +14,9 @@ impl Database {
|
|||
// Constructors
|
||||
|
||||
/// Create new `Self`
|
||||
pub fn build(connection: &Rc<RwLock<Connection>>, profile_id: i64) -> Self {
|
||||
pub fn build(pool: &Pool<SqliteConnectionManager>, profile_id: i64) -> Self {
|
||||
Self {
|
||||
connection: connection.clone(),
|
||||
pool: pool.clone(),
|
||||
profile_id,
|
||||
}
|
||||
}
|
||||
|
|
@ -24,9 +25,12 @@ impl Database {
|
|||
|
||||
/// Get history records from database with optional filter by `request`
|
||||
pub fn records(&self, request: Option<&str>, title: Option<&str>) -> Result<Vec<Item>> {
|
||||
let readable = self.connection.read().unwrap(); // @TODO
|
||||
let tx = readable.unchecked_transaction()?;
|
||||
select(&tx, self.profile_id, request, title)
|
||||
select(
|
||||
&self.pool.get()?.unchecked_transaction()?,
|
||||
self.profile_id,
|
||||
request,
|
||||
title,
|
||||
)
|
||||
}
|
||||
|
||||
// Actions
|
||||
|
|
@ -34,16 +38,16 @@ impl Database {
|
|||
/// Create new history record in database
|
||||
/// * return last insert ID on success
|
||||
pub fn add(&self, item: &Item) -> Result<i64> {
|
||||
let mut writable = self.connection.write().unwrap(); // @TODO
|
||||
let tx = writable.transaction()?;
|
||||
let mut connection = self.pool.get()?;
|
||||
let tx = connection.transaction()?;
|
||||
let id = insert(&tx, self.profile_id, item)?;
|
||||
tx.commit()?;
|
||||
Ok(id)
|
||||
}
|
||||
|
||||
pub fn update(&self, item: &Item) -> Result<usize> {
|
||||
let mut writable = self.connection.write().unwrap(); // @TODO
|
||||
let tx = writable.transaction()?;
|
||||
let mut connection = self.pool.get()?;
|
||||
let tx = connection.transaction()?;
|
||||
let affected = update(&tx, self.profile_id, item)?;
|
||||
tx.commit()?;
|
||||
Ok(affected)
|
||||
|
|
|
|||
|
|
@ -10,8 +10,9 @@ use database::Database;
|
|||
use gtk::glib::DateTime;
|
||||
use item::Item;
|
||||
use memory::Memory;
|
||||
use sqlite::{Connection, Transaction};
|
||||
use std::{rc::Rc, sync::RwLock};
|
||||
use r2d2::Pool;
|
||||
use r2d2_sqlite::SqliteConnectionManager;
|
||||
use sqlite::Transaction;
|
||||
|
||||
/// Authorization wrapper for Gemini protocol
|
||||
///
|
||||
|
|
@ -26,10 +27,13 @@ impl Identity {
|
|||
// Constructors
|
||||
|
||||
/// Create new `Self`
|
||||
pub fn build(connection: &Rc<RwLock<Connection>>, profile_identity_id: i64) -> Result<Self> {
|
||||
pub fn build(
|
||||
database_pool: &Pool<SqliteConnectionManager>,
|
||||
profile_identity_id: i64,
|
||||
) -> Result<Self> {
|
||||
// Init components
|
||||
let auth = Auth::build(connection)?;
|
||||
let database = Database::build(connection, profile_identity_id);
|
||||
let auth = Auth::build(database_pool)?;
|
||||
let database = Database::build(database_pool, profile_identity_id);
|
||||
let memory = Memory::new();
|
||||
|
||||
// Init `Self`
|
||||
|
|
|
|||
|
|
@ -6,24 +6,25 @@ mod memory;
|
|||
use anyhow::Result;
|
||||
use database::Database;
|
||||
use memory::Memory;
|
||||
use sqlite::{Connection, Transaction};
|
||||
use std::{rc::Rc, sync::RwLock};
|
||||
use r2d2::Pool;
|
||||
use r2d2_sqlite::SqliteConnectionManager;
|
||||
use sqlite::Transaction;
|
||||
|
||||
/// Auth pair operations
|
||||
pub struct Auth {
|
||||
database: Rc<Database>,
|
||||
memory: Rc<Memory>,
|
||||
database: Database,
|
||||
memory: Memory,
|
||||
}
|
||||
|
||||
impl Auth {
|
||||
// Constructors
|
||||
|
||||
/// Create new `Self`
|
||||
pub fn build(connection: &Rc<RwLock<Connection>>) -> Result<Self> {
|
||||
pub fn build(database_pool: &Pool<SqliteConnectionManager>) -> Result<Self> {
|
||||
// Init `Self`
|
||||
let this = Self {
|
||||
database: Rc::new(Database::build(connection)),
|
||||
memory: Rc::new(Memory::new()),
|
||||
database: Database::build(database_pool),
|
||||
memory: Memory::new(),
|
||||
};
|
||||
|
||||
// Build initial index
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
use anyhow::Result;
|
||||
use sqlite::{Connection, Transaction};
|
||||
use std::{rc::Rc, sync::RwLock};
|
||||
use r2d2::Pool;
|
||||
use r2d2_sqlite::SqliteConnectionManager;
|
||||
use sqlite::Transaction;
|
||||
|
||||
pub struct Table {
|
||||
pub id: i64,
|
||||
|
|
@ -10,25 +11,23 @@ pub struct Table {
|
|||
|
||||
/// Storage for `profile_identity_id` + `scope` auth pairs
|
||||
pub struct Database {
|
||||
connection: Rc<RwLock<Connection>>,
|
||||
pool: Pool<SqliteConnectionManager>,
|
||||
}
|
||||
|
||||
impl Database {
|
||||
// Constructors
|
||||
|
||||
/// Create new `Self`
|
||||
pub fn build(connection: &Rc<RwLock<Connection>>) -> Self {
|
||||
Self {
|
||||
connection: connection.clone(),
|
||||
}
|
||||
pub fn build(pool: &Pool<SqliteConnectionManager>) -> Self {
|
||||
Self { pool: pool.clone() }
|
||||
}
|
||||
|
||||
// Actions
|
||||
|
||||
/// Create new record in database
|
||||
pub fn add(&self, profile_identity_id: i64, scope: &str) -> Result<i64> {
|
||||
let mut writable = self.connection.write().unwrap(); // @TODO
|
||||
let tx = writable.transaction()?;
|
||||
let mut connection = self.pool.get()?;
|
||||
let tx = connection.transaction()?;
|
||||
let id = insert(&tx, profile_identity_id, scope)?;
|
||||
tx.commit()?;
|
||||
Ok(id)
|
||||
|
|
@ -36,8 +35,8 @@ impl Database {
|
|||
|
||||
/// Delete record with given `id` from database
|
||||
pub fn delete(&self, id: i64) -> Result<()> {
|
||||
let mut writable = self.connection.write().unwrap(); // @TODO
|
||||
let tx = writable.transaction()?;
|
||||
let mut connection = self.pool.get()?;
|
||||
let tx = connection.transaction()?;
|
||||
delete(&tx, id)?;
|
||||
tx.commit()?;
|
||||
Ok(())
|
||||
|
|
@ -47,16 +46,15 @@ impl Database {
|
|||
|
||||
/// Get records from database match current `profile_id` optionally filtered by `scope`
|
||||
pub fn records_scope(&self, scope: Option<&str>) -> Result<Vec<Table>> {
|
||||
let readable = self.connection.read().unwrap(); // @TODO
|
||||
let tx = readable.unchecked_transaction()?;
|
||||
select_scope(&tx, scope)
|
||||
select_scope(&self.pool.get()?.unchecked_transaction()?, scope)
|
||||
}
|
||||
|
||||
/// Get records from database match current `profile_id` optionally filtered by `scope`
|
||||
pub fn records_ref(&self, profile_identity_id: i64) -> Result<Vec<Table>> {
|
||||
let readable = self.connection.read().unwrap(); // @TODO
|
||||
let tx = readable.unchecked_transaction()?;
|
||||
select_ref(&tx, profile_identity_id)
|
||||
select_ref(
|
||||
&self.pool.get()?.unchecked_transaction()?,
|
||||
profile_identity_id,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
use sqlite::{Connection, Error, Transaction};
|
||||
use std::{rc::Rc, sync::RwLock};
|
||||
use anyhow::Result;
|
||||
use r2d2::Pool;
|
||||
use r2d2_sqlite::SqliteConnectionManager;
|
||||
use sqlite::Transaction;
|
||||
|
||||
pub struct Table {
|
||||
pub id: i64,
|
||||
|
|
@ -9,7 +11,7 @@ pub struct Table {
|
|||
|
||||
/// Storage for Gemini auth certificates
|
||||
pub struct Database {
|
||||
connection: Rc<RwLock<Connection>>,
|
||||
pool: Pool<SqliteConnectionManager>,
|
||||
profile_id: i64,
|
||||
}
|
||||
|
||||
|
|
@ -17,9 +19,9 @@ impl Database {
|
|||
// Constructors
|
||||
|
||||
/// Create new `Self`
|
||||
pub fn build(connection: &Rc<RwLock<Connection>>, profile_id: i64) -> Self {
|
||||
pub fn build(pool: &Pool<SqliteConnectionManager>, profile_id: i64) -> Self {
|
||||
Self {
|
||||
connection: connection.clone(),
|
||||
pool: pool.clone(),
|
||||
profile_id,
|
||||
}
|
||||
}
|
||||
|
|
@ -27,10 +29,10 @@ impl Database {
|
|||
// Actions
|
||||
|
||||
/// Create new record in database
|
||||
pub fn add(&self, pem: &str) -> Result<i64, Error> {
|
||||
pub fn add(&self, pem: &str) -> Result<i64> {
|
||||
// Begin new transaction
|
||||
let mut writable = self.connection.write().unwrap(); // @TODO
|
||||
let tx = writable.transaction()?;
|
||||
let mut connection = self.pool.get()?;
|
||||
let tx = connection.transaction()?;
|
||||
|
||||
// Create new record
|
||||
insert(&tx, self.profile_id, pem)?;
|
||||
|
|
@ -39,55 +41,45 @@ impl Database {
|
|||
let id = last_insert_id(&tx);
|
||||
|
||||
// Done
|
||||
match tx.commit() {
|
||||
Ok(_) => Ok(id),
|
||||
Err(e) => Err(e),
|
||||
}
|
||||
tx.commit()?;
|
||||
Ok(id)
|
||||
}
|
||||
|
||||
/// Delete record with given `id` from database
|
||||
pub fn delete(&self, id: i64) -> Result<(), Error> {
|
||||
pub fn delete(&self, id: i64) -> Result<()> {
|
||||
// Begin new transaction
|
||||
let mut writable = self.connection.write().unwrap(); // @TODO
|
||||
let tx = writable.transaction()?;
|
||||
let mut connection = self.pool.get()?;
|
||||
let tx = connection.transaction()?;
|
||||
|
||||
// Create new record
|
||||
delete(&tx, id)?;
|
||||
|
||||
// Done
|
||||
match tx.commit() {
|
||||
Ok(_) => Ok(()),
|
||||
Err(e) => Err(e),
|
||||
}
|
||||
tx.commit()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Get single record match `id`
|
||||
pub fn record(&self, id: i64) -> Result<Option<Table>, Error> {
|
||||
let readable = self.connection.read().unwrap();
|
||||
let tx = readable.unchecked_transaction()?;
|
||||
let records = select(&tx, self.profile_id)?; // @TODO single record query
|
||||
|
||||
pub fn record(&self, id: i64) -> Result<Option<Table>> {
|
||||
let records = select(&self.pool.get()?.unchecked_transaction()?, self.profile_id)?; // @TODO single record query
|
||||
for record in records {
|
||||
if record.id == id {
|
||||
return Ok(Some(record));
|
||||
}
|
||||
}
|
||||
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
/// Get all records match current `profile_id`
|
||||
pub fn records(&self) -> Result<Vec<Table>, Error> {
|
||||
let readable = self.connection.read().unwrap(); // @TODO
|
||||
let tx = readable.unchecked_transaction()?;
|
||||
select(&tx, self.profile_id)
|
||||
pub fn records(&self) -> Result<Vec<Table>> {
|
||||
select(&self.pool.get()?.unchecked_transaction()?, self.profile_id)
|
||||
}
|
||||
}
|
||||
|
||||
// Low-level DB API
|
||||
|
||||
pub fn init(tx: &Transaction) -> Result<usize, Error> {
|
||||
tx.execute(
|
||||
pub fn init(tx: &Transaction) -> Result<usize> {
|
||||
Ok(tx.execute(
|
||||
"CREATE TABLE IF NOT EXISTS `profile_identity`
|
||||
(
|
||||
`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
|
||||
|
|
@ -97,24 +89,24 @@ pub fn init(tx: &Transaction) -> Result<usize, Error> {
|
|||
FOREIGN KEY (`profile_id`) REFERENCES `profile`(`id`)
|
||||
)",
|
||||
[],
|
||||
)
|
||||
)?)
|
||||
}
|
||||
|
||||
pub fn insert(tx: &Transaction, profile_id: i64, pem: &str) -> Result<usize, Error> {
|
||||
tx.execute(
|
||||
pub fn insert(tx: &Transaction, profile_id: i64, pem: &str) -> Result<usize> {
|
||||
Ok(tx.execute(
|
||||
"INSERT INTO `profile_identity` (
|
||||
`profile_id`,
|
||||
`pem`
|
||||
) VALUES (?, ?)",
|
||||
(profile_id, pem),
|
||||
)
|
||||
)?)
|
||||
}
|
||||
|
||||
pub fn delete(tx: &Transaction, id: i64) -> Result<usize, Error> {
|
||||
tx.execute("DELETE FROM `profile_identity` WHERE `id` = ?", [id])
|
||||
pub fn delete(tx: &Transaction, id: i64) -> Result<usize> {
|
||||
Ok(tx.execute("DELETE FROM `profile_identity` WHERE `id` = ?", [id])?)
|
||||
}
|
||||
|
||||
pub fn select(tx: &Transaction, profile_id: i64) -> Result<Vec<Table>, Error> {
|
||||
pub fn select(tx: &Transaction, profile_id: i64) -> Result<Vec<Table>> {
|
||||
let mut stmt = tx.prepare(
|
||||
"SELECT `id`,
|
||||
`profile_id`,
|
||||
|
|
|
|||
|
|
@ -5,8 +5,9 @@ use anyhow::Result;
|
|||
use database::Database;
|
||||
use gtk::glib::Uri;
|
||||
use memory::Memory;
|
||||
use sqlite::{Connection, Transaction};
|
||||
use std::{rc::Rc, sync::RwLock};
|
||||
use r2d2::Pool;
|
||||
use r2d2_sqlite::SqliteConnectionManager;
|
||||
use sqlite::Transaction;
|
||||
|
||||
pub struct Search {
|
||||
database: Database, // permanent storage
|
||||
|
|
@ -17,8 +18,8 @@ impl Search {
|
|||
// Constructors
|
||||
|
||||
/// Create new `Self`
|
||||
pub fn build(connection: &Rc<RwLock<Connection>>, profile_id: i64) -> Result<Self> {
|
||||
let database = Database::init(connection, profile_id)?;
|
||||
pub fn build(database_pool: &Pool<SqliteConnectionManager>, profile_id: i64) -> Result<Self> {
|
||||
let database = Database::init(database_pool, profile_id)?;
|
||||
// Init fast search index
|
||||
let memory = Memory::init();
|
||||
// Build initial index
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
use anyhow::Result;
|
||||
use sqlite::{Connection, Transaction};
|
||||
use std::{rc::Rc, sync::RwLock};
|
||||
use r2d2::Pool;
|
||||
use r2d2_sqlite::SqliteConnectionManager;
|
||||
use sqlite::Transaction;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Row {
|
||||
|
|
@ -11,7 +12,7 @@ pub struct Row {
|
|||
}
|
||||
|
||||
pub struct Database {
|
||||
connection: Rc<RwLock<Connection>>,
|
||||
pool: Pool<SqliteConnectionManager>,
|
||||
profile_id: i64,
|
||||
}
|
||||
|
||||
|
|
@ -19,9 +20,9 @@ impl Database {
|
|||
// Constructors
|
||||
|
||||
/// Create new `Self`
|
||||
pub fn init(connection: &Rc<RwLock<Connection>>, profile_id: i64) -> Result<Self> {
|
||||
let mut writable = connection.write().unwrap(); // @TODO handle
|
||||
let tx = writable.transaction()?;
|
||||
pub fn init(pool: &Pool<SqliteConnectionManager>, profile_id: i64) -> Result<Self> {
|
||||
let mut connection = pool.get()?;
|
||||
let tx = connection.transaction()?;
|
||||
|
||||
let records = select(&tx, profile_id)?;
|
||||
|
||||
|
|
@ -31,7 +32,7 @@ impl Database {
|
|||
}
|
||||
|
||||
Ok(Self {
|
||||
connection: connection.clone(),
|
||||
pool: pool.clone(),
|
||||
profile_id,
|
||||
})
|
||||
}
|
||||
|
|
@ -40,9 +41,7 @@ impl Database {
|
|||
|
||||
/// Get records from database
|
||||
pub fn records(&self) -> Result<Vec<Row>> {
|
||||
let readable = self.connection.read().unwrap(); // @TODO handle
|
||||
let tx = readable.unchecked_transaction()?;
|
||||
select(&tx, self.profile_id)
|
||||
select(&self.pool.get()?.unchecked_transaction()?, self.profile_id)
|
||||
}
|
||||
|
||||
// Setters
|
||||
|
|
@ -50,8 +49,8 @@ impl Database {
|
|||
/// Create new record in database
|
||||
/// * return last insert ID on success
|
||||
pub fn add(&self, query: String, is_default: bool) -> Result<i64> {
|
||||
let mut writable = self.connection.write().unwrap(); // @TODO handle
|
||||
let tx = writable.transaction()?;
|
||||
let mut connection = self.pool.get()?;
|
||||
let tx = connection.transaction()?;
|
||||
if is_default {
|
||||
reset(&tx, self.profile_id, !is_default)?;
|
||||
}
|
||||
|
|
@ -63,8 +62,8 @@ impl Database {
|
|||
/// Delete record from database
|
||||
pub fn delete(&self, id: i64) -> Result<()> {
|
||||
// Begin new transaction
|
||||
let mut writable = self.connection.write().unwrap(); // @TODO
|
||||
let tx = writable.transaction()?;
|
||||
let mut connection = self.pool.get()?;
|
||||
let tx = connection.transaction()?;
|
||||
|
||||
// Delete record by ID
|
||||
delete(&tx, id)?;
|
||||
|
|
@ -97,8 +96,8 @@ impl Database {
|
|||
/// Delete record from database
|
||||
pub fn set_default(&self, id: i64) -> Result<()> {
|
||||
// Begin new transaction
|
||||
let mut writable = self.connection.write().unwrap(); // @TODO
|
||||
let tx = writable.transaction()?;
|
||||
let mut connection = self.pool.get()?;
|
||||
let tx = connection.transaction()?;
|
||||
|
||||
// Make sure only one default provider in set
|
||||
reset(&tx, self.profile_id, false)?;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue