Added list of databases and roles.
Roles works for atleast 9.3 and up. Reorganizing code for communicating with database.
This commit is contained in:
parent
8c077b3d5f
commit
2d962334da
28 changed files with 881 additions and 428 deletions
|
|
@ -138,6 +138,7 @@ public:
|
||||||
float planningTime = 0.f;
|
float planningTime = 0.f;
|
||||||
// Triggers???
|
// Triggers???
|
||||||
float executionTime = 0.f;
|
float executionTime = 0.f;
|
||||||
|
float totalRuntime = 0.f;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
3
src/PgAuthId.cpp
Normal file
3
src/PgAuthId.cpp
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
#include "PgAuthId.h"
|
||||||
|
|
||||||
|
PgAuthId::PgAuthId() = default;
|
||||||
32
src/PgAuthId.h
Normal file
32
src/PgAuthId.h
Normal file
|
|
@ -0,0 +1,32 @@
|
||||||
|
#ifndef PGAUTHID_H
|
||||||
|
#define PGAUTHID_H
|
||||||
|
|
||||||
|
#include <pgsql/libpq-fe.h>
|
||||||
|
#include <QString>
|
||||||
|
#include <QDateTime>
|
||||||
|
|
||||||
|
class PgAuthId {
|
||||||
|
public:
|
||||||
|
PgAuthId();
|
||||||
|
|
||||||
|
Oid oid = InvalidOid;
|
||||||
|
QString name;
|
||||||
|
bool super;
|
||||||
|
bool inherit;
|
||||||
|
bool createRole;
|
||||||
|
bool createDB;
|
||||||
|
bool canlogin;
|
||||||
|
bool replication;
|
||||||
|
bool bypassRls;
|
||||||
|
int connLimit;
|
||||||
|
QDateTime validUntil;
|
||||||
|
|
||||||
|
bool valid() const { return oid != InvalidOid; }
|
||||||
|
|
||||||
|
bool operator==(Oid _oid) const { return oid == _oid; }
|
||||||
|
bool operator==(const QString &n) const { return name == n; }
|
||||||
|
bool operator<(Oid _oid) const { return oid < _oid; }
|
||||||
|
bool operator<(const PgAuthId &rhs) const { return oid < rhs.oid; }
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // PGAUTHID_H
|
||||||
45
src/PgAuthIdContainer.cpp
Normal file
45
src/PgAuthIdContainer.cpp
Normal file
|
|
@ -0,0 +1,45 @@
|
||||||
|
#include "PgAuthIdContainer.h"
|
||||||
|
#include "PgsqlConn.h"
|
||||||
|
#include "PgsqlDatabaseCatalogue.h"
|
||||||
|
|
||||||
|
PgAuthIdContainer::PgAuthIdContainer(PgsqlDatabaseCatalogue *cat)
|
||||||
|
: PgContainer<PgAuthId>(cat)
|
||||||
|
{}
|
||||||
|
|
||||||
|
std::string PgAuthIdContainer::getLoadQuery() const
|
||||||
|
{
|
||||||
|
std::string result =
|
||||||
|
"SELECT oid, rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb, "
|
||||||
|
" rolcanlogin, rolreplication, rolconnlimit, rolvaliduntil";
|
||||||
|
if (m_catalogue->serverVersion() >= 90500)
|
||||||
|
result += ", rolbypassrls";
|
||||||
|
result += "\n"
|
||||||
|
"FROM pg_authid";
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PgAuthIdContainer::load(const Pgsql::Result &res)
|
||||||
|
{
|
||||||
|
const int n_rows = res.rows();
|
||||||
|
m_container.clear();
|
||||||
|
m_container.reserve(n_rows);
|
||||||
|
bool with_rls = (m_catalogue->serverVersion() >= 90500);
|
||||||
|
for (auto row : res) {
|
||||||
|
PgAuthId v;
|
||||||
|
v.oid = row.get(0); // InvalidOid;
|
||||||
|
v.name = row.get(1);
|
||||||
|
v.super = row.get(2);
|
||||||
|
v.inherit = row.get(3);
|
||||||
|
v.createRole = row.get(4);
|
||||||
|
v.createDB = row.get(5);
|
||||||
|
v.canlogin = row.get(6);
|
||||||
|
v.replication = row.get(7);
|
||||||
|
v.connLimit = row.get(8);
|
||||||
|
v.validUntil = row.get(9);
|
||||||
|
v.bypassRls = with_rls ? (bool)row.get(10) : false;
|
||||||
|
// QDateTime
|
||||||
|
m_container.push_back(v);
|
||||||
|
}
|
||||||
|
std::sort(m_container.begin(), m_container.end());
|
||||||
|
}
|
||||||
|
|
||||||
26
src/PgAuthIdContainer.h
Normal file
26
src/PgAuthIdContainer.h
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
#ifndef PGAUTHIDCONTAINER_H
|
||||||
|
#define PGAUTHIDCONTAINER_H
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include "PgContainer.h"
|
||||||
|
#include "PgAuthId.h"
|
||||||
|
|
||||||
|
namespace Pgsql {
|
||||||
|
|
||||||
|
class Result;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class PgAuthIdContainer: public PgContainer<PgAuthId> {
|
||||||
|
public:
|
||||||
|
explicit PgAuthIdContainer(PgsqlDatabaseCatalogue *cat);
|
||||||
|
|
||||||
|
std::string getLoadQuery() const;
|
||||||
|
void load(const Pgsql::Result &res);
|
||||||
|
|
||||||
|
private:
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // PGAUTHIDCONTAINER_H
|
||||||
|
|
@ -5,11 +5,17 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <pgsql/libpq-fe.h>
|
#include <pgsql/libpq-fe.h>
|
||||||
|
|
||||||
|
class PgsqlDatabaseCatalogue;
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
class PgContainer {
|
class PgContainer {
|
||||||
public:
|
public:
|
||||||
using t_Container = std::vector<T>; ///< Do not assume it will stay a vector only expect bidirectional access
|
using t_Container = std::vector<T>; ///< Do not assume it will stay a vector only expect bidirectional access
|
||||||
|
|
||||||
|
explicit PgContainer(PgsqlDatabaseCatalogue *cat)
|
||||||
|
: m_catalogue(cat)
|
||||||
|
{}
|
||||||
|
|
||||||
typename t_Container::const_iterator begin() const
|
typename t_Container::const_iterator begin() const
|
||||||
{
|
{
|
||||||
return m_container.begin();
|
return m_container.begin();
|
||||||
|
|
@ -54,6 +60,7 @@ public:
|
||||||
return m_container.at(idx);
|
return m_container.at(idx);
|
||||||
}
|
}
|
||||||
protected:
|
protected:
|
||||||
|
PgsqlDatabaseCatalogue *m_catalogue;
|
||||||
t_Container m_container;
|
t_Container m_container;
|
||||||
private:
|
private:
|
||||||
T m_invalidInstance;
|
T m_invalidInstance;
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
#include "PgDatabaseContainer.h"
|
#include "PgDatabaseContainer.h"
|
||||||
#include "PgsqlConn.h"
|
#include "PgsqlConn.h"
|
||||||
|
|
||||||
PgDatabaseContainer::PgDatabaseContainer()
|
PgDatabaseContainer::PgDatabaseContainer(PgsqlDatabaseCatalogue *cat)
|
||||||
|
: PgContainer<PgDatabase>(cat)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
std::string PgDatabaseContainer::getLoadQuery() const
|
std::string PgDatabaseContainer::getLoadQuery() const
|
||||||
|
|
@ -12,7 +13,7 @@ std::string PgDatabaseContainer::getLoadQuery() const
|
||||||
|
|
||||||
void PgDatabaseContainer::load(const Pgsql::Result &res)
|
void PgDatabaseContainer::load(const Pgsql::Result &res)
|
||||||
{
|
{
|
||||||
const int n_rows = res.getRows();
|
const int n_rows = res.rows();
|
||||||
m_container.clear();
|
m_container.clear();
|
||||||
m_container.reserve(n_rows);
|
m_container.reserve(n_rows);
|
||||||
for (auto row : res) {
|
for (auto row : res) {
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ namespace Pgsql {
|
||||||
|
|
||||||
class PgDatabaseContainer: public PgContainer<PgDatabase> {
|
class PgDatabaseContainer: public PgContainer<PgDatabase> {
|
||||||
public:
|
public:
|
||||||
PgDatabaseContainer();
|
explicit PgDatabaseContainer(PgsqlDatabaseCatalogue *cat);
|
||||||
|
|
||||||
std::string getLoadQuery() const;
|
std::string getLoadQuery() const;
|
||||||
void load(const Pgsql::Result &res);
|
void load(const Pgsql::Result &res);
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,9 @@
|
||||||
#include "PgsqlConn.h"
|
#include "PgsqlConn.h"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
PgTypeContainer::PgTypeContainer() = default;
|
PgTypeContainer::PgTypeContainer(PgsqlDatabaseCatalogue *cat)
|
||||||
|
: PgContainer<PgType>(cat)
|
||||||
|
{}
|
||||||
|
|
||||||
|
|
||||||
//const PgType& PgTypeContainer::getTypeByOid(Oid oid) const
|
//const PgType& PgTypeContainer::getTypeByOid(Oid oid) const
|
||||||
|
|
@ -41,7 +43,7 @@ std::string PgTypeContainer::getLoadQuery()
|
||||||
|
|
||||||
void PgTypeContainer::load(const Pgsql::Result &res)
|
void PgTypeContainer::load(const Pgsql::Result &res)
|
||||||
{
|
{
|
||||||
const int n_rows = res.getRows();
|
const int n_rows = res.rows();
|
||||||
m_container.clear();
|
m_container.clear();
|
||||||
m_container.reserve(n_rows);
|
m_container.reserve(n_rows);
|
||||||
for (auto row : res) {
|
for (auto row : res) {
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ class PgTypeContainer: public PgContainer<PgType> {
|
||||||
public:
|
public:
|
||||||
// using t_Types = std::vector<PgType>; ///< Do not assume it will stay a vector only expect bidirectional access
|
// using t_Types = std::vector<PgType>; ///< Do not assume it will stay a vector only expect bidirectional access
|
||||||
|
|
||||||
PgTypeContainer();
|
explicit PgTypeContainer(PgsqlDatabaseCatalogue *cat);
|
||||||
|
|
||||||
// t_Types::const_iterator begin() const { return m_types.begin(); }
|
// t_Types::const_iterator begin() const { return m_types.begin(); }
|
||||||
// t_Types::const_iterator end() const { return m_types.end(); }
|
// t_Types::const_iterator end() const { return m_types.end(); }
|
||||||
|
|
|
||||||
|
|
@ -5,205 +5,9 @@
|
||||||
|
|
||||||
using namespace Pgsql;
|
using namespace Pgsql;
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
void set_stdstring_with_charptr(std::string &s, const char *p)
|
|
||||||
{
|
|
||||||
if (p) {
|
|
||||||
s = p;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
s.clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} // einde unnamed namespace
|
|
||||||
|
|
||||||
ErrorDetails ErrorDetails::createErrorDetailsFromPGresult(const PGresult *result)
|
|
||||||
{
|
|
||||||
|
|
||||||
ErrorDetails r;
|
|
||||||
set_stdstring_with_charptr(r.errorMessage, PQresultErrorMessage(result));
|
|
||||||
set_stdstring_with_charptr(r.state, PQresultErrorField(result, PG_DIAG_SQLSTATE)); ///< PG_DIAG_SQLSTATE Error code as listed in https://www.postgresql.org/docs/9.5/static/errcodes-appendix.html
|
|
||||||
set_stdstring_with_charptr(r.severity, PQresultErrorField(result, PG_DIAG_SEVERITY));
|
|
||||||
set_stdstring_with_charptr(r.messagePrimary, PQresultErrorField(result, PG_DIAG_MESSAGE_PRIMARY));
|
|
||||||
set_stdstring_with_charptr(r.messageDetail, PQresultErrorField(result, PG_DIAG_MESSAGE_DETAIL));
|
|
||||||
set_stdstring_with_charptr(r.messageHint, PQresultErrorField(result, PG_DIAG_MESSAGE_HINT));
|
|
||||||
const char * p = PQresultErrorField(result, PG_DIAG_STATEMENT_POSITION);
|
|
||||||
r.statementPosition = p != nullptr ? atoi(p) : -1; ///< First character is one, measured in characters not bytes!
|
|
||||||
p = PQresultErrorField(result, PG_DIAG_INTERNAL_POSITION);
|
|
||||||
r.internalPosition = p != nullptr ? atoi(p) : -1;
|
|
||||||
set_stdstring_with_charptr(r.internalQuery, PQresultErrorField(result, PG_DIAG_INTERNAL_QUERY));
|
|
||||||
set_stdstring_with_charptr(r.context, PQresultErrorField(result, PG_DIAG_CONTEXT));
|
|
||||||
set_stdstring_with_charptr(r.schemaName, PQresultErrorField(result, PG_DIAG_SCHEMA_NAME));
|
|
||||||
set_stdstring_with_charptr(r.tableName, PQresultErrorField(result, PG_DIAG_TABLE_NAME));
|
|
||||||
set_stdstring_with_charptr(r.columnName, PQresultErrorField(result, PG_DIAG_COLUMN_NAME));
|
|
||||||
set_stdstring_with_charptr(r.datatypeName, PQresultErrorField(result, PG_DIAG_DATATYPE_NAME));
|
|
||||||
set_stdstring_with_charptr(r.constraintName, PQresultErrorField(result, PG_DIAG_CONSTRAINT_NAME));
|
|
||||||
set_stdstring_with_charptr(r.sourceFile, PQresultErrorField(result, PG_DIAG_SOURCE_FILE));
|
|
||||||
set_stdstring_with_charptr(r.sourceLine, PQresultErrorField(result, PG_DIAG_SOURCE_LINE));
|
|
||||||
set_stdstring_with_charptr(r.sourceFunction, PQresultErrorField(result, PG_DIAG_SOURCE_FUNCTION));
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool Row::next()
|
|
||||||
{
|
|
||||||
if (m_row < m_result.getRows()) {
|
|
||||||
++m_row;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
Value Row::get(int col) const
|
|
||||||
{
|
|
||||||
return m_result.get(col, m_row);
|
|
||||||
}
|
|
||||||
|
|
||||||
//Value Row::get(const char *colname) const
|
|
||||||
//{
|
|
||||||
|
|
||||||
//}
|
|
||||||
|
|
||||||
Result::Result(PGresult *res)
|
|
||||||
: result(res)
|
|
||||||
{
|
|
||||||
if (res == nullptr) {
|
|
||||||
throw std::runtime_error("Passing nullptr to Result::Result is not allowed");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Result::~Result()
|
|
||||||
{
|
|
||||||
PQclear(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Result::Result(Result &&rhs)
|
|
||||||
: result(rhs.result)
|
|
||||||
{
|
|
||||||
rhs.result = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
Result& Result::operator=(Result &&rhs)
|
|
||||||
{
|
|
||||||
if (result) {
|
|
||||||
PQclear(result);
|
|
||||||
}
|
|
||||||
result = rhs.result;
|
|
||||||
rhs.result = nullptr;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Result::operator bool() const
|
|
||||||
{
|
|
||||||
return result != nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
ExecStatusType Result::resultStatus()
|
|
||||||
{
|
|
||||||
return PQresultStatus(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string Result::getResStatus()
|
|
||||||
{
|
|
||||||
// return PQresStatus(result);
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string Result::diagSqlState()
|
|
||||||
{
|
|
||||||
std::string s(PQresultErrorField(result, PG_DIAG_SQLSTATE));
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
ErrorDetails Result::diagDetails()
|
|
||||||
{
|
|
||||||
// ErrorDetails r;
|
|
||||||
// r.state = PQresultErrorField(result, PG_DIAG_SQLSTATE); ///< PG_DIAG_SQLSTATE Error code as listed in https://www.postgresql.org/docs/9.5/static/errcodes-appendix.html
|
|
||||||
// r.severity = PQresultErrorField(result, PG_DIAG_SEVERITY);
|
|
||||||
// r.messagePrimary = PQresultErrorField(result, PG_DIAG_MESSAGE_PRIMARY);
|
|
||||||
// r.messageDetail = PQresultErrorField(result, PG_DIAG_MESSAGE_DETAIL);
|
|
||||||
// r.messageHint = PQresultErrorField(result, PG_DIAG_MESSAGE_HINT);
|
|
||||||
// r.statementPosition = atoi(PQresultErrorField(result, PG_DIAG_STATEMENT_POSITION)); ///< First character is one, measured in characters not bytes!
|
|
||||||
// r.internalPosition = atoi(PQresultErrorField(result, PG_DIAG_INTERNAL_POSITION));
|
|
||||||
// r.internalQuery = PQresultErrorField(result, PG_DIAG_INTERNAL_QUERY);
|
|
||||||
// r.context = PQresultErrorField(result, PG_DIAG_CONTEXT);
|
|
||||||
// r.schemaName = PQresultErrorField(result, PG_DIAG_SCHEMA_NAME);
|
|
||||||
// r.tableName = PQresultErrorField(result, PG_DIAG_TABLE_NAME);
|
|
||||||
// r.columnName = PQresultErrorField(result, PG_DIAG_COLUMN_NAME);
|
|
||||||
// r.datatypeName = PQresultErrorField(result, PG_DIAG_DATATYPE_NAME);
|
|
||||||
// r.constraintName = PQresultErrorField(result, PG_DIAG_CONSTRAINT_NAME);
|
|
||||||
// r.sourceFile = PQresultErrorField(result, PG_DIAG_SOURCE_FILE);
|
|
||||||
// r.sourceLine = PQresultErrorField(result, PG_DIAG_SOURCE_LINE);
|
|
||||||
// r.sourceFunction = PQresultErrorField(result, PG_DIAG_SOURCE_FUNCTION);
|
|
||||||
|
|
||||||
// return r;
|
|
||||||
return ErrorDetails::createErrorDetailsFromPGresult(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
int Result::tuplesAffected() const
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
char * res = PQcmdTuples(result);
|
|
||||||
if (res) {
|
|
||||||
try {
|
|
||||||
i = std::stoi(res);
|
|
||||||
}
|
|
||||||
catch (std::invalid_argument& ) {
|
|
||||||
i = -1;
|
|
||||||
}
|
|
||||||
catch (std::out_of_range& ) {
|
|
||||||
i = -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
i = -1;
|
|
||||||
}
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
|
|
||||||
int Result::getRows() const
|
|
||||||
{
|
|
||||||
return PQntuples(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
int Result::getCols() const
|
|
||||||
{
|
|
||||||
return PQnfields(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
const char* const Result::getColName(int idx) const
|
|
||||||
{
|
|
||||||
return PQfname(result, idx);
|
|
||||||
}
|
|
||||||
|
|
||||||
const char * Result::getVal(int col, int row) const
|
|
||||||
{
|
|
||||||
return PQgetvalue(result, row, col);
|
|
||||||
}
|
|
||||||
|
|
||||||
Value Result::get(int col, int row) const
|
|
||||||
{
|
|
||||||
return Value(
|
|
||||||
PQgetvalue(result, row, col),
|
|
||||||
PQftype(result, col)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Oid Result::type(int col) const
|
|
||||||
{
|
|
||||||
return PQftype(result, col);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Result::null(int col, int row) const
|
|
||||||
{
|
|
||||||
return PQgetisnull(result, row, col);
|
|
||||||
}
|
|
||||||
|
|
||||||
Canceller::Canceller(PGcancel *c)
|
Canceller::Canceller(PGcancel *c)
|
||||||
: m_cancel(c)
|
: m_cancel(c)
|
||||||
{}
|
{}
|
||||||
|
|
|
||||||
203
src/PgsqlConn.h
203
src/PgsqlConn.h
|
|
@ -12,6 +12,8 @@
|
||||||
|
|
||||||
#include <fmt/format.h>
|
#include <fmt/format.h>
|
||||||
|
|
||||||
|
#include "Pgsql_Result.h"
|
||||||
|
|
||||||
namespace Pgsql {
|
namespace Pgsql {
|
||||||
|
|
||||||
class Connection;
|
class Connection;
|
||||||
|
|
@ -36,213 +38,12 @@ namespace Pgsql {
|
||||||
|
|
||||||
// };
|
// };
|
||||||
|
|
||||||
class ErrorDetails {
|
|
||||||
public:
|
|
||||||
static ErrorDetails createErrorDetailsFromPGresult(const PGresult *res);
|
|
||||||
|
|
||||||
std::string errorMessage;
|
|
||||||
std::string state; ///< PG_DIAG_SQLSTATE Error code as listed in https://www.postgresql.org/docs/9.5/static/errcodes-appendix.html
|
|
||||||
std::string severity;
|
|
||||||
std::string messagePrimary;
|
|
||||||
std::string messageDetail;
|
|
||||||
std::string messageHint;
|
|
||||||
int statementPosition; ///< First character is one, measured in characters not bytes!
|
|
||||||
int internalPosition;
|
|
||||||
std::string internalQuery;
|
|
||||||
std::string context;
|
|
||||||
std::string schemaName;
|
|
||||||
std::string tableName;
|
|
||||||
std::string columnName;
|
|
||||||
std::string datatypeName;
|
|
||||||
std::string constraintName;
|
|
||||||
std::string sourceFile;
|
|
||||||
std::string sourceLine;
|
|
||||||
std::string sourceFunction;
|
|
||||||
};
|
|
||||||
|
|
||||||
/** \brief Class that is returned as value of a cell to facilitate auto conversion.
|
|
||||||
*/
|
|
||||||
class Value {
|
|
||||||
public:
|
|
||||||
Value(const char *val, Oid typ)
|
|
||||||
: m_val(val), m_typ(typ)
|
|
||||||
{}
|
|
||||||
|
|
||||||
QString asQString() const
|
|
||||||
{
|
|
||||||
return QString::fromUtf8(m_val);
|
|
||||||
}
|
|
||||||
|
|
||||||
operator QString() const
|
|
||||||
{
|
|
||||||
return QString::fromUtf8(m_val);
|
|
||||||
}
|
|
||||||
|
|
||||||
operator std::string() const
|
|
||||||
{
|
|
||||||
return m_val;
|
|
||||||
}
|
|
||||||
|
|
||||||
operator short() const
|
|
||||||
{
|
|
||||||
return (short)std::atoi(m_val);
|
|
||||||
}
|
|
||||||
|
|
||||||
operator int() const
|
|
||||||
{
|
|
||||||
return std::atoi(m_val);
|
|
||||||
}
|
|
||||||
|
|
||||||
operator Oid() const
|
|
||||||
{
|
|
||||||
return operator int();
|
|
||||||
}
|
|
||||||
|
|
||||||
operator __int64() const
|
|
||||||
{
|
|
||||||
return strtoull(m_val, nullptr, 10);
|
|
||||||
}
|
|
||||||
|
|
||||||
operator bool() const
|
|
||||||
{
|
|
||||||
return strcmp(m_val, "t") == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
const char *m_val;
|
|
||||||
Oid m_typ;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
class Result;
|
class Result;
|
||||||
|
|
||||||
/** \brief A reference to a specific row from a result.
|
|
||||||
*
|
|
||||||
* As it is a reference its contents won't be valid after its associated result has
|
|
||||||
* been destroyed.
|
|
||||||
*/
|
|
||||||
class Row {
|
|
||||||
public:
|
|
||||||
Row(const Result &result, int row)
|
|
||||||
: m_result(result)
|
|
||||||
, m_row(row)
|
|
||||||
{}
|
|
||||||
|
|
||||||
bool next();
|
|
||||||
bool operator==(const Row& rhs)
|
|
||||||
{
|
|
||||||
return &m_result == &rhs.m_result
|
|
||||||
&& m_row == rhs.m_row;
|
|
||||||
}
|
|
||||||
|
|
||||||
Value get(int col) const;
|
|
||||||
//Value get(const char *colname) const;
|
|
||||||
//bool get(int col, QString &s);
|
|
||||||
private:
|
|
||||||
const Result& m_result;
|
|
||||||
int m_row;
|
|
||||||
};
|
|
||||||
|
|
||||||
/** \brief Non-copyable but movable wrapper for a postgresql result.
|
|
||||||
*
|
|
||||||
* This class makes sure the result is removed from memory. It also supplies an iterator for the
|
|
||||||
* rows from the result facilitating also the use of the cpp for each.
|
|
||||||
*/
|
|
||||||
class Result {
|
|
||||||
public:
|
|
||||||
class const_iterator {
|
|
||||||
public:
|
|
||||||
const_iterator(const Result &r, int rw)
|
|
||||||
: m_row(r, rw)
|
|
||||||
{}
|
|
||||||
|
|
||||||
const_iterator operator++()
|
|
||||||
{
|
|
||||||
const_iterator t(*this);
|
|
||||||
m_row.next();
|
|
||||||
return t;
|
|
||||||
}
|
|
||||||
|
|
||||||
const_iterator& operator++(int)
|
|
||||||
{
|
|
||||||
m_row.next();
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator==(const const_iterator &rhs)
|
|
||||||
{
|
|
||||||
return m_row == rhs.m_row;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator!=(const const_iterator &rhs)
|
|
||||||
{
|
|
||||||
return !operator==(rhs);
|
|
||||||
}
|
|
||||||
|
|
||||||
const Row& operator*()
|
|
||||||
{
|
|
||||||
return m_row;
|
|
||||||
}
|
|
||||||
const Row& operator->()
|
|
||||||
{
|
|
||||||
return m_row;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
Row m_row;
|
|
||||||
};
|
|
||||||
|
|
||||||
Result() = default;
|
|
||||||
Result(PGresult *result);
|
|
||||||
~Result();
|
|
||||||
|
|
||||||
Result(const Result &rhs) = delete;
|
|
||||||
Result& operator=(const Result &rhs) = delete;
|
|
||||||
|
|
||||||
Result(Result &&rhs);
|
|
||||||
Result& operator=(Result &&rhs);
|
|
||||||
|
|
||||||
operator bool() const;
|
|
||||||
|
|
||||||
ExecStatusType resultStatus();
|
|
||||||
|
|
||||||
std::string getResStatus();
|
|
||||||
|
|
||||||
/** Use this to retrieve an error code when this is an error result
|
|
||||||
*
|
|
||||||
* The possible code are listed in https://www.postgresql.org/docs/9.5/static/errcodes-appendix.html
|
|
||||||
*/
|
|
||||||
std::string diagSqlState();
|
|
||||||
/** Retrieves all the error fields. */
|
|
||||||
ErrorDetails diagDetails();
|
|
||||||
|
|
||||||
const_iterator begin() const
|
|
||||||
{
|
|
||||||
return const_iterator(*this, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
const_iterator end() const
|
|
||||||
{
|
|
||||||
return const_iterator(*this, getRows());
|
|
||||||
}
|
|
||||||
|
|
||||||
int tuplesAffected() const;
|
|
||||||
int getRows() const;
|
|
||||||
int getCols() const;
|
|
||||||
|
|
||||||
const char* const getColName(int idx) const;
|
|
||||||
|
|
||||||
const char * getVal(int col, int row) const;
|
|
||||||
Value get(int col, int row) const;
|
|
||||||
Oid type(int col) const;
|
|
||||||
bool null(int col, int row) const;
|
|
||||||
|
|
||||||
|
|
||||||
// iterator begin();
|
|
||||||
private:
|
|
||||||
PGresult *result = nullptr;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/** \brief Wrapper for a cancel object from libpq.
|
/** \brief Wrapper for a cancel object from libpq.
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,23 @@
|
||||||
#include "PgsqlDatabaseCatalogue.h"
|
#include "PgsqlDatabaseCatalogue.h"
|
||||||
#include "PgTypeContainer.h"
|
#include "PgTypeContainer.h"
|
||||||
#include "PgDatabaseContainer.h"
|
#include "PgDatabaseContainer.h"
|
||||||
|
#include "PgAuthIdContainer.h"
|
||||||
#include "PgsqlConn.h"
|
#include "PgsqlConn.h"
|
||||||
|
|
||||||
|
|
||||||
|
QString getRoleNameFromOid(const PgsqlDatabaseCatalogue *cat, Oid oid)
|
||||||
|
{
|
||||||
|
QString name;
|
||||||
|
const PgAuthIdContainer *auth_ids = cat->authIds();
|
||||||
|
if (auth_ids) {
|
||||||
|
const PgAuthId& auth_id = auth_ids->getByOid(oid);
|
||||||
|
if (auth_id.valid()) {
|
||||||
|
name = auth_id.name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
PgsqlDatabaseCatalogue::PgsqlDatabaseCatalogue()
|
PgsqlDatabaseCatalogue::PgsqlDatabaseCatalogue()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
@ -16,28 +31,71 @@ void PgsqlDatabaseCatalogue::loadAll(Pgsql::Connection &conn)
|
||||||
{
|
{
|
||||||
loadTypes(conn);
|
loadTypes(conn);
|
||||||
loadDatabases(conn);
|
loadDatabases(conn);
|
||||||
|
loadAuthIds(conn);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PgsqlDatabaseCatalogue::loadInfo(Pgsql::Connection &conn)
|
||||||
|
{
|
||||||
|
Pgsql::Result r = conn.query("SHOW server_version_num");
|
||||||
|
if (r && r.resultStatus() == PGRES_TUPLES_OK)
|
||||||
|
if (r.rows() == 1)
|
||||||
|
m_serverVersion = r.get(0, 0);
|
||||||
|
|
||||||
|
r = conn.query("SELECT version()");
|
||||||
|
if (r && r.resultStatus() == PGRES_TUPLES_OK)
|
||||||
|
if (r.rows() == 1)
|
||||||
|
m_serverVersionString = r.get(0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PgsqlDatabaseCatalogue::loadTypes(Pgsql::Connection &conn)
|
void PgsqlDatabaseCatalogue::loadTypes(Pgsql::Connection &conn)
|
||||||
{
|
{
|
||||||
if (m_types == nullptr) {
|
if (m_types == nullptr)
|
||||||
m_types = new PgTypeContainer;
|
m_types = new PgTypeContainer(this);
|
||||||
}
|
|
||||||
|
|
||||||
std::string q = m_types->getLoadQuery();
|
std::string q = m_types->getLoadQuery();
|
||||||
Pgsql::Result result = conn.query(q.c_str());
|
Pgsql::Result result = conn.query(q.c_str());
|
||||||
m_types->load(result);
|
if (result && result.resultStatus() == PGRES_TUPLES_OK)
|
||||||
|
m_types->load(result);
|
||||||
|
else
|
||||||
|
throw std::runtime_error("Query failed");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PgsqlDatabaseCatalogue::loadDatabases(Pgsql::Connection &conn)
|
void PgsqlDatabaseCatalogue::loadDatabases(Pgsql::Connection &conn)
|
||||||
{
|
{
|
||||||
if (m_databases == nullptr) {
|
if (m_databases == nullptr)
|
||||||
m_databases = new PgDatabaseContainer;
|
m_databases = new PgDatabaseContainer(this);
|
||||||
}
|
|
||||||
|
|
||||||
std::string q = m_databases->getLoadQuery();
|
std::string q = m_databases->getLoadQuery();
|
||||||
Pgsql::Result result = conn.query(q.c_str());
|
Pgsql::Result result = conn.query(q.c_str());
|
||||||
m_databases->load(result);
|
if (result && result.resultStatus() == PGRES_TUPLES_OK)
|
||||||
|
m_databases->load(result);
|
||||||
|
else
|
||||||
|
throw std::runtime_error("Query failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
void PgsqlDatabaseCatalogue::loadAuthIds(Pgsql::Connection &conn)
|
||||||
|
{
|
||||||
|
if (m_authIds == nullptr)
|
||||||
|
m_authIds = new PgAuthIdContainer(this);
|
||||||
|
|
||||||
|
std::string q = m_authIds->getLoadQuery();
|
||||||
|
Pgsql::Result result = conn.query(q.c_str());
|
||||||
|
if (result && result.resultStatus() == PGRES_TUPLES_OK)
|
||||||
|
m_authIds->load(result);
|
||||||
|
else
|
||||||
|
throw std::runtime_error("Query failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
const QString& PgsqlDatabaseCatalogue::serverVersionString() const
|
||||||
|
{
|
||||||
|
return m_serverVersionString;
|
||||||
|
}
|
||||||
|
|
||||||
|
int PgsqlDatabaseCatalogue::serverVersion() const
|
||||||
|
{
|
||||||
|
return m_serverVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
const PgTypeContainer* PgsqlDatabaseCatalogue::types() const
|
const PgTypeContainer* PgsqlDatabaseCatalogue::types() const
|
||||||
|
|
@ -49,3 +107,8 @@ const PgDatabaseContainer *PgsqlDatabaseCatalogue::databases() const
|
||||||
{
|
{
|
||||||
return m_databases;
|
return m_databases;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const PgAuthIdContainer *PgsqlDatabaseCatalogue::authIds() const
|
||||||
|
{
|
||||||
|
return m_authIds;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
#ifndef PGSQLDATABASECATALOGUE_H
|
#ifndef PGSQLDATABASECATALOGUE_H
|
||||||
#define PGSQLDATABASECATALOGUE_H
|
#define PGSQLDATABASECATALOGUE_H
|
||||||
|
|
||||||
|
#include <pgsql/libpq-fe.h>
|
||||||
|
#include <QString>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace Pgsql {
|
namespace Pgsql {
|
||||||
|
|
@ -11,6 +13,7 @@ namespace Pgsql {
|
||||||
|
|
||||||
class PgTypeContainer;
|
class PgTypeContainer;
|
||||||
class PgDatabaseContainer;
|
class PgDatabaseContainer;
|
||||||
|
class PgAuthIdContainer;
|
||||||
|
|
||||||
class PgsqlDatabaseCatalogue {
|
class PgsqlDatabaseCatalogue {
|
||||||
public:
|
public:
|
||||||
|
|
@ -22,14 +25,25 @@ public:
|
||||||
|
|
||||||
|
|
||||||
void loadAll(Pgsql::Connection &conn);
|
void loadAll(Pgsql::Connection &conn);
|
||||||
|
void loadInfo(Pgsql::Connection &conn);
|
||||||
void loadTypes(Pgsql::Connection &conn);
|
void loadTypes(Pgsql::Connection &conn);
|
||||||
void loadDatabases(Pgsql::Connection &conn);
|
void loadDatabases(Pgsql::Connection &conn);
|
||||||
|
void loadAuthIds(Pgsql::Connection &conn);
|
||||||
|
|
||||||
|
const QString& serverVersionString() const;
|
||||||
|
int serverVersion() const;
|
||||||
|
|
||||||
const PgTypeContainer* types() const;
|
const PgTypeContainer* types() const;
|
||||||
const PgDatabaseContainer *databases() const;
|
const PgDatabaseContainer *databases() const;
|
||||||
|
const PgAuthIdContainer *authIds() const;
|
||||||
private:
|
private:
|
||||||
|
QString m_serverVersionString;
|
||||||
|
int m_serverVersion;
|
||||||
PgTypeContainer *m_types = nullptr;
|
PgTypeContainer *m_types = nullptr;
|
||||||
PgDatabaseContainer *m_databases = nullptr;
|
PgDatabaseContainer *m_databases = nullptr;
|
||||||
|
PgAuthIdContainer *m_authIds = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
QString getRoleNameFromOid(const PgsqlDatabaseCatalogue *cat, Oid oid);
|
||||||
|
|
||||||
#endif // PGSQLDATABASECATALOGUE_H
|
#endif // PGSQLDATABASECATALOGUE_H
|
||||||
|
|
|
||||||
182
src/Pgsql_Result.cpp
Normal file
182
src/Pgsql_Result.cpp
Normal file
|
|
@ -0,0 +1,182 @@
|
||||||
|
#include "Pgsql_Result.h"
|
||||||
|
|
||||||
|
using namespace Pgsql;
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
void set_stdstring_with_charptr(std::string &s, const char *p)
|
||||||
|
{
|
||||||
|
if (p) {
|
||||||
|
s = p;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
s.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // einde unnamed namespace
|
||||||
|
|
||||||
|
ErrorDetails ErrorDetails::createErrorDetailsFromPGresult(const PGresult *result)
|
||||||
|
{
|
||||||
|
|
||||||
|
ErrorDetails r;
|
||||||
|
set_stdstring_with_charptr(r.errorMessage, PQresultErrorMessage(result));
|
||||||
|
set_stdstring_with_charptr(r.state, PQresultErrorField(result, PG_DIAG_SQLSTATE)); ///< PG_DIAG_SQLSTATE Error code as listed in https://www.postgresql.org/docs/9.5/static/errcodes-appendix.html
|
||||||
|
set_stdstring_with_charptr(r.severity, PQresultErrorField(result, PG_DIAG_SEVERITY));
|
||||||
|
set_stdstring_with_charptr(r.messagePrimary, PQresultErrorField(result, PG_DIAG_MESSAGE_PRIMARY));
|
||||||
|
set_stdstring_with_charptr(r.messageDetail, PQresultErrorField(result, PG_DIAG_MESSAGE_DETAIL));
|
||||||
|
set_stdstring_with_charptr(r.messageHint, PQresultErrorField(result, PG_DIAG_MESSAGE_HINT));
|
||||||
|
const char * p = PQresultErrorField(result, PG_DIAG_STATEMENT_POSITION);
|
||||||
|
r.statementPosition = p != nullptr ? atoi(p) : -1; ///< First character is one, measured in characters not bytes!
|
||||||
|
p = PQresultErrorField(result, PG_DIAG_INTERNAL_POSITION);
|
||||||
|
r.internalPosition = p != nullptr ? atoi(p) : -1;
|
||||||
|
set_stdstring_with_charptr(r.internalQuery, PQresultErrorField(result, PG_DIAG_INTERNAL_QUERY));
|
||||||
|
set_stdstring_with_charptr(r.context, PQresultErrorField(result, PG_DIAG_CONTEXT));
|
||||||
|
set_stdstring_with_charptr(r.schemaName, PQresultErrorField(result, PG_DIAG_SCHEMA_NAME));
|
||||||
|
set_stdstring_with_charptr(r.tableName, PQresultErrorField(result, PG_DIAG_TABLE_NAME));
|
||||||
|
set_stdstring_with_charptr(r.columnName, PQresultErrorField(result, PG_DIAG_COLUMN_NAME));
|
||||||
|
set_stdstring_with_charptr(r.datatypeName, PQresultErrorField(result, PG_DIAG_DATATYPE_NAME));
|
||||||
|
set_stdstring_with_charptr(r.constraintName, PQresultErrorField(result, PG_DIAG_CONSTRAINT_NAME));
|
||||||
|
set_stdstring_with_charptr(r.sourceFile, PQresultErrorField(result, PG_DIAG_SOURCE_FILE));
|
||||||
|
set_stdstring_with_charptr(r.sourceLine, PQresultErrorField(result, PG_DIAG_SOURCE_LINE));
|
||||||
|
set_stdstring_with_charptr(r.sourceFunction, PQresultErrorField(result, PG_DIAG_SOURCE_FUNCTION));
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Result::Result(PGresult *res)
|
||||||
|
: result(res)
|
||||||
|
{
|
||||||
|
if (res == nullptr) {
|
||||||
|
throw std::runtime_error("Passing nullptr to Result::Result is not allowed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Result::~Result()
|
||||||
|
{
|
||||||
|
PQclear(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Result::Result(Result &&rhs)
|
||||||
|
: result(rhs.result)
|
||||||
|
{
|
||||||
|
rhs.result = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result& Result::operator=(Result &&rhs)
|
||||||
|
{
|
||||||
|
if (result) {
|
||||||
|
PQclear(result);
|
||||||
|
}
|
||||||
|
result = rhs.result;
|
||||||
|
rhs.result = nullptr;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result::operator bool() const
|
||||||
|
{
|
||||||
|
return result != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
ExecStatusType Result::resultStatus()
|
||||||
|
{
|
||||||
|
return PQresultStatus(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Result::getResStatus()
|
||||||
|
{
|
||||||
|
// return PQresStatus(result);
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Result::diagSqlState()
|
||||||
|
{
|
||||||
|
std::string s(PQresultErrorField(result, PG_DIAG_SQLSTATE));
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ErrorDetails Result::diagDetails()
|
||||||
|
{
|
||||||
|
// ErrorDetails r;
|
||||||
|
// r.state = PQresultErrorField(result, PG_DIAG_SQLSTATE); ///< PG_DIAG_SQLSTATE Error code as listed in https://www.postgresql.org/docs/9.5/static/errcodes-appendix.html
|
||||||
|
// r.severity = PQresultErrorField(result, PG_DIAG_SEVERITY);
|
||||||
|
// r.messagePrimary = PQresultErrorField(result, PG_DIAG_MESSAGE_PRIMARY);
|
||||||
|
// r.messageDetail = PQresultErrorField(result, PG_DIAG_MESSAGE_DETAIL);
|
||||||
|
// r.messageHint = PQresultErrorField(result, PG_DIAG_MESSAGE_HINT);
|
||||||
|
// r.statementPosition = atoi(PQresultErrorField(result, PG_DIAG_STATEMENT_POSITION)); ///< First character is one, measured in characters not bytes!
|
||||||
|
// r.internalPosition = atoi(PQresultErrorField(result, PG_DIAG_INTERNAL_POSITION));
|
||||||
|
// r.internalQuery = PQresultErrorField(result, PG_DIAG_INTERNAL_QUERY);
|
||||||
|
// r.context = PQresultErrorField(result, PG_DIAG_CONTEXT);
|
||||||
|
// r.schemaName = PQresultErrorField(result, PG_DIAG_SCHEMA_NAME);
|
||||||
|
// r.tableName = PQresultErrorField(result, PG_DIAG_TABLE_NAME);
|
||||||
|
// r.columnName = PQresultErrorField(result, PG_DIAG_COLUMN_NAME);
|
||||||
|
// r.datatypeName = PQresultErrorField(result, PG_DIAG_DATATYPE_NAME);
|
||||||
|
// r.constraintName = PQresultErrorField(result, PG_DIAG_CONSTRAINT_NAME);
|
||||||
|
// r.sourceFile = PQresultErrorField(result, PG_DIAG_SOURCE_FILE);
|
||||||
|
// r.sourceLine = PQresultErrorField(result, PG_DIAG_SOURCE_LINE);
|
||||||
|
// r.sourceFunction = PQresultErrorField(result, PG_DIAG_SOURCE_FUNCTION);
|
||||||
|
|
||||||
|
// return r;
|
||||||
|
return ErrorDetails::createErrorDetailsFromPGresult(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
int Result::tuplesAffected() const
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
char * res = PQcmdTuples(result);
|
||||||
|
if (res) {
|
||||||
|
try {
|
||||||
|
i = std::stoi(res);
|
||||||
|
}
|
||||||
|
catch (std::invalid_argument& ) {
|
||||||
|
i = -1;
|
||||||
|
}
|
||||||
|
catch (std::out_of_range& ) {
|
||||||
|
i = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
i = -1;
|
||||||
|
}
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Result::rows() const
|
||||||
|
{
|
||||||
|
return PQntuples(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
int Result::cols() const
|
||||||
|
{
|
||||||
|
return PQnfields(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* const Result::getColName(int idx) const
|
||||||
|
{
|
||||||
|
return PQfname(result, idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char * Result::val(int col, int row) const
|
||||||
|
{
|
||||||
|
return PQgetvalue(result, row, col);
|
||||||
|
}
|
||||||
|
|
||||||
|
Value Result::get(int col, int row) const
|
||||||
|
{
|
||||||
|
return Value(
|
||||||
|
PQgetvalue(result, row, col),
|
||||||
|
PQftype(result, col)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Oid Result::type(int col) const
|
||||||
|
{
|
||||||
|
return PQftype(result, col);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Result::null(int col, int row) const
|
||||||
|
{
|
||||||
|
return PQgetisnull(result, row, col);
|
||||||
|
}
|
||||||
135
src/Pgsql_Result.h
Normal file
135
src/Pgsql_Result.h
Normal file
|
|
@ -0,0 +1,135 @@
|
||||||
|
#ifndef PGSQL_RESULT_H
|
||||||
|
#define PGSQL_RESULT_H
|
||||||
|
|
||||||
|
#include "Pgsql_Row.h"
|
||||||
|
|
||||||
|
namespace Pgsql {
|
||||||
|
|
||||||
|
class ErrorDetails {
|
||||||
|
public:
|
||||||
|
static ErrorDetails createErrorDetailsFromPGresult(const PGresult *res);
|
||||||
|
|
||||||
|
std::string errorMessage;
|
||||||
|
std::string state; ///< PG_DIAG_SQLSTATE Error code as listed in https://www.postgresql.org/docs/9.5/static/errcodes-appendix.html
|
||||||
|
std::string severity;
|
||||||
|
std::string messagePrimary;
|
||||||
|
std::string messageDetail;
|
||||||
|
std::string messageHint;
|
||||||
|
int statementPosition; ///< First character is one, measured in characters not bytes!
|
||||||
|
int internalPosition;
|
||||||
|
std::string internalQuery;
|
||||||
|
std::string context;
|
||||||
|
std::string schemaName;
|
||||||
|
std::string tableName;
|
||||||
|
std::string columnName;
|
||||||
|
std::string datatypeName;
|
||||||
|
std::string constraintName;
|
||||||
|
std::string sourceFile;
|
||||||
|
std::string sourceLine;
|
||||||
|
std::string sourceFunction;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** \brief Non-copyable but movable wrapper for a postgresql result.
|
||||||
|
*
|
||||||
|
* This class makes sure the result is removed from memory. It also supplies an iterator for the
|
||||||
|
* rows from the result facilitating also the use of the cpp for each.
|
||||||
|
*/
|
||||||
|
class Result {
|
||||||
|
public:
|
||||||
|
class const_iterator {
|
||||||
|
public:
|
||||||
|
const_iterator(const Result &r, int rw)
|
||||||
|
: m_row(r, rw)
|
||||||
|
{}
|
||||||
|
|
||||||
|
const_iterator operator++()
|
||||||
|
{
|
||||||
|
const_iterator t(*this);
|
||||||
|
m_row.next();
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
const_iterator& operator++(int)
|
||||||
|
{
|
||||||
|
m_row.next();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(const const_iterator &rhs)
|
||||||
|
{
|
||||||
|
return m_row == rhs.m_row;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator!=(const const_iterator &rhs)
|
||||||
|
{
|
||||||
|
return !operator==(rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
const Row& operator*()
|
||||||
|
{
|
||||||
|
return m_row;
|
||||||
|
}
|
||||||
|
const Row& operator->()
|
||||||
|
{
|
||||||
|
return m_row;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Row m_row;
|
||||||
|
};
|
||||||
|
|
||||||
|
Result() = default;
|
||||||
|
Result(PGresult *result);
|
||||||
|
~Result();
|
||||||
|
|
||||||
|
Result(const Result &rhs) = delete;
|
||||||
|
Result& operator=(const Result &rhs) = delete;
|
||||||
|
|
||||||
|
Result(Result &&rhs);
|
||||||
|
Result& operator=(Result &&rhs);
|
||||||
|
|
||||||
|
operator bool() const;
|
||||||
|
|
||||||
|
ExecStatusType resultStatus();
|
||||||
|
|
||||||
|
std::string getResStatus();
|
||||||
|
|
||||||
|
/** Use this to retrieve an error code when this is an error result
|
||||||
|
*
|
||||||
|
* The possible code are listed in https://www.postgresql.org/docs/9.5/static/errcodes-appendix.html
|
||||||
|
*/
|
||||||
|
std::string diagSqlState();
|
||||||
|
/** Retrieves all the error fields. */
|
||||||
|
ErrorDetails diagDetails();
|
||||||
|
|
||||||
|
const_iterator begin() const
|
||||||
|
{
|
||||||
|
return const_iterator(*this, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
const_iterator end() const
|
||||||
|
{
|
||||||
|
return const_iterator(*this, rows());
|
||||||
|
}
|
||||||
|
|
||||||
|
int tuplesAffected() const;
|
||||||
|
int rows() const;
|
||||||
|
int cols() const;
|
||||||
|
|
||||||
|
const char* const getColName(int idx) const;
|
||||||
|
|
||||||
|
const char * val(int col, int row) const;
|
||||||
|
Value get(int col, int row) const;
|
||||||
|
Oid type(int col) const;
|
||||||
|
bool null(int col, int row) const;
|
||||||
|
|
||||||
|
|
||||||
|
// iterator begin();
|
||||||
|
private:
|
||||||
|
PGresult *result = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // end namespace Pgsql
|
||||||
|
|
||||||
|
#endif // PGSQL_RESULT_H
|
||||||
36
src/Pgsql_Row.cpp
Normal file
36
src/Pgsql_Row.cpp
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
#include "Pgsql_Row.h"
|
||||||
|
#include "Pgsql_Result.h"
|
||||||
|
|
||||||
|
using namespace Pgsql;
|
||||||
|
|
||||||
|
Row::Row(const Result &result, int row)
|
||||||
|
: m_result(result)
|
||||||
|
, m_row(row)
|
||||||
|
{}
|
||||||
|
|
||||||
|
bool Row::next()
|
||||||
|
{
|
||||||
|
if (m_row < m_result.rows()) {
|
||||||
|
++m_row;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Row::operator==(const Row& rhs) const
|
||||||
|
{
|
||||||
|
return &m_result == &rhs.m_result
|
||||||
|
&& m_row == rhs.m_row;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Value Row::get(int col) const
|
||||||
|
{
|
||||||
|
return m_result.get(col, m_row);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Value Row::get(const char *colname) const
|
||||||
|
//{
|
||||||
|
|
||||||
|
//}
|
||||||
|
|
||||||
31
src/Pgsql_Row.h
Normal file
31
src/Pgsql_Row.h
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
#ifndef PGSQL_ROW_H
|
||||||
|
#define PGSQL_ROW_H
|
||||||
|
|
||||||
|
#include "Pgsql_Value.h"
|
||||||
|
|
||||||
|
namespace Pgsql {
|
||||||
|
|
||||||
|
class Result;
|
||||||
|
|
||||||
|
/** \brief A reference to a specific row from a result.
|
||||||
|
*
|
||||||
|
* As it is a reference its contents won't be valid after its associated result has
|
||||||
|
* been destroyed.
|
||||||
|
*/
|
||||||
|
class Row {
|
||||||
|
public:
|
||||||
|
Row(const Result &result, int row);
|
||||||
|
bool next();
|
||||||
|
|
||||||
|
bool operator==(const Row& rhs) const;
|
||||||
|
Value get(int col) const;
|
||||||
|
//Value get(const char *colname) const;
|
||||||
|
//bool get(int col, QString &s);
|
||||||
|
private:
|
||||||
|
const Result& m_result;
|
||||||
|
int m_row;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // end namespace Pgsql
|
||||||
|
|
||||||
|
#endif // PGSQL_ROW_H
|
||||||
56
src/Pgsql_Value.cpp
Normal file
56
src/Pgsql_Value.cpp
Normal file
|
|
@ -0,0 +1,56 @@
|
||||||
|
#include "Pgsql_Value.h"
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
using namespace Pgsql;
|
||||||
|
|
||||||
|
Value::Value(const char *val, Oid typ)
|
||||||
|
: m_val(val), m_typ(typ)
|
||||||
|
{}
|
||||||
|
|
||||||
|
QString Value::asQString() const
|
||||||
|
{
|
||||||
|
return QString::fromUtf8(m_val);
|
||||||
|
}
|
||||||
|
|
||||||
|
Value::operator QString() const
|
||||||
|
{
|
||||||
|
return QString::fromUtf8(m_val);
|
||||||
|
}
|
||||||
|
|
||||||
|
Value::operator QDateTime() const
|
||||||
|
{
|
||||||
|
return QDateTime::fromString(asQString(),
|
||||||
|
"yyyy-MM-dd hh:mm:ss");
|
||||||
|
}
|
||||||
|
|
||||||
|
Value::operator std::string() const
|
||||||
|
{
|
||||||
|
return m_val;
|
||||||
|
}
|
||||||
|
|
||||||
|
Value::operator short() const
|
||||||
|
{
|
||||||
|
return (short)std::atoi(m_val);
|
||||||
|
}
|
||||||
|
|
||||||
|
Value::operator int() const
|
||||||
|
{
|
||||||
|
return std::atoi(m_val);
|
||||||
|
}
|
||||||
|
|
||||||
|
Value::operator Oid() const
|
||||||
|
{
|
||||||
|
return operator int();
|
||||||
|
}
|
||||||
|
|
||||||
|
Value::operator __int64() const
|
||||||
|
{
|
||||||
|
return std::strtoull(m_val, nullptr, 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
Value::operator bool() const
|
||||||
|
{
|
||||||
|
return std::strcmp(m_val, "t") == 0;
|
||||||
|
}
|
||||||
|
|
||||||
33
src/Pgsql_Value.h
Normal file
33
src/Pgsql_Value.h
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
#ifndef PGSQL_VALUE_H
|
||||||
|
#define PGSQL_VALUE_H
|
||||||
|
|
||||||
|
#include "Pgsql_declare.h"
|
||||||
|
#include <QString>
|
||||||
|
#include <QDateTime>
|
||||||
|
|
||||||
|
namespace Pgsql {
|
||||||
|
|
||||||
|
/** \brief Class that is returned as value of a cell to facilitate auto conversion.
|
||||||
|
*/
|
||||||
|
class Value {
|
||||||
|
public:
|
||||||
|
Value(const char *val, Oid typ);
|
||||||
|
QString asQString() const;
|
||||||
|
operator QString() const;
|
||||||
|
operator QDateTime() const;
|
||||||
|
operator std::string() const;
|
||||||
|
operator short() const;
|
||||||
|
operator int() const;
|
||||||
|
operator Oid() const;
|
||||||
|
operator __int64() const;
|
||||||
|
operator bool() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
const char *m_val;
|
||||||
|
Oid m_typ;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // end namespace Pgsql
|
||||||
|
|
||||||
|
#endif // PGSQL_VALUE_H
|
||||||
|
|
@ -11,13 +11,13 @@ QueryResultModel::QueryResultModel(QObject *parent, std::shared_ptr<Pgsql::Resul
|
||||||
|
|
||||||
int QueryResultModel::rowCount(const QModelIndex &) const
|
int QueryResultModel::rowCount(const QModelIndex &) const
|
||||||
{
|
{
|
||||||
int r = result->getRows();
|
int r = result->rows();
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
int QueryResultModel::columnCount(const QModelIndex &) const
|
int QueryResultModel::columnCount(const QModelIndex &) const
|
||||||
{
|
{
|
||||||
int r = result->getCols();
|
int r = result->cols();
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -34,7 +34,7 @@ QVariant QueryResultModel::data(const QModelIndex &index, int role) const
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Oid o = result->type(col);
|
Oid o = result->type(col);
|
||||||
QString s(result->getVal(col, rij));
|
QString s(result->val(col, rij));
|
||||||
switch (o) {
|
switch (o) {
|
||||||
case oid_bool:
|
case oid_bool:
|
||||||
s = (s == "t") ? "TRUE" : "FALSE";
|
s = (s == "t") ? "TRUE" : "FALSE";
|
||||||
|
|
@ -88,7 +88,7 @@ QVariant QueryResultModel::data(const QModelIndex &index, int role) const
|
||||||
r = QBrush(Qt::darkGreen);
|
r = QBrush(Qt::darkGreen);
|
||||||
break;
|
break;
|
||||||
case oid_bool:
|
case oid_bool:
|
||||||
if (strcmp(result->getVal(col, rij), "t") == 0) {
|
if (strcmp(result->val(col, rij), "t") == 0) {
|
||||||
r = QBrush(Qt::darkGreen);
|
r = QBrush(Qt::darkGreen);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
|
||||||
|
|
@ -212,8 +212,8 @@ void QueryTab::explain(bool analyze)
|
||||||
std::thread([this,res]()
|
std::thread([this,res]()
|
||||||
{
|
{
|
||||||
std::shared_ptr<ExplainRoot> explain;
|
std::shared_ptr<ExplainRoot> explain;
|
||||||
if (res->getCols() == 1 && res->getRows() == 1) {
|
if (res->cols() == 1 && res->rows() == 1) {
|
||||||
std::string s = res->getVal(0, 0);
|
std::string s = res->val(0, 0);
|
||||||
Json::Value root; // will contains the root value after parsing.
|
Json::Value root; // will contains the root value after parsing.
|
||||||
Json::Reader reader;
|
Json::Reader reader;
|
||||||
bool parsingSuccessful = reader.parse(s, root);
|
bool parsingSuccessful = reader.parse(s, root);
|
||||||
|
|
|
||||||
123
src/RolesTableModel.cpp
Normal file
123
src/RolesTableModel.cpp
Normal file
|
|
@ -0,0 +1,123 @@
|
||||||
|
#include "RolesTableModel.h"
|
||||||
|
#include "PgAuthIdContainer.h"
|
||||||
|
|
||||||
|
RolesTableModel::RolesTableModel(QObject *parent)
|
||||||
|
: QAbstractTableModel(parent)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void RolesTableModel::setRoleList(const PgAuthIdContainer* roles)
|
||||||
|
{
|
||||||
|
beginResetModel();
|
||||||
|
m_roles = roles;
|
||||||
|
endResetModel();
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant RolesTableModel::headerData(int section, Qt::Orientation orientation, int role) const
|
||||||
|
{
|
||||||
|
QVariant v;
|
||||||
|
if (orientation == Qt::Horizontal) {
|
||||||
|
if (role == Qt::DisplayRole) {
|
||||||
|
switch (section) {
|
||||||
|
case NameCol:
|
||||||
|
v = tr("Name");
|
||||||
|
break;
|
||||||
|
case SuperCol:
|
||||||
|
v = tr("Super");
|
||||||
|
break;
|
||||||
|
case InheritCol:
|
||||||
|
v = tr("Inherit");
|
||||||
|
break;
|
||||||
|
case CreateRoleCol:
|
||||||
|
v = tr("Create role");
|
||||||
|
break;
|
||||||
|
case CreateDBCol:
|
||||||
|
v = tr("Create DB");
|
||||||
|
break;
|
||||||
|
case CanLoginCol:
|
||||||
|
v = tr("Can login");
|
||||||
|
break;
|
||||||
|
case ReplicationCol:
|
||||||
|
v = tr("Replication");
|
||||||
|
break;
|
||||||
|
case BypassRlsCol:
|
||||||
|
v = tr("Bypass RLS");
|
||||||
|
break;
|
||||||
|
case ConnlimitCol:
|
||||||
|
v = tr("Connection limit");
|
||||||
|
break;
|
||||||
|
case ValidUntilCol:
|
||||||
|
v = tr("Valid until");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
int RolesTableModel::rowCount(const QModelIndex &parent) const
|
||||||
|
{
|
||||||
|
int result = 0;
|
||||||
|
if (m_roles) {
|
||||||
|
result = m_roles->count();
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
int RolesTableModel::columnCount(const QModelIndex &parent) const
|
||||||
|
{
|
||||||
|
int result = 10;
|
||||||
|
// if (parent.isValid())
|
||||||
|
// return 10;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant RolesTableModel::data(const QModelIndex &index, int role) const
|
||||||
|
{
|
||||||
|
QVariant v;
|
||||||
|
//if (!index.isValid())
|
||||||
|
if (m_roles) {
|
||||||
|
const PgAuthId &authid = m_roles->getByIdx(index.row());
|
||||||
|
if (role == Qt::DisplayRole) {
|
||||||
|
switch (index.column()) {
|
||||||
|
case NameCol:
|
||||||
|
v = authid.name;
|
||||||
|
break;
|
||||||
|
case SuperCol:
|
||||||
|
// todo lookup role name
|
||||||
|
v = authid.super;
|
||||||
|
break;
|
||||||
|
case InheritCol:
|
||||||
|
// todo lookup encoding name
|
||||||
|
v = authid.inherit;
|
||||||
|
break;
|
||||||
|
case CreateRoleCol:
|
||||||
|
v = authid.createRole;
|
||||||
|
break;
|
||||||
|
case CreateDBCol:
|
||||||
|
v = authid.createDB;
|
||||||
|
break;
|
||||||
|
case CanLoginCol:
|
||||||
|
v = authid.canlogin;
|
||||||
|
break;
|
||||||
|
case ReplicationCol:
|
||||||
|
v = authid.replication;
|
||||||
|
break;
|
||||||
|
case BypassRlsCol:
|
||||||
|
v = authid.bypassRls;
|
||||||
|
break;
|
||||||
|
case ConnlimitCol:
|
||||||
|
// todo lookup tablespace name
|
||||||
|
v = authid.connLimit;
|
||||||
|
break;
|
||||||
|
case ValidUntilCol:
|
||||||
|
v = authid.validUntil;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return v;
|
||||||
|
}
|
||||||
39
src/RolesTableModel.h
Normal file
39
src/RolesTableModel.h
Normal file
|
|
@ -0,0 +1,39 @@
|
||||||
|
#ifndef ROLESTABLEMODEL_H
|
||||||
|
#define ROLESTABLEMODEL_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <QAbstractTableModel>
|
||||||
|
|
||||||
|
class PgAuthIdContainer;
|
||||||
|
|
||||||
|
/** Class for displaying the list of roles of a server in a QTableView
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
class RolesTableModel : public QAbstractTableModel {
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
enum e_Columns : int { NameCol, SuperCol, InheritCol, CreateRoleCol,
|
||||||
|
CreateDBCol, CanLoginCol, ReplicationCol,
|
||||||
|
BypassRlsCol, ConnlimitCol, ValidUntilCol };
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
explicit RolesTableModel(QObject *parent);
|
||||||
|
|
||||||
|
void setRoleList(const PgAuthIdContainer* roles);
|
||||||
|
|
||||||
|
// Header:
|
||||||
|
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
|
||||||
|
|
||||||
|
// Basic functionality:
|
||||||
|
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||||
|
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||||
|
|
||||||
|
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
const PgAuthIdContainer *m_roles = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // ROLESTABLEMODEL_H
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
#include "ui_ServerWindow.h"
|
#include "ui_ServerWindow.h"
|
||||||
#include "OpenDatabase.h"
|
#include "OpenDatabase.h"
|
||||||
#include "DatabasesTableModel.h"
|
#include "DatabasesTableModel.h"
|
||||||
|
#include "RolesTableModel.h"
|
||||||
#include "PgsqlDatabaseCatalogue.h"
|
#include "PgsqlDatabaseCatalogue.h"
|
||||||
|
|
||||||
ServerWindow::ServerWindow(MasterController *master, QWidget *parent)
|
ServerWindow::ServerWindow(MasterController *master, QWidget *parent)
|
||||||
|
|
@ -12,7 +13,10 @@ ServerWindow::ServerWindow(MasterController *master, QWidget *parent)
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
|
|
||||||
m_databasesModel = new DatabasesTableModel(this);
|
m_databasesModel = new DatabasesTableModel(this);
|
||||||
ui->tableView->setModel(m_databasesModel);
|
ui->databasesTableView->setModel(m_databasesModel);
|
||||||
|
|
||||||
|
m_rolesModel = new RolesTableModel(this);
|
||||||
|
ui->rolesTableView->setModel(m_rolesModel);
|
||||||
}
|
}
|
||||||
|
|
||||||
ServerWindow::~ServerWindow()
|
ServerWindow::~ServerWindow()
|
||||||
|
|
@ -29,6 +33,7 @@ void ServerWindow::setConfig(const ConnectionConfig &config)
|
||||||
auto cat = m_database->catalogue();
|
auto cat = m_database->catalogue();
|
||||||
if (cat) {
|
if (cat) {
|
||||||
m_databasesModel->setDatabaseList(cat->databases());
|
m_databasesModel->setDatabaseList(cat->databases());
|
||||||
|
m_rolesModel->setRoleList(cat->authIds());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
QString title = "pglab - ";
|
QString title = "pglab - ";
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ class ServerWindow;
|
||||||
class MasterController;
|
class MasterController;
|
||||||
class OpenDatabase;
|
class OpenDatabase;
|
||||||
class DatabasesTableModel;
|
class DatabasesTableModel;
|
||||||
|
class RolesTableModel;
|
||||||
|
|
||||||
class ServerWindow : public ASyncWindow {
|
class ServerWindow : public ASyncWindow {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
@ -22,10 +23,11 @@ public:
|
||||||
private:
|
private:
|
||||||
Ui::ServerWindow *ui;
|
Ui::ServerWindow *ui;
|
||||||
|
|
||||||
MasterController *m_masterController;
|
MasterController *m_masterController = nullptr;
|
||||||
ConnectionConfig m_config;
|
ConnectionConfig m_config;
|
||||||
OpenDatabase *m_database;
|
OpenDatabase *m_database = nullptr;
|
||||||
DatabasesTableModel *m_databasesModel;
|
DatabasesTableModel *m_databasesModel = nullptr;
|
||||||
|
RolesTableModel *m_rolesModel = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // SERVERWINDOW_H
|
#endif // SERVERWINDOW_H
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@
|
||||||
<item>
|
<item>
|
||||||
<widget class="QTabWidget" name="tabWidget">
|
<widget class="QTabWidget" name="tabWidget">
|
||||||
<property name="currentIndex">
|
<property name="currentIndex">
|
||||||
<number>0</number>
|
<number>2</number>
|
||||||
</property>
|
</property>
|
||||||
<widget class="QWidget" name="databasesTab">
|
<widget class="QWidget" name="databasesTab">
|
||||||
<attribute name="title">
|
<attribute name="title">
|
||||||
|
|
@ -50,7 +50,7 @@
|
||||||
<number>0</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QTableView" name="tableView">
|
<widget class="QTableView" name="databasesTableView">
|
||||||
<property name="alternatingRowColors">
|
<property name="alternatingRowColors">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
|
|
@ -82,7 +82,7 @@
|
||||||
<number>0</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QTableView" name="tableView_2">
|
<widget class="QTableView" name="tablespacesTableView">
|
||||||
<property name="alternatingRowColors">
|
<property name="alternatingRowColors">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
|
|
@ -114,7 +114,7 @@
|
||||||
<number>0</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QTableView" name="tableView_3">
|
<widget class="QTableView" name="rolesTableView">
|
||||||
<property name="alternatingRowColors">
|
<property name="alternatingRowColors">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
|
|
|
||||||
18
src/src.pro
18
src/src.pro
|
|
@ -59,7 +59,13 @@ SOURCES += main.cpp\
|
||||||
DatabasesTableModel.cpp \
|
DatabasesTableModel.cpp \
|
||||||
PgDatabase.cpp \
|
PgDatabase.cpp \
|
||||||
PgDatabaseContainer.cpp \
|
PgDatabaseContainer.cpp \
|
||||||
Pgsql_Params.cpp
|
Pgsql_Params.cpp \
|
||||||
|
RolesTableModel.cpp \
|
||||||
|
PgAuthId.cpp \
|
||||||
|
PgAuthIdContainer.cpp \
|
||||||
|
Pgsql_Result.cpp \
|
||||||
|
Pgsql_Row.cpp \
|
||||||
|
Pgsql_Value.cpp
|
||||||
|
|
||||||
HEADERS += \
|
HEADERS += \
|
||||||
sqlparser.h \
|
sqlparser.h \
|
||||||
|
|
@ -105,7 +111,13 @@ HEADERS += \
|
||||||
PgDatabaseContainer.h \
|
PgDatabaseContainer.h \
|
||||||
PgContainer.h \
|
PgContainer.h \
|
||||||
Pgsql_Params.h \
|
Pgsql_Params.h \
|
||||||
Pgsql_declare.h
|
Pgsql_declare.h \
|
||||||
|
RolesTableModel.h \
|
||||||
|
PgAuthId.h \
|
||||||
|
PgAuthIdContainer.h \
|
||||||
|
Pgsql_Result.h \
|
||||||
|
Pgsql_Row.h \
|
||||||
|
Pgsql_Value.h
|
||||||
|
|
||||||
FORMS += mainwindow.ui \
|
FORMS += mainwindow.ui \
|
||||||
DatabaseWindow.ui \
|
DatabaseWindow.ui \
|
||||||
|
|
@ -119,4 +131,4 @@ FORMS += mainwindow.ui \
|
||||||
RESOURCES += \
|
RESOURCES += \
|
||||||
resources.qrc
|
resources.qrc
|
||||||
|
|
||||||
QMAKE_LFLAGS_WINDOWS = /SUBSYSTEM:WINDOWS,5.01
|
#QMAKE_LFLAGS_WINDOWS = /SUBSYSTEM:WINDOWS,5.01
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue