This commit is contained in:
gwenn 2018-10-28 08:51:02 +01:00
parent 03561e36fb
commit 1598d4bc30
16 changed files with 177 additions and 111 deletions

View File

@ -405,7 +405,8 @@ mod test {
DatabaseName::Attached("my_attached"),
&mut dst,
DatabaseName::Main,
).unwrap();
)
.unwrap();
backup.step(-1).unwrap();
}
@ -422,7 +423,8 @@ mod test {
DatabaseName::Attached("my_attached"),
&mut dst,
DatabaseName::Main,
).unwrap();
)
.unwrap();
backup
.run_to_completion(5, Duration::from_millis(250), None)
.unwrap();

View File

@ -28,7 +28,8 @@
//! db.execute(
//! "INSERT INTO test (content) VALUES (ZEROBLOB(10))",
//! NO_PARAMS,
//! ).unwrap();
//! )
//! .unwrap();
//!
//! let rowid = db.last_insert_rowid();
//! let mut blob = db
@ -36,7 +37,8 @@
//! .unwrap();
//!
//! // Make sure to test that the number of bytes written matches what you expect;
//! // if you try to write too much, the data will be truncated to the size of the BLOB.
//! // if you try to write too much, the data will be truncated to the size of the
//! // BLOB.
//! let bytes_written = blob.write(b"01234567").unwrap();
//! assert_eq!(bytes_written, 8);
//!
@ -171,7 +173,8 @@ impl<'conn> io::Read for Blob<'conn> {
.map(|_| {
self.pos += n;
n as usize
}).map_err(|err| io::Error::new(io::ErrorKind::Other, err))
})
.map_err(|err| io::Error::new(io::ErrorKind::Other, err))
}
}
@ -199,7 +202,8 @@ impl<'conn> io::Write for Blob<'conn> {
.map(|_| {
self.pos += n;
n as usize
}).map_err(|err| io::Error::new(io::ErrorKind::Other, err))
})
.map_err(|err| io::Error::new(io::ErrorKind::Other, err))
}
fn flush(&mut self) -> io::Result<()> {

View File

@ -127,7 +127,8 @@ mod test {
let _ = db2
.query_row("PRAGMA schema_version", NO_PARAMS, |row| {
row.get_checked::<_, i32>(0)
}).expect("unexpected error");
})
.expect("unexpected error");
child.join().unwrap();
}
@ -165,7 +166,8 @@ mod test {
let _ = db2
.query_row("PRAGMA schema_version", NO_PARAMS, |row| {
row.get_checked::<_, i32>(0)
}).expect("unexpected error");
})
.expect("unexpected error");
assert_eq!(CALLED.load(Ordering::Relaxed), true);
child.join().unwrap();

View File

