1use std::error::Error as StdError;
6
7use libc::ENOSPC;
8use rusqlite::{Error as RusqliteError, ffi};
9
10pub const DB_INIT_PRAGMAS: [&str; 2] =
12 ["PRAGMA journal_mode = WAL;", "PRAGMA encoding = 'UTF-16';"];
13
14pub const DB_IN_MEMORY_INIT_PRAGMAS: [&str; 1] = ["PRAGMA encoding = 'UTF-16';"];
16
17pub const DB_PRAGMAS: [&str; 4] = [
19 "PRAGMA synchronous = NORMAL;",
20 "PRAGMA journal_size_limit = 67108864 -- 64 megabytes;",
21 "PRAGMA mmap_size = 67108864 -- 64 megabytes;",
22 "PRAGMA cache_size = 2000;",
23];
24
25pub const DB_IN_MEMORY_PRAGMAS: [&str; 1] = ["PRAGMA cache_size = 2000;"];
27
28pub(crate) fn is_sqlite_disk_full_error(error: &RusqliteError) -> bool {
29 fn has_enospc(mut source: Option<&(dyn StdError + 'static)>) -> bool {
30 while let Some(err) = source {
31 if let Some(io_err) = err.downcast_ref::<std::io::Error>() {
32 if io_err.raw_os_error() == Some(ENOSPC) {
33 return true;
34 }
35 }
36 source = err.source();
37 }
38 false
39 }
40
41 let saw_enospc = has_enospc(Some(error as &(dyn StdError + 'static)));
43
44 match error {
45 RusqliteError::SqliteFailure(sqlite_err, _) => {
46 if sqlite_err.code == ffi::ErrorCode::DiskFull ||
48 sqlite_err.extended_code == ffi::SQLITE_FULL
49 {
50 return true;
51 }
52
53 if saw_enospc &&
55 matches!(
56 sqlite_err.extended_code,
57 ffi::SQLITE_IOERR |
58 ffi::SQLITE_IOERR_WRITE |
59 ffi::SQLITE_IOERR_FSYNC |
60 ffi::SQLITE_IOERR_DIR_FSYNC |
61 ffi::SQLITE_IOERR_TRUNCATE |
62 ffi::SQLITE_IOERR_MMAP
63 )
64 {
65 return true;
66 }
67
68 false
69 },
70 _ => saw_enospc,
71 }
72}