Used slightly different approach. This tab is fully build in source code using subclasses to adjust behaviour of widgets for reuse in the other tabs. Uses custom proxy model for filtering triggers for correct table and supporting out of the box sorting by QTableView. SqlCodePreview: QPlainTextEditor which sql highlighter and in readonly mode but allows copy.
278 lines
6.2 KiB
C++
278 lines
6.2 KiB
C++
#include "PgDatabaseCatalog.h"
|
|
|
|
#include "ASyncDBConnection.h"
|
|
#include "PgAmContainer.h"
|
|
#include "PgAttributeContainer.h"
|
|
#include "PgAuthIdContainer.h"
|
|
#include "PgClassContainer.h"
|
|
#include "PgConstraintContainer.h"
|
|
#include "PgDatabaseContainer.h"
|
|
#include "PgIndexContainer.h"
|
|
#include "PgNamespaceContainer.h"
|
|
#include "PgTablespaceContainer.h"
|
|
#include "PgTriggerContainer.h"
|
|
#include "PgTypeContainer.h"
|
|
#include "Pgsql_Connection.h"
|
|
#include "Pgsql_oids.h"
|
|
|
|
#include <QThread>
|
|
#include <boost/timer/timer.hpp>
|
|
#include <boost/chrono/system_clocks.hpp>
|
|
|
|
using namespace Pgsql;
|
|
|
|
QString getRoleNameFromOid(const PgDatabaseCatalog &cat, Oid oid)
|
|
{
|
|
QString name;
|
|
auto auth_ids = cat.authIds();
|
|
if (auth_ids) {
|
|
const PgAuthId& auth_id = auth_ids->getByKey(oid);
|
|
if (auth_id.valid()) {
|
|
name = auth_id.name;
|
|
}
|
|
}
|
|
return name;
|
|
}
|
|
|
|
QString getRoleDisplayString(const PgDatabaseCatalog &cat, Oid oid)
|
|
{
|
|
QString name = getRoleNameFromOid(cat, oid);
|
|
return name;
|
|
}
|
|
|
|
QString getNamespaceDisplayString(const PgDatabaseCatalog &cat, Oid oid)
|
|
{
|
|
QString result;
|
|
auto nss = cat.namespaces();
|
|
auto ns = nss->getByKey(oid);
|
|
result = ns.name; //QString("ns %1").arg(oid);
|
|
return result;
|
|
}
|
|
|
|
QString getClassDisplayString(const PgDatabaseCatalog &cat, Oid oid)
|
|
{
|
|
QString result;
|
|
auto l = cat.classes();
|
|
auto e = l->getByKey(oid);
|
|
result = e.name;
|
|
return result;
|
|
|
|
}
|
|
|
|
QString getIndexDisplayString(const PgDatabaseCatalog &cat, Oid oid)
|
|
{
|
|
QString result;
|
|
// auto l = cat.indexes();
|
|
// auto e = l->getByKey(oid);
|
|
// if (e)
|
|
result = getClassDisplayString(cat, oid);
|
|
return result;
|
|
}
|
|
|
|
QString getTablespaceDisplayString(const PgDatabaseCatalog &cat, Oid oid)
|
|
{
|
|
// TODO load list and lookup name
|
|
if (oid == 0) {
|
|
auto dbname = cat.getDBName();
|
|
oid = cat.databases()->getByName(dbname).tablespace;
|
|
}
|
|
auto ts = cat.tablespaces()->getByKey(oid);
|
|
return ts.name;
|
|
}
|
|
|
|
QString getTypeDisplayString(const PgDatabaseCatalog &cat, Oid oid, int32_t typmod)
|
|
{
|
|
if (oid == 0) {
|
|
return QString();
|
|
}
|
|
|
|
auto tc = cat.types();
|
|
auto t = tc->getByKey(oid);
|
|
if (t.oid == InvalidOid) {
|
|
return "(invalid/unknown)";
|
|
}
|
|
QString s;
|
|
if (t.category == TypCategory::Array) {
|
|
// auto et = tc->getByKey(t.elem);
|
|
// s = et.name;
|
|
s = getTypeDisplayString(cat, t.elem, typmod);
|
|
s += "[]";
|
|
}
|
|
else {
|
|
s = t.name;
|
|
switch (oid) {
|
|
case varchar_oid:
|
|
case char_oid:
|
|
case text_oid:
|
|
if (typmod > 4)
|
|
s += QString::asprintf("(%d)", typmod-4);
|
|
break;
|
|
case numeric_oid:
|
|
if (typmod > 4) {
|
|
int prec = (typmod - 4) / 65536;
|
|
int scale = (typmod - 4) % 65536;
|
|
if (scale > 0)
|
|
s += QString::asprintf("(%d,%d)", prec, scale);
|
|
else
|
|
s += QString::asprintf("(%d)", prec);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
return s;
|
|
}
|
|
|
|
|
|
PgDatabaseCatalog::PgDatabaseCatalog()
|
|
{
|
|
}
|
|
|
|
PgDatabaseCatalog::~PgDatabaseCatalog()
|
|
{
|
|
}
|
|
|
|
void PgDatabaseCatalog::loadAll(Pgsql::Connection &conn,
|
|
std::function<bool(int, int)> progress_callback)
|
|
{
|
|
loadInfo(conn);
|
|
const int count = 12;
|
|
int n = 0;
|
|
if (progress_callback && !progress_callback(++n, count))
|
|
return;
|
|
load2(m_namespaces, conn);
|
|
if (progress_callback && !progress_callback(++n, count))
|
|
return;
|
|
load2(m_tablespaces, conn);
|
|
if (progress_callback && !progress_callback(++n, count))
|
|
return;
|
|
load2(m_classes, conn); // needs namespaces
|
|
if (progress_callback && !progress_callback(++n, count))
|
|
return;
|
|
load2(m_attributes, conn);
|
|
if (progress_callback && !progress_callback(++n, count))
|
|
return;
|
|
load2(m_authIds, conn);
|
|
if (progress_callback && !progress_callback(++n, count))
|
|
return;
|
|
load2(m_constraints, conn);
|
|
if (progress_callback && !progress_callback(++n, count))
|
|
return;
|
|
load2(m_databases, conn);
|
|
if (progress_callback && !progress_callback(++n, count))
|
|
return;
|
|
load2(m_indexes, conn);
|
|
if (progress_callback && !progress_callback(++n, count))
|
|
return;
|
|
load2(m_ams, conn);
|
|
if (progress_callback && !progress_callback(++n, count))
|
|
return;
|
|
load2(m_triggers, conn);
|
|
if (progress_callback && !progress_callback(++n, count))
|
|
return;
|
|
load2(m_types, conn);
|
|
progress_callback && progress_callback(++n, count);
|
|
|
|
refreshed(this, All);
|
|
}
|
|
|
|
void PgDatabaseCatalog::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).asQString();
|
|
|
|
m_dbName = conn.getDBName();
|
|
}
|
|
|
|
void load(Pgsql::Connection &conn, IPgContainter &pg_cont)
|
|
{
|
|
//QThread::msleep(400);
|
|
std::string q = pg_cont.getLoadQuery();
|
|
Pgsql::Result result = conn.query(q.c_str());
|
|
if (result && result.resultStatus() == PGRES_TUPLES_OK) {
|
|
//boost::timer::auto_cpu_timer t;
|
|
pg_cont.load(result);
|
|
}
|
|
else {
|
|
auto details = result.diagDetails();
|
|
if (details.state == "42501") { // permission denied
|
|
// ignore this for now
|
|
}
|
|
else {
|
|
throw std::runtime_error("Query failed\n" + details.errorMessage);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
const QString& PgDatabaseCatalog::serverVersionString() const
|
|
{
|
|
return m_serverVersionString;
|
|
}
|
|
|
|
int PgDatabaseCatalog::serverVersion() const
|
|
{
|
|
return m_serverVersion;
|
|
}
|
|
|
|
std::shared_ptr<const PgAttributeContainer> PgDatabaseCatalog::attributes() const
|
|
{
|
|
return m_attributes;
|
|
}
|
|
|
|
std::shared_ptr<const PgAuthIdContainer> PgDatabaseCatalog::authIds() const
|
|
{
|
|
return m_authIds;
|
|
}
|
|
|
|
std::shared_ptr<const PgClassContainer> PgDatabaseCatalog::classes() const
|
|
{
|
|
return m_classes;
|
|
}
|
|
|
|
std::shared_ptr<const PgConstraintContainer> PgDatabaseCatalog::constraints() const
|
|
{
|
|
return m_constraints;
|
|
}
|
|
|
|
std::shared_ptr<const PgDatabaseContainer> PgDatabaseCatalog::databases() const
|
|
{
|
|
return m_databases;
|
|
}
|
|
|
|
std::shared_ptr<const PgIndexContainer> PgDatabaseCatalog::indexes() const
|
|
{
|
|
return m_indexes;
|
|
}
|
|
|
|
std::shared_ptr<const PgAmContainer> PgDatabaseCatalog::ams() const
|
|
{
|
|
return m_ams;
|
|
}
|
|
|
|
std::shared_ptr<const PgNamespaceContainer> PgDatabaseCatalog::namespaces() const
|
|
{
|
|
return m_namespaces;
|
|
}
|
|
|
|
std::shared_ptr<const PgTablespaceContainer> PgDatabaseCatalog::tablespaces() const
|
|
{
|
|
return m_tablespaces;
|
|
}
|
|
|
|
std::shared_ptr<const PgTriggerContainer> PgDatabaseCatalog::triggers() const
|
|
{
|
|
return m_triggers;
|
|
}
|
|
|
|
std::shared_ptr<const PgTypeContainer> PgDatabaseCatalog::types() const
|
|
{
|
|
return m_types;
|
|
}
|
|
|