Поддержка iPhone sqlite3_next_stmt () - PullRequest
0 голосов
/ 03 июня 2009

При попытке закрыть соединение с базой данных в методе ApplicationWillTerminate появляется сообщение об ошибке незавершенного оператора.

Чтобы найти источник ошибки, я хочу использовать оператор SQLLite next.

Но, похоже, это утверждение не поддерживается в соответствии с заголовочными файлами в iPhone OS 2.2. Я что-то пропустил ?

Существует ли альтернативный способ выявления неполадок, вызывающих незавершенный оператор в SQLlite. В то время как я, кажется, завершаю, но я предполагаю, что что-то упустил.

1 Ответ

0 голосов
/ 10 июля 2009

Я только что отладил ту же проблему: незавершенные операторы не позволяли мне закрыть базу данных SQLite на iPhone. sqlite3_next_stmt, похоже, ничего не делал, но мне удалось отследить нефинализированные операторы вручную. Мой код базы данных был основан на примере книг SQLite от Apple, особенно с лениво подготовленными утверждениями. Поскольку я делал это для нескольких различных операторов, я решил обернуть эту часть кода во вспомогательный метод, выглядя примерно так:

- (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));
        }
    }
}

Я бы тогда назвал этот код так:

[self updateIntFieldStatement:static_statement WithCString:"UPDATE myTable SET myField = ? WHERE pk = ?" toValue:transmitted];

Проблема в том, что static_statement никогда не изменится, просто останется равным нулю, поэтому будет лениво готовиться снова и снова, и мой код завершения никогда не дойдет до этого. Причиной была эта часть: &update_field_statement. Мое утверждение было sqlite3_stmt *, но sqlite3_prepare_v2 использует sqlite3_stmt **, дескриптор, а не простой указатель. Пример кода от Apple получил дескриптор, взяв адрес указателя, но когда я сделал это в своем вспомогательном методе, я получил дескриптор локального параметра, а не глобальный дескриптор.

Область видимости указателя C: 1, me: 0 ...

Решение состояло в том, чтобы изменить мой вспомогательный метод, чтобы взять ручку:

- (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));
        }
    }
}

и затем получите дескриптор в глобальной области видимости:

[self updateIntFieldStatement:&static_statement WithCString:"UPDATE myTable SET myField = ? WHERE pk = ?" toValue:transmitted];

Теперь оператор готовится только один раз, static_statement назначается правильно, когда это происходит, и затем в конечном итоге завершается, поэтому я могу закрыть базу данных. Надеюсь, это поможет вам или кому-то еще!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...