mirror of
https://github.com/chatmail/core.git
synced 2026-05-22 16:26:31 +03:00
remove tracking of current sql query
this will not work like this anymore with async
This commit is contained in:
25
Cargo.lock
generated
25
Cargo.lock
generated
@@ -796,7 +796,6 @@ dependencies = [
|
|||||||
"surf",
|
"surf",
|
||||||
"tempfile",
|
"tempfile",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"thread-local-object",
|
|
||||||
"url",
|
"url",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -3014,15 +3013,6 @@ dependencies = [
|
|||||||
"syn 1.0.23",
|
"syn 1.0.23",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "thread-local-object"
|
|
||||||
version = "0.1.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "7da3caa820d0308c84c8654f6cafd81cc3195d45433311cbe22fcf44fc8be071"
|
|
||||||
dependencies = [
|
|
||||||
"unsafe-any",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "thread_local"
|
name = "thread_local"
|
||||||
version = "1.0.1"
|
version = "1.0.1"
|
||||||
@@ -3062,12 +3052,6 @@ dependencies = [
|
|||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "traitobject"
|
|
||||||
version = "0.1.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "efd1f82c56340fdf16f2a953d7bda4f8fdffba13d93b00844c25572110b26079"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "try_from"
|
name = "try_from"
|
||||||
version = "0.3.2"
|
version = "0.3.2"
|
||||||
@@ -3145,15 +3129,6 @@ version = "0.2.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c"
|
checksum = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "unsafe-any"
|
|
||||||
version = "0.4.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "f30360d7979f5e9c6e6cea48af192ea8fab4afb3cf72597154b8f08935bc9c7f"
|
|
||||||
dependencies = [
|
|
||||||
"traitobject",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "url"
|
name = "url"
|
||||||
version = "2.1.1"
|
version = "2.1.1"
|
||||||
|
|||||||
@@ -40,7 +40,6 @@ r2d2_sqlite = "0.15.0"
|
|||||||
r2d2 = "0.8.5"
|
r2d2 = "0.8.5"
|
||||||
strum = "0.16.0"
|
strum = "0.16.0"
|
||||||
strum_macros = "0.16.0"
|
strum_macros = "0.16.0"
|
||||||
thread-local-object = "0.1.0"
|
|
||||||
backtrace = "0.3.33"
|
backtrace = "0.3.33"
|
||||||
byteorder = "1.3.1"
|
byteorder = "1.3.1"
|
||||||
itertools = "0.8.0"
|
itertools = "0.8.0"
|
||||||
|
|||||||
82
src/sql.rs
82
src/sql.rs
@@ -1,14 +1,13 @@
|
|||||||
//! # SQLite wrapper
|
//! # SQLite wrapper
|
||||||
|
|
||||||
use async_std::prelude::*;
|
use async_std::prelude::*;
|
||||||
use async_std::sync::{Arc, RwLock};
|
use async_std::sync::RwLock;
|
||||||
|
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
use rusqlite::{Connection, Error as SqlError, OpenFlags};
|
use rusqlite::{Connection, Error as SqlError, OpenFlags};
|
||||||
use thread_local_object::ThreadLocal;
|
|
||||||
|
|
||||||
use crate::chat::{update_device_icon, update_saved_messages_icon};
|
use crate::chat::{update_device_icon, update_saved_messages_icon};
|
||||||
use crate::constants::{ShowEmails, DC_CHAT_ID_TRASH};
|
use crate::constants::{ShowEmails, DC_CHAT_ID_TRASH};
|
||||||
@@ -53,15 +52,12 @@ pub type Result<T> = std::result::Result<T, Error>;
|
|||||||
#[derive(DebugStub)]
|
#[derive(DebugStub)]
|
||||||
pub struct Sql {
|
pub struct Sql {
|
||||||
pool: RwLock<Option<r2d2::Pool<r2d2_sqlite::SqliteConnectionManager>>>,
|
pool: RwLock<Option<r2d2::Pool<r2d2_sqlite::SqliteConnectionManager>>>,
|
||||||
#[debug_stub = "ThreadLocal<String>"]
|
|
||||||
in_use: Arc<ThreadLocal<String>>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Sql {
|
impl Default for Sql {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
pool: RwLock::new(None),
|
pool: RwLock::new(None),
|
||||||
in_use: Arc::new(ThreadLocal::new()),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -77,7 +73,6 @@ impl Sql {
|
|||||||
|
|
||||||
pub async fn close(&self) {
|
pub async fn close(&self) {
|
||||||
let _ = self.pool.write().await.take();
|
let _ = self.pool.write().await.take();
|
||||||
self.in_use.remove();
|
|
||||||
// drop closes the connection
|
// drop closes the connection
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -100,13 +95,9 @@ impl Sql {
|
|||||||
sql: S,
|
sql: S,
|
||||||
params: Vec<&dyn crate::ToSql>,
|
params: Vec<&dyn crate::ToSql>,
|
||||||
) -> Result<usize> {
|
) -> Result<usize> {
|
||||||
self.start_stmt(sql.as_ref());
|
|
||||||
|
|
||||||
let res = {
|
let res = {
|
||||||
let conn = self.get_conn().await?;
|
let conn = self.get_conn().await?;
|
||||||
let res = conn.execute(sql.as_ref(), params);
|
conn.execute(sql.as_ref(), params)
|
||||||
self.in_use.remove();
|
|
||||||
res
|
|
||||||
};
|
};
|
||||||
|
|
||||||
res.map_err(Into::into)
|
res.map_err(Into::into)
|
||||||
@@ -126,18 +117,12 @@ impl Sql {
|
|||||||
F: FnMut(&rusqlite::Row) -> rusqlite::Result<T>,
|
F: FnMut(&rusqlite::Row) -> rusqlite::Result<T>,
|
||||||
G: FnMut(rusqlite::MappedRows<F>) -> Result<H>,
|
G: FnMut(rusqlite::MappedRows<F>) -> Result<H>,
|
||||||
{
|
{
|
||||||
self.start_stmt(sql.as_ref().to_string());
|
|
||||||
let sql = sql.as_ref();
|
let sql = sql.as_ref();
|
||||||
|
|
||||||
let res = {
|
let conn = self.get_conn().await?;
|
||||||
let conn = self.get_conn().await?;
|
let mut stmt = conn.prepare(sql)?;
|
||||||
let mut stmt = conn.prepare(sql)?;
|
let res = stmt.query_map(¶ms, f)?;
|
||||||
let res = stmt.query_map(¶ms, f)?;
|
g(res)
|
||||||
self.in_use.remove();
|
|
||||||
g(res)
|
|
||||||
};
|
|
||||||
|
|
||||||
res
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_conn(
|
pub async fn get_conn(
|
||||||
@@ -161,10 +146,7 @@ impl Sql {
|
|||||||
let pool = lock.as_ref().ok_or_else(|| Error::SqlNoConnection)?;
|
let pool = lock.as_ref().ok_or_else(|| Error::SqlNoConnection)?;
|
||||||
let conn = pool.get()?;
|
let conn = pool.get()?;
|
||||||
|
|
||||||
let res = g(conn);
|
g(conn)
|
||||||
self.in_use.remove();
|
|
||||||
|
|
||||||
res
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn with_conn_async<G, H, Fut>(&self, mut g: G) -> Result<H>
|
pub async fn with_conn_async<G, H, Fut>(&self, mut g: G) -> Result<H>
|
||||||
@@ -175,25 +157,17 @@ impl Sql {
|
|||||||
let lock = self.pool.read().await;
|
let lock = self.pool.read().await;
|
||||||
let pool = lock.as_ref().ok_or_else(|| Error::SqlNoConnection)?;
|
let pool = lock.as_ref().ok_or_else(|| Error::SqlNoConnection)?;
|
||||||
|
|
||||||
let res = {
|
let conn = pool.get()?;
|
||||||
let conn = pool.get()?;
|
g(conn).await
|
||||||
let res = g(conn).await;
|
|
||||||
self.in_use.remove();
|
|
||||||
res
|
|
||||||
};
|
|
||||||
res
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return `true` if a query in the SQL statement it executes returns one or more
|
/// Return `true` if a query in the SQL statement it executes returns one or more
|
||||||
/// rows and false if the SQL returns an empty set.
|
/// rows and false if the SQL returns an empty set.
|
||||||
pub async fn exists(&self, sql: &str, params: Vec<&dyn crate::ToSql>) -> Result<bool> {
|
pub async fn exists(&self, sql: &str, params: Vec<&dyn crate::ToSql>) -> Result<bool> {
|
||||||
self.start_stmt(sql.to_string());
|
|
||||||
let res = {
|
let res = {
|
||||||
let conn = self.get_conn().await?;
|
let conn = self.get_conn().await?;
|
||||||
let mut stmt = conn.prepare(sql)?;
|
let mut stmt = conn.prepare(sql)?;
|
||||||
let res = stmt.exists(¶ms);
|
stmt.exists(¶ms)
|
||||||
self.in_use.remove();
|
|
||||||
res
|
|
||||||
};
|
};
|
||||||
|
|
||||||
res.map_err(Into::into)
|
res.map_err(Into::into)
|
||||||
@@ -209,20 +183,16 @@ impl Sql {
|
|||||||
where
|
where
|
||||||
F: FnOnce(&rusqlite::Row) -> rusqlite::Result<T>,
|
F: FnOnce(&rusqlite::Row) -> rusqlite::Result<T>,
|
||||||
{
|
{
|
||||||
self.start_stmt(sql.as_ref().to_string());
|
|
||||||
let sql = sql.as_ref();
|
let sql = sql.as_ref();
|
||||||
let res = {
|
let res = {
|
||||||
let conn = self.get_conn().await?;
|
let conn = self.get_conn().await?;
|
||||||
let res = conn.query_row(sql, params, f);
|
conn.query_row(sql, params, f)
|
||||||
self.in_use.remove();
|
|
||||||
res
|
|
||||||
};
|
};
|
||||||
|
|
||||||
res.map_err(Into::into)
|
res.map_err(Into::into)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn table_exists(&self, name: impl AsRef<str>) -> Result<bool> {
|
pub async fn table_exists(&self, name: impl AsRef<str>) -> Result<bool> {
|
||||||
self.start_stmt("table_exists");
|
|
||||||
let name = name.as_ref().to_string();
|
let name = name.as_ref().to_string();
|
||||||
self.with_conn(move |conn| {
|
self.with_conn(move |conn| {
|
||||||
let mut exists = false;
|
let mut exists = false;
|
||||||
@@ -317,13 +287,13 @@ impl Sql {
|
|||||||
if exists {
|
if exists {
|
||||||
self.execute(
|
self.execute(
|
||||||
"UPDATE config SET value=? WHERE keyname=?;",
|
"UPDATE config SET value=? WHERE keyname=?;",
|
||||||
paramsv![value.to_string(), key.to_string()],
|
paramsv![(*value).to_string(), key.to_string()],
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
} else {
|
} else {
|
||||||
self.execute(
|
self.execute(
|
||||||
"INSERT INTO config (keyname, value) VALUES (?, ?);",
|
"INSERT INTO config (keyname, value) VALUES (?, ?);",
|
||||||
paramsv![key.to_string(), value.to_string()],
|
paramsv![key.to_string(), (*value).to_string()],
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
@@ -405,20 +375,6 @@ impl Sql {
|
|||||||
.and_then(|r| r.parse().ok())
|
.and_then(|r| r.parse().ok())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn start_stmt(&self, stmt: impl AsRef<str>) {
|
|
||||||
if let Some(query) = self.in_use.get_cloned() {
|
|
||||||
let bt = backtrace::Backtrace::new();
|
|
||||||
eprintln!("old query: {}", query);
|
|
||||||
eprintln!("Connection is already used from this thread: {:?}", bt);
|
|
||||||
panic!(
|
|
||||||
"Connection is already used from this thread: trying to execute {}",
|
|
||||||
stmt.as_ref()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
self.in_use.set(stmt.as_ref().to_string());
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Alternative to sqlite3_last_insert_rowid() which MUST NOT be used due to race conditions, see comment above.
|
/// Alternative to sqlite3_last_insert_rowid() which MUST NOT be used due to race conditions, see comment above.
|
||||||
/// the ORDER BY ensures, this function always returns the most recent id,
|
/// the ORDER BY ensures, this function always returns the most recent id,
|
||||||
/// eg. if a Message-ID is split into different messages.
|
/// eg. if a Message-ID is split into different messages.
|
||||||
@@ -429,13 +385,9 @@ impl Sql {
|
|||||||
field: impl AsRef<str>,
|
field: impl AsRef<str>,
|
||||||
value: impl AsRef<str>,
|
value: impl AsRef<str>,
|
||||||
) -> Result<u32> {
|
) -> Result<u32> {
|
||||||
self.start_stmt("get rowid".to_string());
|
|
||||||
|
|
||||||
let res = {
|
let res = {
|
||||||
let mut conn = self.get_conn().await?;
|
let mut conn = self.get_conn().await?;
|
||||||
let res = get_rowid(&mut conn, table, field, value);
|
get_rowid(&mut conn, table, field, value)
|
||||||
self.in_use.remove();
|
|
||||||
res
|
|
||||||
};
|
};
|
||||||
|
|
||||||
res.map_err(Into::into)
|
res.map_err(Into::into)
|
||||||
@@ -450,13 +402,9 @@ impl Sql {
|
|||||||
field2: impl AsRef<str>,
|
field2: impl AsRef<str>,
|
||||||
value2: i32,
|
value2: i32,
|
||||||
) -> Result<u32> {
|
) -> Result<u32> {
|
||||||
self.start_stmt("get rowid2".to_string());
|
|
||||||
|
|
||||||
let res = {
|
let res = {
|
||||||
let mut conn = self.get_conn().await?;
|
let mut conn = self.get_conn().await?;
|
||||||
let res = get_rowid2(&mut conn, table, field, value, field2, value2);
|
get_rowid2(&mut conn, table, field, value, field2, value2)
|
||||||
self.in_use.remove();
|
|
||||||
res
|
|
||||||
};
|
};
|
||||||
|
|
||||||
res.map_err(Into::into)
|
res.map_err(Into::into)
|
||||||
|
|||||||
Reference in New Issue
Block a user