Improved error reporting
This commit is contained in:
parent
6cf7b52453
commit
457b09f15c
12 changed files with 110 additions and 94 deletions
|
|
@ -254,13 +254,18 @@ void ConnectionConfigurationWidget::testConnection()
|
||||||
cc.setPassword(password);
|
cc.setPassword(password);
|
||||||
|
|
||||||
auto qthis = QPointer(this);
|
auto qthis = QPointer(this);
|
||||||
QFuture<void> result = QtConcurrent::run([cc] {
|
QFuture<void> result = QtConcurrent::run(
|
||||||
|
[cc]
|
||||||
|
{
|
||||||
return TestConnection(cc);
|
return TestConnection(cc);
|
||||||
}).then(qApp, [qthis](TestConnectionResult result) {
|
}
|
||||||
if (qthis) {
|
).then(qApp,
|
||||||
|
[qthis](TestConnectionResult result)
|
||||||
|
{
|
||||||
|
if (qthis)
|
||||||
qthis.data()->handleTestResult(result);
|
qthis.data()->handleTestResult(result);
|
||||||
}
|
}
|
||||||
});
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConnectionConfigurationWidget::handleTestResult(TestConnectionResult result)
|
void ConnectionConfigurationWidget::handleTestResult(TestConnectionResult result)
|
||||||
|
|
|
||||||
|
|
@ -118,6 +118,14 @@ void DatabaseWindow::setConfig(const ConnectionConfig &config)
|
||||||
if (qthis)
|
if (qthis)
|
||||||
qthis.data()->catalogLoaded(db);
|
qthis.data()->catalogLoaded(db);
|
||||||
}
|
}
|
||||||
|
).onFailed(qApp, [qthis](OpenDatabaseException &ex)
|
||||||
|
{
|
||||||
|
if (qthis) {
|
||||||
|
QMessageBox::critical(qthis.data(), "Error reading database",
|
||||||
|
ex.text());
|
||||||
|
qthis.data()->close();
|
||||||
|
}
|
||||||
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,6 @@
|
||||||
#include "CustomDataRole.h"
|
#include "CustomDataRole.h"
|
||||||
#include <QtConcurrent>
|
#include <QtConcurrent>
|
||||||
#include <QFuture>
|
#include <QFuture>
|
||||||
#include <QFutureWatcher>
|
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
#include "Pgsql_oids.h"
|
#include "Pgsql_oids.h"
|
||||||
#include "Pgsql_PgException.h"
|
#include "Pgsql_PgException.h"
|
||||||
|
|
@ -247,9 +246,9 @@ void CrudModel::initRowMapping()
|
||||||
m_rowMapping.emplace_back(i);
|
m_rowMapping.emplace_back(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CrudModel::connectionStateChanged(ASyncDBConnection::State state)
|
void CrudModel::connectionStateChanged(ASyncDBConnection::StateData state)
|
||||||
{
|
{
|
||||||
switch (state) {
|
switch (state.State) {
|
||||||
case ASyncDBConnection::State::NotConnected:
|
case ASyncDBConnection::State::NotConnected:
|
||||||
break;
|
break;
|
||||||
case ASyncDBConnection::State::Connecting:
|
case ASyncDBConnection::State::Connecting:
|
||||||
|
|
|
||||||
|
|
@ -259,7 +259,7 @@ private:
|
||||||
private slots:
|
private slots:
|
||||||
|
|
||||||
void loadIntoModel(std::shared_ptr<Pgsql::Result> data);
|
void loadIntoModel(std::shared_ptr<Pgsql::Result> data);
|
||||||
void connectionStateChanged(ASyncDBConnection::State state);
|
void connectionStateChanged(ASyncDBConnection::StateData state);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // CRUDMODEL_H
|
#endif // CRUDMODEL_H
|
||||||
|
|
|
||||||
|
|
@ -314,11 +314,12 @@ void QueryTool::queryTextChanged()
|
||||||
setQueryTextChanged(true);
|
setQueryTextChanged(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void QueryTool::connectionStateChanged(ASyncDBConnection::State state)
|
void QueryTool::connectionStateChanged(ASyncDBConnection::StateData state)
|
||||||
{
|
{
|
||||||
QString iconname;
|
QString iconname;
|
||||||
switch (state) {
|
switch (state.State) {
|
||||||
case ASyncDBConnection::State::NotConnected:
|
case ASyncDBConnection::State::NotConnected:
|
||||||
|
QMessageBox::warning(this, "pglab", tr("Warning connection and any of its session state has been lost"));
|
||||||
startConnect();
|
startConnect();
|
||||||
iconname = "red.png";
|
iconname = "red.png";
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
|
|
@ -113,7 +113,7 @@ private slots:
|
||||||
void query_ready(std::shared_ptr<Pgsql::Result>, qint64 elapsedms);
|
void query_ready(std::shared_ptr<Pgsql::Result>, qint64 elapsedms);
|
||||||
|
|
||||||
void queryTextChanged();
|
void queryTextChanged();
|
||||||
void connectionStateChanged(ASyncDBConnection::State state);
|
void connectionStateChanged(ASyncDBConnection::StateData state);
|
||||||
void receiveNotice(Pgsql::ErrorDetails notice);
|
void receiveNotice(Pgsql::ErrorDetails notice);
|
||||||
|
|
||||||
void startConnect();
|
void startConnect();
|
||||||
|
|
|
||||||
|
|
@ -79,7 +79,7 @@ private:
|
||||||
bool makeConnection();
|
bool makeConnection();
|
||||||
void communicate();
|
void communicate();
|
||||||
|
|
||||||
void doStateCallback(ASyncDBConnection::State state);
|
void doStateCallback(ASyncDBConnection::StateData state);
|
||||||
/// Wait's for a command to come in and send's it to the server
|
/// Wait's for a command to come in and send's it to the server
|
||||||
void waitForAndSendCommand();
|
void waitForAndSendCommand();
|
||||||
void doNewCommand();
|
void doNewCommand();
|
||||||
|
|
@ -106,7 +106,11 @@ void ASyncDBConnectionThread::run()
|
||||||
SCOPE_EXIT {
|
SCOPE_EXIT {
|
||||||
m_state = ASyncDBConnection::State::NotConnected;
|
m_state = ASyncDBConnection::State::NotConnected;
|
||||||
m_terminated = true;
|
m_terminated = true;
|
||||||
|
m_connection.close();
|
||||||
|
// doStateCallback(ASyncDBConnection::State::NotConnected);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
while (!terminateRequested) {
|
while (!terminateRequested) {
|
||||||
|
|
||||||
// make or recover connection
|
// make or recover connection
|
||||||
|
|
@ -132,7 +136,16 @@ void ASyncDBConnectionThread::run()
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// close connection
|
doStateCallback({ ASyncDBConnection::State::NotConnected, QString("terminating") });
|
||||||
|
}
|
||||||
|
catch (const std::exception &ex)
|
||||||
|
{
|
||||||
|
doStateCallback({ ASyncDBConnection::State::NotConnected, QString::fromUtf8(ex.what()) });
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
doStateCallback({ ASyncDBConnection::State::NotConnected, QString::fromUtf8("Unknown error") });
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -146,19 +159,7 @@ bool ASyncDBConnectionThread::makeConnection()
|
||||||
using namespace std::literals::chrono_literals;
|
using namespace std::literals::chrono_literals;
|
||||||
|
|
||||||
// start connecting
|
// start connecting
|
||||||
// auto keywords = m_config.getKeywords();
|
|
||||||
// auto values = m_config.getValues();
|
|
||||||
QString conn_string = m_config.connectionString();
|
QString conn_string = m_config.connectionString();
|
||||||
#if false
|
|
||||||
try {
|
|
||||||
m_connection.connect(conn_string); //keywords, values, 0);
|
|
||||||
doStateCallback(ASyncDBConnection::State::Connected);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
catch (Pgsql::PgConnectionError &) {
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
#else
|
|
||||||
while (!terminateRequested) {
|
while (!terminateRequested) {
|
||||||
|
|
||||||
bool ok = m_connection.connectStart(conn_string); //keywords, values);
|
bool ok = m_connection.connectStart(conn_string); //keywords, values);
|
||||||
|
|
@ -190,20 +191,21 @@ bool ASyncDBConnectionThread::makeConnection()
|
||||||
if (res == wait_result_socket_event) {
|
if (res == wait_result_socket_event) {
|
||||||
auto poll_state = m_connection.connectPoll();
|
auto poll_state = m_connection.connectPoll();
|
||||||
if (poll_state == PGRES_POLLING_OK) {
|
if (poll_state == PGRES_POLLING_OK) {
|
||||||
|
qDebug() << "ASyncDBConnection Connected";
|
||||||
// if connected return true
|
// if connected return true
|
||||||
doStateCallback(ASyncDBConnection::State::Connected);
|
doStateCallback({ ASyncDBConnection::State::Connected, "Success" });
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if (poll_state == PGRES_POLLING_FAILED) {
|
else if (poll_state == PGRES_POLLING_FAILED) {
|
||||||
doStateCallback(ASyncDBConnection::State::NotConnected);
|
doStateCallback({ ASyncDBConnection::State::NotConnected, "Failed to connect" });
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else if (poll_state == PGRES_POLLING_READING) {
|
else if (poll_state == PGRES_POLLING_READING) {
|
||||||
doStateCallback(ASyncDBConnection::State::Connecting);
|
doStateCallback({ ASyncDBConnection::State::Connecting, "Negotiating" });
|
||||||
fd = FD_READ;
|
fd = FD_READ;
|
||||||
}
|
}
|
||||||
else if (poll_state == PGRES_POLLING_WRITING) {
|
else if (poll_state == PGRES_POLLING_WRITING) {
|
||||||
doStateCallback(ASyncDBConnection::State::Connecting);
|
doStateCallback({ ASyncDBConnection::State::Connecting, "Negotiating" });
|
||||||
fd = FD_WRITE;
|
fd = FD_WRITE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -216,7 +218,6 @@ bool ASyncDBConnectionThread::makeConnection()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ASyncDBConnectionThread::communicate()
|
void ASyncDBConnectionThread::communicate()
|
||||||
|
|
@ -252,13 +253,9 @@ void ASyncDBConnectionThread::stop()
|
||||||
m_stopEvent.set();
|
m_stopEvent.set();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ASyncDBConnectionThread::doStateCallback(ASyncDBConnection::State state)
|
void ASyncDBConnectionThread::doStateCallback(ASyncDBConnection::StateData state)
|
||||||
{
|
{
|
||||||
m_state = state;
|
m_state = state.State;
|
||||||
// std::lock_guard<std::mutex> lg(m_stateCallback.m_mutex);
|
|
||||||
// if (m_stateCallback.m_func) {
|
|
||||||
// m_stateCallback.m_func(state);
|
|
||||||
// }
|
|
||||||
Q_EMIT asyncConnObject->onStateChanged(state);
|
Q_EMIT asyncConnObject->onStateChanged(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -289,21 +286,13 @@ void ASyncDBConnectionThread::doNewCommand()
|
||||||
const Command &command = m_commandQueue.m_queue.front();
|
const Command &command = m_commandQueue.m_queue.front();
|
||||||
bool query_send = false;
|
bool query_send = false;
|
||||||
if (command.params.empty())
|
if (command.params.empty())
|
||||||
query_send = m_connection.sendQuery(command.command.c_str());
|
m_connection.sendQuery(command.command.c_str());
|
||||||
else
|
else
|
||||||
query_send = m_connection.sendQueryParams(command.command.c_str(), command.params);
|
m_connection.sendQueryParams(command.command.c_str(), command.params);
|
||||||
|
|
||||||
if (query_send) {
|
|
||||||
m_timer.start();
|
m_timer.start();
|
||||||
doStateCallback(ASyncDBConnection::State::QuerySend);
|
doStateCallback(ASyncDBConnection::State::QuerySend);
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
std::string error = m_connection.getErrorMessage();
|
|
||||||
qDebug() << "Error sending query " << QString::fromStdString(error);
|
|
||||||
// todo: need to report the error
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ASyncDBConnectionThread::consumeResultInput()
|
bool ASyncDBConnectionThread::consumeResultInput()
|
||||||
|
|
@ -332,7 +321,7 @@ bool ASyncDBConnectionThread::consumeResultInput()
|
||||||
// error during consume
|
// error during consume
|
||||||
auto error_msg = m_connection.getErrorMessage();
|
auto error_msg = m_connection.getErrorMessage();
|
||||||
qDebug() << "error while communicating with server " << QString::fromStdString(error_msg);
|
qDebug() << "error while communicating with server " << QString::fromStdString(error_msg);
|
||||||
doStateCallback(ASyncDBConnection::State::NotConnected);
|
doStateCallback({ASyncDBConnection::State::NotConnected, QString::fromStdString(error_msg)});
|
||||||
finished = true;
|
finished = true;
|
||||||
stop();
|
stop();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ class ASyncDBConnectionThread;
|
||||||
class ASyncDBConnection: public QObject {
|
class ASyncDBConnection: public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
|
|
||||||
enum class State {
|
enum class State {
|
||||||
NotConnected,
|
NotConnected,
|
||||||
Connecting,
|
Connecting,
|
||||||
|
|
@ -30,6 +31,17 @@ public:
|
||||||
Terminating ///< shutting down
|
Terminating ///< shutting down
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class StateData {
|
||||||
|
public:
|
||||||
|
State State;
|
||||||
|
QString Message;
|
||||||
|
|
||||||
|
StateData(enum State state, QString message = QString())
|
||||||
|
: State(state)
|
||||||
|
, Message(message)
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
using on_result_callback = std::function<void(Expected<std::shared_ptr<Pgsql::Result>>, qint64)>;
|
using on_result_callback = std::function<void(Expected<std::shared_ptr<Pgsql::Result>>, qint64)>;
|
||||||
|
|
||||||
explicit ASyncDBConnection();
|
explicit ASyncDBConnection();
|
||||||
|
|
@ -51,7 +63,7 @@ public:
|
||||||
bool cancel();
|
bool cancel();
|
||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
void onStateChanged(ASyncDBConnection::State state);
|
void onStateChanged(ASyncDBConnection::StateData state);
|
||||||
void onNotice(Pgsql::ErrorDetails notice);
|
void onNotice(Pgsql::ErrorDetails notice);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
||||||
|
|
@ -115,19 +115,21 @@ Result Connection::queryParam(const QString &command, const Params ¶ms)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool Connection::sendQuery(const char *query)
|
void Connection::sendQuery(const char *query)
|
||||||
{
|
{
|
||||||
int res = PQsendQuery(conn, query);
|
int res = PQsendQuery(conn, query);
|
||||||
return res == 1;
|
if (res == 0)
|
||||||
|
throw PgConnectionError(PQerrorMessage(conn));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Connection::sendQueryParams(const char * command, const Params ¶ms)
|
void Connection::sendQueryParams(const char * command, const Params ¶ms)
|
||||||
{
|
{
|
||||||
int res = PQsendQueryParams(conn, command, params.size(), params.types(),
|
int res = PQsendQueryParams(conn, command, params.size(), params.types(),
|
||||||
params.values(), params.lengths(), params.formats(),
|
params.values(), params.lengths(), params.formats(),
|
||||||
0); // text format
|
0); // text format
|
||||||
|
|
||||||
return res == 1;
|
if (res == 0)
|
||||||
|
throw PgConnectionError(PQerrorMessage(conn));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<Result> Connection::getResult()
|
std::shared_ptr<Result> Connection::getResult()
|
||||||
|
|
|
||||||
|
|
@ -85,17 +85,17 @@ namespace Pgsql {
|
||||||
Result queryParam(const char * command, const Params ¶ms);
|
Result queryParam(const char * command, const Params ¶ms);
|
||||||
Result queryParam(const QString &command, const Params ¶ms);
|
Result queryParam(const QString &command, const Params ¶ms);
|
||||||
|
|
||||||
bool sendQuery(const char * query);
|
void sendQuery(const char * query);
|
||||||
bool sendQuery(const std::string &command)
|
void sendQuery(const std::string &command)
|
||||||
{
|
{
|
||||||
return sendQuery(command.c_str());
|
sendQuery(command.c_str());
|
||||||
}
|
}
|
||||||
bool sendQuery(const QString &command)
|
void sendQuery(const QString &command)
|
||||||
{
|
{
|
||||||
return sendQuery(command.toUtf8().data());
|
sendQuery(command.toUtf8().data());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool sendQueryParams(const char * command, const Params ¶ms);
|
void sendQueryParams(const char * command, const Params ¶ms);
|
||||||
|
|
||||||
std::shared_ptr<Result> getResult();
|
std::shared_ptr<Result> getResult();
|
||||||
std::shared_ptr<Result> getResultNoThrow();
|
std::shared_ptr<Result> getResultNoThrow();
|
||||||
|
|
|
||||||
|
|
@ -84,32 +84,32 @@ namespace Pgsql {
|
||||||
return m_conn->queryParam(command, params);
|
return m_conn->queryParam(command, params);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Transaction::sendQuery(const char * query)
|
void Transaction::sendQuery(const char * query)
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(m_conn != nullptr);
|
BOOST_ASSERT(m_conn != nullptr);
|
||||||
BOOST_ASSERT(m_committed == false);
|
BOOST_ASSERT(m_committed == false);
|
||||||
BOOST_ASSERT(m_rolledback == false);
|
BOOST_ASSERT(m_rolledback == false);
|
||||||
|
|
||||||
return m_conn->sendQuery(query);
|
m_conn->sendQuery(query);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Transaction::sendQuery(const std::string &command)
|
void Transaction::sendQuery(const std::string &command)
|
||||||
{
|
{
|
||||||
return sendQuery(command.c_str());
|
sendQuery(command.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Transaction::sendQuery(const QString &command)
|
void Transaction::sendQuery(const QString &command)
|
||||||
{
|
{
|
||||||
return sendQuery(command.toUtf8().data());
|
sendQuery(command.toUtf8().data());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Transaction::sendQueryParams(const char * command, const Params ¶ms)
|
void Transaction::sendQueryParams(const char * command, const Params ¶ms)
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(m_conn != nullptr);
|
BOOST_ASSERT(m_conn != nullptr);
|
||||||
BOOST_ASSERT(m_committed == false);
|
BOOST_ASSERT(m_committed == false);
|
||||||
BOOST_ASSERT(m_rolledback == false);
|
BOOST_ASSERT(m_rolledback == false);
|
||||||
|
|
||||||
return m_conn->sendQueryParams(command, params);
|
m_conn->sendQueryParams(command, params);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<Result> Transaction::getResult()
|
std::shared_ptr<Result> Transaction::getResult()
|
||||||
|
|
|
||||||
|
|
@ -25,10 +25,10 @@ namespace Pgsql {
|
||||||
Result query(const QString &command);
|
Result query(const QString &command);
|
||||||
Result queryParam(const char * command, const Params ¶ms);
|
Result queryParam(const char * command, const Params ¶ms);
|
||||||
Result queryParam(const QString &command, const Params ¶ms);
|
Result queryParam(const QString &command, const Params ¶ms);
|
||||||
bool sendQuery(const char * query);
|
void sendQuery(const char * query);
|
||||||
bool sendQuery(const std::string &command);
|
void sendQuery(const std::string &command);
|
||||||
bool sendQuery(const QString &command);
|
void sendQuery(const QString &command);
|
||||||
bool sendQueryParams(const char * command, const Params ¶ms);
|
void sendQueryParams(const char * command, const Params ¶ms);
|
||||||
std::shared_ptr<Result> getResult();
|
std::shared_ptr<Result> getResult();
|
||||||
bool consumeInput();
|
bool consumeInput();
|
||||||
bool isBusy();
|
bool isBusy();
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue