Repository: nomic-ai/gpt4all
File: gpt4all-chat/src/database.cpp (C++)

Code before:
        qDebug() << "retrieve rowid:" << rowid
                 << "chunk_text:" << chunk_text;
#endif
    }

    for (int id : searchResults)
        if (tempResults.contains(id))
            results->append(tempResults.value(id));
}

bool Database::ftsIntegrityCheck()
{
    bool isConsistent = false;

    QSqlQuery q(m_db);
    if (!q.prepare("insert into chunks_fts(chunks_fts, rank) values('integrity-check', 1);")) {
        qWarning() << "ERROR: Cannot prepare sql for fts integrity check" << q.lastError();
        return false;
    }

    // Returns an error executing sql if it the integrity check fails
    // See: https://www.sqlite.org/fts5.html#the_integrity_check_command
    isConsistent = q.exec();

    if (!isConsistent) {
        if (!q.prepare("insert into chunks_fts(chunks_fts) values('rebuild');")) {
            qWarning() << "ERROR: Cannot prepare sql for fts rebuild" << q.lastError();
            return false;
        }

        if (!q.exec()) {
            qWarning() << "ERROR: Cannot exec sql for fts rebuild" << q.lastError();
            return false;
        }
    }

    return true;
}

// FIXME This is very slow and non-interruptible and when we close the application and we're
// cleaning a large table this can cause the app to take forever to shut down. This would ideally be
// interruptible and we'd continue 'cleaning' when we restart
bool Database::cleanDB()
{
#if defined(DEBUG)
    qDebug() << "cleanDB";
#endif

    // Scan all folders in db to make sure they still exist
    QSqlQuery q(m_db);
    QList<CollectionItem> collections;

Review comment (suggestion):
If we don't use any bind values, why don't we exec in-place?
```suggestion
        if (!q.exec("insert into chunks_fts(chunks_fts) values('rebuild');")) {
```

Code after:
        info.text = chunk_text;
        info.page = page;
        info.from = from;
        info.to = to;
        tempResults.insert(rowid, info);
#if defined(DEBUG)
        qDebug() << "retrieve rowid:" << rowid
                 << "chunk_text:" << chunk_text;
#endif
    }

    for (int id : searchResults)
        if (tempResults.contains(id))
            results->append(tempResults.value(id));
}

bool Database::ftsIntegrityCheck()
{
    QSqlQuery q(m_db);

    // Returns an error executing sql if it the integrity check fails
    // See: https://www.sqlite.org/fts5.html#the_integrity_check_command
    const bool success = q.exec(FTS_INTEGRITY_SQL);
    if (!success && q.lastError().nativeErrorCode() != "267" /*SQLITE_CORRUPT_VTAB from sqlite header*/) {
        qWarning() << "ERROR: Cannot prepare sql for fts integrity check" << q.lastError();
        return false;
    }

    if (!success && !q.exec(FTS_REBUILD_SQL)) {
        qWarning() << "ERROR: Cannot exec sql for fts rebuild" << q.lastError();
        return false;
    }

    return true;
}

// FIXME This is very slow and non-interruptible and when we close the application and we're
// cleaning a large table this can cause the app to take forever to shut down. This would ideally be
// interruptible and we'd continue 'cleaning' when we restart
bool Database::cleanDB()
{
#if defined(DEBUG)
    qDebug() << "cleanDB";
#endif

    // Scan all folders in db to make sure they still exist
    QSqlQuery q(m_db);
    QList<CollectionItem> collections;
    if (!selectAllFromCollections(q, &collections)) {
        qWarning() << "ERROR: Cannot select collections" << q.lastError();
        return false;