@ -269,7 +269,8 @@ mod test {
CREATE TABLE foo (x INT);
INSERT INTO foo VALUES (1);
"#,
).unwrap();
)
.unwrap();
let sql = "SELECT * FROM foo";
@ -290,7 +291,8 @@ mod test {
ALTER TABLE foo ADD COLUMN y INT;
UPDATE foo SET y = 2;
"#,
).unwrap();
)
.unwrap();
{
let mut stmt = db.prepare_cached(sql).unwrap();

View File

@ -47,7 +47,8 @@
//! "SELECT regexp('[aeiou]*', 'aaaaeeeiii')",
//! NO_PARAMS,
//! |row| row.get(0),
//! ).unwrap();
//! )
//! .unwrap();
//!
//! assert!(is_match);
//! }
@ -540,8 +541,10 @@ mod test {
let is_match = {
let re = saved_re.unwrap_or_else(|| new_re.as_ref().unwrap());
let text = ctx.get_raw(1).as_str().map_err(|e|
Error::UserFunctionError(e.into()))?;
let text = ctx
.get_raw(1)
.as_str()
.map_err(|e| Error::UserFunctionError(e.into()))?;
re.is_match(text)
};
@ -563,7 +566,8 @@ mod test {
INSERT INTO foo VALUES ('lXsi');
INSERT INTO foo VALUES ('lisX');
END;",
).unwrap();
)
.unwrap();
db.create_scalar_function("regexp", 2, true, regexp_with_auxilliary)
.unwrap();
@ -593,7 +597,8 @@ mod test {
INSERT INTO foo VALUES ('lXsi');
INSERT INTO foo VALUES ('lisX');
END;",
).unwrap();
)
.unwrap();
// This implementation of a regexp scalar function uses a captured HashMap
// to keep cached regular expressions around (even across multiple queries)
@ -617,7 +622,8 @@ mod test {
let text = try!(ctx.get::<String>(1));
Ok(regex.is_match(&text))
}).unwrap();
})
.unwrap();
let result: Result<bool> =
db.query_row("SELECT regexp('l.s[aeiouy]', 'lisa')", NO_PARAMS, |r| {
@ -647,7 +653,8 @@ mod test {
}
Ok(ret)
}).unwrap();
})
.unwrap();
for &(expected, query) in &[
("", "SELECT my_concat()"),

View File

@ -28,7 +28,8 @@
//! data BLOB
//! )",
//! NO_PARAMS,
//! ).unwrap();
//! )
//! .unwrap();
//! let me = Person {
//! id: 0,
//! name: "Steven".to_string(),
@ -39,7 +40,8 @@
//! "INSERT INTO person (name, time_created, data)
//! VALUES (?1, ?2, ?3)",
//! &[&me.name as &ToSql, &me.time_created, &me.data],
//! ).unwrap();
//! )
//! .unwrap();
//!
//! let mut stmt = conn
//! .prepare("SELECT id, name, time_created, data FROM person")
@ -50,7 +52,8 @@
//! name: row.get(1),
//! time_created: row.get(2),
//! data: row.get(3),
//! }).unwrap();
//! })
//! .unwrap();
//!
//! for person in person_iter {
//! println!("Found person {:?}", person.unwrap());
@ -83,7 +86,7 @@ use std::ptr;
use std::result;
use std::str;
use std::sync::atomic::{AtomicBool, Ordering, ATOMIC_BOOL_INIT};
use std::sync::{Once, ONCE_INIT, Arc, Mutex};
use std::sync::{Arc, Mutex, Once, ONCE_INIT};
use cache::StatementCache;
use error::{error_from_handle, error_from_sqlite_code};
@ -576,8 +579,8 @@ impl Connection {
self.db.borrow().db()
}
/// Get access to a handle that can be used to interrupt long running queries
/// from another thread.
/// Get access to a handle that can be used to interrupt long running
/// queries from another thread.
pub fn get_interrupt_handle(&self) -> InterruptHandle {
self.db.borrow().get_interrupt_handle()
}
@ -892,8 +895,10 @@ impl InnerConnection {
}
self.remove_hooks();
let mut shared_handle = self.interrupt_lock.lock().unwrap();
assert!(!shared_handle.is_null(),
"Bug: Somehow interrupt_lock was cleared before the DB was closed");
assert!(
!shared_handle.is_null(),
"Bug: Somehow interrupt_lock was cleared before the DB was closed"
);
unsafe {
let r = ffi::sqlite3_close(self.db);
// Need to use _raw because _guard has a reference out, and
@ -1116,7 +1121,8 @@ mod test {
"
BEGIN; CREATE TABLE foo(x INTEGER);
INSERT INTO foo VALUES(42); END;",
).expect("create temp db");
)
.expect("create temp db");
let mut db1 = Connection::open(&path).unwrap();
let mut db2 = Connection::open(&path).unwrap();
@ -1530,29 +1536,30 @@ mod test {
db.execute_batch("CREATE TABLE dummy(id)").unwrap();
let interrupt_handle = db.get_interrupt_handle();
// generate an arbitrary query which will be very slow to execute.
let sql = format!("{};",
(0..100_000).into_iter()
let sql = format!(
"{};",
(0..100_000)
.into_iter()
.map(|i| format!("INSERT INTO dummy(id) VALUES({})", i))
.collect::<Vec<_>>()
.join(";\n"));
.join(";\n")
);
// Do this on the main thread to minimize the amount of time spent
// when interrupt won't do anything (because we haven't started
// executing the query).
let c_sql = str_to_cstring(&sql).unwrap();
let joiner = thread::spawn(move || {
unsafe {
let raw_db = db.db.borrow().db;
let r = ffi::sqlite3_exec(
raw_db,
c_sql.as_ptr(),
None,
ptr::null_mut(),
ptr::null_mut(),
);
db.decode_result(r)
}
let joiner = thread::spawn(move || unsafe {
let raw_db = db.db.borrow().db;
let r = ffi::sqlite3_exec(
raw_db,
c_sql.as_ptr(),
None,
ptr::null_mut(),
ptr::null_mut(),
);
db.decode_result(r)
});
// Try a few times to make sure we don't catch it too early.
@ -1603,7 +1610,12 @@ mod test {
let mut insert_stmt = db.prepare("INSERT INTO foo(i, x) VALUES(?, ?)").unwrap();
for (i, v) in vals.iter().enumerate() {
let i_to_insert = i as i64;
assert_eq!(insert_stmt.execute(&[&i_to_insert as &dyn ToSql, &v]).unwrap(), 1);
assert_eq!(
insert_stmt
.execute(&[&i_to_insert as &dyn ToSql, &v])
.unwrap(),
1
);
}
let mut query = db.prepare("SELECT i, x FROM foo").unwrap();
@ -1729,7 +1741,8 @@ mod test {
let results: CustomResult<Vec<String>> = query
.query_and_then(NO_PARAMS, |row| {
row.get_checked(1).map_err(CustomError::Sqlite)
}).unwrap()
})
.unwrap()
.collect();
assert_eq!(results.unwrap().concat(), "hello, world!");
@ -1751,7 +1764,8 @@ mod test {
let bad_type: CustomResult<Vec<f64>> = query
.query_and_then(NO_PARAMS, |row| {
row.get_checked(1).map_err(CustomError::Sqlite)
}).unwrap()
})
.unwrap()
.collect();
match bad_type.unwrap_err() {
@ -1762,7 +1776,8 @@ mod test {
let bad_idx: CustomResult<Vec<String>> = query
.query_and_then(NO_PARAMS, |row| {
row.get_checked(3).map_err(CustomError::Sqlite)
}).unwrap()
})
.unwrap()
.collect();
match bad_idx.unwrap_err() {
@ -1846,7 +1861,8 @@ mod test {
db.query_row("SELECT * FROM foo", NO_PARAMS, |r| {
assert_eq!(2, r.column_count())
}).unwrap();
})
.unwrap();
}
}
}

