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 4010db8 commit 0f89722
Show file tree
Hide file tree
Showing 5 changed files with 396 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
40 changes: 34 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 @@ -169,8 +163,42 @@ class OCSYNC_EXPORT SqlQuery
QByteArray _sql;

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

#endif // OWNSQL_H
Loading

0 comments on commit 0f89722

Please sign in to comment.