0

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?

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Siscia
  • 1,421
  • 1
  • 12
  • 29
  • 4
    I'd suggest you re-read the **WARNING** section of [`CString::as_ptr`](https://doc.rust-lang.org/std/ffi/struct.CString.html#method.as_ptr): *It is your responsibility to make sure that the underlying memory is not freed too early*. Probably a duplicate of [Raw pointer turns null passing from Rust to C](http://stackoverflow.com/q/39218479/155423); [How to stop memory leaks when using `as_ptr()`?](http://stackoverflow.com/q/31083223/155423); or [What is the proper way to go from a String to a *const i8?](http://stackoverflow.com/q/28649311/155423); whichever is most useful. – Shepmaster Apr 07 '17 at 14:03
  • @Shepmaster that was the correct answer, if you post is as an answer I would definitely choose it as the correct one. – Siscia Apr 09 '17 at 15:35
  • 1
    Thanks for letting me know! I've marked it as a duplicate of two questions; one which has a title which highly matches your problem (but is a bit wordy), and a shorter one which gets to the heart of the problem very succinctly. – Shepmaster Apr 09 '17 at 15:51

0 Answers0