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.
This commit is contained in:
Martin Kleusberg
2019-02-21 14:10:14 +01:00
parent 042e925f9f
commit 282387ced7
4 changed files with 65 additions and 5 deletions

View File

@@ -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

View File

@@ -1082,6 +1082,11 @@ You can drag SQL statements from an object row and drop them into other applicat
<string>Application</string>
</property>
</item>
<item>
<property name="text">
<string>Error Log</string>
</property>
</item>
</widget>
</item>
<item>
@@ -1145,6 +1150,17 @@ You can drag SQL statements from an object row and drop them into other applicat
<bool>true</bool>
</property>
</widget>
<widget class="ExtendedScintilla" name="editLogErrorLog">
<property name="font">
<font>
<family>Monospace</family>
<pointsize>8</pointsize>
</font>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</widget>
</item>
</layout>
@@ -2523,6 +2539,12 @@ You can drag SQL statements from the Schema column and drop them into the SQL ed
<signal>foreignKeyClicked(sqlb::ObjectIdentifier,QString,QByteArray)</signal>
</slots>
</customwidget>
<customwidget>
<class>ExtendedScintilla</class>
<extends>QTextEdit</extends>
<header>ExtendedScintilla.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<tabstops>
<tabstop>mainTab</tabstop>
@@ -3107,6 +3129,22 @@ You can drag SQL statements from the Schema column and drop them into the SQL ed
</hint>
</hints>
</connection>
<connection>
<sender>buttonLogClear</sender>
<signal>clicked()</signal>
<receiver>editLogErrorLog</receiver>
<slot>clear()</slot>
<hints>
<hint type="sourcelabel">
<x>989</x>
<y>126</y>
</hint>
<hint type="destinationlabel">
<x>632</x>
<y>173</y>
</hint>
</hints>
</connection>
<connection>
<sender>comboLogSubmittedBy</sender>
<signal>currentIndexChanged(int)</signal>

View File

@@ -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<void(void*, int, const char*)>::func = std::bind(&DBBrowserDB::errorLogCallback, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3);
void (*log_callback)(void*, int, const char*) = static_cast<decltype(log_callback)>(Callback<void(void*, int, const char*)>::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();

View File

@@ -15,10 +15,11 @@
struct sqlite3;
class CipherSettings;
enum
enum LogMessageType
{
kLogMsg_User,
kLogMsg_App
kLogMsg_App,
kLogMsg_ErrorLog
};
typedef QMultiMap<QString, sqlb::ObjectPtr> 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);