Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>I just debugged the same issue, unfinalized statements preventing me from closing my SQLite database on iPhone. <code>sqlite3_next_stmt</code> didn't appear to do anything, but I managed to track down the unfinalized statements manually. My db code was based on the SQLite Books example from Apple, specifically with the lazily prepared statements. Since I was doing this for several different statements, I decided to wrap this part of the code in an auxillary method, looking something like this:</p> <pre><code>- (void)updateIntFieldStatement:(sqlite3_stmt *)update_field_statement WithCString:(char*)cString toValue:(int)value { if (update_field_statement == nil) { if (sqlite3_prepare_v2(database, cString, -1, &update_field_statement, NULL) != SQLITE_OK) { NSAssert1(0, @"Error: failed to prepare statement with message '%s'.", sqlite3_errmsg(database)); } } }</code></pre> <p>I would then call this code like this:</p> <pre><code>[self updateIntFieldStatement:static_statement WithCString:"UPDATE myTable SET myField = ? WHERE pk = ?" toValue:transmitted]; </code></pre> <p>The problem is, <code>static_statement</code> would never get changed, it just stayed nil, so it would get lazily prepared again and again, and my finalization code never got to it. The reason was this part: <code>&amp;update_field_statement</code>. My statement was an <code>sqlite3_stmt *</code>, but <code>sqlite3_prepare_v2</code> takes an <code>sqlite3_stmt **</code>, a handle rather than a simple pointer. The sample code from Apple got the handle by taking the address of the pointer, but when I did this in my auxillary method, I got the local parameter handle, not a global handle. </p> <p>C pointer scoping: 1, me: 0...</p> <p>The solution was to change my auxillary method to take a handle:</p> <pre><code>- (void)updateIntFieldStatement:(sqlite3_stmt **)update_field_statement WithCString:(char*)cString toValue:(int)value { if (*update_field_statement == nil) { if (sqlite3_prepare_v2(database, cString, -1, update_field_statement, NULL) != SQLITE_OK) { NSAssert1(0, @"Error: failed to prepare statement with message '%s'.", sqlite3_errmsg(database)); } } }</code></pre> <p>and then get the handle at a global scope:</p> <pre><code>[self updateIntFieldStatement:&amp;static_statement WithCString:"UPDATE myTable SET myField = ? WHERE pk = ?" toValue:transmitted]; </code></pre> <p>Now the the statement only gets prepared once, <code>static_statement</code> gets assigned correctly when this happens and then eventually finalized, so I can close the database. Hope this helps you or someone else out there!</p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload