1pub const SQLITE_NO_PARAM: &[SqlBindableRef] = &[];
6pub type SqlBindableRef<'a> = &'a (dyn SqlBindable + 'a);
7pub type SqlBindableBox<'a> = Box<dyn SqlBindable + 'a>;
8
9pub struct SqliteConnection {
10 info: SqliteConnectionInfo,
11 connection: Mutex<Connection>,
12 cached_statements: Mutex<StatementCache>,
13}
14
15impl MallocSizeOf for SqliteConnection {
16 fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize { unimplemented!() }
17}
18
19pub struct SqliteConnectionInfo {
20 pub readonly: bool,
21 pub path: PathBuf,
22 pub open_flags: OpenFlags,
23}
24
25type StatementCache = HashMap<String, ScopedStatement>;
26
27impl Drop for SqliteConnection {
28 fn drop(&mut self) {
29 self.cached_statements.get_mut().clear();
33 unsafe {
42 if let Ok(new_connection) = Connection::open_with_flags(
43 self.info.path.clone(),
44 Self::default_open_flags().set_read_write(),
45 ) {
46 self.connection.get_mut().remove_busy_handler().ok();
47 if self.close().is_err() {
48 error!(
49 "Closing sqlite connection while still being used.
50 The sqlite connection will be closed when all pending
51 resources are released. However it suggests that the
52 code may not managing object ownership and lifetime
53 of sqlite execution well."
54 );
55 self.close_v2().ok();
56 }
57
58 std::ptr::write(self.connection.get_mut(), new_connection);
59 }
60 }
61 }
62}
63
64unsafe impl Send for SqliteConnection {}
65unsafe impl Sync for SqliteConnection {}
66
67impl SqliteConnection {
68 pub fn close(&mut self) -> Result<()> {
69 match unsafe { sqlite_ffi::sqlite3_close(self.get_db_mut().as_raw()) } {
70 sqlite_ffi::SQLITE_OK => Ok(()),
71 code => bail!(sqlite::Error {
72 code: Some(code as isize),
73 message: None
74 }),
75 }
76 }
77
78 pub fn close_v2(&mut self) -> Result<()> {
79 match unsafe {
80 sqlite_ffi::sqlite3_close_v2(self.get_db_mut().as_raw())
81 } {
82 sqlite_ffi::SQLITE_OK => Ok(()),
83 code => bail!(sqlite::Error {
84 code: Some(code as isize),
85 message: None
86 }),
87 }
88 }
89
90 pub fn default_open_flags() -> OpenFlags {
91 unsafe {
94 std::mem::transmute::<i32, OpenFlags>(
95 sqlite_ffi::SQLITE_OPEN_NOMUTEX
96 | sqlite_ffi::SQLITE_OPEN_SHAREDCACHE
98 | sqlite_ffi::SQLITE_OPEN_URI,
99 )
100 }
101 }
102
103 pub fn create_and_init<P: AsRef<Path>>(
108 path: P, unsafe_mode: bool,
109 ) -> Result<()> {
110 let conn = Connection::open_with_flags(
111 &path,
112 Self::default_open_flags().set_read_write().set_create(),
113 )?;
114 if unsafe_mode {
115 conn.execute("PRAGMA journal_mode=OFF")?;
116 conn.execute("PRAGMA synchronous=OFF")?;
117 } else {
118 conn.execute("PRAGMA journal_mode=WAL")?;
119 }
120 conn.execute("PRAGMA locking_mode=EXCLUSIVE")?;
124 Ok(())
125 }
126
127 pub fn create_and_open<P: AsRef<Path>>(
128 path: P, open_flags: OpenFlags, unsafe_mode: bool,
129 ) -> Result<Self> {
130 Self::create_and_init(path.as_ref(), unsafe_mode)?;
131 Self::open(path, false, open_flags)
132 }
133
134 pub fn open<P: AsRef<Path>>(
135 path: P, readonly: bool, open_flags: OpenFlags,
136 ) -> Result<Self> {
137 let conn_open_flags = if readonly {
138 open_flags.set_read_only()
139 } else {
140 open_flags.set_read_write()
141 };
142
143 Ok(Self {
144 info: SqliteConnectionInfo {
145 readonly,
146 path: path.as_ref().to_path_buf(),
147 open_flags,
148 },
149 connection: Mutex::new(Connection::open_with_flags(
150 path,
151 conn_open_flags,
152 )?),
153 cached_statements: Mutex::new(HashMap::new()),
154 })
155 }
156
157 pub fn try_clone(&self) -> Result<Self> {
158 Self::open(&self.info.path, self.info.readonly, self.info.open_flags)
159 }
160
161 pub fn prepare<'db>(
162 db: &'db mut Connection, statement_cache: &'db mut StatementCache,
163 sql: &str,
164 ) -> Result<&'db mut ScopedStatement> {
165 Ok(unsafe {
168 let maybe_statement = statement_cache
169 .get_mut(sql)
170 .map(|x| x as *mut ScopedStatement);
171 if maybe_statement.is_some() {
172 &mut *maybe_statement.unwrap()
173 } else {
174 statement_cache.entry(sql.to_string()).or_insert(
175 ScopedStatement::new(db.prepare(sql)?),
179 )
180 }
181 })
182 }
183
184 pub fn execute_locked<'db, 'p, Param: Borrow<dyn SqlBindable + 'p>>(
188 statement: &'db mut ScopedStatement, params: &[Param],
189 ) -> Result<MaybeRows<'db>> {
190 Ok(MaybeRows(statement.execute(params)?))
191 }
192
193 pub fn execute<'p, Param: Borrow<dyn SqlBindable + 'p>>(
194 &mut self, sql: &str, params: &[Param],
195 ) -> Result<MaybeRows<'_>> {
196 let db = self.connection.get_mut();
197 let statement =
198 Self::prepare(db, self.cached_statements.get_mut(), sql)?;
199
200 Self::execute_locked(statement, params)
201 }
202
203 pub fn get_db_mut(&mut self) -> &mut Connection {
204 self.connection.get_mut()
205 }
206
207 pub fn lock_db(&self) -> MutexGuard<'_, Connection> {
208 self.connection.lock()
209 }
210
211 pub fn lock_statement_cache(&self) -> MutexGuard<'_, StatementCache> {
212 self.cached_statements.lock()
213 }
214
215 pub fn possible_temporary_files(db_path: &str) -> Vec<String> {
216 let mut paths = vec![];
217 paths.push(Self::wal_path(db_path));
218 paths.push(Self::shm_path(db_path));
219
220 paths
221 }
222
223 fn wal_path(db_path: &str) -> String { db_path.to_string() + "-wal" }
224
225 fn shm_path(db_path: &str) -> String { db_path.to_string() + "-shm" }
226}
227
228pub trait SqlBindable {
232 fn bind(&self, statement: &mut Statement, i: usize) -> sqlite::Result<()>;
233}
234
235pub trait SqlDerefBindable<'a> {
238 type Type: Bindable;
239
240 fn as_bindable(&'a self) -> Self::Type;
241}
242
243impl<'a, T: ?Sized + 'a + Deref> SqlDerefBindable<'a> for T
244where &'a T::Target: Bindable
245{
246 type Type = &'a T::Target;
247
248 fn as_bindable(&'a self) -> Self::Type { self.deref() }
249}
250
251impl SqlBindable for i64 {
252 fn bind(&self, statement: &mut Statement, i: usize) -> sqlite::Result<()> {
253 Bindable::bind(*self as i64, statement, i)
254 }
255}
256
257impl<'a, T: 'a + Deref> SqlBindable for Pin<T>
258where for<'x> &'x T::Target: Bindable
259{
260 fn bind(&self, statement: &mut Statement, i: usize) -> sqlite::Result<()> {
261 Bindable::bind(&**self, statement, i)
262 }
263}
264
265impl<'a, T: 'a + ?Sized> SqlBindable for &'a T
266where T: SqlDerefBindable<'a>
267{
268 fn bind(&self, statement: &mut Statement, i: usize) -> sqlite::Result<()> {
269 Bindable::bind(self.as_bindable(), statement, i)
270 }
271}
272
273pub trait SqlReadable: SqlReadableIntoSelf + Sized {
274 fn from_column(row: &Statement<'_>, column: usize) -> Result<Self>;
275}
276
277impl SqlReadable for Vec<u8> {
278 fn from_column(row: &Statement<'_>, column: usize) -> Result<Self> {
279 Ok(Self::read(row, column)?)
280 }
281}
282
283impl SqlReadable for Box<[u8]> {
284 fn from_column(row: &Statement<'_>, column: usize) -> Result<Self> {
285 Ok(Vec::<u8>::read(row, column)?.into_boxed_slice())
286 }
287}
288
289impl SqlReadable for i64 {
290 fn from_column(row: &Statement<'_>, column: usize) -> Result<Self> {
291 Ok(i64::read(row, column)?)
292 }
293}
294
295pub trait SqlReadableIntoSelf {
297 fn read_into_self(
298 &mut self, row: &Statement<'_>, column: usize,
299 ) -> Result<()>;
300}
301
302impl<T: SqlReadable> SqlReadableIntoSelf for T {
303 fn read_into_self(
304 &mut self, row: &Statement<'_>, column: usize,
305 ) -> Result<()> {
306 Ok(*self = Self::from_column(row, column)?)
307 }
308}
309
310impl<'a> Bindable for &'a dyn SqlBindable {
311 fn bind(self, statement: &mut Statement, i: usize) -> sqlite::Result<()> {
312 self.bind(statement, i)
313 }
314}
315
316type MaybeUnfinishedStatement<'db> = Option<&'db mut Statement<'db>>;
317
318#[derive(Default)]
319pub struct MaybeRows<'db>(MaybeUnfinishedStatement<'db>);
320
321impl<'db> MaybeRows<'db> {
322 pub fn finish_ignore_rows(&mut self) -> Result<()> {
323 while Self::next(&mut self.0)?.is_some() {}
324 Ok(())
325 }
326
327 pub fn map<Item, F: FnMut(&Statement<'db>) -> Item>(
328 mut self, f: F,
329 ) -> MappedRows<'db, F> {
330 MappedRows {
331 maybe_rows: self.0.take(),
332 f,
333 }
334 }
335
336 pub fn statement_ref<'a>(
337 maybe_statement: &'a mut MaybeUnfinishedStatement<'db>,
338 ) -> &'a Statement<'db> {
339 maybe_statement.as_ref().unwrap()
340 }
341
342 pub fn next<'a>(
343 maybe_statement: &'a mut MaybeUnfinishedStatement<'db>,
344 ) -> Result<Option<&'a Statement<'db>>> {
345 let state = match maybe_statement {
346 None => return Ok(None),
347 Some(statement) => statement.next()?,
348 };
349
350 match state {
351 State::Row => Ok(Some(Self::statement_ref(maybe_statement))),
352 State::Done => {
353 *maybe_statement = None;
354 Ok(None)
355 }
356 }
357 }
358}
359
360#[allow(dead_code)]
361pub struct ConnectionWithRowParser<Connection, RowParser>(
362 pub Connection,
363 pub RowParser,
364);
365
366pub struct MappedRows<'db, F> {
367 maybe_rows: MaybeUnfinishedStatement<'db>,
370 f: F,
371}
372
373impl<'db, Item, F: FnMut(&Statement<'db>) -> Item> MappedRows<'db, F> {
374 pub fn expect_one_row(&mut self) -> Result<Option<Item>> {
375 if self.maybe_rows.is_none() {
376 Ok(None)
377 } else {
378 let row_mapped =
379 (self.f)(MaybeRows::statement_ref(&mut self.maybe_rows));
380 if MaybeRows::next(&mut self.maybe_rows)?.is_none() {
381 Ok(Some(row_mapped))
382 } else {
383 bail!(Error::DbValueError)
384 }
385 }
386 }
387}
388
389impl<'db, Item, F: FnMut(&Statement<'db>) -> Result<Item>> FallibleIterator
390 for MappedRows<'db, F>
391{
392 type Error = Error;
393 type Item = Item;
394
395 fn next(&mut self) -> Result<Option<Self::Item>> {
396 if self.maybe_rows.is_none() {
397 Ok(None)
398 } else {
399 let value =
400 (self.f)(MaybeRows::statement_ref(&mut self.maybe_rows))?;
401 MaybeRows::next(&mut self.maybe_rows)?;
402 Ok(Some(value))
403 }
404 }
405}
406
407pub struct ScopedStatement {
419 stmt: Statement<'static>,
420}
421
422impl ScopedStatement {
423 unsafe fn new<'a>(scoped_statement: Statement<'a>) -> Self {
426 Self {
427 stmt: std::mem::transmute::<Statement<'a>, Statement<'static>>(
428 scoped_statement,
429 ),
430 }
431 }
432
433 fn as_mut(&mut self) -> &mut Statement<'_> {
434 unsafe {
435 std::mem::transmute::<&mut Statement<'static>, &mut Statement<'_>>(
436 &mut self.stmt,
437 )
438 }
439 }
440
441 fn bind<'p, Param: Borrow<dyn SqlBindable + 'p>>(
452 &mut self, params: &[Param],
453 ) -> Result<()> {
454 self.stmt.reset().ok();
455 for i in 0..params.len() {
456 self.stmt.bind(i + 1, params[i].borrow())?
458 }
459 Ok(())
460 }
461
462 fn execute<'p, Param: Borrow<dyn SqlBindable + 'p>>(
463 &mut self, params: &[Param],
464 ) -> Result<MaybeUnfinishedStatement<'_>> {
465 self.bind(params)?;
466
467 let result = self.stmt.next();
469 match result {
470 Ok(State::Done) => Ok(None),
471 Ok(State::Row) => Ok(Some(self.as_mut())),
472 Err(e) => {
473 bail!(e);
474 }
475 }
476 }
477}
478
479pub trait ValueReadImpl<Kind: ?Sized>: Sized {
480 fn from_row_impl(row: &Statement<'_>, value_column: usize) -> Result<Self>;
481 fn from_kv_row_impl(
482 row: &Statement<'_>, key: &mut dyn SqlReadableIntoSelf,
483 ) -> Result<Self>;
484}
485
486pub trait ValueRead {
487 type Kind: ?Sized;
488}
489
490impl ValueRead for () {
491 type Kind = ();
492}
493
494impl ValueRead for Box<[u8]> {
495 type Kind = dyn SqlReadableIntoSelf;
496}
497
498impl ValueReadImpl<()> for () {
499 fn from_row_impl(
500 _row: &Statement<'_>, _value_column: usize,
501 ) -> Result<Self> {
502 Ok(())
503 }
504
505 fn from_kv_row_impl(
506 row: &Statement<'_>, key: &mut dyn SqlReadableIntoSelf,
507 ) -> Result<Self> {
508 key.read_into_self(row, 0)?;
509 Ok(())
510 }
511}
512
513impl<ValueType: SqlReadable> ValueReadImpl<dyn SqlReadableIntoSelf>
514 for ValueType
515{
516 fn from_row_impl(row: &Statement<'_>, value_column: usize) -> Result<Self> {
517 ValueType::from_column(row, value_column)
518 }
519
520 fn from_kv_row_impl(
521 row: &Statement<'_>, key: &mut dyn SqlReadableIntoSelf,
522 ) -> Result<Self> {
523 key.read_into_self(row, 0)?;
524 ValueType::from_column(row, 1)
525 }
526}
527
528impl<
529 ValueType: Default + TupleIndexExt + TupleIterate<dyn SqlReadableIntoSelf>,
530 > ValueRead for ValueType
531{
532 type Kind = dyn ElementSatisfy<dyn SqlReadableIntoSelf>;
533}
534
535impl<
536 ValueType: Default + TupleIndexExt + TupleIterate<dyn SqlReadableIntoSelf>,
537 > ValueReadImpl<dyn ElementSatisfy<dyn SqlReadableIntoSelf>> for ValueType
538{
539 fn from_row_impl(
540 row: &Statement<'_>, value_column: usize,
541 ) -> Result<ValueType> {
542 let mut result = Ok(ValueType::default());
543
544 struct Load<'r, 'db, ValueType> {
545 t: &'r mut ValueType,
546 row: &'r Statement<'db>,
547 error: Option<Error>,
548 value_column: usize,
549 }
550
551 impl<ValueType: TupleIndexExt>
552 IterCallFamilyTrait<ValueType, dyn SqlReadableIntoSelf>
553 for &mut Load<'_, '_, ValueType>
554 {
555 fn iter_step<
556 Index: OfElementSatisfiesOnTuple<ValueType, dyn SqlReadableIntoSelf>,
557 >(
558 &mut self, _: &'static Index, index: usize,
559 ) {
560 match self.error {
561 None => {
562 let column_read_result = ElementSatisfy::<
563 dyn SqlReadableIntoSelf,
564 >::to_constrain_object_mut(
565 Index::getter_for_tuple_mut(self.t).get_mut_impl(),
566 )
567 .read_into_self(self.row, index + self.value_column);
568
569 if column_read_result.is_err() {
570 self.error = column_read_result.err()
571 }
572 }
573 _ => { }
574 }
575 }
576 }
577
578 let mut loader = Load {
579 t: result.as_mut().unwrap(),
580 row,
581 error: None,
582 value_column,
583 };
584 ValueType::iterate(&mut loader);
585
586 match loader.error {
587 Some(e) => bail!(e),
588 None => result,
589 }
590 }
591
592 fn from_kv_row_impl(
593 row: &Statement<'_>, key: &mut dyn SqlReadableIntoSelf,
594 ) -> Result<Self> {
595 key.read_into_self(row, 0)?;
596 Self::from_row_impl(row, 1)
597 }
598}
599
600pub trait SqlBindableValue {
601 type Kind: ?Sized;
602}
603
604impl SqlBindableValue for () {
605 type Kind = ();
606}
607
608impl SqlBindableValue for [u8] {
609 type Kind = dyn SqlBindable;
611}
612
613impl SqlBindableValue for i64 {
614 type Kind = dyn SqlBindable;
615}
616
617impl<
618 ValueType: Default + TupleIndexExt + TupleIterate<dyn SqlReadableIntoSelf>,
619 > SqlBindableValue for ValueType
620{
621 type Kind = dyn ElementSatisfy<dyn BindValueAppendImpl<dyn SqlBindable>>;
622}
623
624impl<
625 ValueType: Default + TupleIndexExt + TupleIterate<dyn SqlReadableIntoSelf>,
626 > DbValueType for ValueType
627{
628 type Type = ValueType;
629}
630
631pub trait BindValueAppendImpl<Kind: ?Sized> {
633 fn make_bind_list(&self) -> Vec<SqlBindableBox<'_>>;
634}
635
636impl<T: 'static + SqlBindableValue + SqlBindable + Clone>
638 BindValueAppendImpl<dyn SqlBindable> for T
639{
640 fn make_bind_list(&self) -> Vec<SqlBindableBox<'_>> {
641 vec![Box::new(self.clone())]
642 }
643}
644
645impl BindValueAppendImpl<()> for () {
646 fn make_bind_list(&self) -> Vec<Box<dyn SqlBindable>> { vec![] }
647}
648
649impl BindValueAppendImpl<dyn SqlBindable> for [u8] {
650 fn make_bind_list(&self) -> Vec<SqlBindableBox<'_>> {
651 vec![Box::new(Pin::new(self))]
652 }
653}
654
655impl BindValueAppendImpl<dyn SqlBindable> for Box<[u8]> {
656 fn make_bind_list(&self) -> Vec<SqlBindableBox<'_>> {
657 vec![Box::new(Pin::new(self.deref()))]
658 }
659}
660
661impl<
662 ValueType: TupleIndexExt + TupleIterate<dyn BindValueAppendImpl<dyn SqlBindable>>,
663 >
664 BindValueAppendImpl<
665 dyn ElementSatisfy<dyn BindValueAppendImpl<dyn SqlBindable>>,
666 > for ValueType
667{
668 fn make_bind_list(&self) -> Vec<SqlBindableBox<'_>> {
669 struct Append<'x, ValueType> {
670 v: &'x ValueType,
671 l: *mut Vec<SqlBindableBox<'x>>,
672 }
673
674 impl<'x, ValueType>
675 IterCallFamilyTrait<
676 ValueType,
677 dyn BindValueAppendImpl<dyn SqlBindable>,
678 > for Append<'x, ValueType>
679 {
680 fn iter_step<
686 Index: OfElementSatisfiesOnTuple<
687 ValueType,
688 dyn BindValueAppendImpl<dyn SqlBindable>,
689 >,
690 >(
691 &mut self, _: &'static Index, _: usize,
692 ) {
693 let mut to_append = ElementSatisfy::<
694 dyn BindValueAppendImpl<dyn SqlBindable>,
695 >::to_constrain_object(
696 Index::getter_for_tuple(self.v).get_impl(),
697 )
698 .make_bind_list();
699 unsafe { &mut *self.l }.append(&mut to_append);
700 }
701 }
702
703 let mut bind_list =
704 Vec::<SqlBindableBox<'_>>::with_capacity(ValueType::size_tuple());
705 {
706 let append = Append {
707 v: self,
708 l: &mut bind_list,
709 };
710 ValueType::iterate(append);
711 }
712
713 bind_list
714 }
715}
716
717use super::super::{
718 super::{storage_db::key_value_db::DbValueType, utils::tuple::*},
719 errors::*,
720};
721use fallible_iterator::FallibleIterator;
722use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
723use parking_lot::{Mutex, MutexGuard};
724use sqlite::{Bindable, Connection, OpenFlags, Readable, State, Statement};
725use sqlite3_sys as sqlite_ffi;
726use std::{
727 borrow::Borrow,
728 collections::HashMap,
729 ops::Deref,
730 path::{Path, PathBuf},
731 pin::Pin,
732};