1#![allow(non_snake_case, non_camel_case_types, clippy::type_complexity)]
2#![cfg_attr(test, allow(deref_nullptr))] use std::default::Default;
5use std::error;
6use std::fmt;
7use std::marker::PhantomData;
8use std::mem;
9use std::os::raw::c_int;
10
11#[cfg(feature = "wasmtime-bindings")]
12pub use libsql_wasm::{
13 libsql_compile_wasm_module, libsql_free_wasm_module, libsql_run_wasm, libsql_wasm_engine_new,
14};
15
16pub use bindgen::*;
17mod bindgen {
18 #![allow(dead_code)]
19 include!(concat!(env!("OUT_DIR"), "/bindgen.rs"));
20}
21
22#[must_use]
23pub fn SQLITE_STATIC() -> sqlite3_destructor_type {
24 None
25}
26
27#[must_use]
28pub fn SQLITE_TRANSIENT() -> sqlite3_destructor_type {
29 Some(unsafe { mem::transmute(-1_isize) })
30}
31
32impl Default for sqlite3_vtab {
33 fn default() -> Self {
34 unsafe { mem::zeroed() }
35 }
36}
37
38impl Default for sqlite3_vtab_cursor {
39 fn default() -> Self {
40 unsafe { mem::zeroed() }
41 }
42}
43
44pub struct PageHdrIter<'a> {
45 current_ptr: *const PgHdr,
46 page_size: usize,
47 _pth: PhantomData<&'a ()>,
48}
49
50impl<'a> PageHdrIter<'a> {
51 pub fn new(current_ptr: *const PgHdr, page_size: usize) -> Self {
52 Self {
53 current_ptr,
54 page_size,
55 _pth: PhantomData,
56 }
57 }
58
59 pub fn current_ptr(&self) -> *const PgHdr {
60 self.current_ptr
61 }
62}
63
64impl<'a> std::iter::Iterator for PageHdrIter<'a> {
65 type Item = (u32, &'a [u8]);
66
67 fn next(&mut self) -> Option<Self::Item> {
68 if self.current_ptr.is_null() {
69 return None;
70 }
71 let current_hdr: &PgHdr = unsafe { &*self.current_ptr };
72 let raw_data =
73 unsafe { std::slice::from_raw_parts(current_hdr.pData as *const u8, self.page_size) };
74 let item = Some((current_hdr.pgno, raw_data));
75 self.current_ptr = current_hdr.pDirty;
76 item
77 }
78}
79
80pub struct PageHdrIterMut<'a> {
81 current_ptr: *mut PgHdr,
82 page_size: usize,
83 _pth: PhantomData<&'a ()>,
84}
85
86impl<'a> PageHdrIterMut<'a> {
87 pub fn new(current_ptr: *mut PgHdr, page_size: usize) -> Self {
88 Self {
89 current_ptr,
90 page_size,
91 _pth: PhantomData,
92 }
93 }
94}
95
96impl<'a> std::iter::Iterator for PageHdrIterMut<'a> {
97 type Item = (u32, &'a mut [u8]);
98
99 fn next(&mut self) -> Option<Self::Item> {
100 if self.current_ptr.is_null() {
101 return None;
102 }
103 let current_hdr: &PgHdr = unsafe { &*self.current_ptr };
104 let raw_data =
105 unsafe { std::slice::from_raw_parts_mut(current_hdr.pData as *mut u8, self.page_size) };
106 let item = Some((current_hdr.pgno, raw_data));
107 self.current_ptr = current_hdr.pDirty;
108 item
109 }
110}
111
112#[derive(Clone, Copy, Debug, PartialEq, Eq)]
114#[non_exhaustive]
115pub enum ErrorCode {
116 InternalMalfunction,
118 PermissionDenied,
120 OperationAborted,
122 DatabaseBusy,
124 DatabaseLocked,
126 OutOfMemory,
128 ReadOnly,
130 OperationInterrupted,
132 SystemIoFailure,
134 DatabaseCorrupt,
136 NotFound,
138 DiskFull,
140 CannotOpen,
142 FileLockingProtocolFailed,
144 SchemaChanged,
146 TooBig,
148 ConstraintViolation,
150 TypeMismatch,
152 ApiMisuse,
154 NoLargeFileSupport,
156 AuthorizationForStatementDenied,
158 ParameterOutOfRange,
160 NotADatabase,
162 Unknown,
164}
165
166#[derive(Clone, Copy, Debug, PartialEq, Eq)]
167pub struct Error {
168 pub code: ErrorCode,
169 pub extended_code: c_int,
170}
171
172impl Error {
173 #[must_use]
174 pub fn new(result_code: c_int) -> Error {
175 let code = match result_code & 0xff {
176 SQLITE_INTERNAL => ErrorCode::InternalMalfunction,
177 SQLITE_PERM => ErrorCode::PermissionDenied,
178 SQLITE_ABORT => ErrorCode::OperationAborted,
179 SQLITE_BUSY => ErrorCode::DatabaseBusy,
180 SQLITE_LOCKED => ErrorCode::DatabaseLocked,
181 SQLITE_NOMEM => ErrorCode::OutOfMemory,
182 SQLITE_READONLY => ErrorCode::ReadOnly,
183 SQLITE_INTERRUPT => ErrorCode::OperationInterrupted,
184 SQLITE_IOERR => ErrorCode::SystemIoFailure,
185 SQLITE_CORRUPT => ErrorCode::DatabaseCorrupt,
186 SQLITE_NOTFOUND => ErrorCode::NotFound,
187 SQLITE_FULL => ErrorCode::DiskFull,
188 SQLITE_CANTOPEN => ErrorCode::CannotOpen,
189 SQLITE_PROTOCOL => ErrorCode::FileLockingProtocolFailed,
190 SQLITE_SCHEMA => ErrorCode::SchemaChanged,
191 SQLITE_TOOBIG => ErrorCode::TooBig,
192 SQLITE_CONSTRAINT => ErrorCode::ConstraintViolation,
193 SQLITE_MISMATCH => ErrorCode::TypeMismatch,
194 SQLITE_MISUSE => ErrorCode::ApiMisuse,
195 SQLITE_NOLFS => ErrorCode::NoLargeFileSupport,
196 SQLITE_AUTH => ErrorCode::AuthorizationForStatementDenied,
197 SQLITE_RANGE => ErrorCode::ParameterOutOfRange,
198 SQLITE_NOTADB => ErrorCode::NotADatabase,
199 _ => ErrorCode::Unknown,
200 };
201
202 Error {
203 code,
204 extended_code: result_code,
205 }
206 }
207}
208
209impl fmt::Display for Error {
210 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
211 write!(
212 f,
213 "Error code {}: {}",
214 self.extended_code,
215 code_to_str(self.extended_code)
216 )
217 }
218}
219
220impl error::Error for Error {
221 fn description(&self) -> &str {
222 code_to_str(self.extended_code)
223 }
224}
225
226#[must_use]
227pub fn code_to_str(code: c_int) -> &'static str {
228 match code {
229 SQLITE_OK => "Successful result",
230 SQLITE_ERROR => "SQL error or missing database",
231 SQLITE_INTERNAL => "Internal logic error in SQLite",
232 SQLITE_PERM => "Access permission denied",
233 SQLITE_ABORT => "Callback routine requested an abort",
234 SQLITE_BUSY => "The database file is locked",
235 SQLITE_LOCKED => "A table in the database is locked",
236 SQLITE_NOMEM => "A malloc() failed",
237 SQLITE_READONLY => "Attempt to write a readonly database",
238 SQLITE_INTERRUPT => "Operation terminated by sqlite3_interrupt()",
239 SQLITE_IOERR => "Some kind of disk I/O error occurred",
240 SQLITE_CORRUPT => "The database disk image is malformed",
241 SQLITE_NOTFOUND => "Unknown opcode in sqlite3_file_control()",
242 SQLITE_FULL => "Insertion failed because database is full",
243 SQLITE_CANTOPEN => "Unable to open the database file",
244 SQLITE_PROTOCOL => "Database lock protocol error",
245 SQLITE_EMPTY => "Database is empty",
246 SQLITE_SCHEMA => "The database schema changed",
247 SQLITE_TOOBIG => "String or BLOB exceeds size limit",
248 SQLITE_CONSTRAINT=> "Abort due to constraint violation",
249 SQLITE_MISMATCH => "Data type mismatch",
250 SQLITE_MISUSE => "Library used incorrectly",
251 SQLITE_NOLFS => "Uses OS features not supported on host",
252 SQLITE_AUTH => "Authorization denied",
253 SQLITE_FORMAT => "Auxiliary database format error",
254 SQLITE_RANGE => "2nd parameter to sqlite3_bind out of range",
255 SQLITE_NOTADB => "File opened that is not a database file",
256 SQLITE_NOTICE => "Notifications from sqlite3_log()",
257 SQLITE_WARNING => "Warnings from sqlite3_log()",
258 SQLITE_ROW => "sqlite3_step() has another row ready",
259 SQLITE_DONE => "sqlite3_step() has finished executing",
260
261 SQLITE_ERROR_MISSING_COLLSEQ => "SQLITE_ERROR_MISSING_COLLSEQ",
262 SQLITE_ERROR_RETRY => "SQLITE_ERROR_RETRY",
263 SQLITE_ERROR_SNAPSHOT => "SQLITE_ERROR_SNAPSHOT",
264
265 SQLITE_IOERR_READ => "Error reading from disk",
266 SQLITE_IOERR_SHORT_READ => "Unable to obtain number of requested bytes (file truncated?)",
267 SQLITE_IOERR_WRITE => "Error writing to disk",
268 SQLITE_IOERR_FSYNC => "Error flushing data to persistent storage (fsync)",
269 SQLITE_IOERR_DIR_FSYNC => "Error calling fsync on a directory",
270 SQLITE_IOERR_TRUNCATE => "Error attempting to truncate file",
271 SQLITE_IOERR_FSTAT => "Error invoking fstat to get file metadata",
272 SQLITE_IOERR_UNLOCK => "I/O error within xUnlock of a VFS object",
273 SQLITE_IOERR_RDLOCK => "I/O error within xLock of a VFS object (trying to obtain a read lock)",
274 SQLITE_IOERR_DELETE => "I/O error within xDelete of a VFS object",
275 SQLITE_IOERR_BLOCKED => "SQLITE_IOERR_BLOCKED", SQLITE_IOERR_NOMEM => "Out of memory in I/O layer",
277 SQLITE_IOERR_ACCESS => "I/O error within xAccess of a VFS object",
278 SQLITE_IOERR_CHECKRESERVEDLOCK => "I/O error within then xCheckReservedLock method",
279 SQLITE_IOERR_LOCK => "I/O error in the advisory file locking layer",
280 SQLITE_IOERR_CLOSE => "I/O error within the xClose method",
281 SQLITE_IOERR_DIR_CLOSE => "SQLITE_IOERR_DIR_CLOSE", SQLITE_IOERR_SHMOPEN => "I/O error within the xShmMap method (trying to open a new shared-memory segment)",
283 SQLITE_IOERR_SHMSIZE => "I/O error within the xShmMap method (trying to resize an existing shared-memory segment)",
284 SQLITE_IOERR_SHMLOCK => "SQLITE_IOERR_SHMLOCK", SQLITE_IOERR_SHMMAP => "I/O error within the xShmMap method (trying to map a shared-memory segment into process address space)",
286 SQLITE_IOERR_SEEK => "I/O error within the xRead or xWrite (trying to seek within a file)",
287 SQLITE_IOERR_DELETE_NOENT => "File being deleted does not exist",
288 SQLITE_IOERR_MMAP => "I/O error while trying to map or unmap part of the database file into process address space",
289 SQLITE_IOERR_GETTEMPPATH => "VFS is unable to determine a suitable directory for temporary files",
290 SQLITE_IOERR_CONVPATH => "cygwin_conv_path() system call failed",
291 SQLITE_IOERR_VNODE => "SQLITE_IOERR_VNODE", SQLITE_IOERR_AUTH => "SQLITE_IOERR_AUTH",
293 SQLITE_IOERR_BEGIN_ATOMIC => "SQLITE_IOERR_BEGIN_ATOMIC",
294 SQLITE_IOERR_COMMIT_ATOMIC => "SQLITE_IOERR_COMMIT_ATOMIC",
295 SQLITE_IOERR_ROLLBACK_ATOMIC => "SQLITE_IOERR_ROLLBACK_ATOMIC",
296 SQLITE_IOERR_DATA => "SQLITE_IOERR_DATA",
297
298 SQLITE_LOCKED_SHAREDCACHE => "Locking conflict due to another connection with a shared cache",
299 SQLITE_LOCKED_VTAB => "SQLITE_LOCKED_VTAB",
300
301 SQLITE_BUSY_RECOVERY => "Another process is recovering a WAL mode database file",
302 SQLITE_BUSY_SNAPSHOT => "Cannot promote read transaction to write transaction because of writes by another connection",
303 SQLITE_BUSY_TIMEOUT => "SQLITE_BUSY_TIMEOUT",
304
305 SQLITE_CANTOPEN_NOTEMPDIR => "SQLITE_CANTOPEN_NOTEMPDIR", SQLITE_CANTOPEN_ISDIR => "Attempted to open directory as file",
307 SQLITE_CANTOPEN_FULLPATH => "Unable to convert filename into full pathname",
308 SQLITE_CANTOPEN_CONVPATH => "cygwin_conv_path() system call failed",
309 SQLITE_CANTOPEN_SYMLINK => "SQLITE_CANTOPEN_SYMLINK",
310
311 SQLITE_CORRUPT_VTAB => "Content in the virtual table is corrupt",
312 SQLITE_CORRUPT_SEQUENCE => "SQLITE_CORRUPT_SEQUENCE",
313 SQLITE_CORRUPT_INDEX => "SQLITE_CORRUPT_INDEX",
314
315 SQLITE_READONLY_RECOVERY => "WAL mode database file needs recovery (requires write access)",
316 SQLITE_READONLY_CANTLOCK => "Shared-memory file associated with WAL mode database is read-only",
317 SQLITE_READONLY_ROLLBACK => "Database has hot journal that must be rolled back (requires write access)",
318 SQLITE_READONLY_DBMOVED => "Database cannot be modified because database file has moved",
319 SQLITE_READONLY_CANTINIT => "SQLITE_READONLY_CANTINIT",
320 SQLITE_READONLY_DIRECTORY => "SQLITE_READONLY_DIRECTORY",
321
322 SQLITE_ABORT_ROLLBACK => "Transaction was rolled back",
323
324 SQLITE_CONSTRAINT_CHECK => "A CHECK constraint failed",
325 SQLITE_CONSTRAINT_COMMITHOOK => "Commit hook caused rollback",
326 SQLITE_CONSTRAINT_FOREIGNKEY => "Foreign key constraint failed",
327 SQLITE_CONSTRAINT_FUNCTION => "Error returned from extension function",
328 SQLITE_CONSTRAINT_NOTNULL => "A NOT NULL constraint failed",
329 SQLITE_CONSTRAINT_PRIMARYKEY => "A PRIMARY KEY constraint failed",
330 SQLITE_CONSTRAINT_TRIGGER => "A RAISE function within a trigger fired",
331 SQLITE_CONSTRAINT_UNIQUE => "A UNIQUE constraint failed",
332 SQLITE_CONSTRAINT_VTAB => "An application-defined virtual table error occurred",
333 SQLITE_CONSTRAINT_ROWID => "A non-unique rowid occurred",
334 SQLITE_CONSTRAINT_PINNED => "SQLITE_CONSTRAINT_PINNED",
335 SQLITE_CONSTRAINT_DATATYPE => "SQLITE_CONSTRAINT_DATATYPE",
336
337 SQLITE_NOTICE_RECOVER_WAL => "A WAL mode database file was recovered",
338 SQLITE_NOTICE_RECOVER_ROLLBACK => "Hot journal was rolled back",
339
340 SQLITE_WARNING_AUTOINDEX => "Automatic indexing used - database might benefit from additional indexes",
341
342 SQLITE_AUTH_USER => "SQLITE_AUTH_USER", _ => "Unknown error code",
345 }
346}