Fix: openening not accessible database crashes program.

OpenDatabase::createOpenDatabase now uses QException derived exception to report failure.
This makes it possible to catch the exception in a background thread and rethrow it when the Future is read.
Which makes it possible for the database window to properly report the problem.
This commit is contained in:
eelke 2019-01-29 19:41:27 +01:00
parent 3820fb2600
commit ecae0464f9
5 changed files with 36 additions and 24 deletions

View file

@ -1,6 +1,7 @@
#include "DatabaseWindow.h" #include "DatabaseWindow.h"
#include "plugin_support/IPluginContentWidgetContext.h" #include "plugin_support/IPluginContentWidgetContext.h"
#include "util.h" #include "util.h"
#include "OpenDatabase.h"
#include "MasterController.h" #include "MasterController.h"
#include "TaskExecutor.h" #include "TaskExecutor.h"
#include <QApplication> #include <QApplication>
@ -84,9 +85,8 @@ void DatabaseWindow::catalogLoaded()
m_tabWidget->addTab(sequences_page, "Sequences"); m_tabWidget->addTab(sequences_page, "Sequences");
newCreateTablePage(); newCreateTablePage();
} catch (std::runtime_error &ex) { } catch (const OpenDatabaseException &ex) {
QMessageBox::critical(this, "Error reading database", QMessageBox::critical(this, "Error reading database", ex.text());
QString::fromUtf8(ex.what()));
close(); close();
} }

View file

@ -51,8 +51,7 @@ private:
OpenDatabase::OpenDatabaseSPtr run(TaskControl& ) override OpenDatabase::OpenDatabaseSPtr run(TaskControl& ) override
{ {
auto res = OpenDatabase::createOpenDatabase(m_config); return OpenDatabase::createOpenDatabase(m_config);
return res.get();
} }
private: private:

View file

@ -1,22 +1,19 @@
#include "OpenDatabase.h" #include "OpenDatabase.h"
#include "catalog/PgDatabaseCatalog.h" #include "catalog/PgDatabaseCatalog.h"
#include "Pgsql_Connection.h" #include "Pgsql_Connection.h"
#include "Pgsql_PgException.h"
#include "model/TypeSelectionItemModel.h" #include "model/TypeSelectionItemModel.h"
Expected<OpenDatabase::OpenDatabaseSPtr> OpenDatabase::createOpenDatabase(const ConnectionConfig &cfg) OpenDatabase::OpenDatabaseSPtr OpenDatabase::createOpenDatabase(const ConnectionConfig &cfg)
{ {
return Expected<OpenDatabase::OpenDatabaseSPtr>::fromCode( try {
[&cfg] () -> auto { OpenDatabaseSPtr odb(new OpenDatabase(cfg));
OpenDatabaseSPtr odb(new OpenDatabase(cfg)); odb->Init();
odb->Init(); return odb;
return odb; }
}); catch (const Pgsql::PgException &ex) {
// catch (const PgException &ex) { throw OpenDatabaseException(ex.what());
// return }
// }
// return Expected<OpenDatabaseSPtr>::fromException(
// std::runtime_error("Failed to get database information"));
} }
OpenDatabase::OpenDatabase(const ConnectionConfig& cfg) OpenDatabase::OpenDatabase(const ConnectionConfig& cfg)

View file

@ -2,19 +2,33 @@
#define OPENDATABASE_H #define OPENDATABASE_H
#include "ConnectionConfig.h" #include "ConnectionConfig.h"
#include "Expected.h" #include <QException>
#include <memory> #include <memory>
class PgDatabaseCatalog; class PgDatabaseCatalog;
class TypeSelectionItemModel; class TypeSelectionItemModel;
class OpenDatabaseException : public QException {
public:
OpenDatabaseException(QString message)
: m_message(std::move(message))
{}
QString text() const { return m_message; }
void raise() const override { throw *this; }
OpenDatabaseException *clone() const override { return new OpenDatabaseException(*this); }
private:
QString m_message;
};
/** Instances of this class represent a single database on which atleast one /** Instances of this class represent a single database on which atleast one
* window is opened. This class is used to track details about that database. * window is opened. This class is used to track details about that database.
*/ */
class OpenDatabase { class OpenDatabase {
public: public:
using OpenDatabaseSPtr = std::shared_ptr<OpenDatabase>; using OpenDatabaseSPtr = std::shared_ptr<OpenDatabase>;
static Expected<OpenDatabaseSPtr> createOpenDatabase(const ConnectionConfig &cfg); static OpenDatabaseSPtr createOpenDatabase(const ConnectionConfig &cfg);
// using on_createResult_callback = std::function<void(Expected<std::shared_ptr<Pgsql::Result>>)>; // using on_createResult_callback = std::function<void(Expected<std::shared_ptr<Pgsql::Result>>)>;
// void asyncCreateOpenDatabase(const ConnectionConfig &cfg, on_createResult_callback); // void asyncCreateOpenDatabase(const ConnectionConfig &cfg, on_createResult_callback);

View file

@ -4,6 +4,7 @@
#include "DatabasesTableModel.h" #include "DatabasesTableModel.h"
#include "RolesTableModel.h" #include "RolesTableModel.h"
#include "catalog/PgDatabaseCatalog.h" #include "catalog/PgDatabaseCatalog.h"
#include <QDebug>
ServerWindow::ServerWindow(MasterController *master, QWidget *parent) ServerWindow::ServerWindow(MasterController *master, QWidget *parent)
: QMainWindow(parent) : QMainWindow(parent)
@ -27,17 +28,18 @@ ServerWindow::~ServerWindow()
void ServerWindow::setConfig(const ConnectionConfig &config) void ServerWindow::setConfig(const ConnectionConfig &config)
{ {
m_config = config; m_config = config;
auto res = OpenDatabase::createOpenDatabase(config); try {
if (res.valid()) { m_database = OpenDatabase::createOpenDatabase(config);
m_database = res.get();
auto cat = m_database->catalog(); auto cat = m_database->catalog();
if (cat) { if (cat) {
m_databasesModel->setDatabaseList(cat); m_databasesModel->setDatabaseList(cat);
m_rolesModel->setRoleList(cat->authIds()); m_rolesModel->setRoleList(cat->authIds());
} }
} }
catch (const OpenDatabaseException &ex) {
qWarning() << ex.text();
}
QString title = "pglab - "; QString title = "pglab - ";
title += m_config.name().c_str(); title += m_config.name().c_str();
setWindowTitle(title); setWindowTitle(title);
// newSqlPage();
} }