Это происходит, если игнорировать результат из sqlite3_step()
.Если он возвращает SQLITE_ROW
, код не может действовать, как если бы он возвратил SQLITE_DONE
.Нужно продолжать вызывать sqlite3_step()
до тех пор, пока запрос не будет выполнен: прагма или нет, запрос - это запрос, и он не будет выполнен, пока, ну, ну, SQLITE_DONE
:).Это происходит, чтобы удалить одну страницу за раз:
bool do_incremental_vacuum(sqlite3 *db) {
sqlite3_stmt *stmt = nullptr;
auto rc = sqlite3_prepare_v2(db, "pragma freelist_count;", -1, &stmt);
if (rc != SQLITE_OK) return false;
rc = sqlite3_step(stmt);
if (rc != SQLITE_DONE && rc != SQLITE_ROW) return false;
auto freelist_count = sqlite3_column_int64(stmt, 0);
rc = sqlite3_errcode(db);
if (rc != SQLITE_OK && rc != SQLITE_DONE && rc != SQLITE_ROW) return false;
std::cout << "There are " << freelist_count << " pages in the free list." << std::endl;
rc = sqlite3_prepare_v2(db, "pragma incremental_vacuum;", -1, &stmt, nullptr);
uint64_t pages = 0;
if (rc != SQLITE_OK) return false;
do {
rc = sqlite3_step(stmt);
if (rc == SQLITE_ROW) ++ pages;
} while (rc == SQLITE_ROW);
if (rc != SQLITE_DONE) return false;
std::cout << "Freed " << pages << " pages" << std::endl;
return true;
}