View File

@ -141,10 +141,9 @@ impl<'a, 'stmt> Row<'a, 'stmt> {
///
/// * If the underlying SQLite column type is not a valid type as a
/// source for `T`
/// * If the underlying SQLite integral value is
/// outside the range representable by `T`
/// * If `idx` is outside the range of columns in the
/// returned query
/// * If the underlying SQLite integral value is outside the range
/// representable by `T`
/// * If `idx` is outside the range of columns in the returned query
pub fn get<I: RowIndex, T: FromSql>(&self, idx: I) -> T {
self.get_checked(idx).unwrap()
}
@ -175,9 +174,7 @@ impl<'a, 'stmt> Row<'a, 'stmt> {
Error::FromSqlConversionFailure(idx as usize, value.data_type(), err)
}
#[cfg(feature = "i128_blob")]
FromSqlError::InvalidI128Size(_) => {
Error::InvalidColumnType(idx, value.data_type())
}
FromSqlError::InvalidI128Size(_) => Error::InvalidColumnType(idx, value.data_type()),
})
}

View File

@ -697,7 +697,8 @@ mod test {
"SELECT SUM(x) FROM foo WHERE x > :x",
&[(":x", &0i32)],
|r| r.get(0)
).unwrap()
)
.unwrap()
);
}
@ -719,7 +720,8 @@ mod test {
"SELECT COUNT(*) FROM test WHERE name = :name",
&[(":name", &"one")],
|r| r.get(0)
).unwrap()
)
.unwrap()
);
}
@ -757,7 +759,8 @@ mod test {
.query_map_named(&[(":name", &"one")], |row| {
let id: i32 = row.get(0);
2 * id
}).unwrap();
})
.unwrap();
let doubled_id: i32 = rows.next().unwrap().unwrap();
assert_eq!(2, doubled_id);
@ -784,7 +787,8 @@ mod test {
} else {
Err(Error::SqliteSingleThreadedMode)
}
}).unwrap();
})
.unwrap();
// first row should be Ok
let doubled_id: i32 = rows.next().unwrap().unwrap();
@ -812,7 +816,8 @@ mod test {
let result: Option<String> = db
.query_row("SELECT y FROM test WHERE x = 'one'", NO_PARAMS, |row| {
row.get(0)
}).unwrap();
})
.unwrap();
assert!(result.is_none());
}
@ -831,7 +836,8 @@ mod test {
let result: String = db
.query_row("SELECT x FROM test WHERE y = 'two'", NO_PARAMS, |row| {
row.get(0)
}).unwrap();
})
.unwrap();
assert_eq!(result, "one");
}
@ -867,7 +873,8 @@ mod test {
CREATE TABLE foo(x INTEGER);
CREATE TABLE bar(x INTEGER);
",
).unwrap();
)
.unwrap();
assert_eq!(
db.prepare("INSERT INTO foo VALUES (10)")

View File

@ -236,7 +236,8 @@ mod test {
let v4: DateTime<Utc> = db
.query_row("SELECT '2016-02-23 23:56:04.789+00:00'", NO_PARAMS, |r| {
r.get(0)
}).unwrap();
})
.unwrap();
assert_eq!(utc, v4);
}

