mirror of
https://github.com/isar/rusqlite.git
synced 2024-11-23 00:39:20 +08:00
Merge pull request #684 from thomcc/internal-unsafe
Clean up internal unsafe code
This commit is contained in:
commit
cf3cdecf12
@ -77,8 +77,8 @@ impl Connection {
|
|||||||
|
|
||||||
match r {
|
match r {
|
||||||
Done => Ok(()),
|
Done => Ok(()),
|
||||||
Busy => Err(error_from_handle(ptr::null_mut(), ffi::SQLITE_BUSY)),
|
Busy => Err(unsafe { error_from_handle(ptr::null_mut(), ffi::SQLITE_BUSY) }),
|
||||||
Locked => Err(error_from_handle(ptr::null_mut(), ffi::SQLITE_LOCKED)),
|
Locked => Err(unsafe { error_from_handle(ptr::null_mut(), ffi::SQLITE_LOCKED) }),
|
||||||
More => unreachable!(),
|
More => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -123,8 +123,8 @@ impl Connection {
|
|||||||
|
|
||||||
match r {
|
match r {
|
||||||
Done => Ok(()),
|
Done => Ok(()),
|
||||||
Busy => Err(error_from_handle(ptr::null_mut(), ffi::SQLITE_BUSY)),
|
Busy => Err(unsafe { error_from_handle(ptr::null_mut(), ffi::SQLITE_BUSY) }),
|
||||||
Locked => Err(error_from_handle(ptr::null_mut(), ffi::SQLITE_LOCKED)),
|
Locked => Err(unsafe { error_from_handle(ptr::null_mut(), ffi::SQLITE_LOCKED) }),
|
||||||
More => unreachable!(),
|
More => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -357,11 +357,11 @@ pub fn error_from_sqlite_code(code: c_int, message: Option<String>) -> Error {
|
|||||||
Error::SqliteFailure(ffi::Error::new(code), message)
|
Error::SqliteFailure(ffi::Error::new(code), message)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn error_from_handle(db: *mut ffi::sqlite3, code: c_int) -> Error {
|
pub unsafe fn error_from_handle(db: *mut ffi::sqlite3, code: c_int) -> Error {
|
||||||
let message = if db.is_null() {
|
let message = if db.is_null() {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
Some(unsafe { errmsg_to_string(ffi::sqlite3_errmsg(db)) })
|
Some(errmsg_to_string(ffi::sqlite3_errmsg(db)))
|
||||||
};
|
};
|
||||||
error_from_sqlite_code(code, message)
|
error_from_sqlite_code(code, message)
|
||||||
}
|
}
|
||||||
|
16
src/hooks.rs
16
src/hooks.rs
@ -102,7 +102,7 @@ impl InnerConnection {
|
|||||||
// `sqlite3_commit_hook`. so we keep the `xDestroy` function in
|
// `sqlite3_commit_hook`. so we keep the `xDestroy` function in
|
||||||
// `InnerConnection.free_boxed_hook`.
|
// `InnerConnection.free_boxed_hook`.
|
||||||
let free_commit_hook = if hook.is_some() {
|
let free_commit_hook = if hook.is_some() {
|
||||||
Some(free_boxed_hook::<F> as fn(*mut c_void))
|
Some(free_boxed_hook::<F> as unsafe fn(*mut c_void))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
@ -122,7 +122,7 @@ impl InnerConnection {
|
|||||||
};
|
};
|
||||||
if !previous_hook.is_null() {
|
if !previous_hook.is_null() {
|
||||||
if let Some(free_boxed_hook) = self.free_commit_hook {
|
if let Some(free_boxed_hook) = self.free_commit_hook {
|
||||||
free_boxed_hook(previous_hook);
|
unsafe { free_boxed_hook(previous_hook) };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.free_commit_hook = free_commit_hook;
|
self.free_commit_hook = free_commit_hook;
|
||||||
@ -143,7 +143,7 @@ impl InnerConnection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let free_rollback_hook = if hook.is_some() {
|
let free_rollback_hook = if hook.is_some() {
|
||||||
Some(free_boxed_hook::<F> as fn(*mut c_void))
|
Some(free_boxed_hook::<F> as unsafe fn(*mut c_void))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
@ -163,7 +163,7 @@ impl InnerConnection {
|
|||||||
};
|
};
|
||||||
if !previous_hook.is_null() {
|
if !previous_hook.is_null() {
|
||||||
if let Some(free_boxed_hook) = self.free_rollback_hook {
|
if let Some(free_boxed_hook) = self.free_rollback_hook {
|
||||||
free_boxed_hook(previous_hook);
|
unsafe { free_boxed_hook(previous_hook) };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.free_rollback_hook = free_rollback_hook;
|
self.free_rollback_hook = free_rollback_hook;
|
||||||
@ -202,7 +202,7 @@ impl InnerConnection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let free_update_hook = if hook.is_some() {
|
let free_update_hook = if hook.is_some() {
|
||||||
Some(free_boxed_hook::<F> as fn(*mut c_void))
|
Some(free_boxed_hook::<F> as unsafe fn(*mut c_void))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
@ -222,15 +222,15 @@ impl InnerConnection {
|
|||||||
};
|
};
|
||||||
if !previous_hook.is_null() {
|
if !previous_hook.is_null() {
|
||||||
if let Some(free_boxed_hook) = self.free_update_hook {
|
if let Some(free_boxed_hook) = self.free_update_hook {
|
||||||
free_boxed_hook(previous_hook);
|
unsafe { free_boxed_hook(previous_hook) };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.free_update_hook = free_update_hook;
|
self.free_update_hook = free_update_hook;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn free_boxed_hook<F>(p: *mut c_void) {
|
unsafe fn free_boxed_hook<F>(p: *mut c_void) {
|
||||||
drop(unsafe { Box::from_raw(p as *mut F) });
|
drop(Box::from_raw(p as *mut F));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
use std::ffi::CString;
|
use std::ffi::CString;
|
||||||
use std::mem::MaybeUninit;
|
|
||||||
use std::os::raw::{c_char, c_int};
|
use std::os::raw::{c_char, c_int};
|
||||||
#[cfg(feature = "load_extension")]
|
#[cfg(feature = "load_extension")]
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
@ -27,17 +26,17 @@ pub struct InnerConnection {
|
|||||||
// interrupt would only acquire the lock after the query's completion.
|
// interrupt would only acquire the lock after the query's completion.
|
||||||
interrupt_lock: Arc<Mutex<*mut ffi::sqlite3>>,
|
interrupt_lock: Arc<Mutex<*mut ffi::sqlite3>>,
|
||||||
#[cfg(feature = "hooks")]
|
#[cfg(feature = "hooks")]
|
||||||
pub free_commit_hook: Option<fn(*mut ::std::os::raw::c_void)>,
|
pub free_commit_hook: Option<unsafe fn(*mut ::std::os::raw::c_void)>,
|
||||||
#[cfg(feature = "hooks")]
|
#[cfg(feature = "hooks")]
|
||||||
pub free_rollback_hook: Option<fn(*mut ::std::os::raw::c_void)>,
|
pub free_rollback_hook: Option<unsafe fn(*mut ::std::os::raw::c_void)>,
|
||||||
#[cfg(feature = "hooks")]
|
#[cfg(feature = "hooks")]
|
||||||
pub free_update_hook: Option<fn(*mut ::std::os::raw::c_void)>,
|
pub free_update_hook: Option<unsafe fn(*mut ::std::os::raw::c_void)>,
|
||||||
owned: bool,
|
owned: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl InnerConnection {
|
impl InnerConnection {
|
||||||
#[allow(clippy::mutex_atomic)]
|
#[allow(clippy::mutex_atomic)]
|
||||||
pub fn new(db: *mut ffi::sqlite3, owned: bool) -> InnerConnection {
|
pub unsafe fn new(db: *mut ffi::sqlite3, owned: bool) -> InnerConnection {
|
||||||
InnerConnection {
|
InnerConnection {
|
||||||
db,
|
db,
|
||||||
interrupt_lock: Arc::new(Mutex::new(db)),
|
interrupt_lock: Arc::new(Mutex::new(db)),
|
||||||
@ -81,9 +80,8 @@ impl InnerConnection {
|
|||||||
};
|
};
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let mut db = MaybeUninit::uninit();
|
let mut db: *mut ffi::sqlite3 = ptr::null_mut();
|
||||||
let r = ffi::sqlite3_open_v2(c_path.as_ptr(), db.as_mut_ptr(), flags.bits(), z_vfs);
|
let r = ffi::sqlite3_open_v2(c_path.as_ptr(), &mut db, flags.bits(), z_vfs);
|
||||||
let db: *mut ffi::sqlite3 = db.assume_init();
|
|
||||||
if r != ffi::SQLITE_OK {
|
if r != ffi::SQLITE_OK {
|
||||||
let e = if db.is_null() {
|
let e = if db.is_null() {
|
||||||
error_from_sqlite_code(r, Some(c_path.to_string_lossy().to_string()))
|
error_from_sqlite_code(r, Some(c_path.to_string_lossy().to_string()))
|
||||||
@ -127,10 +125,10 @@ impl InnerConnection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn decode_result(&mut self, code: c_int) -> Result<()> {
|
pub fn decode_result(&mut self, code: c_int) -> Result<()> {
|
||||||
InnerConnection::decode_result_raw(self.db(), code)
|
unsafe { InnerConnection::decode_result_raw(self.db(), code) }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn decode_result_raw(db: *mut ffi::sqlite3, code: c_int) -> Result<()> {
|
unsafe fn decode_result_raw(db: *mut ffi::sqlite3, code: c_int) -> Result<()> {
|
||||||
if code == ffi::SQLITE_OK {
|
if code == ffi::SQLITE_OK {
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
@ -196,28 +194,22 @@ impl InnerConnection {
|
|||||||
pub fn load_extension(&self, dylib_path: &Path, entry_point: Option<&str>) -> Result<()> {
|
pub fn load_extension(&self, dylib_path: &Path, entry_point: Option<&str>) -> Result<()> {
|
||||||
let dylib_str = super::path_to_cstring(dylib_path)?;
|
let dylib_str = super::path_to_cstring(dylib_path)?;
|
||||||
unsafe {
|
unsafe {
|
||||||
let mut errmsg = MaybeUninit::uninit();
|
let mut errmsg: *mut c_char = ptr::null_mut();
|
||||||
let r = if let Some(entry_point) = entry_point {
|
let r = if let Some(entry_point) = entry_point {
|
||||||
let c_entry = str_to_cstring(entry_point)?;
|
let c_entry = str_to_cstring(entry_point)?;
|
||||||
ffi::sqlite3_load_extension(
|
ffi::sqlite3_load_extension(
|
||||||
self.db,
|
self.db,
|
||||||
dylib_str.as_ptr(),
|
dylib_str.as_ptr(),
|
||||||
c_entry.as_ptr(),
|
c_entry.as_ptr(),
|
||||||
errmsg.as_mut_ptr(),
|
&mut errmsg,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
ffi::sqlite3_load_extension(
|
ffi::sqlite3_load_extension(self.db, dylib_str.as_ptr(), ptr::null(), &mut errmsg)
|
||||||
self.db,
|
|
||||||
dylib_str.as_ptr(),
|
|
||||||
ptr::null(),
|
|
||||||
errmsg.as_mut_ptr(),
|
|
||||||
)
|
|
||||||
};
|
};
|
||||||
if r == ffi::SQLITE_OK {
|
if r == ffi::SQLITE_OK {
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
let errmsg: *mut c_char = errmsg.assume_init();
|
let message = super::errmsg_to_string(errmsg);
|
||||||
let message = super::errmsg_to_string(&*errmsg);
|
|
||||||
ffi::sqlite3_free(errmsg as *mut ::std::os::raw::c_void);
|
ffi::sqlite3_free(errmsg as *mut ::std::os::raw::c_void);
|
||||||
Err(error_from_sqlite_code(r, Some(message)))
|
Err(error_from_sqlite_code(r, Some(message)))
|
||||||
}
|
}
|
||||||
@ -229,9 +221,9 @@ impl InnerConnection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn prepare<'a>(&mut self, conn: &'a Connection, sql: &str) -> Result<Statement<'a>> {
|
pub fn prepare<'a>(&mut self, conn: &'a Connection, sql: &str) -> Result<Statement<'a>> {
|
||||||
let mut c_stmt = MaybeUninit::uninit();
|
let mut c_stmt = ptr::null_mut();
|
||||||
let (c_sql, len, _) = str_for_sqlite(sql.as_bytes())?;
|
let (c_sql, len, _) = str_for_sqlite(sql.as_bytes())?;
|
||||||
let mut c_tail = MaybeUninit::uninit();
|
let mut c_tail = ptr::null();
|
||||||
let r = unsafe {
|
let r = unsafe {
|
||||||
if cfg!(feature = "unlock_notify") {
|
if cfg!(feature = "unlock_notify") {
|
||||||
let mut rc;
|
let mut rc;
|
||||||
@ -240,8 +232,8 @@ impl InnerConnection {
|
|||||||
self.db(),
|
self.db(),
|
||||||
c_sql,
|
c_sql,
|
||||||
len,
|
len,
|
||||||
c_stmt.as_mut_ptr(),
|
&mut c_stmt as *mut *mut ffi::sqlite3_stmt,
|
||||||
c_tail.as_mut_ptr(),
|
&mut c_tail as *mut *const c_char,
|
||||||
);
|
);
|
||||||
if !unlock_notify::is_locked(self.db, rc) {
|
if !unlock_notify::is_locked(self.db, rc) {
|
||||||
break;
|
break;
|
||||||
@ -257,8 +249,8 @@ impl InnerConnection {
|
|||||||
self.db(),
|
self.db(),
|
||||||
c_sql,
|
c_sql,
|
||||||
len,
|
len,
|
||||||
c_stmt.as_mut_ptr(),
|
&mut c_stmt as *mut *mut ffi::sqlite3_stmt,
|
||||||
c_tail.as_mut_ptr(),
|
&mut c_tail as *mut *const c_char,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -266,11 +258,13 @@ impl InnerConnection {
|
|||||||
self.decode_result(r)?;
|
self.decode_result(r)?;
|
||||||
// If the input text contains no SQL (if the input is an empty string or a
|
// If the input text contains no SQL (if the input is an empty string or a
|
||||||
// comment) then *ppStmt is set to NULL.
|
// comment) then *ppStmt is set to NULL.
|
||||||
let c_stmt: *mut ffi::sqlite3_stmt = unsafe { c_stmt.assume_init() };
|
let c_stmt: *mut ffi::sqlite3_stmt = c_stmt;
|
||||||
let c_tail: *const c_char = unsafe { c_tail.assume_init() };
|
let c_tail: *const c_char = c_tail;
|
||||||
// TODO ignore spaces, comments, ... at the end
|
// TODO ignore spaces, comments, ... at the end
|
||||||
let tail = !c_tail.is_null() && unsafe { c_tail != c_sql.offset(len as isize) };
|
let tail = !c_tail.is_null() && unsafe { c_tail != c_sql.offset(len as isize) };
|
||||||
Ok(Statement::new(conn, RawStatement::new(c_stmt, tail)))
|
Ok(Statement::new(conn, unsafe {
|
||||||
|
RawStatement::new(c_stmt, tail)
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn changes(&mut self) -> usize {
|
pub fn changes(&mut self) -> usize {
|
||||||
|
@ -1028,25 +1028,23 @@ mod test {
|
|||||||
// statement first.
|
// statement first.
|
||||||
let raw_stmt = {
|
let raw_stmt = {
|
||||||
use super::str_to_cstring;
|
use super::str_to_cstring;
|
||||||
use std::mem::MaybeUninit;
|
|
||||||
use std::os::raw::c_int;
|
use std::os::raw::c_int;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
|
|
||||||
let raw_db = db.db.borrow_mut().db;
|
let raw_db = db.db.borrow_mut().db;
|
||||||
let sql = "SELECT 1";
|
let sql = "SELECT 1";
|
||||||
let mut raw_stmt = MaybeUninit::uninit();
|
let mut raw_stmt: *mut ffi::sqlite3_stmt = ptr::null_mut();
|
||||||
let cstring = str_to_cstring(sql).unwrap();
|
let cstring = str_to_cstring(sql).unwrap();
|
||||||
let rc = unsafe {
|
let rc = unsafe {
|
||||||
ffi::sqlite3_prepare_v2(
|
ffi::sqlite3_prepare_v2(
|
||||||
raw_db,
|
raw_db,
|
||||||
cstring.as_ptr(),
|
cstring.as_ptr(),
|
||||||
(sql.len() + 1) as c_int,
|
(sql.len() + 1) as c_int,
|
||||||
raw_stmt.as_mut_ptr(),
|
&mut raw_stmt,
|
||||||
ptr::null_mut(),
|
ptr::null_mut(),
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
assert_eq!(rc, ffi::SQLITE_OK);
|
assert_eq!(rc, ffi::SQLITE_OK);
|
||||||
let raw_stmt: *mut ffi::sqlite3_stmt = unsafe { raw_stmt.assume_init() };
|
|
||||||
raw_stmt
|
raw_stmt
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@ use std::ptr;
|
|||||||
pub struct RawStatement(*mut ffi::sqlite3_stmt, bool);
|
pub struct RawStatement(*mut ffi::sqlite3_stmt, bool);
|
||||||
|
|
||||||
impl RawStatement {
|
impl RawStatement {
|
||||||
pub fn new(stmt: *mut ffi::sqlite3_stmt, tail: bool) -> RawStatement {
|
pub unsafe fn new(stmt: *mut ffi::sqlite3_stmt, tail: bool) -> RawStatement {
|
||||||
RawStatement(stmt, tail)
|
RawStatement(stmt, tail)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -64,10 +64,10 @@ impl RawStatement {
|
|||||||
let mut rc;
|
let mut rc;
|
||||||
loop {
|
loop {
|
||||||
rc = unsafe { ffi::sqlite3_step(self.0) };
|
rc = unsafe { ffi::sqlite3_step(self.0) };
|
||||||
if !unlock_notify::is_locked(db, rc) {
|
if unsafe { !unlock_notify::is_locked(db, rc) } {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
rc = unlock_notify::wait_for_unlock_notify(db);
|
rc = unsafe { unlock_notify::wait_for_unlock_notify(db) };
|
||||||
if rc != ffi::SQLITE_OK {
|
if rc != ffi::SQLITE_OK {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,6 @@
|
|||||||
use std::ffi::CStr;
|
use std::ffi::CStr;
|
||||||
use std::io::{Read, Write};
|
use std::io::{Read, Write};
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
use std::mem::MaybeUninit;
|
|
||||||
use std::os::raw::{c_char, c_int, c_uchar, c_void};
|
use std::os::raw::{c_char, c_int, c_uchar, c_void};
|
||||||
use std::panic::{catch_unwind, RefUnwindSafe};
|
use std::panic::{catch_unwind, RefUnwindSafe};
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
@ -43,9 +42,8 @@ impl Session<'_> {
|
|||||||
|
|
||||||
let db = db.db.borrow_mut().db;
|
let db = db.db.borrow_mut().db;
|
||||||
|
|
||||||
let mut s = MaybeUninit::uninit();
|
let mut s: *mut ffi::sqlite3_session = ptr::null_mut();
|
||||||
check!(unsafe { ffi::sqlite3session_create(db, name.as_ptr(), s.as_mut_ptr()) });
|
check!(unsafe { ffi::sqlite3session_create(db, name.as_ptr(), &mut s) });
|
||||||
let s: *mut ffi::sqlite3_session = unsafe { s.assume_init() };
|
|
||||||
|
|
||||||
Ok(Session {
|
Ok(Session {
|
||||||
phantom: PhantomData,
|
phantom: PhantomData,
|
||||||
@ -113,9 +111,8 @@ impl Session<'_> {
|
|||||||
/// Generate a Changeset
|
/// Generate a Changeset
|
||||||
pub fn changeset(&mut self) -> Result<Changeset> {
|
pub fn changeset(&mut self) -> Result<Changeset> {
|
||||||
let mut n = 0;
|
let mut n = 0;
|
||||||
let mut cs = MaybeUninit::uninit();
|
let mut cs: *mut c_void = ptr::null_mut();
|
||||||
check!(unsafe { ffi::sqlite3session_changeset(self.s, &mut n, cs.as_mut_ptr()) });
|
check!(unsafe { ffi::sqlite3session_changeset(self.s, &mut n, &mut cs) });
|
||||||
let cs: *mut c_void = unsafe { cs.assume_init() };
|
|
||||||
Ok(Changeset { cs, n })
|
Ok(Changeset { cs, n })
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -135,9 +132,8 @@ impl Session<'_> {
|
|||||||
/// Generate a Patchset
|
/// Generate a Patchset
|
||||||
pub fn patchset(&mut self) -> Result<Changeset> {
|
pub fn patchset(&mut self) -> Result<Changeset> {
|
||||||
let mut n = 0;
|
let mut n = 0;
|
||||||
let mut ps = MaybeUninit::uninit();
|
let mut ps: *mut c_void = ptr::null_mut();
|
||||||
check!(unsafe { ffi::sqlite3session_patchset(self.s, &mut n, ps.as_mut_ptr()) });
|
check!(unsafe { ffi::sqlite3session_patchset(self.s, &mut n, &mut ps) });
|
||||||
let ps: *mut c_void = unsafe { ps.assume_init() };
|
|
||||||
// TODO Validate: same struct
|
// TODO Validate: same struct
|
||||||
Ok(Changeset { cs: ps, n })
|
Ok(Changeset { cs: ps, n })
|
||||||
}
|
}
|
||||||
@ -160,10 +156,11 @@ impl Session<'_> {
|
|||||||
let from = from.to_cstring()?;
|
let from = from.to_cstring()?;
|
||||||
let table = str_to_cstring(table)?.as_ptr();
|
let table = str_to_cstring(table)?.as_ptr();
|
||||||
unsafe {
|
unsafe {
|
||||||
let mut errmsg = MaybeUninit::uninit();
|
let mut errmsg = ptr::null_mut();
|
||||||
let r = ffi::sqlite3session_diff(self.s, from.as_ptr(), table, errmsg.as_mut_ptr());
|
let r =
|
||||||
|
ffi::sqlite3session_diff(self.s, from.as_ptr(), table, &mut errmsg as *mut *mut _);
|
||||||
if r != ffi::SQLITE_OK {
|
if r != ffi::SQLITE_OK {
|
||||||
let errmsg: *mut c_char = errmsg.assume_init();
|
let errmsg: *mut c_char = errmsg;
|
||||||
let message = errmsg_to_string(&*errmsg);
|
let message = errmsg_to_string(&*errmsg);
|
||||||
ffi::sqlite3_free(errmsg as *mut ::std::os::raw::c_void);
|
ffi::sqlite3_free(errmsg as *mut ::std::os::raw::c_void);
|
||||||
return Err(error_from_sqlite_code(r, Some(message)));
|
return Err(error_from_sqlite_code(r, Some(message)));
|
||||||
@ -258,17 +255,17 @@ impl Changeset {
|
|||||||
/// Invert a changeset
|
/// Invert a changeset
|
||||||
pub fn invert(&self) -> Result<Changeset> {
|
pub fn invert(&self) -> Result<Changeset> {
|
||||||
let mut n = 0;
|
let mut n = 0;
|
||||||
let mut cs = MaybeUninit::uninit();
|
let mut cs = ptr::null_mut();
|
||||||
check!(unsafe { ffi::sqlite3changeset_invert(self.n, self.cs, &mut n, cs.as_mut_ptr()) });
|
check!(unsafe {
|
||||||
let cs: *mut c_void = unsafe { cs.assume_init() };
|
ffi::sqlite3changeset_invert(self.n, self.cs, &mut n, &mut cs as *mut *mut _)
|
||||||
|
});
|
||||||
Ok(Changeset { cs, n })
|
Ok(Changeset { cs, n })
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create an iterator to traverse a changeset
|
/// Create an iterator to traverse a changeset
|
||||||
pub fn iter(&self) -> Result<ChangesetIter<'_>> {
|
pub fn iter(&self) -> Result<ChangesetIter<'_>> {
|
||||||
let mut it = MaybeUninit::uninit();
|
let mut it = ptr::null_mut();
|
||||||
check!(unsafe { ffi::sqlite3changeset_start(it.as_mut_ptr(), self.n, self.cs) });
|
check!(unsafe { ffi::sqlite3changeset_start(&mut it as *mut *mut _, self.n, self.cs) });
|
||||||
let it: *mut ffi::sqlite3_changeset_iter = unsafe { it.assume_init() };
|
|
||||||
Ok(ChangesetIter {
|
Ok(ChangesetIter {
|
||||||
phantom: PhantomData,
|
phantom: PhantomData,
|
||||||
it,
|
it,
|
||||||
@ -279,11 +276,10 @@ impl Changeset {
|
|||||||
/// Concatenate two changeset objects
|
/// Concatenate two changeset objects
|
||||||
pub fn concat(a: &Changeset, b: &Changeset) -> Result<Changeset> {
|
pub fn concat(a: &Changeset, b: &Changeset) -> Result<Changeset> {
|
||||||
let mut n = 0;
|
let mut n = 0;
|
||||||
let mut cs = MaybeUninit::uninit();
|
let mut cs = ptr::null_mut();
|
||||||
check!(unsafe {
|
check!(unsafe {
|
||||||
ffi::sqlite3changeset_concat(a.n, a.cs, b.n, b.cs, &mut n, cs.as_mut_ptr())
|
ffi::sqlite3changeset_concat(a.n, a.cs, b.n, b.cs, &mut n, &mut cs as *mut *mut _)
|
||||||
});
|
});
|
||||||
let cs: *mut c_void = unsafe { cs.assume_init() };
|
|
||||||
Ok(Changeset { cs, n })
|
Ok(Changeset { cs, n })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -307,15 +303,14 @@ pub struct ChangesetIter<'changeset> {
|
|||||||
impl ChangesetIter<'_> {
|
impl ChangesetIter<'_> {
|
||||||
/// Create an iterator on `input`
|
/// Create an iterator on `input`
|
||||||
pub fn start_strm<'input>(input: &&'input mut dyn Read) -> Result<ChangesetIter<'input>> {
|
pub fn start_strm<'input>(input: &&'input mut dyn Read) -> Result<ChangesetIter<'input>> {
|
||||||
let mut it = MaybeUninit::uninit();
|
let mut it = ptr::null_mut();
|
||||||
check!(unsafe {
|
check!(unsafe {
|
||||||
ffi::sqlite3changeset_start_strm(
|
ffi::sqlite3changeset_start_strm(
|
||||||
it.as_mut_ptr(),
|
&mut it as *mut *mut _,
|
||||||
Some(x_input),
|
Some(x_input),
|
||||||
input as *const &mut dyn Read as *mut c_void,
|
input as *const &mut dyn Read as *mut c_void,
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
let it: *mut ffi::sqlite3_changeset_iter = unsafe { it.assume_init() };
|
|
||||||
Ok(ChangesetIter {
|
Ok(ChangesetIter {
|
||||||
phantom: PhantomData,
|
phantom: PhantomData,
|
||||||
it,
|
it,
|
||||||
@ -396,13 +391,12 @@ impl ChangesetItem {
|
|||||||
/// `SQLITE_CHANGESET_CONFLICT` conflict handler callback.
|
/// `SQLITE_CHANGESET_CONFLICT` conflict handler callback.
|
||||||
pub fn conflict(&self, col: usize) -> Result<ValueRef<'_>> {
|
pub fn conflict(&self, col: usize) -> Result<ValueRef<'_>> {
|
||||||
unsafe {
|
unsafe {
|
||||||
let mut p_value = MaybeUninit::uninit();
|
let mut p_value: *mut ffi::sqlite3_value = ptr::null_mut();
|
||||||
check!(ffi::sqlite3changeset_conflict(
|
check!(ffi::sqlite3changeset_conflict(
|
||||||
self.it,
|
self.it,
|
||||||
col as i32,
|
col as i32,
|
||||||
p_value.as_mut_ptr()
|
&mut p_value,
|
||||||
));
|
));
|
||||||
let p_value: *mut ffi::sqlite3_value = p_value.assume_init();
|
|
||||||
Ok(ValueRef::from_value(p_value))
|
Ok(ValueRef::from_value(p_value))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -425,13 +419,8 @@ impl ChangesetItem {
|
|||||||
/// `SQLITE_INSERT`.
|
/// `SQLITE_INSERT`.
|
||||||
pub fn new_value(&self, col: usize) -> Result<ValueRef<'_>> {
|
pub fn new_value(&self, col: usize) -> Result<ValueRef<'_>> {
|
||||||
unsafe {
|
unsafe {
|
||||||
let mut p_value = MaybeUninit::uninit();
|
let mut p_value: *mut ffi::sqlite3_value = ptr::null_mut();
|
||||||
check!(ffi::sqlite3changeset_new(
|
check!(ffi::sqlite3changeset_new(self.it, col as i32, &mut p_value,));
|
||||||
self.it,
|
|
||||||
col as i32,
|
|
||||||
p_value.as_mut_ptr()
|
|
||||||
));
|
|
||||||
let p_value: *mut ffi::sqlite3_value = p_value.assume_init();
|
|
||||||
Ok(ValueRef::from_value(p_value))
|
Ok(ValueRef::from_value(p_value))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -442,13 +431,8 @@ impl ChangesetItem {
|
|||||||
/// `SQLITE_UPDATE`.
|
/// `SQLITE_UPDATE`.
|
||||||
pub fn old_value(&self, col: usize) -> Result<ValueRef<'_>> {
|
pub fn old_value(&self, col: usize) -> Result<ValueRef<'_>> {
|
||||||
unsafe {
|
unsafe {
|
||||||
let mut p_value = MaybeUninit::uninit();
|
let mut p_value: *mut ffi::sqlite3_value = ptr::null_mut();
|
||||||
check!(ffi::sqlite3changeset_old(
|
check!(ffi::sqlite3changeset_old(self.it, col as i32, &mut p_value,));
|
||||||
self.it,
|
|
||||||
col as i32,
|
|
||||||
p_value.as_mut_ptr()
|
|
||||||
));
|
|
||||||
let p_value: *mut ffi::sqlite3_value = p_value.assume_init();
|
|
||||||
Ok(ValueRef::from_value(p_value))
|
Ok(ValueRef::from_value(p_value))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -459,15 +443,14 @@ impl ChangesetItem {
|
|||||||
let mut code = 0;
|
let mut code = 0;
|
||||||
let mut indirect = 0;
|
let mut indirect = 0;
|
||||||
let tab = unsafe {
|
let tab = unsafe {
|
||||||
let mut pz_tab = MaybeUninit::uninit();
|
let mut pz_tab: *const c_char = ptr::null();
|
||||||
check!(ffi::sqlite3changeset_op(
|
check!(ffi::sqlite3changeset_op(
|
||||||
self.it,
|
self.it,
|
||||||
pz_tab.as_mut_ptr(),
|
&mut pz_tab,
|
||||||
&mut number_of_columns,
|
&mut number_of_columns,
|
||||||
&mut code,
|
&mut code,
|
||||||
&mut indirect
|
&mut indirect
|
||||||
));
|
));
|
||||||
let pz_tab: *const c_char = pz_tab.assume_init();
|
|
||||||
CStr::from_ptr(pz_tab)
|
CStr::from_ptr(pz_tab)
|
||||||
};
|
};
|
||||||
let table_name = tab.to_str()?;
|
let table_name = tab.to_str()?;
|
||||||
@ -483,13 +466,12 @@ impl ChangesetItem {
|
|||||||
pub fn pk(&self) -> Result<&[u8]> {
|
pub fn pk(&self) -> Result<&[u8]> {
|
||||||
let mut number_of_columns = 0;
|
let mut number_of_columns = 0;
|
||||||
unsafe {
|
unsafe {
|
||||||
let mut pks = MaybeUninit::uninit();
|
let mut pks: *mut c_uchar = ptr::null_mut();
|
||||||
check!(ffi::sqlite3changeset_pk(
|
check!(ffi::sqlite3changeset_pk(
|
||||||
self.it,
|
self.it,
|
||||||
pks.as_mut_ptr(),
|
&mut pks,
|
||||||
&mut number_of_columns
|
&mut number_of_columns
|
||||||
));
|
));
|
||||||
let pks: *mut c_uchar = pks.assume_init();
|
|
||||||
Ok(from_raw_parts(pks, number_of_columns as usize))
|
Ok(from_raw_parts(pks, number_of_columns as usize))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -503,9 +485,8 @@ pub struct Changegroup {
|
|||||||
|
|
||||||
impl Changegroup {
|
impl Changegroup {
|
||||||
pub fn new() -> Result<Self> {
|
pub fn new() -> Result<Self> {
|
||||||
let mut cg = MaybeUninit::uninit();
|
let mut cg = ptr::null_mut();
|
||||||
check!(unsafe { ffi::sqlite3changegroup_new(cg.as_mut_ptr()) });
|
check!(unsafe { ffi::sqlite3changegroup_new(&mut cg) });
|
||||||
let cg: *mut ffi::sqlite3_changegroup = unsafe { cg.assume_init() };
|
|
||||||
Ok(Changegroup { cg })
|
Ok(Changegroup { cg })
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -531,9 +512,8 @@ impl Changegroup {
|
|||||||
/// Obtain a composite Changeset
|
/// Obtain a composite Changeset
|
||||||
pub fn output(&mut self) -> Result<Changeset> {
|
pub fn output(&mut self) -> Result<Changeset> {
|
||||||
let mut n = 0;
|
let mut n = 0;
|
||||||
let mut output = MaybeUninit::uninit();
|
let mut output: *mut c_void = ptr::null_mut();
|
||||||
check!(unsafe { ffi::sqlite3changegroup_output(self.cg, &mut n, output.as_mut_ptr()) });
|
check!(unsafe { ffi::sqlite3changegroup_output(self.cg, &mut n, &mut output) });
|
||||||
let output: *mut c_void = unsafe { output.assume_init() };
|
|
||||||
Ok(Changeset { cs: output, n })
|
Ok(Changeset { cs: output, n })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -619,7 +619,7 @@ impl Statement<'_> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn finalize_(&mut self) -> Result<()> {
|
fn finalize_(&mut self) -> Result<()> {
|
||||||
let mut stmt = RawStatement::new(ptr::null_mut(), false);
|
let mut stmt = unsafe { RawStatement::new(ptr::null_mut(), false) };
|
||||||
mem::swap(&mut stmt, &mut self.stmt);
|
mem::swap(&mut stmt, &mut self.stmt);
|
||||||
self.conn.decode_result(stmt.finalize())
|
self.conn.decode_result(stmt.finalize())
|
||||||
}
|
}
|
||||||
@ -710,7 +710,7 @@ impl Statement<'_> {
|
|||||||
|
|
||||||
impl Into<RawStatement> for Statement<'_> {
|
impl Into<RawStatement> for Statement<'_> {
|
||||||
fn into(mut self) -> RawStatement {
|
fn into(mut self) -> RawStatement {
|
||||||
let mut stmt = RawStatement::new(ptr::null_mut(), false);
|
let mut stmt = unsafe { RawStatement::new(ptr::null_mut(), false) };
|
||||||
mem::swap(&mut stmt, &mut self.stmt);
|
mem::swap(&mut stmt, &mut self.stmt);
|
||||||
stmt
|
stmt
|
||||||
}
|
}
|
||||||
|
@ -53,10 +53,10 @@ unsafe extern "C" fn unlock_notify_cb(ap_arg: *mut *mut c_void, n_arg: c_int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "unlock_notify")]
|
#[cfg(feature = "unlock_notify")]
|
||||||
pub fn is_locked(db: *mut ffi::sqlite3, rc: c_int) -> bool {
|
pub unsafe fn is_locked(db: *mut ffi::sqlite3, rc: c_int) -> bool {
|
||||||
rc == ffi::SQLITE_LOCKED_SHAREDCACHE
|
rc == ffi::SQLITE_LOCKED_SHAREDCACHE
|
||||||
|| (rc & 0xFF) == ffi::SQLITE_LOCKED
|
|| (rc & 0xFF) == ffi::SQLITE_LOCKED
|
||||||
&& unsafe { ffi::sqlite3_extended_errcode(db) } == ffi::SQLITE_LOCKED_SHAREDCACHE
|
&& ffi::sqlite3_extended_errcode(db) == ffi::SQLITE_LOCKED_SHAREDCACHE
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This function assumes that an SQLite API call (either `sqlite3_prepare_v2()`
|
/// This function assumes that an SQLite API call (either `sqlite3_prepare_v2()`
|
||||||
@ -72,16 +72,14 @@ pub fn is_locked(db: *mut ffi::sqlite3, rc: c_int) -> bool {
|
|||||||
/// this case the caller should not retry the operation and should roll
|
/// this case the caller should not retry the operation and should roll
|
||||||
/// back the current transaction (if any).
|
/// back the current transaction (if any).
|
||||||
#[cfg(feature = "unlock_notify")]
|
#[cfg(feature = "unlock_notify")]
|
||||||
pub fn wait_for_unlock_notify(db: *mut ffi::sqlite3) -> c_int {
|
pub unsafe fn wait_for_unlock_notify(db: *mut ffi::sqlite3) -> c_int {
|
||||||
let mut un = UnlockNotification::new();
|
let mut un = UnlockNotification::new();
|
||||||
/* Register for an unlock-notify callback. */
|
/* Register for an unlock-notify callback. */
|
||||||
let rc = unsafe {
|
let rc = ffi::sqlite3_unlock_notify(
|
||||||
ffi::sqlite3_unlock_notify(
|
db,
|
||||||
db,
|
Some(unlock_notify_cb),
|
||||||
Some(unlock_notify_cb),
|
&mut un as *mut UnlockNotification as *mut c_void,
|
||||||
&mut un as *mut UnlockNotification as *mut c_void,
|
);
|
||||||
)
|
|
||||||
};
|
|
||||||
debug_assert!(
|
debug_assert!(
|
||||||
rc == ffi::SQLITE_LOCKED || rc == ffi::SQLITE_LOCKED_SHAREDCACHE || rc == ffi::SQLITE_OK
|
rc == ffi::SQLITE_LOCKED || rc == ffi::SQLITE_LOCKED_SHAREDCACHE || rc == ffi::SQLITE_OK
|
||||||
);
|
);
|
||||||
@ -92,12 +90,12 @@ pub fn wait_for_unlock_notify(db: *mut ffi::sqlite3) -> c_int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "unlock_notify"))]
|
#[cfg(not(feature = "unlock_notify"))]
|
||||||
pub fn is_locked(_db: *mut ffi::sqlite3, _rc: c_int) -> bool {
|
pub unsafe fn is_locked(_db: *mut ffi::sqlite3, _rc: c_int) -> bool {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "unlock_notify"))]
|
#[cfg(not(feature = "unlock_notify"))]
|
||||||
pub fn wait_for_unlock_notify(_db: *mut ffi::sqlite3) -> c_int {
|
pub unsafe fn wait_for_unlock_notify(_db: *mut ffi::sqlite3) -> c_int {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user