1 use std::error;
2 use std::fmt;
3 use std::os::raw::c_int;
4
5 /// Error Codes
6 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
7 #[non_exhaustive]
8 pub enum ErrorCode {
9 /// Internal logic error in SQLite
10 InternalMalfunction,
11 /// Access permission denied
12 PermissionDenied,
13 /// Callback routine requested an abort
14 OperationAborted,
15 /// The database file is locked
16 DatabaseBusy,
17 /// A table in the database is locked
18 DatabaseLocked,
19 /// A malloc() failed
20 OutOfMemory,
21 /// Attempt to write a readonly database
22 ReadOnly,
23 /// Operation terminated by sqlite3_interrupt()
24 OperationInterrupted,
25 /// Some kind of disk I/O error occurred
26 SystemIOFailure,
27 /// The database disk image is malformed
28 DatabaseCorrupt,
29 /// Unknown opcode in sqlite3_file_control()
30 NotFound,
31 /// Insertion failed because database is full
32 DiskFull,
33 /// Unable to open the database file
34 CannotOpen,
35 /// Database lock protocol error
36 FileLockingProtocolFailed,
37 /// The database schema changed
38 SchemaChanged,
39 /// String or BLOB exceeds size limit
40 TooBig,
41 /// Abort due to constraint violation
42 ConstraintViolation,
43 /// Data type mismatch
44 TypeMismatch,
45 /// Library used incorrectly
46 APIMisuse,
47 /// Uses OS features not supported on host
48 NoLargeFileSupport,
49 /// Authorization denied
50 AuthorizationForStatementDenied,
51 /// 2nd parameter to sqlite3_bind out of range
52 ParameterOutOfRange,
53 /// File opened that is not a database file
54 NotADatabase,
55 /// SQL error or missing database
56 Unknown,
57 }
58
59 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
60 pub struct Error {
61 pub code: ErrorCode,
62 pub extended_code: c_int,
63 }
64
65 impl Error {
new(result_code: c_int) -> Error66 pub fn new(result_code: c_int) -> Error {
67 let code = match result_code & 0xff {
68 super::SQLITE_INTERNAL => ErrorCode::InternalMalfunction,
69 super::SQLITE_PERM => ErrorCode::PermissionDenied,
70 super::SQLITE_ABORT => ErrorCode::OperationAborted,
71 super::SQLITE_BUSY => ErrorCode::DatabaseBusy,
72 super::SQLITE_LOCKED => ErrorCode::DatabaseLocked,
73 super::SQLITE_NOMEM => ErrorCode::OutOfMemory,
74 super::SQLITE_READONLY => ErrorCode::ReadOnly,
75 super::SQLITE_INTERRUPT => ErrorCode::OperationInterrupted,
76 super::SQLITE_IOERR => ErrorCode::SystemIOFailure,
77 super::SQLITE_CORRUPT => ErrorCode::DatabaseCorrupt,
78 super::SQLITE_NOTFOUND => ErrorCode::NotFound,
79 super::SQLITE_FULL => ErrorCode::DiskFull,
80 super::SQLITE_CANTOPEN => ErrorCode::CannotOpen,
81 super::SQLITE_PROTOCOL => ErrorCode::FileLockingProtocolFailed,
82 super::SQLITE_SCHEMA => ErrorCode::SchemaChanged,
83 super::SQLITE_TOOBIG => ErrorCode::TooBig,
84 super::SQLITE_CONSTRAINT => ErrorCode::ConstraintViolation,
85 super::SQLITE_MISMATCH => ErrorCode::TypeMismatch,
86 super::SQLITE_MISUSE => ErrorCode::APIMisuse,
87 super::SQLITE_NOLFS => ErrorCode::NoLargeFileSupport,
88 super::SQLITE_AUTH => ErrorCode::AuthorizationForStatementDenied,
89 super::SQLITE_RANGE => ErrorCode::ParameterOutOfRange,
90 super::SQLITE_NOTADB => ErrorCode::NotADatabase,
91 _ => ErrorCode::Unknown,
92 };
93
94 Error {
95 code,
96 extended_code: result_code,
97 }
98 }
99 }
100
101 impl fmt::Display for Error {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result102 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
103 write!(
104 f,
105 "Error code {}: {}",
106 self.extended_code,
107 code_to_str(self.extended_code)
108 )
109 }
110 }
111
112 impl error::Error for Error {
description(&self) -> &str113 fn description(&self) -> &str {
114 code_to_str(self.extended_code)
115 }
116 }
117
118 // Result codes.
119 // Note: These are not public because our bindgen bindings export whichever
120 // constants are present in the current version of SQLite. We repeat them here
121 // so we don't have to worry about which version of SQLite added which
122 // constants, and we only use them to implement code_to_str below.
123
124 const SQLITE_NOTICE: c_int = 27;
125 const SQLITE_WARNING: c_int = 28;
126
127 // Extended result codes.
128
129 const SQLITE_ERROR_MISSING_COLLSEQ: c_int = super::SQLITE_ERROR | (1 << 8);
130 const SQLITE_ERROR_RETRY: c_int = super::SQLITE_ERROR | (2 << 8);
131 const SQLITE_ERROR_SNAPSHOT: c_int = super::SQLITE_ERROR | (3 << 8);
132
133 const SQLITE_IOERR_SHMOPEN: c_int = super::SQLITE_IOERR | (18 << 8);
134 const SQLITE_IOERR_SHMSIZE: c_int = super::SQLITE_IOERR | (19 << 8);
135 const SQLITE_IOERR_SHMLOCK: c_int = super::SQLITE_IOERR | (20 << 8);
136 const SQLITE_IOERR_SHMMAP: c_int = super::SQLITE_IOERR | (21 << 8);
137 const SQLITE_IOERR_SEEK: c_int = super::SQLITE_IOERR | (22 << 8);
138 const SQLITE_IOERR_DELETE_NOENT: c_int = super::SQLITE_IOERR | (23 << 8);
139 const SQLITE_IOERR_MMAP: c_int = super::SQLITE_IOERR | (24 << 8);
140 const SQLITE_IOERR_GETTEMPPATH: c_int = super::SQLITE_IOERR | (25 << 8);
141 const SQLITE_IOERR_CONVPATH: c_int = super::SQLITE_IOERR | (26 << 8);
142 const SQLITE_IOERR_VNODE: c_int = super::SQLITE_IOERR | (27 << 8);
143 const SQLITE_IOERR_AUTH: c_int = super::SQLITE_IOERR | (28 << 8);
144 const SQLITE_IOERR_BEGIN_ATOMIC: c_int = super::SQLITE_IOERR | (29 << 8);
145 const SQLITE_IOERR_COMMIT_ATOMIC: c_int = super::SQLITE_IOERR | (30 << 8);
146 const SQLITE_IOERR_ROLLBACK_ATOMIC: c_int = super::SQLITE_IOERR | (31 << 8);
147
148 const SQLITE_LOCKED_SHAREDCACHE: c_int = super::SQLITE_LOCKED | (1 << 8);
149 const SQLITE_LOCKED_VTAB: c_int = super::SQLITE_LOCKED | (2 << 8);
150
151 const SQLITE_BUSY_RECOVERY: c_int = super::SQLITE_BUSY | (1 << 8);
152 const SQLITE_BUSY_SNAPSHOT: c_int = super::SQLITE_BUSY | (2 << 8);
153
154 const SQLITE_CANTOPEN_NOTEMPDIR: c_int = super::SQLITE_CANTOPEN | (1 << 8);
155 const SQLITE_CANTOPEN_ISDIR: c_int = super::SQLITE_CANTOPEN | (2 << 8);
156 const SQLITE_CANTOPEN_FULLPATH: c_int = super::SQLITE_CANTOPEN | (3 << 8);
157 const SQLITE_CANTOPEN_CONVPATH: c_int = super::SQLITE_CANTOPEN | (4 << 8);
158 const SQLITE_CANTOPEN_SYMLINK: c_int = super::SQLITE_CANTOPEN | (6 << 8);
159
160 const SQLITE_CORRUPT_VTAB: c_int = super::SQLITE_CORRUPT | (1 << 8);
161 const SQLITE_CORRUPT_SEQUENCE: c_int = super::SQLITE_CORRUPT | (2 << 8);
162
163 const SQLITE_READONLY_RECOVERY: c_int = super::SQLITE_READONLY | (1 << 8);
164 const SQLITE_READONLY_CANTLOCK: c_int = super::SQLITE_READONLY | (2 << 8);
165 const SQLITE_READONLY_ROLLBACK: c_int = super::SQLITE_READONLY | (3 << 8);
166 const SQLITE_READONLY_DBMOVED: c_int = super::SQLITE_READONLY | (4 << 8);
167 const SQLITE_READONLY_CANTINIT: c_int = super::SQLITE_READONLY | (5 << 8);
168 const SQLITE_READONLY_DIRECTORY: c_int = super::SQLITE_READONLY | (6 << 8);
169
170 const SQLITE_ABORT_ROLLBACK: c_int = super::SQLITE_ABORT | (2 << 8);
171
172 const SQLITE_CONSTRAINT_CHECK: c_int = super::SQLITE_CONSTRAINT | (1 << 8);
173 const SQLITE_CONSTRAINT_COMMITHOOK: c_int = super::SQLITE_CONSTRAINT | (2 << 8);
174 const SQLITE_CONSTRAINT_FOREIGNKEY: c_int = super::SQLITE_CONSTRAINT | (3 << 8);
175 const SQLITE_CONSTRAINT_FUNCTION: c_int = super::SQLITE_CONSTRAINT | (4 << 8);
176 const SQLITE_CONSTRAINT_NOTNULL: c_int = super::SQLITE_CONSTRAINT | (5 << 8);
177 const SQLITE_CONSTRAINT_PRIMARYKEY: c_int = super::SQLITE_CONSTRAINT | (6 << 8);
178 const SQLITE_CONSTRAINT_TRIGGER: c_int = super::SQLITE_CONSTRAINT | (7 << 8);
179 const SQLITE_CONSTRAINT_UNIQUE: c_int = super::SQLITE_CONSTRAINT | (8 << 8);
180 const SQLITE_CONSTRAINT_VTAB: c_int = super::SQLITE_CONSTRAINT | (9 << 8);
181 const SQLITE_CONSTRAINT_ROWID: c_int = super::SQLITE_CONSTRAINT | (10 << 8);
182 const SQLITE_CONSTRAINT_PINNED: c_int = super::SQLITE_CONSTRAINT | (11 << 8);
183
184 const SQLITE_NOTICE_RECOVER_WAL: c_int = SQLITE_NOTICE | (1 << 8);
185 const SQLITE_NOTICE_RECOVER_ROLLBACK: c_int = SQLITE_NOTICE | (2 << 8);
186
187 const SQLITE_WARNING_AUTOINDEX: c_int = SQLITE_WARNING | (1 << 8);
188
189 const SQLITE_AUTH_USER: c_int = super::SQLITE_AUTH | (1 << 8);
190
code_to_str(code: c_int) -> &'static str191 pub fn code_to_str(code: c_int) -> &'static str {
192 match code {
193 super::SQLITE_OK => "Successful result",
194 super::SQLITE_ERROR => "SQL error or missing database",
195 super::SQLITE_INTERNAL => "Internal logic error in SQLite",
196 super::SQLITE_PERM => "Access permission denied",
197 super::SQLITE_ABORT => "Callback routine requested an abort",
198 super::SQLITE_BUSY => "The database file is locked",
199 super::SQLITE_LOCKED => "A table in the database is locked",
200 super::SQLITE_NOMEM => "A malloc() failed",
201 super::SQLITE_READONLY => "Attempt to write a readonly database",
202 super::SQLITE_INTERRUPT => "Operation terminated by sqlite3_interrupt()",
203 super::SQLITE_IOERR => "Some kind of disk I/O error occurred",
204 super::SQLITE_CORRUPT => "The database disk image is malformed",
205 super::SQLITE_NOTFOUND => "Unknown opcode in sqlite3_file_control()",
206 super::SQLITE_FULL => "Insertion failed because database is full",
207 super::SQLITE_CANTOPEN => "Unable to open the database file",
208 super::SQLITE_PROTOCOL => "Database lock protocol error",
209 super::SQLITE_EMPTY => "Database is empty",
210 super::SQLITE_SCHEMA => "The database schema changed",
211 super::SQLITE_TOOBIG => "String or BLOB exceeds size limit",
212 super::SQLITE_CONSTRAINT=> "Abort due to constraint violation",
213 super::SQLITE_MISMATCH => "Data type mismatch",
214 super::SQLITE_MISUSE => "Library used incorrectly",
215 super::SQLITE_NOLFS => "Uses OS features not supported on host",
216 super::SQLITE_AUTH => "Authorization denied",
217 super::SQLITE_FORMAT => "Auxiliary database format error",
218 super::SQLITE_RANGE => "2nd parameter to sqlite3_bind out of range",
219 super::SQLITE_NOTADB => "File opened that is not a database file",
220 SQLITE_NOTICE => "Notifications from sqlite3_log()",
221 SQLITE_WARNING => "Warnings from sqlite3_log()",
222 super::SQLITE_ROW => "sqlite3_step() has another row ready",
223 super::SQLITE_DONE => "sqlite3_step() has finished executing",
224
225 SQLITE_ERROR_MISSING_COLLSEQ => "SQLITE_ERROR_MISSING_COLLSEQ",
226 SQLITE_ERROR_RETRY => "SQLITE_ERROR_RETRY",
227 SQLITE_ERROR_SNAPSHOT => "SQLITE_ERROR_SNAPSHOT",
228
229 super::SQLITE_IOERR_READ => "Error reading from disk",
230 super::SQLITE_IOERR_SHORT_READ => "Unable to obtain number of requested bytes (file truncated?)",
231 super::SQLITE_IOERR_WRITE => "Error writing to disk",
232 super::SQLITE_IOERR_FSYNC => "Error flushing data to persistent storage (fsync)",
233 super::SQLITE_IOERR_DIR_FSYNC => "Error calling fsync on a directory",
234 super::SQLITE_IOERR_TRUNCATE => "Error attempting to truncate file",
235 super::SQLITE_IOERR_FSTAT => "Error invoking fstat to get file metadata",
236 super::SQLITE_IOERR_UNLOCK => "I/O error within xUnlock of a VFS object",
237 super::SQLITE_IOERR_RDLOCK => "I/O error within xLock of a VFS object (trying to obtain a read lock)",
238 super::SQLITE_IOERR_DELETE => "I/O error within xDelete of a VFS object",
239 super::SQLITE_IOERR_BLOCKED => "SQLITE_IOERR_BLOCKED", // no longer used
240 super::SQLITE_IOERR_NOMEM => "Out of memory in I/O layer",
241 super::SQLITE_IOERR_ACCESS => "I/O error within xAccess of a VFS object",
242 super::SQLITE_IOERR_CHECKRESERVEDLOCK => "I/O error within then xCheckReservedLock method",
243 super::SQLITE_IOERR_LOCK => "I/O error in the advisory file locking layer",
244 super::SQLITE_IOERR_CLOSE => "I/O error within the xClose method",
245 super::SQLITE_IOERR_DIR_CLOSE => "SQLITE_IOERR_DIR_CLOSE", // no longer used
246 SQLITE_IOERR_SHMOPEN => "I/O error within the xShmMap method (trying to open a new shared-memory segment)",
247 SQLITE_IOERR_SHMSIZE => "I/O error within the xShmMap method (trying to resize an existing shared-memory segment)",
248 SQLITE_IOERR_SHMLOCK => "SQLITE_IOERR_SHMLOCK", // no longer used
249 SQLITE_IOERR_SHMMAP => "I/O error within the xShmMap method (trying to map a shared-memory segment into process address space)",
250 SQLITE_IOERR_SEEK => "I/O error within the xRead or xWrite (trying to seek within a file)",
251 SQLITE_IOERR_DELETE_NOENT => "File being deleted does not exist",
252 SQLITE_IOERR_MMAP => "I/O error while trying to map or unmap part of the database file into process address space",
253 SQLITE_IOERR_GETTEMPPATH => "VFS is unable to determine a suitable directory for temporary files",
254 SQLITE_IOERR_CONVPATH => "cygwin_conv_path() system call failed",
255 SQLITE_IOERR_VNODE => "SQLITE_IOERR_VNODE", // not documented?
256 SQLITE_IOERR_AUTH => "SQLITE_IOERR_AUTH",
257 SQLITE_IOERR_BEGIN_ATOMIC => "SQLITE_IOERR_BEGIN_ATOMIC",
258 SQLITE_IOERR_COMMIT_ATOMIC => "SQLITE_IOERR_COMMIT_ATOMIC",
259 SQLITE_IOERR_ROLLBACK_ATOMIC => "SQLITE_IOERR_ROLLBACK_ATOMIC",
260
261 SQLITE_LOCKED_SHAREDCACHE => "Locking conflict due to another connection with a shared cache",
262 SQLITE_LOCKED_VTAB => "SQLITE_LOCKED_VTAB",
263
264 SQLITE_BUSY_RECOVERY => "Another process is recovering a WAL mode database file",
265 SQLITE_BUSY_SNAPSHOT => "Cannot promote read transaction to write transaction because of writes by another connection",
266
267 SQLITE_CANTOPEN_NOTEMPDIR => "SQLITE_CANTOPEN_NOTEMPDIR", // no longer used
268 SQLITE_CANTOPEN_ISDIR => "Attempted to open directory as file",
269 SQLITE_CANTOPEN_FULLPATH => "Unable to convert filename into full pathname",
270 SQLITE_CANTOPEN_CONVPATH => "cygwin_conv_path() system call failed",
271 SQLITE_CANTOPEN_SYMLINK => "SQLITE_CANTOPEN_SYMLINK",
272
273 SQLITE_CORRUPT_VTAB => "Content in the virtual table is corrupt",
274 SQLITE_CORRUPT_SEQUENCE => "SQLITE_CORRUPT_SEQUENCE",
275
276 SQLITE_READONLY_RECOVERY => "WAL mode database file needs recovery (requires write access)",
277 SQLITE_READONLY_CANTLOCK => "Shared-memory file associated with WAL mode database is read-only",
278 SQLITE_READONLY_ROLLBACK => "Database has hot journal that must be rolled back (requires write access)",
279 SQLITE_READONLY_DBMOVED => "Database cannot be modified because database file has moved",
280 SQLITE_READONLY_CANTINIT => "SQLITE_READONLY_CANTINIT",
281 SQLITE_READONLY_DIRECTORY => "SQLITE_READONLY_DIRECTORY",
282
283 SQLITE_ABORT_ROLLBACK => "Transaction was rolled back",
284
285 SQLITE_CONSTRAINT_CHECK => "A CHECK constraint failed",
286 SQLITE_CONSTRAINT_COMMITHOOK => "Commit hook caused rollback",
287 SQLITE_CONSTRAINT_FOREIGNKEY => "Foreign key constraint failed",
288 SQLITE_CONSTRAINT_FUNCTION => "Error returned from extension function",
289 SQLITE_CONSTRAINT_NOTNULL => "A NOT NULL constraint failed",
290 SQLITE_CONSTRAINT_PRIMARYKEY => "A PRIMARY KEY constraint failed",
291 SQLITE_CONSTRAINT_TRIGGER => "A RAISE function within a trigger fired",
292 SQLITE_CONSTRAINT_UNIQUE => "A UNIQUE constraint failed",
293 SQLITE_CONSTRAINT_VTAB => "An application-defined virtual table error occurred",
294 SQLITE_CONSTRAINT_ROWID => "A non-unique rowid occurred",
295 SQLITE_CONSTRAINT_PINNED => "SQLITE_CONSTRAINT_PINNED",
296
297 SQLITE_NOTICE_RECOVER_WAL => "A WAL mode database file was recovered",
298 SQLITE_NOTICE_RECOVER_ROLLBACK => "Hot journal was rolled back",
299
300 SQLITE_WARNING_AUTOINDEX => "Automatic indexing used - database might benefit from additional indexes",
301
302 SQLITE_AUTH_USER => "SQLITE_AUTH_USER", // not documented?
303
304 _ => "Unknown error code",
305 }
306 }
307