View File

@ -28,8 +28,9 @@ impl fmt::Display for FromSqlError {
FromSqlError::InvalidType => write!(f, "Invalid type"),
FromSqlError::OutOfRange(i) => write!(f, "Value {} out of range", i),
#[cfg(feature = "i128_blob")]
FromSqlError::InvalidI128Size(s) =>
write!(f, "Cannot read 128bit value out of {} byte blob", s),
FromSqlError::InvalidI128Size(s) => {
write!(f, "Cannot read 128bit value out of {} byte blob", s)
}
FromSqlError::Other(ref err) => err.fmt(f),
}
}
@ -41,8 +42,7 @@ impl Error for FromSqlError {
FromSqlError::InvalidType => "invalid type",
FromSqlError::OutOfRange(_) => "value out of range",
#[cfg(feature = "i128_blob")]
FromSqlError::InvalidI128Size(_) =>
"unexpected blob size for 128bit value",
FromSqlError::InvalidI128Size(_) => "unexpected blob size for 128bit value",
FromSqlError::Other(ref err) => err.description(),
}
}

View File

@ -46,7 +46,8 @@
//! }
//! }
//!
//! # // Prevent this doc test from being wrapped in a `fn main()` so that it will compile.
//! # // Prevent this doc test from being wrapped in a `fn main()` so that it
//! # // will compile.
//! # fn main() {}
//! ```
//!
@ -239,7 +240,8 @@ mod test {
db.execute(
"INSERT INTO foo(b, t, i, f) VALUES (X'0102', 'text', 1, 1.5)",
NO_PARAMS,
).unwrap();
)
.unwrap();
let mut stmt = db.prepare("SELECT b, t, i, f, n FROM foo").unwrap();
let mut rows = stmt.query(NO_PARAMS).unwrap();
@ -354,7 +356,8 @@ mod test {
db.execute(
"INSERT INTO foo(b, t, i, f) VALUES (X'0102', 'text', 1, 1.5)",
NO_PARAMS,
).unwrap();
)
.unwrap();
let mut stmt = db.prepare("SELECT b, t, i, f, n FROM foo").unwrap();
let mut rows = stmt.query(NO_PARAMS).unwrap();

View File

@ -20,7 +20,8 @@ impl FromSql for Value {
ValueRef::Text(s) => serde_json::from_str(s),
ValueRef::Blob(b) => serde_json::from_slice(b),
_ => return Err(FromSqlError::InvalidType),
}.map_err(|err| FromSqlError::Other(Box::new(err)))
}
.map_err(|err| FromSqlError::Other(Box::new(err)))
}
}
@ -46,7 +47,8 @@ mod test {
db.execute(
"INSERT INTO foo (t, b) VALUES (?, ?)",
&[&data as &ToSql, &json.as_bytes()],
).unwrap();
)
.unwrap();
let t: serde_json::Value = db
.query_row("SELECT t FROM foo", NO_PARAMS, |r| r.get(0))

View File

@ -25,7 +25,8 @@ impl FromSql for time::Timespec {
time::strptime(s, SQLITE_DATETIME_FMT_LEGACY)
.or_else(|_| Err(FromSqlError::Other(Box::new(err))))
})
}).map(|tm| tm.to_timespec())
})
.map(|tm| tm.to_timespec())
}
}

View File

