pgLab/pglablib/PgDatabaseCatalog.cpp
eelke 0cef509771 Correct tablespace names are now shown in the list of tables.
Slightly more complex then you may expect because the tablespace specified by the tables tends to be oid 0
which means the default tablespace is used. However this does not mean pg_default, it means the tablespace
as defined as standard in the database definition. So we need to know what the current dbname is retrieve
it's details from the catalog and retrieve that tablespace to know what to show for an oid of 0.
2018-08-27 21:14:57 +02:00

267 lines
6 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 "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 = 11;
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_types, conn);
progress_callback && progress_callback(++n, count);
}
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 PgTypeContainer> PgDatabaseCatalog::types() const
{
return m_types;
}