Always reset prepared sql statements

This allow the creation of checkpoints and fixes the growing wal issue

Fixes: #7646
This commit is contained in:
Hannah von Reth 2021-01-15 16:31:57 +01:00 committed by Matthieu Gallien (Rebase PR Action)
parent 6e0a43b570
commit 3b99b11849
4 changed files with 448 additions and 370 deletions

View file

@ -490,18 +490,28 @@ void SqlQuery::reset_and_clear_bindings()
} }
} }
bool SqlQuery::initOrReset(const QByteArray &sql, OCC::SqlDatabase &db) PreparedSqlQueryRAII::PreparedSqlQueryRAII(SqlQuery *query)
: _query(query)
{ {
ENFORCE(!_sqldb || &db == _sqldb); Q_ASSERT(!sqlite3_stmt_busy(_query->_stmt));
_sqldb = &db; }
_db = db.sqliteDb();
if (_stmt) { PreparedSqlQueryRAII::PreparedSqlQueryRAII(SqlQuery *query, const QByteArray &sql, SqlDatabase &db)
reset_and_clear_bindings(); : _query(query)
return true; {
} else { Q_ASSERT(!sqlite3_stmt_busy(_query->_stmt));
return prepare(sql) == 0; ENFORCE(!query->_sqldb || &db == query->_sqldb)
query->_sqldb = &db;
query->_db = db.sqliteDb();
if (!query->_stmt) {
_ok = query->prepare(sql) == 0;
} }
} }
PreparedSqlQueryRAII::~PreparedSqlQueryRAII()
{
_query->reset_and_clear_bindings();
}
} // namespace OCC } // namespace OCC

View file

@ -103,12 +103,6 @@ public:
explicit SqlQuery() = default; explicit SqlQuery() = default;
explicit SqlQuery(SqlDatabase &db); explicit SqlQuery(SqlDatabase &db);
explicit SqlQuery(const QByteArray &sql, SqlDatabase &db); explicit SqlQuery(const QByteArray &sql, SqlDatabase &db);
/**
* Prepare the SqlQuery if it was not prepared yet.
* Otherwise, clear the results and the bindings.
* return false if there is an error
*/
bool initOrReset(const QByteArray &sql, SqlDatabase &db);
/** /**
* Prepare the SqlQuery. * Prepare the SqlQuery.
* If the query was already prepared, this will first call finish(), and re-prepare it. * If the query was already prepared, this will first call finish(), and re-prepare it.
@ -174,8 +168,42 @@ private:
QByteArray _sql; QByteArray _sql;
friend class SqlDatabase; friend class SqlDatabase;
friend class PreparedSqlQueryRAII;
}; };
class OCSYNC_EXPORT PreparedSqlQueryRAII
{
public:
/**
* Simple Guard which allow reuse of prepared querys.
* The queries are reset in the destructor to prevent wal locks
*/
PreparedSqlQueryRAII(SqlQuery *query);
/**
* Prepare the SqlQuery if it was not prepared yet.
*/
PreparedSqlQueryRAII(SqlQuery *query, const QByteArray &sql, SqlDatabase &db);
~PreparedSqlQueryRAII();
explicit operator bool() const { return _ok; }
SqlQuery *operator->() const
{
Q_ASSERT(_ok);
return _query;
}
SqlQuery &operator*() const &
{
Q_ASSERT(_ok);
return *_query;
}
private:
SqlQuery *const _query;
bool _ok = true;
Q_DISABLE_COPY(PreparedSqlQueryRAII);
};
} // namespace OCC } // namespace OCC
#endif // OWNSQL_H #endif // OWNSQL_H

File diff suppressed because it is too large Load diff

View file

@ -137,7 +137,7 @@ private slots:
SqlQuery q3("SELECT * FROM addresses", _db); SqlQuery q3("SELECT * FROM addresses", _db);
SqlQuery q4; SqlQuery q4;
SqlQuery q5; SqlQuery q5;
q5.initOrReset("SELECT * FROM addresses", _db); PreparedSqlQueryRAII testQuery(&q5, "SELECT * FROM addresses", _db);
db.reset(); db.reset();
} }