Improve error handling

This commit is contained in:
eelke 2022-08-17 18:18:10 +02:00
parent 457b09f15c
commit 80272e81c3
5 changed files with 68 additions and 84 deletions

View file

@ -166,7 +166,8 @@ QVariant TablesTableModel::data(const QModelIndex &index, int role) const
return getData(index); return getData(index);
else if (role == CustomDataTypeRole) else if (role == CustomDataTypeRole)
return getType(index.column()); return getType(index.column());
else if (role == CustomDataMeaningRole) { else if (role == CustomDataMeaningRole)
{
switch (index.column()) { switch (index.column()) {
case TotalSizeCol: case TotalSizeCol:
case TableSizeCol: case TableSizeCol:
@ -191,9 +192,7 @@ void TablesTableModel::StartLoadTableSizes(std::map<Oid, int> oidIndex)
.then(qApp, [p, oidIndex] (TableSizes sizes) .then(qApp, [p, oidIndex] (TableSizes sizes)
{ {
if (p) if (p)
{
p.data()->PopulateSizes(std::move(oidIndex), std::move(sizes)); p.data()->PopulateSizes(std::move(oidIndex), std::move(sizes));
}
}); });
} }

View file

@ -16,6 +16,7 @@
#include "json/json.h" #include "json/json.h"
#include "OpenDatabase.h" #include "OpenDatabase.h"
#include "catalog/PgDatabaseCatalog.h" #include "catalog/PgDatabaseCatalog.h"
#include "Pgsql_PgException.h"
#include "QueryParamListController.h" #include "QueryParamListController.h"
#include "util.h" #include "util.h"
#include "UserConfiguration.h" #include "UserConfiguration.h"
@ -155,16 +156,23 @@ void QueryTool::execute()
auto cb = [this](Expected<std::shared_ptr<Pgsql::Result>> res, qint64 elapsedms) auto cb = [this](Expected<std::shared_ptr<Pgsql::Result>> res, qint64 elapsedms)
{ {
if (res.valid()) { try
auto && dbresult = res.get(); {
QMetaObject::invokeMethod(this, "query_ready", auto dbres = res.get();
Q_ARG(std::shared_ptr<Pgsql::Result>, dbresult), QMetaObject::invokeMethod(this, "query_ready",
Q_ARG(qint64, elapsedms)); Q_ARG(std::shared_ptr<Pgsql::Result>, dbres),
} Q_ARG(qint64, elapsedms));
else { }
/// \todo handle error catch (Pgsql::PgException &ex)
{
//QMessageBox::critical(this, "pglab", QString::fromStdString(ex.what()));
QMetaObject::invokeMethod(this, [this, ex] ()
{
QMessageBox::critical(this, "pglab", QString::fromStdString(ex.what()));
});
}
}
}; };
try { try {
@ -454,78 +462,52 @@ std::string QueryTool::getCommandUtf8() const
void QueryTool::query_ready(std::shared_ptr<Pgsql::Result> dbres, qint64 elapsedms) void QueryTool::query_ready(std::shared_ptr<Pgsql::Result> dbres, qint64 elapsedms)
{ {
if (dbres) { if (!dbres)
addLog("query_ready with result"); {
auto st = dbres->resultStatus(); m_stopwatch.stop();
if (st == PGRES_TUPLES_OK) { addLog("query_ready with NO result");
//int n_rows = dbres->getRows(); return;
//QString rowcount_str = QString("rows: %1").arg(dbres->getRows()); }
auto result_model = std::make_shared<QueryResultModel>(nullptr , dbres, addLog("query_ready with result");
m_catalog); auto st = dbres->resultStatus();
TuplesResultWidget *trw = new TuplesResultWidget; if (st == PGRES_TUPLES_OK) {
trw->setResult(result_model, elapsedms); //int n_rows = dbres->getRows();
resultList.push_back(trw); //QString rowcount_str = QString("rows: %1").arg(dbres->getRows());
ui->tabWidget->addTab(trw, "Data");
if (resultList.size() == 1)
ui->tabWidget->setCurrentWidget(trw);
} auto result_model = std::make_shared<QueryResultModel>(nullptr , dbres,
else { m_catalog);
if (st == PGRES_COMMAND_OK) { TuplesResultWidget *trw = new TuplesResultWidget;
int tuples_affected = dbres->tuplesAffected(); trw->setResult(result_model, elapsedms);
QString msg; resultList.push_back(trw);
if (tuples_affected >= 0) ui->tabWidget->addTab(trw, "Data");
msg = tr("Query returned succesfully: %1 rows affected, execution time %2") if (resultList.size() == 1)
.arg(QString::number(tuples_affected)) ui->tabWidget->setCurrentWidget(trw);
.arg(msfloatToHumanReadableString(elapsedms));
else
msg = tr("Query returned succesfully, execution time %1")
.arg(msfloatToHumanReadableString(elapsedms));
ui->messagesEdit->append(msg); }
else {
if (st == PGRES_COMMAND_OK) {
int tuples_affected = dbres->tuplesAffected();
QString msg;
if (tuples_affected >= 0)
msg = tr("Query returned succesfully: %1 rows affected, execution time %2")
.arg(QString::number(tuples_affected))
.arg(msfloatToHumanReadableString(elapsedms));
else
msg = tr("Query returned succesfully, execution time %1")
.arg(msfloatToHumanReadableString(elapsedms));
ui->tabWidget->setCurrentWidget(ui->messageTab); ui->messagesEdit->append(msg);
}
else { ui->tabWidget->setCurrentWidget(ui->messageTab);
// if (st == PGRES_EMPTY_QUERY) { }
// statusBar()->showMessage(tr("Empty query.")); else {
// } ui->tabWidget->setCurrentWidget(ui->messageTab);
// else if (st == PGRES_COPY_OUT) { auto details = dbres->diagDetails();
// statusBar()->showMessage(tr("COPY OUT.")); markError(details);
// } receiveNotice(details);
// else if (st == PGRES_COPY_IN) { }
// statusBar()->showMessage(tr("COPY IN.")); }
// }
// else if (st == PGRES_BAD_RESPONSE) {
// statusBar()->showMessage(tr("BAD RESPONSE."));
// }
// else if (st == PGRES_NONFATAL_ERROR) {
// statusBar()->showMessage(tr("NON FATAL ERROR."));
// }
// else if (st == PGRES_FATAL_ERROR) {
// statusBar()->showMessage(tr("FATAL ERROR."));
// }
// else if (st == PGRES_COPY_BOTH) {
// statusBar()->showMessage(tr("COPY BOTH shouldn't happen is for replication."));
// }
// else if (st == PGRES_SINGLE_TUPLE) {
// statusBar()->showMessage(tr("SINGLE TUPLE result."));
// }
// else {
// statusBar()->showMessage(tr("No tuples returned, possibly an error..."));
// }
ui->tabWidget->setCurrentWidget(ui->messageTab);
auto details = dbres->diagDetails();
markError(details);
receiveNotice(details);
}
}
}
else {
m_stopwatch.stop();
addLog("query_ready with NO result");
}
} }
void QueryTool::markError(const Pgsql::ErrorDetails &details) void QueryTool::markError(const Pgsql::ErrorDetails &details)

View file

@ -110,7 +110,7 @@ private:
private slots: private slots:
void explain_ready(ExplainRoot::SPtr explain); void explain_ready(ExplainRoot::SPtr explain);
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::StateData state); void connectionStateChanged(ASyncDBConnection::StateData state);

View file

@ -427,7 +427,7 @@ void ASyncDBConnection::closeConnection()
bool ASyncDBConnection::send(const std::string &command, on_result_callback on_result) bool ASyncDBConnection::send(const std::string &command, on_result_callback on_result)
{ {
if (command.empty()) if (command.empty() || state() == State::NotConnected)
return false; return false;
{ {
@ -440,7 +440,10 @@ bool ASyncDBConnection::send(const std::string &command, on_result_callback on_r
bool ASyncDBConnection::send(const std::string &command, Pgsql::Params params, on_result_callback on_result) bool ASyncDBConnection::send(const std::string &command, Pgsql::Params params, on_result_callback on_result)
{ {
{ if (command.empty() || state() == State::NotConnected)
return false;
{
std::lock_guard<std::mutex> lg(m_threadData->m_commandQueue.m_mutex); std::lock_guard<std::mutex> lg(m_threadData->m_commandQueue.m_mutex);
m_threadData->m_commandQueue.m_queue.emplace(command, std::move(params), on_result); m_threadData->m_commandQueue.m_queue.emplace(command, std::move(params), on_result);
m_threadData->m_commandQueue.m_newEvent.set(); m_threadData->m_commandQueue.m_newEvent.set();

View file

@ -246,7 +246,7 @@ void Connection::throwError(PGresult *result) const
{ {
auto state = PQresultStatus(result); auto state = PQresultStatus(result);
if (state == PGRES_BAD_RESPONSE) if (state == PGRES_BAD_RESPONSE)
; // communication problem throw PgException("Communication issue");
else if (state == PGRES_FATAL_ERROR) else if (state == PGRES_FATAL_ERROR)
{ {
auto details = Pgsql::ErrorDetails::createErrorDetailsFromPGresult(result); auto details = Pgsql::ErrorDetails::createErrorDetailsFromPGresult(result);