inmemory_sqlite/
lib.rs

1use std::sync::atomic::AtomicU64;
2use std::sync::atomic::Ordering;
3
4use std::ops::Deref;
5
6use std::convert;
7use std::result;
8
9use rusqlite::*;
10
11use thread_local::ThreadLocal;
12
13static COUNTER: AtomicU64 = AtomicU64::new(0u64);
14
15pub fn open_shared(name: &str) -> Result<Connection> {
16    let uri = format!("file:{}?mode=memory&cache=shared", name);
17    Connection::open(uri)
18}
19
20pub fn new_shared() -> Result<Connection> {
21    open_shared(&format!(
22        "shared_{}",
23        COUNTER.fetch_add(1u64, Ordering::AcqRel)
24    ))
25}
26
27pub struct SyncSqliteConnection {
28    connection: ThreadLocal<Connection>,
29    name: String,
30}
31
32impl SyncSqliteConnection {
33    pub fn new() -> Result<Self> {
34        let name = format!("shared_{}", COUNTER.fetch_add(1u64, Ordering::AcqRel));
35
36        let this = SyncSqliteConnection {
37            connection: ThreadLocal::new(),
38            name: name,
39        };
40
41        this.try_get()?;
42        Result::Ok(this)
43    }
44
45    pub fn open(name: String) -> Result<Self> {
46        let this = SyncSqliteConnection {
47            connection: ThreadLocal::new(),
48            name: name,
49        };
50
51        this.try_get()?;
52        Result::Ok(this)
53    }
54
55    pub fn name(&self) -> &String {
56        &self.name
57    }
58
59    fn try_get(&self) -> Result<&Connection> {
60        self.connection.get_or_try(|| open_shared(&self.name()))
61    }
62
63    pub fn force(&self) -> &Connection {
64        self.try_get()
65            .expect("ERROR: Creating the connection to the sqlite in memory database has failed!")
66    }
67
68    pub fn prepare(&self, sql: &str) -> Result<SyncStatement<'_>> {
69        SyncStatement::new(self, sql.to_owned())
70    }
71}
72
73impl Deref for SyncSqliteConnection {
74    type Target = Connection;
75    fn deref(&self) -> &Self::Target {
76        self.force()
77    }
78}
79
80impl Clone for SyncSqliteConnection {
81    fn clone(&self) -> Self {
82        SyncSqliteConnection::open(self.name().clone())
83            .expect("ERROR: opening the sqlite database has failed!")
84    }
85
86    fn clone_from(&mut self, source: &Self) {
87        self.name = source.name().clone();
88        self.connection.clear();
89    }
90}
91
92struct SendStatement<'a>(Statement<'a>);
93
94unsafe impl<'a> Send for SendStatement<'a> {}
95
96pub struct SyncStatement<'conn> {
97    conn: &'conn SyncSqliteConnection,
98    stmt: ThreadLocal<SendStatement<'conn>>,
99    sql: String,
100}
101
102impl<'conn> SyncStatement<'conn> {
103    fn new(conn: &'conn SyncSqliteConnection, sql: String) -> Result<SyncStatement<'conn>> {
104        let this = SyncStatement {
105            conn: conn,
106            stmt: ThreadLocal::new(),
107            sql: sql,
108        };
109
110        this.try_get()?;
111        Result::Ok(this)
112    }
113
114    fn try_get(&self) -> Result<&Statement<'_>> {
115        self.stmt
116            .get_or_try(|| {
117                self.conn
118                    .try_get()
119                    .and_then(|conn| conn.prepare(&self.sql).map(|stmt| SendStatement(stmt)))
120            })
121            .map(|ss| &ss.0)
122    }
123
124    pub fn execute<P>(&self, params: P) -> Result<usize>
125    where
126        P: IntoIterator,
127        P::Item: ToSql,
128    {
129        let statement = self.try_get()?;
130        unsafe { &mut *(statement as *const _ as *mut Statement) }.execute(params)
131    }
132
133    pub fn execute_named(&self, params: &[(&str, &dyn ToSql)]) -> Result<usize> {
134        let statement = self.try_get()?;
135        unsafe { &mut *(statement as *const _ as *mut Statement) }.execute_named(params)
136    }
137
138    pub fn exists<P>(&self, params: P) -> Result<bool>
139    where
140        P: IntoIterator,
141        P::Item: ToSql,
142    {
143        let statement = self.try_get()?;
144        unsafe { &mut *(statement as *const _ as *mut Statement) }.exists(params)
145    }
146
147    pub fn insert<P>(&self, params: P) -> Result<i64>
148    where
149        P: IntoIterator,
150        P::Item: ToSql,
151    {
152        let statement = self.try_get()?;
153        unsafe { &mut *(statement as *const _ as *mut Statement) }.insert(params)
154    }
155
156    pub fn query<P>(&self, params: P) -> Result<Rows<'_>>
157    where
158        P: IntoIterator,
159        P::Item: ToSql,
160    {
161        let statement = self.try_get()?;
162        unsafe { &mut *(statement as *const _ as *mut Statement) }.query(params)
163    }
164
165    pub fn query_named(&self, params: &[(&str, &dyn ToSql)]) -> Result<Rows<'_>> {
166        let statement = self.try_get()?;
167        unsafe { &mut *(statement as *const _ as *mut Statement) }.query_named(params)
168    }
169
170    pub fn query_map<T, P, F>(&self, params: P, f: F) -> Result<MappedRows<'_, F>>
171    where
172        P: IntoIterator,
173        P::Item: ToSql,
174        F: FnMut(&Row<'_>) -> Result<T>,
175    {
176        let statement = self.try_get()?;
177        unsafe { &mut *(statement as *const _ as *mut Statement) }.query_map(params, f)
178    }
179
180    pub fn query_map_named<T, F>(
181        &self,
182        params: &[(&str, &dyn ToSql)],
183        f: F,
184    ) -> Result<MappedRows<'_, F>>
185    where
186        F: FnMut(&Row<'_>) -> Result<T>,
187    {
188        let statement = self.try_get()?;
189        unsafe { &mut *(statement as *const _ as *mut Statement) }.query_map_named(params, f)
190    }
191
192    pub fn query_and_then<T, E, P, F>(&self, params: P, f: F) -> Result<AndThenRows<'_, F>>
193    where
194        P: IntoIterator,
195        P::Item: ToSql,
196        E: convert::From<Error>,
197        F: FnMut(&Row<'_>) -> result::Result<T, E>,
198    {
199        let statement = self.try_get()?;
200        unsafe { &mut *(statement as *const _ as *mut Statement) }.query_and_then(params, f)
201    }
202
203    pub fn query_and_then_named<T, E, F>(
204        &self,
205        params: &[(&str, &dyn ToSql)],
206        f: F,
207    ) -> Result<AndThenRows<'_, F>>
208    where
209        E: convert::From<Error>,
210        F: FnMut(&Row<'_>) -> result::Result<T, E>,
211    {
212        let statement = self.try_get()?;
213        unsafe { &mut *(statement as *const _ as *mut Statement) }.query_and_then_named(params, f)
214    }
215
216    pub fn query_row<T, P, F>(&self, params: P, f: F) -> Result<T>
217    where
218        P: IntoIterator,
219        P::Item: ToSql,
220        F: FnOnce(&Row<'_>) -> Result<T>,
221    {
222        let statement = self.try_get()?;
223        unsafe { &mut *(statement as *const _ as *mut Statement) }.query_row(params, f)
224    }
225
226    pub fn query_row_named<T, F>(&self, params: &[(&str, &dyn ToSql)], f: F) -> Result<T>
227    where
228        F: FnOnce(&Row<'_>) -> Result<T>,
229    {
230        let statement = self.try_get()?;
231        unsafe { &mut *(statement as *const _ as *mut Statement) }.query_row_named(params, f)
232    }
233
234    pub fn parameter_index(&self, name: &str) -> Result<Option<usize>> {
235        let statement = self.try_get()?;
236        unsafe { &mut *(statement as *const _ as *mut Statement) }.parameter_index(name)
237    }
238
239    pub fn force(&self) -> &Statement<'_> {
240        self.try_get()
241            .expect("ERROR: Building the prepared statement has failed!")
242    }
243
244    pub fn deref(&self) -> &Statement<'_> {
245        self.force()
246    }
247}
248
249impl<'conn> Clone for SyncStatement<'conn> {
250    fn clone(&self) -> Self {
251        SyncStatement::new(self.conn, self.sql.clone())
252            .expect("ERROR: creating the sqlitet prepared statement has failed!")
253    }
254
255    fn clone_from(&mut self, source: &Self) {
256        self.conn = source.conn;
257        self.sql = source.sql.clone();
258        self.stmt.clear();
259    }
260}
261
262mod test {
263
264    #[test]
265    fn testnew() {
266        let _ignore = crate::SyncSqliteConnection::new();
267    }
268
269    #[test]
270    fn testnewrealconnection() {
271        let _connection = crate::SyncSqliteConnection::new().unwrap();
272    }
273
274    #[test]
275    fn test_open() {
276        let dummy = crate::SyncSqliteConnection::new().unwrap();
277
278        let c1 = crate::SyncSqliteConnection::new().unwrap();
279
280        let c2 = crate::SyncSqliteConnection::open(c1.name().clone()).unwrap();
281
282        assert_eq!(c1.name(), c2.name());
283        assert_ne!(dummy.name(), c1.name());
284    }
285
286    #[test]
287    fn test_clone() {
288        let c1 = crate::SyncSqliteConnection::new().unwrap();
289
290        let c2 = c1.clone();
291        assert_eq!(c1.name(), c2.name());
292    }
293}