Improved support from removing rows in crud tabs.

It can handle now complex selections and reports back errors encountered
when removing the rows fails.
This commit is contained in:
eelke 2018-12-15 11:24:58 +01:00
parent 950fea873c
commit 62c6ad5bfb
10 changed files with 365 additions and 116 deletions

View file

@ -1,5 +1,6 @@
#include "Pgsql_Connection.h"
#include "Pgsql_declare.h"
#include "Pgsql_PgException.h"
#include "Pgsql_Params.h"
#include <memory>
#include <stdexcept>
@ -107,6 +108,7 @@ std::string Connection::getErrorMessage() const
Result Connection::query(const char * command)
{
PGresult *result = PQexec(conn, command);
throwError(result);
return Result(result);
}
@ -114,6 +116,7 @@ Result Connection::queryParam(const char * command, const Params &params)
{
PGresult *result = PQexecParams(conn, command, params.size(), params.types(),
params.values(), params.lengths(), params.formats(), 0);
throwError(result);
return Result(result);
}
@ -142,6 +145,7 @@ std::shared_ptr<Result> Connection::getResult()
{
PGresult *r = PQgetResult(conn);
if (r) {
throwError(r);
return std::make_shared<Result>(r);
}
else {
@ -225,3 +229,32 @@ QString Connection::getDBName() const
{
return QString::fromUtf8(PQdb(conn));
}
void Connection::throwError(PGresult *result) const
{
auto state = PQresultStatus(result);
if (state == PGRES_BAD_RESPONSE) {
// communication problem
}
else if (state == PGRES_FATAL_ERROR) {
auto details = Pgsql::ErrorDetails::createErrorDetailsFromPGresult(result);
throw PgResultError(details);
}
}
//PGRES_EMPTY_QUERY = 0, /* empty query string was executed */
//PGRES_COMMAND_OK, /* a query command that doesn't return
// * anything was executed properly by the
// * backend */
//PGRES_TUPLES_OK, /* a query command that returns tuples was
// * executed properly by the backend, PGresult
// * contains the result tuples */
//PGRES_COPY_OUT, /* Copy Out data transfer in progress */
//PGRES_COPY_IN, /* Copy In data transfer in progress */
//PGRES_BAD_RESPONSE, /* an unexpected response was recv'd from the
// * backend */
//PGRES_NONFATAL_ERROR, /* notice or warning message */
//PGRES_FATAL_ERROR, /* query failed */
//PGRES_COPY_BOTH, /* Copy In/Out data transfer in progress */
//PGRES_SINGLE_TUPLE /* single tuple from larger resultset */

View file

@ -114,6 +114,7 @@ namespace Pgsql {
PGconn *conn = nullptr;
std::function<void(const PGresult *)> notifyReceiver;
void throwError(PGresult *result) const;
static void notifyReceiveFunc(void *arg, const PGresult *result);
};

View file

@ -1 +1,54 @@
#include "Pgsql_PgException.h"
#include "Pgsql_PgException.h"
namespace Pgsql {
ResultCode::ResultCode(std::string result_code)
: m_resultCode(std::move(result_code))
{
assert(m_resultCode.length() == 5);
}
std::string ResultCode::getClass() const
{
return m_resultCode.substr(1,2);
}
/** Helper to easily check the class of the error
*
*/
bool ResultCode::isClass(const std::string_view cls)
{
return m_resultCode.compare(1, 2, cls);
}
const std::string& ResultCode::getSpecific() const
{
return m_resultCode;
}
PgException::PgException(const char *msg)
: std::runtime_error(msg)
{}
PgException::PgException(std::string msg)
: std::runtime_error(msg)
{}
PgResultError::PgResultError(const Pgsql::ErrorDetails &details)
: PgException(details.errorMessage)
, m_details(details)
{}
ResultCode PgResultError::getResultCode() const
{
return ResultCode(m_details.state);
}
const Pgsql::ErrorDetails& PgResultError::details() const
{
return m_details;
}
}

View file

@ -1,6 +1,7 @@
#ifndef PGEXCEPTION_H
#define PGEXCEPTION_H
#include "Pgsql_ErrorDetails.h"
#include <cassert>
#include <stdexcept>
#include <utility>
@ -9,68 +10,39 @@ namespace Pgsql {
class ResultCode {
public:
explicit ResultCode(std::string result_code)
: m_resultCode(std::move(result_code))
{
assert(m_resultCode.length() == 5);
}
std::string getClass() const
{
return m_resultCode.substr(1,2);
}
/** Helper to easily check the class of the error
*
*/
bool isClass(const std::string_view cls)
{
return m_resultCode.compare(1, 2, cls);
}
const std::string& getSpecific() const
{
return m_resultCode;
}
explicit ResultCode(std::string result_code);
std::string getClass() const;
bool isClass(const std::string_view cls);
const std::string& getSpecific() const;
private:
std::string m_resultCode;
};
class PgException: public std::runtime_error {
public:
PgException(const char *msg)
: std::runtime_error(msg)
{}
PgException(std::string msg)
: std::runtime_error(msg)
{}
PgException(const char *msg);
PgException(std::string msg);
private:
};
class PgResultError: public PgException {
public:
PgResultError(std::string msg, std::string result_code)
: PgException(std::move(msg))
, m_resultCode(result_code)
{}
ResultCode getResultCode() const { return m_resultCode; }
PgResultError(const Pgsql::ErrorDetails &details);
ResultCode getResultCode() const;
const Pgsql::ErrorDetails& details() const;
private:
ResultCode m_resultCode;
Pgsql::ErrorDetails m_details;
};
class PgConnectionError: public PgResultError {
public:
PgConnectionError(const std::string &msg, std::string result_code)
: PgResultError(msg, std::move(result_code))
{}
// class PgConnectionError: public PgException {
// public:
// PgConnectionError(const std::string &msg, std::string result_code)
// : PgResultError(msg, std::move(result_code))
// {}
private:
// private:
};
// };