user7024226
user7024226

Reputation: 79

SQLite "where" return 21

I'm trying to get from the table all the the rows that have same USERID I thinking that something wrong with sqlite3_prepare_v2 or with sqlite3_bind_text, to debugging this code, I've printed

print(sqlite3_step(sqlite3_stmt))
print(sqlite3_step(sqlite3_stmt))

In the first time printed as 101 and the second time printed 21

However "SELECT * from IMAGE_TABLE" working good

Thanks!

  var sqlite3_stmt: OpaquePointer? = nil

    if (sqlite3_prepare_v2(database,"SELECT * from IMAGE_TABLE where USERID = ?;",-1,&sqlite3_stmt,nil) == SQLITE_OK){


        sqlite3_bind_text(sqlite3_stmt, 1, uid.cString(using: .utf8), 1,nil);

        while(sqlite3_step(sqlite3_stmt) == SQLITE_ROW){


            let imageDescription = String(validatingUTF8:sqlite3_column_text(sqlite3_stmt,0))
            let imageUrl = String(validatingUTF8:sqlite3_column_text(sqlite3_stmt,2))
            let imageName = String(validatingUTF8:sqlite3_column_text(sqlite3_stmt,3))
            let pic = Picture(imageDescription!,imageUrl!,imageName!)
            picList.append(pic)
        }

Upvotes: 2

Views: 423

Answers (1)

Rob
Rob

Reputation: 437622

The 101 is SQLITE_DONE, meaning there are no more rows to return, i.e. there was no record matching your WHERE clause. The 21 is SQLITE_MISUSE, because you called sqlite3_step to retrieve the next record after it just told you there were no more records.

There are two problems here:

  1. Your ? placeholder is being bound with sqlite3_bind_text, but you're using 1 for the fourth parameter. That means that it will only use the first character of the uid string. I suspect you meant to use -1, a negative value, which instructs sqlite3_bind_text to use the entire string up to the zero terminator.

  2. You also should use SQLITE_TRANSIENT in your sqlite3_bind_text call. So, if you haven't already, define those constants:

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

    And then use that in your sqlite3_bind_text call:

    guard sqlite3_bind_text(statement, 1, uid.cString(using: .utf8), -1, SQLITE_TRANSIENT) == SQLITE_OK else {
        ...
    }
    

    This instructs SQLite to make its own copy of that C-string, because you have no assurances regarding the lifespan of your own C-string.

Upvotes: 2

Related Questions