From 282387ced75a501c9d2cb87e4de92c2cb221cc0e Mon Sep 17 00:00:00 2001 From: Martin Kleusberg Date: Thu, 21 Feb 2019 14:10:14 +0100 Subject: [PATCH] Add new logging section for SQLite's error log Add a new logging section to the SQL log panel called "Error Log". Register a callback to receive errors and warnings from SQLite and add them to the new error log section. See issue #1754. --- src/MainWindow.cpp | 8 +++++++- src/MainWindow.ui | 38 ++++++++++++++++++++++++++++++++++++++ src/sqlitedb.cpp | 15 ++++++++++++++- src/sqlitedb.h | 9 ++++++--- 4 files changed, 65 insertions(+), 5 deletions(-) diff --git a/src/MainWindow.cpp b/src/MainWindow.cpp index 3dde85bf..bd049f09 100644 --- a/src/MainWindow.cpp +++ b/src/MainWindow.cpp @@ -933,6 +933,7 @@ bool MainWindow::fileClose() // Clear the SQL Log ui->editLogApplication->clear(); ui->editLogUser->clear(); + ui->editLogErrorLog->clear(); return true; } @@ -2118,9 +2119,12 @@ void MainWindow::logSql(const QString& sql, int msgtype) { ui->editLogUser->append(sql + "\n"); ui->editLogUser->verticalScrollBar()->setValue(ui->editLogUser->verticalScrollBar()->maximum()); - } else { + } else if(msgtype == kLogMsg_App) { ui->editLogApplication->append(sql + "\n"); ui->editLogApplication->verticalScrollBar()->setValue(ui->editLogApplication->verticalScrollBar()->maximum()); + } else if(msgtype == kLogMsg_ErrorLog) { + ui->editLogErrorLog->append(sql + "\n"); + ui->editLogErrorLog->verticalScrollBar()->setValue(ui->editLogErrorLog->verticalScrollBar()->maximum()); } } @@ -2378,8 +2382,10 @@ void MainWindow::reloadSettings() // Set font for SQL logs and edit dialog ui->editLogApplication->reloadSettings(); ui->editLogUser->reloadSettings(); + ui->editLogErrorLog->reloadSettings(); ui->editLogApplication->setFont(logfont); ui->editLogUser->setFont(logfont); + ui->editLogErrorLog->setFont(logfont); editDock->reloadSettings(); // Load extensions diff --git a/src/MainWindow.ui b/src/MainWindow.ui index bd36d7cc..ac039b17 100644 --- a/src/MainWindow.ui +++ b/src/MainWindow.ui @@ -1082,6 +1082,11 @@ You can drag SQL statements from an object row and drop them into other applicat Application + + + Error Log + + @@ -1145,6 +1150,17 @@ You can drag SQL statements from an object row and drop them into other applicat true + + + + Monospace + 8 + + + + true + + @@ -2523,6 +2539,12 @@ You can drag SQL statements from the Schema column and drop them into the SQL ed foreignKeyClicked(sqlb::ObjectIdentifier,QString,QByteArray) + + ExtendedScintilla + QTextEdit +
ExtendedScintilla.h
+ 1 +
mainTab @@ -3107,6 +3129,22 @@ You can drag SQL statements from the Schema column and drop them into the SQL ed + + buttonLogClear + clicked() + editLogErrorLog + clear() + + + 989 + 126 + + + 632 + 173 + + + comboLogSubmittedBy currentIndexChanged(int) diff --git a/src/sqlitedb.cpp b/src/sqlitedb.cpp index 73d5df32..185911f1 100644 --- a/src/sqlitedb.cpp +++ b/src/sqlitedb.cpp @@ -74,6 +74,13 @@ void DBBrowserDB::collationNeeded(void* /*pData*/, sqlite3* /*db*/, int eTextRep } } +void DBBrowserDB::errorLogCallback(void* /*user_data*/, int error_code, const char* message) +{ + QString msg = QString("(%1) %2").arg(error_code).arg(message); + + logSQL(msg, kLogMsg_ErrorLog); +} + static void regexp(sqlite3_context* ctx, int /*argc*/, sqlite3_value* argv[]) { // Get arguments and check their values @@ -115,6 +122,12 @@ bool DBBrowserDB::open(const QString& db, bool readOnly) if(tryEncryptionSettings(db, &isEncrypted, cipherSettings) == false) return false; + // Register error log callback. We need to make sure SQLite is being shut down before calling sqlite3_config. + sqlite3_shutdown(); + Callback::func = std::bind(&DBBrowserDB::errorLogCallback, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3); + void (*log_callback)(void*, int, const char*) = static_cast(Callback::callback); + sqlite3_config(SQLITE_CONFIG_LOG, log_callback, nullptr); + // Open database file if(sqlite3_open_v2(db.toUtf8(), &_db, readOnly ? SQLITE_OPEN_READONLY : SQLITE_OPEN_READWRITE, nullptr) != SQLITE_OK) { @@ -1777,7 +1790,7 @@ objectMap DBBrowserDB::getBrowsableObjects(const QString& schema) const return res; } -void DBBrowserDB::logSQL(QString statement, int msgtype) +void DBBrowserDB::logSQL(QString statement, LogMessageType msgtype) { // Remove any leading and trailing spaces, tabs, or line breaks first statement = statement.trimmed(); diff --git a/src/sqlitedb.h b/src/sqlitedb.h index d50cb7d3..1722a37b 100644 --- a/src/sqlitedb.h +++ b/src/sqlitedb.h @@ -15,10 +15,11 @@ struct sqlite3; class CipherSettings; -enum +enum LogMessageType { kLogMsg_User, - kLogMsg_App + kLogMsg_App, + kLogMsg_ErrorLog }; typedef QMultiMap objectMap; // Maps from object type (table, index, view, trigger) to a pointer to the object representation @@ -211,7 +212,7 @@ public: QString currentFile() const { return curDBFilename; } /// log an SQL statement [thread-safe] - void logSQL(QString statement, int msgtype); + void logSQL(QString statement, LogMessageType msgtype); QString getPragma(const QString& pragma); bool setPragma(const QString& pragma, const QString& value); @@ -262,7 +263,9 @@ private: QString primaryKeyForEditing(const sqlb::ObjectIdentifier& table, const QString& pseudo_pk) const; + // SQLite Callbacks void collationNeeded(void* pData, sqlite3* db, int eTextRep, const char* sCollationName); + void errorLogCallback(void* user_data, int error_code, const char* message); bool tryEncryptionSettings(const QString& filename, bool* encrypted, CipherSettings*& cipherSettings);