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}