@ -207,34 +207,45 @@ mod test {
#[cfg(feature = "i128_blob")]
#[test]
fn test_i128() {
use {Connection, NO_PARAMS};
use std::i128;
use {Connection, NO_PARAMS};
let db = Connection::open_in_memory().unwrap();
db.execute_batch("CREATE TABLE foo (i128 BLOB, desc TEXT)").unwrap();
db.execute("
db.execute_batch("CREATE TABLE foo (i128 BLOB, desc TEXT)")
.unwrap();
db.execute(
"
INSERT INTO foo(i128, desc) VALUES
(?, 'zero'),
(?, 'neg one'), (?, 'neg two'),
(?, 'pos one'), (?, 'pos two'),
(?, 'min'), (?, 'max')",
&[0i128, -1i128, -2i128, 1i128, 2i128, i128::MIN, i128::MAX]
).unwrap();
&[0i128, -1i128, -2i128, 1i128, 2i128, i128::MIN, i128::MAX],
)
.unwrap();
let mut stmt = db.prepare("SELECT i128, desc FROM foo ORDER BY i128 ASC").unwrap();
let mut stmt = db
.prepare("SELECT i128, desc FROM foo ORDER BY i128 ASC")
.unwrap();
let res = stmt.query_map(
NO_PARAMS,
|row| (row.get::<_, i128>(0), row.get::<_, String>(1))
).unwrap().collect::<Result<Vec<_>, _>>().unwrap();
let res = stmt
.query_map(NO_PARAMS, |row| {
(row.get::<_, i128>(0), row.get::<_, String>(1))
})
.unwrap()
.collect::<Result<Vec<_>, _>>()
.unwrap();
assert_eq!(res, &[
(i128::MIN, "min".to_owned()),
(-2, "neg two".to_owned()),
(-1, "neg one".to_owned()),
(0, "zero".to_owned()),
(1, "pos one".to_owned()),
(2, "pos two".to_owned()),
(i128::MAX, "max".to_owned()),
]);
assert_eq!(
res,
&[
(i128::MIN, "min".to_owned()),
(-2, "neg two".to_owned()),
(-1, "neg one".to_owned()),
(0, "zero".to_owned()),
(1, "pos one".to_owned()),
(2, "pos two".to_owned()),
(i128::MAX, "max".to_owned()),
]
);
}
}

View File

@ -379,7 +379,8 @@ mod test {
.prepare(
"SELECT v1.rowid, v1.* FROM vtab v1 NATURAL JOIN vtab v2 WHERE \
v1.rowid < v2.rowid",
).unwrap();
)
.unwrap();
let mut rows = s.query(NO_PARAMS).unwrap();
let row = rows.next().unwrap().unwrap();

View File

