1use super::{ffi, mutex::SQLiteMutexGuard, sqlite3_require_version, Connection};
2use std::{
3 ffi::CStr,
4 os::raw::{c_char, c_int},
5};
6
7pub const SQLITE_LOCKED: Error = Error::Sqlite(ffi::SQLITE_LOCKED, None);
9pub const SQLITE_NOMEM: Error = Error::Sqlite(ffi::SQLITE_NOMEM, None);
11pub const SQLITE_READONLY: Error = Error::Sqlite(ffi::SQLITE_READONLY, None);
13pub const SQLITE_NOTFOUND: Error = Error::Sqlite(ffi::SQLITE_NOTFOUND, None);
15pub const SQLITE_EMPTY: Error = Error::Sqlite(ffi::SQLITE_EMPTY, None);
17pub const SQLITE_CONSTRAINT: Error = Error::Sqlite(ffi::SQLITE_CONSTRAINT, None);
19pub const SQLITE_MISMATCH: Error = Error::Sqlite(ffi::SQLITE_MISMATCH, None);
21pub const SQLITE_MISUSE: Error = Error::Sqlite(ffi::SQLITE_MISUSE, None);
23pub const SQLITE_RANGE: Error = Error::Sqlite(ffi::SQLITE_RANGE, None);
25
26#[derive(Clone, Eq, PartialEq)]
27pub enum Error {
28 Sqlite(i32, Option<String>),
30 Utf8Error(std::str::Utf8Error),
33 NulError(std::ffi::NulError),
35 VersionNotSatisfied(std::os::raw::c_int),
38 Module(String),
42 NoChange,
45}
46
47impl Error {
48 pub fn from_sqlite(rc: i32) -> Result<()> {
51 match rc {
52 ffi::SQLITE_OK | ffi::SQLITE_ROW | ffi::SQLITE_DONE => Ok(()),
53 _ => Err(Error::Sqlite(rc, None)),
54 }
55 }
56
57 pub fn from_sqlite_desc(rc: i32, guard: SQLiteMutexGuard<'_, Connection>) -> Result<()> {
61 unsafe { Self::from_sqlite_desc_unchecked(rc, guard.as_mut_ptr()) }
62 }
63
64 pub unsafe fn from_sqlite_desc_unchecked(rc: i32, conn: *mut ffi::sqlite3) -> Result<()> {
72 match rc {
73 ffi::SQLITE_OK | ffi::SQLITE_ROW | ffi::SQLITE_DONE => Ok(()),
74 rc => {
75 let msg = CStr::from_ptr(ffi::sqlite3_errmsg(conn));
76 let msg = msg.to_str()?.to_owned();
77 Err(Error::Sqlite(rc, Some(msg)))
78 }
79 }
80 }
81
82 pub(crate) fn into_sqlite(self, msg: *mut *mut c_char) -> c_int {
83 match self {
84 Error::Sqlite(code, s) => {
85 if let Some(s) = s {
86 if let Ok(s) = ffi::str_to_sqlite3(&s) {
87 unsafe { *msg = s };
88 }
89 }
90 code
91 }
92 e @ Error::Utf8Error(_)
93 | e @ Error::NulError(_)
94 | e @ Error::VersionNotSatisfied(_)
95 | e @ Error::Module(_)
96 | e @ Error::NoChange => {
97 if !msg.is_null() {
98 if let Ok(s) = ffi::str_to_sqlite3(&format!("{e}")) {
99 unsafe { *msg = s };
100 }
101 }
102 ffi::SQLITE_ERROR
103 }
104 }
105 }
106}
107
108impl From<String> for Error {
109 fn from(msg: String) -> Self {
110 Self::Module(msg)
111 }
112}
113
114impl From<&str> for Error {
115 fn from(msg: &str) -> Self {
116 Self::Module(msg.to_string())
117 }
118}
119
120impl std::fmt::Display for Error {
121 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
122 match self {
123 Error::Sqlite(_, Some(desc)) => write!(f, "{desc}"),
124 Error::Sqlite(i, None) => {
125 let errstr: Result<&str> = sqlite3_require_version!(3_007_015, unsafe {
126 std::ffi::CStr::from_ptr(ffi::sqlite3_errstr(*i))
127 .to_str()
128 .map_err(Error::Utf8Error)
129 });
130 match errstr {
131 Ok(s) => write!(f, "{s}"),
132 _ => write!(f, "SQLite error {i}"),
133 }
134 }
135 Error::Utf8Error(e) => e.fmt(f),
136 Error::NulError(e) => e.fmt(f),
137 Error::Module(s) => write!(f, "{s}"),
138 Error::VersionNotSatisfied(v) => write!(
139 f,
140 "requires SQLite version {}.{}.{} or above",
141 v / 1_000_000,
142 (v / 1000) % 1000,
143 v % 1000
144 ),
145 Error::NoChange => write!(f, "invalid Error::NoChange"),
146 }
147 }
148}
149
150impl std::fmt::Debug for Error {
151 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
152 match self {
153 Error::Sqlite(i, Some(desc)) => f.debug_tuple("Sqlite").field(&i).field(&desc).finish(),
154 Error::Sqlite(i, None) => {
155 let errstr: Result<&str> = sqlite3_require_version!(3_007_015, unsafe {
156 std::ffi::CStr::from_ptr(ffi::sqlite3_errstr(*i))
157 .to_str()
158 .map_err(Error::Utf8Error)
159 });
160 match errstr {
161 Ok(s) => f.debug_tuple("Sqlite").field(&i).field(&s).finish(),
162 _ => f.debug_tuple("Sqlite").field(&i).finish(),
163 }
164 }
165 Error::Utf8Error(e) => f.debug_tuple("Utf8Error").field(&e).finish(),
166 Error::NulError(e) => f.debug_tuple("NulError").field(&e).finish(),
167 Error::Module(s) => f.debug_tuple("Module").field(&s).finish(),
168 Error::VersionNotSatisfied(v) => {
169 f.debug_tuple("VersionNotSatisfied").field(&v).finish()
170 }
171 Error::NoChange => f.debug_tuple("NoChange").finish(),
172 }
173 }
174}
175
176impl std::error::Error for Error {}
177
178impl From<std::str::Utf8Error> for Error {
179 fn from(err: std::str::Utf8Error) -> Self {
180 Self::Utf8Error(err)
181 }
182}
183
184impl From<std::ffi::NulError> for Error {
185 fn from(err: std::ffi::NulError) -> Self {
186 Self::NulError(err)
187 }
188}
189
190pub type Result<T> = std::result::Result<T, Error>;