1#![allow(non_camel_case_types)]
7#![allow(clippy::upper_case_acronyms)]
8#![allow(clippy::unreadable_literal)] use std::ffi::{c_char, c_double, c_int, c_void};
11
12#[repr(C)]
14pub struct sqlite3 {
15 _private: [u8; 0],
16}
17
18#[repr(C)]
20pub struct sqlite3_stmt {
21 _private: [u8; 0],
22}
23
24#[repr(C)]
26pub struct sqlite3_backup {
27 _private: [u8; 0],
28}
29
30pub const SQLITE_OK: c_int = 0;
32pub const SQLITE_ERROR: c_int = 1;
33pub const SQLITE_INTERNAL: c_int = 2;
34pub const SQLITE_PERM: c_int = 3;
35pub const SQLITE_ABORT: c_int = 4;
36pub const SQLITE_BUSY: c_int = 5;
37pub const SQLITE_LOCKED: c_int = 6;
38pub const SQLITE_NOMEM: c_int = 7;
39pub const SQLITE_READONLY: c_int = 8;
40pub const SQLITE_INTERRUPT: c_int = 9;
41pub const SQLITE_IOERR: c_int = 10;
42pub const SQLITE_CORRUPT: c_int = 11;
43pub const SQLITE_NOTFOUND: c_int = 12;
44pub const SQLITE_FULL: c_int = 13;
45pub const SQLITE_CANTOPEN: c_int = 14;
46pub const SQLITE_PROTOCOL: c_int = 15;
47pub const SQLITE_EMPTY: c_int = 16;
48pub const SQLITE_SCHEMA: c_int = 17;
49pub const SQLITE_TOOBIG: c_int = 18;
50pub const SQLITE_CONSTRAINT: c_int = 19;
51pub const SQLITE_MISMATCH: c_int = 20;
52pub const SQLITE_MISUSE: c_int = 21;
53pub const SQLITE_NOLFS: c_int = 22;
54pub const SQLITE_AUTH: c_int = 23;
55pub const SQLITE_FORMAT: c_int = 24;
56pub const SQLITE_RANGE: c_int = 25;
57pub const SQLITE_NOTADB: c_int = 26;
58pub const SQLITE_NOTICE: c_int = 27;
59pub const SQLITE_WARNING: c_int = 28;
60pub const SQLITE_ROW: c_int = 100;
61pub const SQLITE_DONE: c_int = 101;
62
63pub const SQLITE_CONSTRAINT_UNIQUE: c_int = SQLITE_CONSTRAINT | (8 << 8);
65
66pub const SQLITE_OPEN_READONLY: c_int = 0x00000001;
68pub const SQLITE_OPEN_READWRITE: c_int = 0x00000002;
69pub const SQLITE_OPEN_CREATE: c_int = 0x00000004;
70pub const SQLITE_OPEN_URI: c_int = 0x00000040;
71pub const SQLITE_OPEN_MEMORY: c_int = 0x00000080;
72pub const SQLITE_OPEN_NOMUTEX: c_int = 0x00008000;
73pub const SQLITE_OPEN_FULLMUTEX: c_int = 0x00010000;
74pub const SQLITE_OPEN_SHAREDCACHE: c_int = 0x00020000;
75pub const SQLITE_OPEN_PRIVATECACHE: c_int = 0x00040000;
76
77pub const SQLITE_INTEGER: c_int = 1;
79pub const SQLITE_FLOAT: c_int = 2;
80pub const SQLITE_TEXT: c_int = 3;
81pub const SQLITE_BLOB: c_int = 4;
82pub const SQLITE_NULL: c_int = 5;
83
84pub type sqlite3_destructor_type = Option<unsafe extern "C" fn(*mut c_void)>;
86
87#[inline]
95pub fn sqlite_transient() -> sqlite3_destructor_type {
96 const SQLITE_TRANSIENT_SENTINEL: isize = -1;
99 unsafe { std::mem::transmute::<isize, sqlite3_destructor_type>(SQLITE_TRANSIENT_SENTINEL) }
100}
101
102unsafe extern "C" {
107 pub fn sqlite3_open(filename: *const c_char, ppDb: *mut *mut sqlite3) -> c_int;
109
110 pub fn sqlite3_open_v2(
111 filename: *const c_char,
112 ppDb: *mut *mut sqlite3,
113 flags: c_int,
114 zVfs: *const c_char,
115 ) -> c_int;
116
117 pub fn sqlite3_close(db: *mut sqlite3) -> c_int;
118 pub fn sqlite3_close_v2(db: *mut sqlite3) -> c_int;
119 pub fn sqlite3_backup_init(
121 pDest: *mut sqlite3,
122 zDestName: *const c_char,
123 pSource: *mut sqlite3,
124 zSourceName: *const c_char,
125 ) -> *mut sqlite3_backup;
126 pub fn sqlite3_backup_step(p: *mut sqlite3_backup, nPage: c_int) -> c_int;
127 pub fn sqlite3_backup_finish(p: *mut sqlite3_backup) -> c_int;
128 pub fn sqlite3_backup_remaining(p: *mut sqlite3_backup) -> c_int;
129 pub fn sqlite3_backup_pagecount(p: *mut sqlite3_backup) -> c_int;
130
131 pub fn sqlite3_errmsg(db: *mut sqlite3) -> *const c_char;
133 pub fn sqlite3_errcode(db: *mut sqlite3) -> c_int;
134 pub fn sqlite3_extended_errcode(db: *mut sqlite3) -> c_int;
135 pub fn sqlite3_errstr(errcode: c_int) -> *const c_char;
136
137 pub fn sqlite3_prepare_v2(
139 db: *mut sqlite3,
140 zSql: *const c_char,
141 nByte: c_int,
142 ppStmt: *mut *mut sqlite3_stmt,
143 pzTail: *mut *const c_char,
144 ) -> c_int;
145
146 pub fn sqlite3_finalize(pStmt: *mut sqlite3_stmt) -> c_int;
147 pub fn sqlite3_reset(pStmt: *mut sqlite3_stmt) -> c_int;
148 pub fn sqlite3_clear_bindings(pStmt: *mut sqlite3_stmt) -> c_int;
149
150 pub fn sqlite3_bind_null(pStmt: *mut sqlite3_stmt, index: c_int) -> c_int;
152
153 pub fn sqlite3_bind_int(pStmt: *mut sqlite3_stmt, index: c_int, value: c_int) -> c_int;
154
155 pub fn sqlite3_bind_int64(pStmt: *mut sqlite3_stmt, index: c_int, value: i64) -> c_int;
156
157 pub fn sqlite3_bind_double(pStmt: *mut sqlite3_stmt, index: c_int, value: c_double) -> c_int;
158
159 pub fn sqlite3_bind_text(
160 pStmt: *mut sqlite3_stmt,
161 index: c_int,
162 value: *const c_char,
163 nBytes: c_int,
164 destructor: sqlite3_destructor_type,
165 ) -> c_int;
166
167 pub fn sqlite3_bind_blob(
168 pStmt: *mut sqlite3_stmt,
169 index: c_int,
170 value: *const c_void,
171 nBytes: c_int,
172 destructor: sqlite3_destructor_type,
173 ) -> c_int;
174
175 pub fn sqlite3_bind_parameter_count(pStmt: *mut sqlite3_stmt) -> c_int;
176 pub fn sqlite3_bind_parameter_index(pStmt: *mut sqlite3_stmt, name: *const c_char) -> c_int;
177 pub fn sqlite3_bind_parameter_name(pStmt: *mut sqlite3_stmt, index: c_int) -> *const c_char;
178
179 pub fn sqlite3_step(pStmt: *mut sqlite3_stmt) -> c_int;
181
182 pub fn sqlite3_column_count(pStmt: *mut sqlite3_stmt) -> c_int;
184 pub fn sqlite3_column_name(pStmt: *mut sqlite3_stmt, index: c_int) -> *const c_char;
185 pub fn sqlite3_column_type(pStmt: *mut sqlite3_stmt, index: c_int) -> c_int;
186 pub fn sqlite3_column_decltype(pStmt: *mut sqlite3_stmt, index: c_int) -> *const c_char;
187
188 pub fn sqlite3_column_int(pStmt: *mut sqlite3_stmt, index: c_int) -> c_int;
190 pub fn sqlite3_column_int64(pStmt: *mut sqlite3_stmt, index: c_int) -> i64;
191 pub fn sqlite3_column_double(pStmt: *mut sqlite3_stmt, index: c_int) -> c_double;
192 pub fn sqlite3_column_text(pStmt: *mut sqlite3_stmt, index: c_int) -> *const c_char;
193 pub fn sqlite3_column_blob(pStmt: *mut sqlite3_stmt, index: c_int) -> *const c_void;
194 pub fn sqlite3_column_bytes(pStmt: *mut sqlite3_stmt, index: c_int) -> c_int;
195
196 pub fn sqlite3_exec(
198 db: *mut sqlite3,
199 sql: *const c_char,
200 callback: Option<
201 unsafe extern "C" fn(*mut c_void, c_int, *mut *mut c_char, *mut *mut c_char) -> c_int,
202 >,
203 arg: *mut c_void,
204 errmsg: *mut *mut c_char,
205 ) -> c_int;
206
207 pub fn sqlite3_free(ptr: *mut c_void);
208
209 pub fn sqlite3_changes(db: *mut sqlite3) -> c_int;
211 pub fn sqlite3_total_changes(db: *mut sqlite3) -> c_int;
212 pub fn sqlite3_last_insert_rowid(db: *mut sqlite3) -> i64;
213
214 pub fn sqlite3_busy_timeout(db: *mut sqlite3, ms: c_int) -> c_int;
216
217 pub fn sqlite3_libversion() -> *const c_char;
219 pub fn sqlite3_libversion_number() -> c_int;
220}
221
222pub fn version() -> &'static str {
224 unsafe {
226 let ptr = sqlite3_libversion();
227 std::ffi::CStr::from_ptr(ptr).to_str().unwrap_or("unknown")
228 }
229}
230
231pub fn version_number() -> i32 {
233 unsafe { sqlite3_libversion_number() }
235}
236
237pub fn error_string(code: c_int) -> &'static str {
239 unsafe {
241 let ptr = sqlite3_errstr(code);
242 std::ffi::CStr::from_ptr(ptr)
243 .to_str()
244 .unwrap_or("unknown error")
245 }
246}
247
248#[cfg(test)]
249mod tests {
250 use super::*;
251
252 #[test]
253 fn test_version() {
254 let v = version();
255 assert!(!v.is_empty());
256 assert!(v.starts_with('3'));
258 }
259
260 #[test]
261 fn test_version_number() {
262 let v = version_number();
263 assert!(v >= 3_000_000);
266 }
267
268 #[test]
269 fn test_error_string() {
270 assert_eq!(error_string(SQLITE_OK), "not an error");
271 assert_eq!(error_string(SQLITE_ERROR), "SQL logic error");
272 assert_eq!(error_string(SQLITE_BUSY), "database is locked");
273 assert_eq!(error_string(SQLITE_CONSTRAINT), "constraint failed");
274 }
275
276 #[test]
277 fn test_result_codes() {
278 assert_eq!(SQLITE_OK, 0);
280 assert_eq!(SQLITE_ROW, 100);
281 assert_eq!(SQLITE_DONE, 101);
282 }
283}