diff options
author | Hannah von Reth <hannah.vonreth@owncloud.com> | 2022-08-19 12:35:52 +0300 |
---|---|---|
committer | Hannah von Reth <vonreth@kde.org> | 2022-11-02 12:45:42 +0300 |
commit | 18bbbe7c6973d19756b776b13d05f7a418365269 (patch) | |
tree | b3f8fa44fad9fc57997869e7eae74528f8f43bc3 | |
parent | f6cff6f7cb4d6b0274ffc770747e227518a7e92a (diff) |
When pretty printing sqlit, also log converted type
-rw-r--r-- | src/common/ownsql.cpp | 41 | ||||
-rw-r--r-- | src/common/ownsql.h | 28 |
2 files changed, 47 insertions, 22 deletions
diff --git a/src/common/ownsql.cpp b/src/common/ownsql.cpp index ab946845a..c317dba2d 100644 --- a/src/common/ownsql.cpp +++ b/src/common/ownsql.cpp @@ -272,22 +272,19 @@ int SqlQuery::prepare(const QByteArray &sql, bool allow_failure) if (_stmt) { finish(); } - _boundQuery = QString::fromUtf8(_sql); if (!_sql.isEmpty()) { - int rc = {}; for (int n = 0; n < SQLITE_REPEAT_COUNT; ++n) { qCDebug(lcSql) << "SQL prepare" << _sql << "Try:" << n; - rc = sqlite3_prepare_v2(_db, _sql.constData(), -1, &_stmt, nullptr); - if (rc != SQLITE_OK) { + _errId = sqlite3_prepare_v2(_db, _sql.constData(), -1, &_stmt, nullptr); + if (_errId != SQLITE_OK) { qCWarning(lcSql) << "SQL prepare failed" << _sql << QString::fromUtf8(sqlite3_errmsg(_db)); - if ((rc == SQLITE_BUSY) || (rc == SQLITE_LOCKED)) { + if ((_errId == SQLITE_BUSY) || (_errId == SQLITE_LOCKED)) { std::this_thread::sleep_for(SQLITE_SLEEP_TIME); continue; } } break; } - _errId = rc; if (_errId != SQLITE_OK) { _error = QString::fromUtf8(sqlite3_errmsg(_db)); @@ -296,6 +293,13 @@ int SqlQuery::prepare(const QByteArray &sql, bool allow_failure) } else { OC_ASSERT(_stmt); _sqldb->_queries.insert(this); + + if (lcSql().isDebugEnabled()) { + _boundValues.resize(sqlite3_bind_parameter_count(_stmt)); + for (int i = 1; i <= _boundValues.size(); ++i) { + _boundValues[i - 1].name = QString::fromUtf8(sqlite3_bind_parameter_name(_stmt, i)); + } + } } } return _errId; @@ -328,20 +332,32 @@ bool SqlQuery::exec() } // Don't do anything for selects, that is how we use the lib :-| if (!isSelect() && !isPragma()) { - int rc = 0; for (int n = 0; n < SQLITE_REPEAT_COUNT; ++n) { - qCDebug(lcSql) << "SQL exec" << _boundQuery << "Try:" << n; - rc = sqlite3_step(_stmt); - if (rc != SQLITE_DONE && rc != SQLITE_ROW) { + if (lcSql().isDebugEnabled()) { + if (!_boundValues.isEmpty()) { + // Try to create a pretty printed version of the sql query + // the result can be inaccurate + QString query = QString::fromUtf8(_sql); + for (const auto &v : _boundValues) { + query.replace(query.indexOf(v.name), v.name.size(), v.value); + } + char *actualQuery = sqlite3_expanded_sql(_stmt); + qCDebug(lcSql) << "SQL exec: Estimated query:" << query << "Actual query:" << QString::fromUtf8(actualQuery) << "Try:" << n; + sqlite3_free(actualQuery); + } else { + qCDebug(lcSql) << "SQL exec:" << _sql << "Try:" << n; + } + } + _errId = sqlite3_step(_stmt); + if (_errId != SQLITE_DONE && _errId != SQLITE_ROW) { qCWarning(lcSql) << "SQL exec failed" << _sql << QString::fromUtf8(sqlite3_errmsg(_db)); - if (rc == SQLITE_LOCKED || rc == SQLITE_BUSY) { + if (_errId == SQLITE_LOCKED || _errId == SQLITE_BUSY) { std::this_thread::sleep_for(SQLITE_SLEEP_TIME); continue; } } break; } - _errId = rc; if (_errId != SQLITE_DONE && _errId != SQLITE_ROW) { _error = QString::fromUtf8(sqlite3_errmsg(_db)); @@ -512,7 +528,6 @@ void SqlQuery::reset_and_clear_bindings() if (_stmt) { SQLITE_DO(sqlite3_reset(_stmt)); SQLITE_DO(sqlite3_clear_bindings(_stmt)); - _boundQuery = QString::fromUtf8(_sql); } } diff --git a/src/common/ownsql.h b/src/common/ownsql.h index 13c4f17b8..0f6963c53 100644 --- a/src/common/ownsql.h +++ b/src/common/ownsql.h @@ -136,10 +136,15 @@ public: template <class T> void bindValue(int pos, const T &value) { - QString s; - QDebug(&s).noquote().nospace() << '\'' << value << '\''; - _boundQuery.replace(QStringLiteral("?%1").arg(QString::number(pos)), s); - bindValueConvert(pos, value); + const auto converted = convertValue(value); + if (lcSql().isDebugEnabled()) { + auto stream = QDebug(&_boundValues[pos - 1].value).noquote().nospace() << '\'' << value; + if (typeid(converted) != typeid(value)) { + stream << " [" << converted << ']'; + } + stream << '\''; + } + bindValueInternal(pos, converted); } const QByteArray &lastQuery() const; @@ -148,15 +153,15 @@ public: private: template <class T, typename std::enable_if<std::is_enum<T>::value, int>::type = 0> - void bindValueConvert(int pos, const T &value) + auto convertValue(const T &value) { - bindValueInternal(pos, static_cast<int>(value)); + return static_cast<int>(value); } template <class T, typename std::enable_if<!std::is_enum<T>::value, int>::type = 0> - void bindValueConvert(int pos, const T &value) + auto convertValue(const T &value) { - bindValueInternal(pos, value); + return value; } void bindValueInternal(int pos, const QVariant &value); @@ -168,7 +173,12 @@ private: QString _error; int _errId; QByteArray _sql; - QString _boundQuery; + struct Binding + { + QString name; + QString value; + }; + QVector<Binding> _boundValues; friend class SqlDatabase; friend class PreparedSqlQueryManager; |