1extern crate alloc;
2
3use alloc::boxed::Box;
4use alloc::ffi::{IntoStringError, NulError};
5use alloc::vec::Vec;
6use alloc::{ffi::CString, string::String};
7use core::array::TryFromSliceError;
8use core::cell::{BorrowError, BorrowMutError};
9use core::ffi::{CStr, c_char, c_int, c_void};
10use core::ptr::null_mut;
11use core::{error::Error, slice, str::Utf8Error};
12
13use num_derive::FromPrimitive;
14use num_traits::FromPrimitive;
15
16use crate::bindings;
17use crate::capi as sqlite3_capi;
18pub use crate::capi::*;
19
20#[derive(FromPrimitive, PartialEq, Debug, Clone, Copy)]
22pub enum ActionCode {
23 COPY = 0,
24 CREATE_INDEX = 1,
25 CREATE_TABLE = 2,
26 CREATE_TEMP_INDEX = 3,
27 CREATE_TEMP_TABLE = 4,
28 CREATE_TEMP_TRIGGER = 5,
29 CREATE_TEMP_VIEW = 6,
30 CREATE_TRIGGER = 7,
31 CREATE_VIEW = 8,
32 DELETE = 9,
33 DROP_INDEX = 10,
34 DROP_TABLE = 11,
35 DROP_TEMP_INDEX = 12,
36 DROP_TEMP_TABLE = 13,
37 DROP_TEMP_TRIGGER = 14,
38 DROP_TEMP_VIEW = 15,
39 DROP_TRIGGER = 16,
40 DROP_VIEW = 17,
41 INSERT = 18,
42 PRAGMA = 19,
43 READ = 20,
44 SELECT = 21,
45 TRANSACTION = 22,
46 UPDATE = 23,
47 ATTACH = 24,
48 DETACH = 25,
49 ALTER_TABLE = 26,
50 REINDEX = 27,
51 ANALYZE = 28,
52 CREATE_VTABLE = 29,
53 DROP_VTABLE = 30,
54 FUNCTION = 31,
55 SAVEPOINT = 32,
56 RECURSIVE = 33,
57}
58
59#[derive(FromPrimitive, PartialEq, Debug, Clone, Copy)]
60pub enum ResultCode {
61 OK = 0,
62 ERROR = 1,
63 INTERNAL = 2,
64 PERM = 3,
65 ABORT = 4,
66 BUSY = 5,
67 LOCKED = 6,
68 NOMEM = 7,
69 READONLY = 8,
70 INTERRUPT = 9,
71 IOERR = 10,
72 CORRUPT = 11,
73 NOTFOUND = 12,
74 FULL = 13,
75 CANTOPEN = 14,
76 PROTOCOL = 15,
77 EMPTY = 16,
78 SCHEMA = 17,
79 TOOBIG = 18,
80 CONSTRAINT = 19,
81 MISMATCH = 20,
82 MISUSE = 21,
83 NOLFS = 22,
84 AUTH = 23,
85 FORMAT = 24,
86 RANGE = 25,
87 NOTADB = 26,
88 NOTICE = 27,
89 WARNING = 28,
90 ROW = 100,
91 DONE = 101,
92 ERROR_MISSING_COLLSEQ = bindings::SQLITE_ERROR_MISSING_COLLSEQ as isize,
93 ERROR_RETRY = bindings::SQLITE_ERROR_RETRY as isize,
94 ERROR_SNAPSHOT = bindings::SQLITE_ERROR_SNAPSHOT as isize,
95 IOERR_READ = bindings::SQLITE_IOERR_READ as isize,
96 IOERR_SHORT_READ = bindings::SQLITE_IOERR_SHORT_READ as isize,
97 IOERR_WRITE = bindings::SQLITE_IOERR_WRITE as isize,
98 IOERR_FSYNC = bindings::SQLITE_IOERR_FSYNC as isize,
99 IOERR_DIR_FSYNC = bindings::SQLITE_IOERR_DIR_FSYNC as isize,
100 IOERR_TRUNCATE = bindings::SQLITE_IOERR_TRUNCATE as isize,
101 IOERR_FSTAT = bindings::SQLITE_IOERR_FSTAT as isize,
102 IOERR_UNLOCK = bindings::SQLITE_IOERR_UNLOCK as isize,
103 IOERR_RDLOCK = bindings::SQLITE_IOERR_RDLOCK as isize,
104 IOERR_DELETE = bindings::SQLITE_IOERR_DELETE as isize,
105 IOERR_BLOCKED = bindings::SQLITE_IOERR_BLOCKED as isize,
106 IOERR_NOMEM = bindings::SQLITE_IOERR_NOMEM as isize,
107 IOERR_ACCESS = bindings::SQLITE_IOERR_ACCESS as isize,
108 IOERR_CHECKRESERVEDLOCK = bindings::SQLITE_IOERR_CHECKRESERVEDLOCK as isize,
109 IOERR_LOCK = bindings::SQLITE_IOERR_LOCK as isize,
110 IOERR_CLOSE = bindings::SQLITE_IOERR_CLOSE as isize,
111 IOERR_DIR_CLOSE = bindings::SQLITE_IOERR_DIR_CLOSE as isize,
112 IOERR_SHMOPEN = bindings::SQLITE_IOERR_SHMOPEN as isize,
113 IOERR_SHMSIZE = bindings::SQLITE_IOERR_SHMSIZE as isize,
114 IOERR_SHMLOCK = bindings::SQLITE_IOERR_SHMLOCK as isize,
115 IOERR_SHMMAP = bindings::SQLITE_IOERR_SHMMAP as isize,
116 IOERR_SEEK = bindings::SQLITE_IOERR_SEEK as isize,
117 IOERR_DELETE_NOENT = bindings::SQLITE_IOERR_DELETE_NOENT as isize,
118 IOERR_MMAP = bindings::SQLITE_IOERR_MMAP as isize,
119 IOERR_GETTEMPPATH = bindings::SQLITE_IOERR_GETTEMPPATH as isize,
120 IOERR_CONVPATH = bindings::SQLITE_IOERR_CONVPATH as isize,
121 IOERR_VNODE = bindings::SQLITE_IOERR_VNODE as isize,
122 IOERR_AUTH = bindings::SQLITE_IOERR_AUTH as isize,
123 IOERR_BEGIN_ATOMIC = bindings::SQLITE_IOERR_BEGIN_ATOMIC as isize,
124 IOERR_COMMIT_ATOMIC = bindings::SQLITE_IOERR_COMMIT_ATOMIC as isize,
125 IOERR_ROLLBACK_ATOMIC = bindings::SQLITE_IOERR_ROLLBACK_ATOMIC as isize,
126 IOERR_DATA = bindings::SQLITE_IOERR_DATA as isize,
127 IOERR_CORRUPTFS = bindings::SQLITE_IOERR_CORRUPTFS as isize,
128 LOCKED_SHAREDCACHE = bindings::SQLITE_LOCKED_SHAREDCACHE as isize,
129 LOCKED_VTAB = bindings::SQLITE_LOCKED_VTAB as isize,
130 BUSY_RECOVERY = bindings::SQLITE_BUSY_RECOVERY as isize,
131 BUSY_SNAPSHOT = bindings::SQLITE_BUSY_SNAPSHOT as isize,
132 BUSY_TIMEOUT = bindings::SQLITE_BUSY_TIMEOUT as isize,
133 CANTOPEN_NOTEMPDIR = bindings::SQLITE_CANTOPEN_NOTEMPDIR as isize,
134 CANTOPEN_ISDIR = bindings::SQLITE_CANTOPEN_ISDIR as isize,
135 CANTOPEN_FULLPATH = bindings::SQLITE_CANTOPEN_FULLPATH as isize,
136 CANTOPEN_CONVPATH = bindings::SQLITE_CANTOPEN_CONVPATH as isize,
137 CANTOPEN_DIRTYWAL = bindings::SQLITE_CANTOPEN_DIRTYWAL as isize,
138 CANTOPEN_SYMLINK = bindings::SQLITE_CANTOPEN_SYMLINK as isize,
139 CORRUPT_VTAB = bindings::SQLITE_CORRUPT_VTAB as isize,
140 CORRUPT_SEQUENCE = bindings::SQLITE_CORRUPT_SEQUENCE as isize,
141 CORRUPT_INDEX = bindings::SQLITE_CORRUPT_INDEX as isize,
142 READONLY_RECOVERY = bindings::SQLITE_READONLY_RECOVERY as isize,
143 READONLY_CANTLOCK = bindings::SQLITE_READONLY_CANTLOCK as isize,
144 READONLY_ROLLBACK = bindings::SQLITE_READONLY_ROLLBACK as isize,
145 READONLY_DBMOVED = bindings::SQLITE_READONLY_DBMOVED as isize,
146 READONLY_CANTINIT = bindings::SQLITE_READONLY_CANTINIT as isize,
147 READONLY_DIRECTORY = bindings::SQLITE_READONLY_DIRECTORY as isize,
148 ABORT_ROLLBACK = bindings::SQLITE_ABORT_ROLLBACK as isize,
149 CONSTRAINT_CHECK = bindings::SQLITE_CONSTRAINT_CHECK as isize,
150 CONSTRAINT_COMMITHOOK = bindings::SQLITE_CONSTRAINT_COMMITHOOK as isize,
151 CONSTRAINT_FOREIGNKEY = bindings::SQLITE_CONSTRAINT_FOREIGNKEY as isize,
152 CONSTRAINT_FUNCTION = bindings::SQLITE_CONSTRAINT_FUNCTION as isize,
153 CONSTRAINT_NOTNULL = bindings::SQLITE_CONSTRAINT_NOTNULL as isize,
154 CONSTRAINT_PRIMARYKEY = bindings::SQLITE_CONSTRAINT_PRIMARYKEY as isize,
155 CONSTRAINT_TRIGGER = bindings::SQLITE_CONSTRAINT_TRIGGER as isize,
156 CONSTRAINT_UNIQUE = bindings::SQLITE_CONSTRAINT_UNIQUE as isize,
157 CONSTRAINT_VTAB = bindings::SQLITE_CONSTRAINT_VTAB as isize,
158 CONSTRAINT_ROWID = bindings::SQLITE_CONSTRAINT_ROWID as isize,
159 CONSTRAINT_PINNED = bindings::SQLITE_CONSTRAINT_PINNED as isize,
160 CONSTRAINT_DATATYPE = bindings::SQLITE_CONSTRAINT_DATATYPE as isize,
161 NOTICE_RECOVER_WAL = bindings::SQLITE_NOTICE_RECOVER_WAL as isize,
162 NOTICE_RECOVER_ROLLBACK = bindings::SQLITE_NOTICE_RECOVER_ROLLBACK as isize,
163 WARNING_AUTOINDEX = bindings::SQLITE_WARNING_AUTOINDEX as isize,
164 AUTH_USER = bindings::SQLITE_AUTH_USER as isize,
165 OK_LOAD_PERMANENTLY = bindings::SQLITE_OK_LOAD_PERMANENTLY as isize,
166 OK_SYMLINK = bindings::SQLITE_OK_SYMLINK as isize,
167
168 NULL = 5000,
169}
170
171impl core::fmt::Display for ResultCode {
172 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
173 write!(f, "{:?}", self)
174 }
175}
176
177impl Error for ResultCode {}
178
179impl From<Utf8Error> for ResultCode {
180 fn from(_error: Utf8Error) -> Self {
181 ResultCode::FORMAT
182 }
183}
184
185impl From<TryFromSliceError> for ResultCode {
186 fn from(_error: TryFromSliceError) -> Self {
187 ResultCode::RANGE
188 }
189}
190
191impl From<NulError> for ResultCode {
192 fn from(_error: NulError) -> Self {
193 ResultCode::NOMEM
194 }
195}
196
197impl From<IntoStringError> for ResultCode {
198 fn from(_error: IntoStringError) -> Self {
199 ResultCode::FORMAT
200 }
201}
202
203impl From<BorrowError> for ResultCode {
204 fn from(_error: BorrowError) -> Self {
205 ResultCode::ERROR
206 }
207}
208
209impl From<BorrowMutError> for ResultCode {
210 fn from(_error: BorrowMutError) -> Self {
211 ResultCode::ERROR
212 }
213}
214
215impl From<String> for ResultCode {
216 fn from(_error: String) -> Self {
217 ResultCode::ERROR
218 }
219}
220
221#[derive(FromPrimitive, PartialEq, Debug, Clone, Copy)]
222pub enum ColumnType {
223 Integer = 1,
224 Float = 2,
225 Text = 3,
226 Blob = 4,
227 Null = 5,
228}
229
230pub fn open(filename: *const c_char) -> Result<ManagedConnection, ResultCode> {
231 let mut db = core::ptr::null_mut();
232 let rc =
233 ResultCode::from_i32(sqlite3_capi::open(filename, &mut db as *mut *mut sqlite3)).unwrap();
234 if rc == ResultCode::OK {
235 Ok(ManagedConnection { db })
236 } else {
237 Err(rc)
238 }
239}
240
241pub fn libversion() -> &'static str {
242 unsafe { CStr::from_ptr(sqlite3_capi::libversion()) }
243 .to_str()
244 .unwrap()
245}
246
247pub fn libversion_number() -> c_int {
248 sqlite3_capi::libversion_number()
249}
250
251pub fn randomness(blob: &mut [u8]) {
252 sqlite3_capi::randomness(blob.len() as c_int, blob.as_mut_ptr() as *mut c_void)
253}
254
255pub struct ManagedConnection {
256 pub db: *mut sqlite3,
257}
258
259pub trait Connection {
260 fn commit_hook(&self, callback: Option<xCommitHook>, user_data: *mut c_void) -> *mut c_void;
261
262 fn create_function_v2(
263 &self,
264 name: &str,
265 n_arg: i32,
266 flags: u32,
267 user_data: Option<*mut c_void>,
268 func: Option<xFunc>,
269 step: Option<xStep>,
270 final_func: Option<xFinal>,
271 destroy: Option<xDestroy>,
272 ) -> Result<ResultCode, ResultCode>;
273
274 fn create_module_v2(
275 &self,
276 name: &str,
277 module: *const module,
278 user_data: Option<*mut c_void>,
279 destroy: Option<xDestroy>,
280 ) -> Result<ResultCode, ResultCode>;
281
282 fn changes64(&self) -> i64;
283
284 fn errcode(&self) -> ResultCode;
285 fn errmsg(&self) -> Result<String, IntoStringError>;
286 fn error_offset(&self) -> Option<usize>;
287
288 unsafe fn exec(&self, sql: *const c_char) -> Result<ResultCode, ResultCode>;
293
294 fn exec_safe(&self, sql: &str) -> Result<ResultCode, ResultCode>;
295
296 fn next_stmt(&self, s: Option<*mut stmt>) -> Option<*mut stmt>;
297
298 fn prepare_v2(&self, sql: &str) -> Result<ManagedStmt, ResultCode>;
299
300 fn prepare_v3(&self, sql: &str, flags: u32) -> Result<ManagedStmt, ResultCode>;
301
302 fn set_authorizer(
303 &self,
304 x_auth: Option<XAuthorizer>,
305 user_data: *mut c_void,
306 ) -> Result<ResultCode, ResultCode>;
307
308 fn rollback_hook(&self, callback: Option<xRollbackHook>, ctx: *mut c_void) -> *mut c_void;
309
310 fn update_hook(&self, callback: Option<xUpdateHook>, ctx: *mut c_void) -> *mut c_void;
311
312 fn get_autocommit(&self) -> bool;
313}
314
315impl Connection for ManagedConnection {
316 fn changes64(&self) -> i64 {
317 self.db.changes64()
318 }
319
320 fn commit_hook(&self, callback: Option<xCommitHook>, user_data: *mut c_void) -> *mut c_void {
321 self.db.commit_hook(callback, user_data)
322 }
323
324 fn create_function_v2(
327 &self,
328 name: &str,
329 n_arg: i32,
330 flags: u32,
331 user_data: Option<*mut c_void>,
332 func: Option<xFunc>,
333 step: Option<xStep>,
334 final_func: Option<xFinal>,
335 destroy: Option<xDestroy>,
336 ) -> Result<ResultCode, ResultCode> {
337 self.db.create_function_v2(
338 name, n_arg, flags, user_data, func, step, final_func, destroy,
339 )
340 }
341
342 fn set_authorizer(
343 &self,
344 x_auth: Option<XAuthorizer>,
345 user_data: *mut c_void,
346 ) -> Result<ResultCode, ResultCode> {
347 self.db.set_authorizer(x_auth, user_data)
348 }
349
350 fn create_module_v2(
351 &self,
352 name: &str,
353 module: *const module,
354 user_data: Option<*mut c_void>,
355 destroy: Option<xDestroy>,
356 ) -> Result<ResultCode, ResultCode> {
357 self.db.create_module_v2(name, module, user_data, destroy)
358 }
359
360 #[inline]
361 fn next_stmt(&self, s: Option<*mut stmt>) -> Option<*mut stmt> {
362 self.db.next_stmt(s)
363 }
364
365 #[inline]
366 fn prepare_v2(&self, sql: &str) -> Result<ManagedStmt, ResultCode> {
367 self.db.prepare_v2(sql)
368 }
369
370 #[inline]
371 fn prepare_v3(&self, sql: &str, flags: u32) -> Result<ManagedStmt, ResultCode> {
372 self.db.prepare_v3(sql, flags)
373 }
374
375 #[inline]
376 unsafe fn exec(&self, sql: *const c_char) -> Result<ResultCode, ResultCode> {
377 unsafe { self.db.exec(sql) }
378 }
379
380 #[inline]
381 fn exec_safe(&self, sql: &str) -> Result<ResultCode, ResultCode> {
382 self.db.exec_safe(sql)
383 }
384
385 #[inline]
386 fn errmsg(&self) -> Result<String, IntoStringError> {
387 self.db.errmsg()
388 }
389
390 #[inline]
391 fn errcode(&self) -> ResultCode {
392 self.db.errcode()
393 }
394
395 fn error_offset(&self) -> Option<usize> {
396 self.db.error_offset()
397 }
398
399 #[inline]
400 fn get_autocommit(&self) -> bool {
401 self.db.get_autocommit()
402 }
403
404 fn rollback_hook(&self, callback: Option<xRollbackHook>, ctx: *mut c_void) -> *mut c_void {
405 self.db.rollback_hook(callback, ctx)
406 }
407
408 fn update_hook(&self, callback: Option<xUpdateHook>, ctx: *mut c_void) -> *mut c_void {
409 self.db.update_hook(callback, ctx)
410 }
411}
412
413impl Drop for ManagedConnection {
414 fn drop(&mut self) {
415 let rc = sqlite3_capi::close(self.db);
417 if rc != 0 {
418 panic!(
425 "SQLite returned error {:?} when trying to close the db!",
426 rc
427 );
428 }
429 }
430}
431
432impl Connection for *mut sqlite3 {
433 fn changes64(&self) -> i64 {
434 changes64(*self)
435 }
436
437 fn commit_hook(&self, callback: Option<xCommitHook>, user_data: *mut c_void) -> *mut c_void {
438 commit_hook(*self, callback, user_data)
439 }
440
441 fn create_function_v2(
442 &self,
443 name: &str,
444 n_arg: i32,
445 flags: u32,
446 user_data: Option<*mut c_void>,
447 func: Option<xFunc>,
448 step: Option<xStep>,
449 final_func: Option<xFinal>,
450 destroy: Option<xDestroy>,
451 ) -> Result<ResultCode, ResultCode> {
452 if let Ok(name) = CString::new(name) {
453 convert_rc(create_function_v2(
454 *self,
455 name.as_ptr(),
456 n_arg,
457 flags as c_int,
458 user_data.unwrap_or(core::ptr::null_mut()),
459 func,
460 step,
461 final_func,
462 destroy,
463 ))
464 } else {
465 Err(ResultCode::NOMEM)
466 }
467 }
468
469 fn create_module_v2(
470 &self,
471 name: &str,
472 module: *const module,
473 user_data: Option<*mut c_void>,
474 destroy: Option<xDestroy>,
475 ) -> Result<ResultCode, ResultCode> {
476 if let Ok(name) = CString::new(name) {
477 convert_rc(create_module_v2(
478 *self,
479 name.as_ptr(),
480 module,
481 user_data.unwrap_or(core::ptr::null_mut()),
482 destroy,
483 ))
484 } else {
485 Err(ResultCode::NOMEM)
486 }
487 }
488
489 #[inline]
490 fn prepare_v2(&self, sql: &str) -> Result<ManagedStmt, ResultCode> {
491 let mut stmt = core::ptr::null_mut();
492 let mut tail = core::ptr::null();
493 let rc = ResultCode::from_i32(prepare_v2(
494 *self,
495 sql.as_ptr() as *const c_char,
496 sql.len() as i32,
497 &mut stmt as *mut *mut stmt,
498 &mut tail as *mut *const c_char,
499 ))
500 .unwrap();
501 if rc == ResultCode::OK {
502 Ok(ManagedStmt { stmt: stmt })
503 } else {
504 Err(rc)
505 }
506 }
507
508 #[inline]
509 fn prepare_v3(&self, sql: &str, flags: u32) -> Result<ManagedStmt, ResultCode> {
510 let mut stmt = core::ptr::null_mut();
511 let mut tail = core::ptr::null();
512 let rc = ResultCode::from_i32(prepare_v3(
513 *self,
514 sql.as_ptr() as *const c_char,
515 sql.len() as i32,
516 flags,
517 &mut stmt as *mut *mut stmt,
518 &mut tail as *mut *const c_char,
519 ))
520 .unwrap();
521 if rc == ResultCode::OK {
522 Ok(ManagedStmt { stmt: stmt })
523 } else {
524 Err(rc)
525 }
526 }
527
528 #[inline]
529 unsafe fn exec(&self, sql: *const c_char) -> Result<ResultCode, ResultCode> {
530 convert_rc(exec(*self, sql))
531 }
532
533 #[inline]
534 fn exec_safe(&self, sql: &str) -> Result<ResultCode, ResultCode> {
535 if let Ok(sql) = CString::new(sql) {
536 convert_rc(exec(*self, sql.as_ptr()))
537 } else {
538 return Err(ResultCode::NOMEM);
539 }
540 }
541
542 #[inline]
543 fn next_stmt(&self, s: Option<*mut stmt>) -> Option<*mut stmt> {
544 let s = if let Some(s) = s {
545 s
546 } else {
547 core::ptr::null_mut()
548 };
549
550 let ptr = next_stmt(*self, s);
551 if ptr.is_null() { None } else { Some(ptr) }
552 }
553
554 fn set_authorizer(
555 &self,
556 x_auth: Option<XAuthorizer>,
557 user_data: *mut c_void,
558 ) -> Result<ResultCode, ResultCode> {
559 convert_rc(set_authorizer(*self, x_auth, user_data))
560 }
561
562 fn errmsg(&self) -> Result<String, IntoStringError> {
563 errmsg(*self).into_string()
564 }
565
566 fn errcode(&self) -> ResultCode {
567 ResultCode::from_i32(errcode(*self)).unwrap()
568 }
569
570 fn error_offset(&self) -> Option<usize> {
571 match error_offset(*self) {
572 -1 => None,
573 other => Some(other as usize),
574 }
575 }
576
577 fn get_autocommit(&self) -> bool {
578 get_autocommit(*self) != 0
579 }
580
581 fn rollback_hook(&self, callback: Option<xRollbackHook>, ctx: *mut c_void) -> *mut c_void {
582 rollback_hook(*self, callback, ctx)
583 }
584
585 fn update_hook(&self, callback: Option<xUpdateHook>, ctx: *mut c_void) -> *mut c_void {
586 update_hook(*self, callback, ctx)
587 }
588}
589
590pub fn convert_rc(rc: i32) -> Result<ResultCode, ResultCode> {
591 let rc = ResultCode::from_i32(rc).unwrap_or(ResultCode::ABORT);
592 if rc == ResultCode::OK {
593 Ok(rc)
594 } else {
595 Err(rc)
596 }
597}
598
599pub struct ManagedStmt {
600 pub stmt: *mut stmt,
601}
602
603impl ManagedStmt {
604 pub fn reset(&self) -> Result<ResultCode, ResultCode> {
605 convert_rc(reset(self.stmt))
606 }
607
608 pub fn step(&self) -> Result<ResultCode, ResultCode> {
609 let rc = ResultCode::from_i32(step(self.stmt)).unwrap();
610 if (rc == ResultCode::ROW) || (rc == ResultCode::DONE) {
611 Ok(rc)
612 } else {
613 Err(rc)
614 }
615 }
616
617 pub fn sql(&self) -> Result<&str, ResultCode> {
618 let ptr = sql(self.stmt);
619 Ok(unsafe { CStr::from_ptr(ptr) }.to_str()?)
620 }
621
622 #[inline]
623 pub fn column_count(&self) -> i32 {
624 column_count(self.stmt)
625 }
626
627 #[inline]
631 pub fn column_name(&self, i: i32) -> Result<&str, ResultCode> {
632 let ptr = column_name(self.stmt, i);
633 if ptr.is_null() {
634 Err(ResultCode::NULL)
635 } else {
636 Ok(
637 unsafe {
638 core::str::from_utf8_unchecked(core::ffi::CStr::from_ptr(ptr).to_bytes())
639 },
640 )
641 }
642 }
643
644 #[inline]
645 pub fn column_type(&self, i: i32) -> Result<ColumnType, ResultCode> {
646 ColumnType::from_i32(column_type(self.stmt, i)).ok_or(ResultCode::NULL)
647 }
648
649 #[inline]
650 pub fn column_text(&self, i: i32) -> Result<&str, ResultCode> {
651 let len = column_bytes(self.stmt, i);
652 let ptr = column_text_ptr(self.stmt, i);
653 if ptr.is_null() {
654 Err(ResultCode::NULL)
655 } else {
656 Ok(unsafe {
657 let slice = core::slice::from_raw_parts(ptr as *const u8, len as usize);
658 core::str::from_utf8_unchecked(slice)
659 })
660 }
661 }
662
663 #[inline]
664 pub fn column_blob(&self, i: i32) -> Result<&[u8], ResultCode> {
665 let len = column_bytes(self.stmt, i);
666 let ptr = column_blob(self.stmt, i);
667 if ptr.is_null() {
668 Err(ResultCode::NULL)
669 } else {
670 Ok(unsafe { core::slice::from_raw_parts(ptr as *const u8, len as usize) })
671 }
672 }
673
674 #[inline]
675 pub fn column_double(&self, i: i32) -> f64 {
676 column_double(self.stmt, i)
677 }
678
679 #[inline]
680 pub fn column_int(&self, i: i32) -> i32 {
681 column_int(self.stmt, i)
682 }
683
684 #[inline]
685 pub fn column_int64(&self, i: i32) -> int64 {
686 column_int64(self.stmt, i)
687 }
688
689 #[inline]
691 pub fn column_value(&self, i: i32) -> Result<*mut value, ResultCode> {
692 let ptr = column_value(self.stmt, i);
693 if ptr.is_null() {
694 Err(ResultCode::NULL)
695 } else {
696 Ok(ptr)
697 }
698 }
699
700 pub fn bind_blob(&self, i: i32, val: &[u8], d: Destructor) -> Result<ResultCode, ResultCode> {
701 convert_rc(bind_blob(
702 self.stmt,
703 i,
704 val.as_ptr() as *const c_void,
705 val.len() as i32,
706 d,
707 ))
708 }
709
710 #[inline]
711 pub fn bind_value(&self, i: i32, val: *mut value) -> Result<ResultCode, ResultCode> {
712 convert_rc(bind_value(self.stmt, i, val))
713 }
714
715 #[inline]
716 pub fn bind_text(&self, i: i32, text: &str, d: Destructor) -> Result<ResultCode, ResultCode> {
717 convert_rc(bind_text(
718 self.stmt,
719 i,
720 text.as_ptr() as *const c_char,
721 text.len() as i32,
722 d,
723 ))
724 }
725
726 #[inline]
727 pub fn bind_int64(&self, i: i32, val: int64) -> Result<ResultCode, ResultCode> {
728 convert_rc(bind_int64(self.stmt, i, val))
729 }
730
731 #[inline]
732 pub fn bind_int(&self, i: i32, val: i32) -> Result<ResultCode, ResultCode> {
733 convert_rc(bind_int(self.stmt, i, val))
734 }
735
736 #[inline]
737 pub fn bind_double(&self, i: i32, val: f64) -> Result<ResultCode, ResultCode> {
738 convert_rc(bind_double(self.stmt, i, val))
739 }
740
741 #[inline]
742 pub fn bind_null(&self, i: i32) -> Result<ResultCode, ResultCode> {
743 convert_rc(bind_null(self.stmt, i))
744 }
745
746 #[inline]
747 pub fn clear_bindings(&self) -> Result<ResultCode, ResultCode> {
748 convert_rc(clear_bindings(self.stmt))
749 }
750
751 #[inline]
752 pub fn bind_parameter_count(&self) -> c_int {
753 bind_parameter_count(self.stmt)
754 }
755
756 pub fn bind_parameter_name(&self, i: i32) -> Result<Option<&str>, Utf8Error> {
757 let ptr = bind_parameter_name(self.stmt, i);
758 if ptr.is_null() {
759 Ok(None)
760 } else {
761 let name = unsafe { CStr::from_ptr(ptr) };
762 Ok(Some(name.to_str()?))
763 }
764 }
765
766 #[inline]
767 pub fn finalize(self) -> Result<ResultCode, ResultCode> {
768 self.stmt.finalize()
769 }
770
771 pub fn into_raw(self) -> *mut stmt {
772 let stmt = self.stmt;
773 core::mem::forget(self);
774 stmt
775 }
776}
777
778impl Drop for ManagedStmt {
779 fn drop(&mut self) {
780 finalize(self.stmt);
781 }
782}
783
784pub trait Context {
785 fn result_text_transient(&self, text: &str);
786 fn result_text_static(&self, text: &str);
787 fn result_blob_transient(&self, blob: &[u8]);
788 fn result_blob_static(&self, blob: &[u8]);
789 fn result_error(&self, text: &str);
790 fn result_error_code(&self, code: ResultCode);
791 fn result_value(&self, value: *mut value);
792 fn result_double(&self, value: f64);
793 fn result_int(&self, value: i32);
794 fn result_int64(&self, value: int64);
795 fn result_null(&self);
796 fn result_subtype(&self, subtype: u32);
797 fn db_handle(&self) -> *mut sqlite3;
798 fn user_data(&self) -> *mut c_void;
799}
800
801impl Context for *mut context {
802 #[inline]
803 fn result_null(&self) {
804 result_null(*self)
805 }
806
807 #[inline]
810 fn result_text_transient(&self, text: &str) {
811 result_text(
812 *self,
813 text.as_ptr() as *mut c_char,
814 text.len() as i32,
815 Destructor::TRANSIENT,
816 );
817 }
818
819 #[inline]
822 fn result_text_static(&self, text: &str) {
823 result_text(
824 *self,
825 text.as_ptr() as *mut c_char,
826 text.len() as i32,
827 Destructor::STATIC,
828 );
829 }
830
831 #[inline]
833 fn result_blob_transient(&self, blob: &[u8]) {
834 result_blob(
835 *self,
836 blob.as_ptr(),
837 blob.len() as i32,
838 Destructor::TRANSIENT,
839 );
840 }
841
842 #[inline]
843 fn result_blob_static(&self, blob: &[u8]) {
844 result_blob(*self, blob.as_ptr(), blob.len() as i32, Destructor::STATIC);
845 }
846
847 #[inline]
848 fn result_error(&self, text: &str) {
849 result_error(*self, text.as_ptr() as *mut c_char, text.len() as c_int);
850 }
851
852 #[inline]
853 fn result_error_code(&self, code: ResultCode) {
854 result_error_code(*self, code as c_int);
855 }
856
857 #[inline]
858 fn result_value(&self, value: *mut value) {
859 result_value(*self, value);
860 }
861
862 #[inline]
863 fn result_double(&self, value: f64) {
864 result_double(*self, value);
865 }
866
867 #[inline]
868 fn result_int64(&self, value: int64) {
869 result_int64(*self, value);
870 }
871
872 #[inline]
873 fn result_int(&self, value: i32) {
874 result_int(*self, value);
875 }
876
877 #[inline]
878 fn result_subtype(&self, subtype: u32) {
879 result_subtype(*self, subtype);
880 }
881
882 #[inline]
883 fn db_handle(&self) -> *mut sqlite3 {
884 context_db_handle(*self)
885 }
886
887 #[inline]
888 fn user_data(&self) -> *mut c_void {
889 user_data(*self)
890 }
891}
892
893pub trait Stmt {
894 fn sql(&self) -> &str;
895 fn bind_blob(&self, i: i32, val: &[u8], d: Destructor) -> Result<ResultCode, ResultCode>;
896 fn bind_value(&self, i: i32, val: *mut value) -> Result<ResultCode, ResultCode>;
897 fn bind_text(&self, i: i32, text: &str, d: Destructor) -> Result<ResultCode, ResultCode>;
898 fn bind_int64(&self, i: i32, val: int64) -> Result<ResultCode, ResultCode>;
899 fn bind_int(&self, i: i32, val: i32) -> Result<ResultCode, ResultCode>;
900 fn bind_double(&self, i: i32, val: f64) -> Result<ResultCode, ResultCode>;
901 fn bind_null(&self, i: i32) -> Result<ResultCode, ResultCode>;
902
903 fn clear_bindings(&self) -> Result<ResultCode, ResultCode>;
904
905 fn column_value(&self, i: i32) -> *mut value;
906 fn column_int64(&self, i: i32) -> int64;
907 fn column_int(&self, i: i32) -> i32;
908 fn column_blob(&self, i: i32) -> &[u8];
909 fn column_double(&self, i: i32) -> f64;
910 fn column_text(&self, i: i32) -> &str;
911 fn column_bytes(&self, i: i32) -> i32;
912
913 fn finalize(&self) -> Result<ResultCode, ResultCode>;
914
915 fn reset(&self) -> Result<ResultCode, ResultCode>;
916 fn step(&self) -> Result<ResultCode, ResultCode>;
917}
918
919impl Stmt for *mut stmt {
920 fn sql(&self) -> &str {
921 unsafe { core::str::from_utf8_unchecked(core::ffi::CStr::from_ptr(sql(*self)).to_bytes()) }
922 }
923
924 #[inline]
925 fn bind_blob(&self, i: i32, val: &[u8], d: Destructor) -> Result<ResultCode, ResultCode> {
926 convert_rc(bind_blob(
927 *self,
928 i,
929 val.as_ptr() as *const c_void,
930 val.len() as i32,
931 d,
932 ))
933 }
934
935 #[inline]
936 fn bind_double(&self, i: i32, val: f64) -> Result<ResultCode, ResultCode> {
937 convert_rc(bind_double(*self, i, val))
938 }
939
940 #[inline]
941 fn bind_value(&self, i: i32, val: *mut value) -> Result<ResultCode, ResultCode> {
942 convert_rc(bind_value(*self, i, val))
943 }
944
945 #[inline]
946 fn bind_text(&self, i: i32, text: &str, d: Destructor) -> Result<ResultCode, ResultCode> {
947 convert_rc(bind_text(
948 *self,
949 i,
950 text.as_ptr() as *const c_char,
951 text.len() as i32,
952 d,
953 ))
954 }
955
956 #[inline]
957 fn bind_int64(&self, i: i32, val: int64) -> Result<ResultCode, ResultCode> {
958 convert_rc(bind_int64(*self, i, val))
959 }
960
961 #[inline]
962 fn bind_int(&self, i: i32, val: i32) -> Result<ResultCode, ResultCode> {
963 convert_rc(bind_int(*self, i, val))
964 }
965
966 #[inline]
967 fn bind_null(&self, i: i32) -> Result<ResultCode, ResultCode> {
968 convert_rc(bind_null(*self, i))
969 }
970
971 #[inline]
972 fn clear_bindings(&self) -> Result<ResultCode, ResultCode> {
973 convert_rc(clear_bindings(*self))
974 }
975
976 #[inline]
977 fn column_value(&self, i: i32) -> *mut value {
978 column_value(*self, i)
979 }
980
981 #[inline]
982 fn column_int64(&self, i: i32) -> int64 {
983 column_int64(*self, i)
984 }
985
986 #[inline]
987 fn column_int(&self, i: i32) -> i32 {
988 column_int(*self, i)
989 }
990
991 #[inline]
992 fn column_blob(&self, i: i32) -> &[u8] {
993 let len = column_bytes(*self, i);
994 let ptr = column_blob(*self, i);
995 unsafe { core::slice::from_raw_parts(ptr as *const u8, len as usize) }
996 }
997
998 #[inline]
999 fn column_double(&self, i: i32) -> f64 {
1000 column_double(*self, i)
1001 }
1002
1003 #[inline]
1004 fn column_text(&self, i: i32) -> &str {
1005 column_text(*self, i)
1006 }
1007
1008 #[inline]
1009 fn column_bytes(&self, i: i32) -> i32 {
1010 column_bytes(*self, i)
1011 }
1012
1013 #[inline]
1014 fn reset(&self) -> Result<ResultCode, ResultCode> {
1015 convert_rc(reset(*self))
1016 }
1017
1018 #[inline]
1019 fn step(&self) -> Result<ResultCode, ResultCode> {
1020 match ResultCode::from_i32(step(*self)) {
1021 Some(ResultCode::ROW) => Ok(ResultCode::ROW),
1022 Some(ResultCode::DONE) => Ok(ResultCode::DONE),
1023 Some(rc) => Err(rc),
1024 None => Err(ResultCode::ERROR),
1025 }
1026 }
1027
1028 #[inline]
1029 fn finalize(&self) -> Result<ResultCode, ResultCode> {
1030 match ResultCode::from_i32(finalize(*self)) {
1031 Some(ResultCode::OK) => Ok(ResultCode::OK),
1032 Some(rc) => Err(rc),
1033 None => Err(ResultCode::ABORT),
1034 }
1035 }
1036}
1037
1038pub trait Value {
1039 fn blob(&self) -> &[u8];
1040 fn double(&self) -> f64;
1041 fn int(&self) -> i32;
1042 fn int64(&self) -> int64;
1043 fn text(&self) -> &str;
1044 fn bytes(&self) -> i32;
1045 fn value_type(&self) -> ColumnType;
1046}
1047
1048impl Value for *mut value {
1049 #[inline]
1050 fn value_type(&self) -> ColumnType {
1051 ColumnType::from_i32(value_type(*self)).unwrap()
1052 }
1053
1054 #[inline]
1055 fn blob(&self) -> &[u8] {
1056 value_blob(*self)
1057 }
1058
1059 #[inline]
1060 fn double(&self) -> f64 {
1061 value_double(*self)
1062 }
1063
1064 #[inline]
1065 fn int(&self) -> i32 {
1066 value_int(*self)
1067 }
1068
1069 #[inline]
1070 fn int64(&self) -> int64 {
1071 value_int64(*self)
1072 }
1073
1074 #[inline]
1075 fn text(&self) -> &str {
1076 value_text(*self)
1077 }
1078
1079 #[inline]
1080 fn bytes(&self) -> i32 {
1081 value_bytes(*self)
1082 }
1083}
1084
1085pub trait StrRef {
1086 fn set(&self, val: &str);
1087}
1088
1089impl StrRef for *mut *mut c_char {
1090 fn set(&self, val: &str) {
1095 unsafe {
1096 if **self != null_mut() {
1097 return;
1098 }
1099 if let Ok(cstring) = CString::new(val) {
1100 **self = cstring.into_raw();
1101 } else {
1102 if let Ok(s) = CString::new("Failed setting error message.") {
1103 **self = s.into_raw();
1104 }
1105 }
1106 }
1107 }
1108}
1109
1110pub trait VTabRef {
1112 fn set<T>(&self, val: Box<T>);
1113}
1114
1115impl VTabRef for *mut *mut vtab {
1116 fn set<T>(&self, val: Box<T>) {
1117 unsafe {
1118 let raw_val = Box::into_raw(val);
1119 **self = raw_val.cast::<sqlite3_capi::vtab>();
1120 }
1121 }
1122}
1123
1124pub trait CursorRef {
1125 fn set<T>(&self, val: Box<T>);
1126}
1127
1128impl CursorRef for *mut *mut vtab_cursor {
1129 fn set<T>(&self, val: Box<T>) {
1130 unsafe {
1131 let raw_val = Box::into_raw(val);
1132 **self = raw_val.cast::<sqlite3_capi::vtab_cursor>();
1133 }
1134 }
1135}
1136
1137pub trait VTab {
1138 fn set_err(&self, val: &str);
1139}
1140
1141impl VTab for *mut vtab {
1142 fn set_err(&self, val: &str) {
1147 unsafe {
1148 if (**self).zErrMsg != null_mut() {
1149 return;
1150 }
1151 if let Ok(e) = CString::new(val) {
1152 (**self).zErrMsg = e.into_raw();
1153 }
1154 }
1155 }
1156}
1157
1158pub struct VTabArgs<'a> {
1160 pub module_name: &'a str,
1165 pub database_name: &'a str,
1170
1171 pub table_name: &'a str,
1176 pub arguments: Vec<&'a str>,
1180}
1181
1182fn c_string_to_str<'a>(c: *const c_char) -> Result<&'a str, Utf8Error> {
1184 let s = unsafe { CStr::from_ptr(c).to_str()? };
1185 Ok(s)
1186}
1187
1188pub fn parse_vtab_args<'a>(
1189 argc: c_int,
1190 argv: *const *const c_char,
1191) -> Result<VTabArgs<'a>, Utf8Error> {
1192 let raw_args = unsafe { slice::from_raw_parts(argv, argc as usize) };
1193 let mut args = Vec::with_capacity(argc as usize);
1194 for arg in raw_args {
1195 args.push(c_string_to_str(*arg)?);
1196 }
1197
1198 let module_name = args
1201 .get(0)
1202 .expect("argv[0] should be the name of the module");
1203 let database_name = args
1204 .get(1)
1205 .expect("argv[1] should be the name of the database the module is in");
1206 let table_name = args
1207 .get(2)
1208 .expect("argv[2] should be the name of the virtual table");
1209 let arguments = &args[3..];
1210
1211 Ok(VTabArgs {
1212 module_name,
1213 database_name,
1214 table_name,
1215 arguments: arguments.to_vec(),
1216 })
1217}
1218
1219pub fn declare_vtab(db: *mut sqlite3, def: &str) -> Result<ResultCode, ResultCode> {
1220 let cstring = CString::new(def)?;
1221 let ret = sqlite3_capi::declare_vtab(db, cstring.as_ptr());
1222 convert_rc(ret)
1223}
1224
1225pub fn vtab_config(db: *mut sqlite3, options: u32) -> Result<ResultCode, ResultCode> {
1226 let rc = sqlite3_capi::vtab_config(db, options);
1227 convert_rc(rc)
1228}
1229
1230