sqlite for swift is unstable sqlite for swift is unstable sqlite sqlite

sqlite for swift is unstable


I had the same problem. I found the way to resolve this problem.

sqlite3_bind_text(statement, 1, itemName, -1, nil) --> itemName should be UTF8 String

You should convert itemName as NSString and use UTF8String to convert your string to UTF8. Right code is the same here

let itemName = item.itemName as NSStringsqlite3_bind_text(statement, 1, itemName.UTF8String, -1, nil)

Good luck.


In swift SQLite doesn't have SQLITE_TRANSIENT and SQLITE_STATIC defined, so we need to explicitly define it.

swift 3 & 4

Define following property of SQLITE

let SQLITE_STATIC = unsafeBitCast(0, to: sqlite3_destructor_type.self)let SQLITE_TRANSIENT = unsafeBitCast(-1, to: sqlite3_destructor_type.self)

SQL functionAdd SQLITE_TRANSIENT instead of nil as last parameter while binding text sqlite3_bind_text.

let update = "INSERT INTO ToDoItem (itemName, completed, goalDate) " + "VALUES (?, ?, ?);"var statement: OpaquePointer = nilif sqlite3_prepare_v2(database, update, -1, &statement, nil) == SQLITE_OK {    let itemName = item.itemName as String    let completed = item.completed == true ? 1 : 0    sqlite3_bind_text(statement, 1, itemName, -1, SQLITE_TRANSIENT)    sqlite3_bind_int(statement, 2, Int32(completed))    if let goalDate = item.goalDate?.toString() {        sqlite3_bind_text(statement, 3, goalDate, -1, SQLITE_TRANSIENT)    } else {        sqlite3_bind_text(statement, 3, "", -1, SQLITE_TRANSIENT)    }    //println("inserting \(itemName), \(completed) and \(item.goalDate?.toString())")    //println("")}if sqlite3_step(statement) != SQLITE_DONE {    println("error updateing table")    sqlite3_close(database)    return}sqlite3_finalize(statement)sqlite3_close(database)

Referenced from SQLITE_TRANSIENT undefined in Swift


This behavior actually does conform to the specification and the bug is in your code.

The source of your problem is in the swift String you are passing to sqlite3_bind_text. sqlite3_bind_text accepts the text as a const char* which is bridged as UnsafePointer<CChar> in Swift. The behavior when passing a Swift String to a function that accepts UnsafePointer<CChar> is documented in the "Constant Pointers" section of the Interacting with C APIs. It says:

The string will automatically be converted to UTF8 in a buffer, and a pointer to that buffer is passed to the function.

Which is probably what you want to have happen.

BUT it also says:

The pointer passed to the function is guaranteed to be valid only for the duration of the function call. Don’t try to persist the pointer and access it after the function has returned.

This is the source of your bug. sqlite3_bind_text() does in fact persist the pointer in the prepared statement possibly until sqlite3_finalize() is called so that it can use it in future sqlite3_step() calls.

Another answer suggested using NSString.UTF8String. This has a lifetime that is a little longer and seems like it should be enough. The documentation says:

This C string is a pointer to a structure inside the string object, which may have a lifetime shorter than the string object and will certainly not have a longer lifetime. Therefore, you should copy the C string if it needs to be stored outside of the memory context in which you use this property.

"memory context" here seems vague. I'm not sure if it means the current function, or until the current autoreleasepool is drained, or something else. If it is one of the first two, you are safe. If not, well I would say you are still safe because it seems like NSString.UTF8String has been used in situations like these for a long time without issues..