1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
#![allow(non_camel_case_types)] #[cfg(test)] extern crate temporary; extern crate libc; use libc::{c_char, c_double, c_int, c_longlong, c_ulonglong, c_void}; #[repr(C)] pub struct sqlite3; #[repr(C)] pub struct sqlite3_stmt; pub type sqlite_int64 = c_longlong; pub type sqlite_uint64 = c_ulonglong; pub type sqlite3_int64 = sqlite_int64; pub type sqlite3_uint64 = sqlite_uint64; pub const SQLITE_OK: c_int = 0; pub const SQLITE_ERROR: c_int = 1; pub const SQLITE_INTERNAL: c_int = 2; pub const SQLITE_PERM: c_int = 3; pub const SQLITE_ABORT: c_int = 4; pub const SQLITE_BUSY: c_int = 5; pub const SQLITE_LOCKED: c_int = 6; pub const SQLITE_NOMEM: c_int = 7; pub const SQLITE_READONLY: c_int = 8; pub const SQLITE_INTERRUPT: c_int = 9; pub const SQLITE_IOERR: c_int = 10; pub const SQLITE_CORRUPT: c_int = 11; pub const SQLITE_NOTFOUND: c_int = 12; pub const SQLITE_FULL: c_int = 13; pub const SQLITE_CANTOPEN: c_int = 14; pub const SQLITE_PROTOCOL: c_int = 15; pub const SQLITE_EMPTY: c_int = 16; pub const SQLITE_SCHEMA: c_int = 17; pub const SQLITE_TOOBIG: c_int = 18; pub const SQLITE_CONSTRAINT: c_int = 19; pub const SQLITE_MISMATCH: c_int = 20; pub const SQLITE_MISUSE: c_int = 21; pub const SQLITE_NOLFS: c_int = 22; pub const SQLITE_AUTH: c_int = 23; pub const SQLITE_FORMAT: c_int = 24; pub const SQLITE_RANGE: c_int = 25; pub const SQLITE_NOTADB: c_int = 26; pub const SQLITE_NOTICE: c_int = 27; pub const SQLITE_WARNING: c_int = 28; pub const SQLITE_ROW: c_int = 100; pub const SQLITE_DONE: c_int = 101; pub type sqlite3_exec_callback = extern fn(*mut c_void, c_int, *mut *mut c_char, *mut *mut c_char) -> c_int; pub type sqlite3_bind_callback = extern fn(*mut c_void); extern "C" { pub fn sqlite3_bind_double(stmt: *mut sqlite3_stmt, i: c_int, value: c_double) -> c_int; pub fn sqlite3_bind_int(stmt: *mut sqlite3_stmt, i: c_int, value: c_int) -> c_int; pub fn sqlite3_bind_int64(stmt: *mut sqlite3_stmt, i: c_int, value: sqlite3_int64) -> c_int; pub fn sqlite3_bind_text(stmt: *mut sqlite3_stmt, i: c_int, data: *const c_char, n: c_int, del: Option<sqlite3_bind_callback>) -> c_int; pub fn sqlite3_close(db: *mut sqlite3) -> c_int; pub fn sqlite3_errmsg(db: *mut sqlite3) -> *const c_char; pub fn sqlite3_exec(db: *mut sqlite3, sql: *const c_char, callback: Option<sqlite3_exec_callback>, arg: *mut c_void, errmsg: *mut *mut c_char) -> c_int; pub fn sqlite3_finalize(stmt: *mut sqlite3_stmt) -> c_int; pub fn sqlite3_free(p: *mut c_void); pub fn sqlite3_malloc(n: c_int) -> *mut c_void; pub fn sqlite3_open(filename: *const c_char, db: *mut *mut sqlite3) -> c_int; pub fn sqlite3_prepare(db: *mut sqlite3, sql: *const c_char, n: c_int, stmt: *mut *mut sqlite3_stmt, tail: *mut *const c_char) -> c_int; pub fn sqlite3_reset(stmt: *mut sqlite3_stmt) -> c_int; pub fn sqlite3_step(stmt: *mut sqlite3_stmt) -> c_int; } #[cfg(test)] mod tests { use std::ffi::CString; use temporary::Directory; macro_rules! ok( ($result:expr) => ($result.unwrap()); ); macro_rules! success( ($result:expr) => (assert!($result == ::SQLITE_OK)); ); macro_rules! c_str( ($string:expr) => (ok!(CString::new($string))); ); #[test] fn workflow() { open(|database| unsafe { success!(::sqlite3_exec(database, c_str!( "CREATE TABLE `users` (id INTEGER, name VARCHAR(255), age REAL);" ).as_ptr(), None, 0 as *mut _, 0 as *mut _)); let mut statement = 0 as *mut _; let mut tail = 0 as *const _; success!(::sqlite3_prepare(database, c_str!( "INSERT INTO `users` (id, name, age) VALUES (?, ?, ?);" ).as_ptr(), -1, &mut statement, &mut tail)); let name = c_str!("Alice"); success!(::sqlite3_bind_int(statement, 1, 1)); success!(::sqlite3_bind_text(statement, 2, name.as_ptr(), -1, None)); assert!(::sqlite3_step(statement) == ::SQLITE_DONE); success!(::sqlite3_finalize(statement)); }); } fn open<F>(mut code: F) where F: FnMut(*mut ::sqlite3) { let (path, _directory) = setup(); let mut database = 0 as *mut _; unsafe { success!(::sqlite3_open(path.as_ptr(), &mut database)); code(database); success!(::sqlite3_close(database)); } } fn setup() -> (CString, Directory) { let directory = ok!(Directory::new("sqlite-sys")); let path = directory.path().join("database.sqlite3"); let path = c_str!(ok!(path.to_str())); (path, directory) } }