|
@@ -318,6 +318,18 @@ impl Bindable for usize {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+impl Bindable for f32 {
|
|
|
+ fn bind_to(&self, ctx: &StatementContext, index: i32) -> DBResult<()> {
|
|
|
+ (*self as f64).bind_to(ctx, index)
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+impl Bindable for f64 {
|
|
|
+ fn bind_to(&self, ctx: &StatementContext, index: i32) -> DBResult<()> {
|
|
|
+ unsafe { check_rcode(None, sq::sqlite3_bind_double(ctx.stmt.stmt, index, *self)) }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
impl<'a> Bindable for &'a str {
|
|
|
fn bind_to(&self, ctx: &StatementContext, index: i32) -> DBResult<()> {
|
|
|
unsafe {
|
|
@@ -374,6 +386,24 @@ impl Readable for i64 {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+impl Readable for usize {
|
|
|
+ fn read_from(sr: &StatementRow<'_>, index: i32) -> DBResult<Self> {
|
|
|
+ i64::read_from(sr, index).map(|i| i as usize)
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+impl Readable for f32 {
|
|
|
+ fn read_from(sr: &StatementRow<'_>, index: i32) -> DBResult<Self> {
|
|
|
+ f64::read_from(sr, index).map(|i| i as f32)
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+impl Readable for f64 {
|
|
|
+ fn read_from(sr: &StatementRow<'_>, index: i32) -> DBResult<Self> {
|
|
|
+ unsafe { Ok(sq::sqlite3_column_double(sr.stmt.stmt, index)) }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
impl Readable for String {
|
|
|
fn read_from(sr: &StatementRow<'_>, index: i32) -> DBResult<Self> {
|
|
|
unsafe {
|
|
@@ -408,24 +438,6 @@ impl Readable for Vec<u8> {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-/*
|
|
|
-
|
|
|
-pub type DBConnection = std::sync::Arc<Connection>;
|
|
|
-
|
|
|
-pub(crate) struct CachedStatement {
|
|
|
- stmt: sqlite::Statement<'static>,
|
|
|
- sql: String,
|
|
|
-}
|
|
|
-
|
|
|
-pub struct Connection {
|
|
|
- // we leak the ConnectionThreadSafe and make sure that the only references to it are stored in
|
|
|
- // statement_cache, so as long as we drop the statement_cache first there are no correctness
|
|
|
- // issues, and we get to have static-lifetime statements for caching purposes.
|
|
|
- conn: &'static sqlite::ConnectionThreadSafe,
|
|
|
- statement_cache: Mutex<HashMap<u64, CachedStatement>>,
|
|
|
-}
|
|
|
-
|
|
|
-/*
|
|
|
#[cfg(test)]
|
|
|
mod sendsync_check {
|
|
|
struct CheckSend<T: Send>(std::marker::PhantomData<T>);
|
|
@@ -433,82 +445,11 @@ mod sendsync_check {
|
|
|
|
|
|
#[test]
|
|
|
fn check_send() {
|
|
|
- let cs = CheckSend::<super::DBConnection>(Default::default());
|
|
|
+ let _ = CheckSend::<super::Connection>(Default::default());
|
|
|
}
|
|
|
-}
|
|
|
-*/
|
|
|
|
|
|
-impl Connection {
|
|
|
- pub fn open<U: AsRef<str>>(uri: U) -> Result<DBConnection, Error> {
|
|
|
- match sqlite::Connection::open_thread_safe_with_flags(
|
|
|
- uri.as_ref(),
|
|
|
- sqlite::OpenFlags::new()
|
|
|
- .with_create()
|
|
|
- .with_full_mutex()
|
|
|
- .with_read_write(),
|
|
|
- ) {
|
|
|
- Ok(conn) => {
|
|
|
- let conn = Box::leak(Box::new(conn));
|
|
|
- Ok(Arc::new(Self {
|
|
|
- conn,
|
|
|
- statement_cache: Default::default(),
|
|
|
- }))
|
|
|
- }
|
|
|
- Err(e) => Err(Error::Sqlite(e)),
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- pub(crate) fn execute_raw(&self, sql: &str) -> Result<(), Error> {
|
|
|
- Ok(self.conn.execute(sql)?)
|
|
|
- }
|
|
|
-
|
|
|
- pub(crate) fn with_prepared<R>(
|
|
|
- &self,
|
|
|
- hash_key: impl PreparedKey,
|
|
|
- build_query: impl Fn() -> String,
|
|
|
- run_query: impl Fn(&mut sqlite::Statement<'static>) -> DBResult<R>,
|
|
|
- ) -> DBResult<R> {
|
|
|
- match self.statement_cache.lock()?.entry(hash_key.into_u64()) {
|
|
|
- std::collections::hash_map::Entry::Vacant(e) => {
|
|
|
- let sql = build_query();
|
|
|
-
|
|
|
- let q: sqlite::Statement<'static> = self
|
|
|
- .conn
|
|
|
- .prepare(sql.as_str())
|
|
|
- .map_err(|e| Error::from(e).sqlite_to_query(sql.as_str()))?;
|
|
|
-
|
|
|
- log::trace!("prepared new SQL query: {sql}");
|
|
|
-
|
|
|
- let inserted = e.insert(CachedStatement {
|
|
|
- sql: sql.clone(),
|
|
|
- stmt: q,
|
|
|
- });
|
|
|
- run_query(&mut inserted.stmt).map_err(|e| e.sqlite_to_query(sql.as_str()))
|
|
|
- }
|
|
|
- std::collections::hash_map::Entry::Occupied(mut e) => run_query(&mut e.get_mut().stmt)
|
|
|
- .map_err(|err| err.sqlite_to_query(&e.get_mut().sql)),
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-impl Drop for Connection {
|
|
|
- fn drop(&mut self) {
|
|
|
- // first we drop the statement cache, if we can get it
|
|
|
- // if this fails then we're entering UD, but we probably panicked anyway
|
|
|
- self.statement_cache.lock().map(|mut sc| sc.clear()).ok();
|
|
|
- // then we drop the connection
|
|
|
- unsafe {
|
|
|
- drop(Box::from_raw(
|
|
|
- self.conn as *const _ as *mut sqlite::ConnectionThreadSafe,
|
|
|
- ));
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-impl std::fmt::Debug for Connection {
|
|
|
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
|
- f.write_str("microrm::Connection")
|
|
|
+ #[test]
|
|
|
+ fn check_sync() {
|
|
|
+ let _ = CheckSync::<super::Connection>(Default::default());
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
-*/
|