I am porting some code to Rust that reads a database path from stdin, opens the database and loops for queries. I have done something similar in C so I am pretty sure that the problem is my non-understanding of Rust FFI.
I am using the sqlite3 binding provided by libsqlite3-sys, the one from rusqlite. The whole code is here.
open_connection
initializes a pointer and passes it to sqlite3_open_v2
and checks if everything went well.
// Line 54 of complete code
fn open_connection(s: String) -> Result<RawConnection, SQLite3Error> {
unsafe {
let mut db: *mut sqlite3::sqlite3 = mem::uninitialized();
let r = sqlite3::sqlite3_open_v2(CString::new(s).unwrap().as_ptr(),
&mut db,
sqlite3::SQLITE_OPEN_CREATE |
sqlite3::SQLITE_OPEN_READWRITE,
ptr::null());
match r {
sqlite3::SQLITE_OK => Ok(RawConnection { db: db }),
_ => return Err(SQLite3Error::OpenError),
}
}
}
I create an SQL statement by converting the query from a Rust String to a C String, creating another pointer for the location of the statement itself and I go on creating a statement and checking the output:
// Line 35 of complete code
fn create_statement(conn: &RawConnection, query: String) -> Result<Statement, SQLite3Error> {
let len = query.len();
let raw_query = CString::new(query).unwrap().as_ptr();
unsafe {
let mut stmt: *mut sqlite3::sqlite3_stmt = mem::uninitialized();
if stmt.is_null() {
println!("Now it is null!");
}
match sqlite3::sqlite3_prepare_v2(conn.db,
raw_query,
len as i32,
&mut stmt,
ptr::null_mut()) {
sqlite3::SQLITE_OK => Ok(Statement { stmt: stmt }),
_ => Err(SQLite3Error::StatementError),
}
}
}
I try to execute a statement
// Line 81 of complete code
fn execute_statement(conn: &RawConnection, stmt: Statement) -> Result<Cursor, SQLite3Error> {
match unsafe { sqlite3::sqlite3_step(stmt.stmt) } {
sqlite3::SQLITE_OK => Ok(Cursor::OKCursor),
sqlite3::SQLITE_DONE => Ok(Cursor::DONECursor),
sqlite3::SQLITE_ROW => {
let n_columns = unsafe { sqlite3::sqlite3_column_count(stmt.stmt) } as i32;
let mut types: Vec<EntityType> = Vec::new();
for i in 0..n_columns {
types.push(match unsafe { sqlite3::sqlite3_column_type(stmt.stmt, i) } {
sqlite3::SQLITE_INTEGER => EntityType::Integer,
sqlite3::SQLITE_FLOAT => EntityType::Float,
sqlite3::SQLITE_TEXT => EntityType::Text,
sqlite3::SQLITE_BLOB => EntityType::Blob,
sqlite3::SQLITE_NULL => EntityType::Null,
_ => EntityType::Null,
})
}
Ok(Cursor::RowsCursor {
stmt: stmt,
num_columns: n_columns,
types: types,
previous_status: sqlite3::SQLITE_ROW,
})
}
x => {
println!("{}", x);
return Err(SQLite3Error::ExecuteError);
}
}
}
This always fails with the error code 21 MISUSE. Usually, this error happens when you try to execute a NULL statement but I have no idea how to figure it out.
Do you see any other problem that may cause a code 21 MISUSE?