@ -2,9 +2,11 @@
//!
//! Follow these steps to create your own virtual table:
//! 1. Write implemenation of `VTab` and `VTabCursor` traits.
//! 2. Create an instance of the `Module` structure specialized for `VTab` impl. from step 1.
//! 2. Create an instance of the `Module` structure specialized for `VTab` impl.
//! from step 1.
//! 3. Register your `Module` structure using `Connection.create_module`.
//! 4. Run a `CREATE VIRTUAL TABLE` command that specifies the new module in the `USING` clause.
//! 4. Run a `CREATE VIRTUAL TABLE` command that specifies the new module in the
//! `USING` clause.
//!
//! (See [SQLite doc](http://sqlite.org/vtab.html))
use std::borrow::Cow::{self, Borrowed, Owned};
@ -108,8 +110,9 @@ pub fn read_only_module<T: CreateVTab>(version: c_int) -> Module<T> {
///
/// Step 2 of [Creating New Virtual Table Implementations](https://sqlite.org/vtab.html#creating_new_virtual_table_implementations).
pub fn eponymous_only_module<T: VTab>(version: c_int) -> Module<T> {
// A virtual table is eponymous if its xCreate method is the exact same function as the xConnect method
// For eponymous-only virtual tables, the xCreate method is NULL
// A virtual table is eponymous if its xCreate method is the exact same function
// as the xConnect method For eponymous-only virtual tables, the xCreate
// method is NULL
let ffi_module = ffi::sqlite3_module {
iVersion: version,
xCreate: None,
@ -152,10 +155,11 @@ impl VTabConnection {
///
/// # Warning
///
/// You should not need to use this function. If you do need to, please [open an issue
/// on the rusqlite repository](https://github.com/jgallagher/rusqlite/issues) and describe
/// your use case. This function is unsafe because it gives you raw access to the SQLite
/// connection, and what you do with it could impact the safety of this `Connection`.
/// You should not need to use this function. If you do need to, please
/// [open an issue on the rusqlite repository](https://github.com/jgallagher/rusqlite/issues) and describe
/// your use case. This function is unsafe because it gives you raw access
/// to the SQLite connection, and what you do with it could impact the
/// safety of this `Connection`.
pub unsafe fn handle(&mut self) -> *mut ffi::sqlite3 {
self.0
}
@ -200,9 +204,10 @@ pub trait VTab: Sized {
///
/// (See [SQLite doc](https://sqlite.org/c3ref/vtab.html))
pub trait CreateVTab: VTab {
/// Create a new instance of a virtual table in response to a CREATE VIRTUAL TABLE statement.
/// The `db` parameter is a pointer to the SQLite database connection that is executing
/// the CREATE VIRTUAL TABLE statement.
/// Create a new instance of a virtual table in response to a CREATE VIRTUAL
/// TABLE statement. The `db` parameter is a pointer to the SQLite
/// database connection that is executing the CREATE VIRTUAL TABLE
/// statement.
///
/// Call `connect` by default.
/// (See [SQLite doc](https://sqlite.org/vtab.html#the_xcreate_method))
@ -214,7 +219,8 @@ pub trait CreateVTab: VTab {
Self::connect(db, aux, args)
}
/// Destroy the underlying table implementation. This method undoes the work of `create`.
/// Destroy the underlying table implementation. This method undoes the work
/// of `create`.
///
/// Do nothing by default.
/// (See [SQLite doc](https://sqlite.org/vtab.html#the_xdestroy_method))
@ -236,7 +242,8 @@ bitflags! {
}
}
/// Pass information into and receive the reply from the `VTab.best_index` method.
/// Pass information into and receive the reply from the `VTab.best_index`
/// method.
///
/// (See [SQLite doc](http://sqlite.org/c3ref/index_info.html))
pub struct IndexInfo(*mut ffi::sqlite3_index_info);
@ -409,8 +416,8 @@ pub trait VTabCursor: Sized {
/// Advance cursor to the next row of a result set initiated by `filter`.
/// (See [SQLite doc](https://sqlite.org/vtab.html#the_xnext_method))
fn next(&mut self) -> Result<()>;
/// Must return `false` if the cursor currently points to a valid row of data,
/// or `true` otherwise.
/// Must return `false` if the cursor currently points to a valid row of
/// data, or `true` otherwise.
/// (See [SQLite doc](https://sqlite.org/vtab.html#the_xeof_method))
fn eof(&self) -> bool;
/// Find the value for the `i`-th column of the current row.
@ -436,7 +443,8 @@ impl Context {
// TODO sqlite3_vtab_nochange (http://sqlite.org/c3ref/vtab_nochange.html)
}
/// Wrapper to `VTabCursor.filter` arguments, the values requested by `VTab.best_index`.
/// Wrapper to `VTabCursor.filter` arguments, the values requested by
/// `VTab.best_index`.
pub struct Values<'a> {
args: &'a [*mut ffi::sqlite3_value],
}
@ -894,7 +902,8 @@ where
}
}
/// Virtual table cursors can set an error message by assigning a string to `zErrMsg`.
/// Virtual table cursors can set an error message by assigning a string to
/// `zErrMsg`.
unsafe fn cursor_error<T>(cursor: *mut ffi::sqlite3_vtab_cursor, result: Result<T>) -> c_int {
use std::error::Error as StdError;
match result {
@ -912,7 +921,8 @@ unsafe fn cursor_error<T>(cursor: *mut ffi::sqlite3_vtab_cursor, result: Result<
}
}
/// Virtual tables methods can set an error message by assigning a string to `zErrMsg`.
/// Virtual tables methods can set an error message by assigning a string to
/// `zErrMsg`.
unsafe fn set_err_msg(vtab: *mut ffi::sqlite3_vtab, err_msg: &str) {
if !(*vtab).zErrMsg.is_null() {
ffi::sqlite3_free((*vtab).zErrMsg as *mut c_void);
@ -920,8 +930,8 @@ unsafe fn set_err_msg(vtab: *mut ffi::sqlite3_vtab, err_msg: &str) {
(*vtab).zErrMsg = mprintf(err_msg);
}
/// To raise an error, the `column` method should use this method to set the error message
/// and return the error code.
/// To raise an error, the `column` method should use this method to set the
/// error message and return the error code.
unsafe fn result_error<T>(ctx: *mut ffi::sqlite3_context, result: Result<T>) -> c_int {
use std::error::Error as StdError;
match result {