Skip to content

Commit

Permalink
Always reset prepared sql statements
Browse files Browse the repository at this point in the history
This allow the creation of checkpoints and fixes the growing wal issue

Fixes: #7646
  • Loading branch information
TheOneRing committed Jan 18, 2021
1 parent 7d11079 commit 0bd392b
Show file tree
Hide file tree
Showing 5 changed files with 397 additions and 320 deletions.
5 changes: 5 additions & 0 deletions changelog/unreleased/7646
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Bugfix: SQLite wal file grows to several gigabyte

We fixed a bug where the SQLite wal file growed until the client was quit.

https://github.com/owncloud/client/issues/7646
28 changes: 19 additions & 9 deletions src/common/ownsql.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -494,18 +494,28 @@ void SqlQuery::reset_and_clear_bindings()
}
}

bool SqlQuery::initOrReset(const QByteArray &sql, OCC::SqlDatabase &db)
PreparedSqlQueryRAII::PreparedSqlQueryRAII(SqlQuery *query)
: _query(query)
{
OC_ENFORCE(!_sqldb || &db == _sqldb);
_sqldb = &db;
_db = db.sqliteDb();
if (_stmt) {
reset_and_clear_bindings();
return true;
} else {
return prepare(sql) == 0;
Q_ASSERT(!sqlite3_stmt_busy(_query->_stmt));
}

PreparedSqlQueryRAII::PreparedSqlQueryRAII(SqlQuery *query, const QByteArray &sql, SqlDatabase &db)
: _query(query)
{
Q_ASSERT(!sqlite3_stmt_busy(_query->_stmt));
OC_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
41 changes: 35 additions & 6 deletions src/common/ownsql.h
Original file line number Diff line number Diff line change
Expand Up @@ -104,12 +104,6 @@ class OCSYNC_EXPORT SqlQuery
explicit SqlQuery() = default;
explicit SqlQuery(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.
* If the query was already prepared, this will first call finish(), and re-prepare it.
Expand Down Expand Up @@ -167,8 +161,43 @@ class OCSYNC_EXPORT SqlQuery
QString _error;
int _errId;
QByteArray _sql;

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

#endif // OWNSQL_H
Loading

0 comments on commit 0bd392b

Please sign in to comment.