PgAttribute loading + ColummnTableModel

Required enchancement to PgContainer to make multifield key work.
This commit is contained in:
eelke 2017-12-12 20:13:53 +01:00
parent f9caadb59e
commit e9d72d391d
32 changed files with 698 additions and 99 deletions

149
pglab/ColumnTableModel.cpp Normal file
View file

@ -0,0 +1,149 @@
#include "ColumnTableModel.h"
#include "PgDatabaseCatalog.h"
#include "PgAttribute.h"
#include "PgAttributeContainer.h"
#include "PgType.h"
#include "PgTypeContainer.h"
#include "ScopeGuard.h"
#include <QBrush>
void ColumnTableModel::setData(std::shared_ptr<const PgDatabaseCatalog> cat, Oid table_oid)
{
beginResetModel();
SCOPE_EXIT { endResetModel(); };
m_catalog = cat;
m_columns = cat->attributes()->getColumnsForRelation(table_oid);
// hide system columns
m_columns.erase(std::remove_if(m_columns.begin(), m_columns.end(),
[](auto &e) { return e.num <= 0; } ),
m_columns.end());
// sort remaining columns by order in table
std::sort(m_columns.begin(), m_columns.end(),
[] (auto &l, auto &r) -> bool { return l.num < r.num; });
}
QVariant ColumnTableModel::headerData(int section, Qt::Orientation orientation, int role) const
{
QVariant v;
if (orientation == Qt::Horizontal) {
if (role == Qt::DisplayRole) {
QString c;
switch (section) {
case NameCol:
c = tr("Name");
break;
case TypeCol:
c = tr("Type");
break;
case NullCol:
c = tr("Nullable");
break;
case DefaultCol:
c = tr("Default");
break;
case CollationCol:
c = tr("Collation");
break;
}
v = c;
}
}
return v;
}
int ColumnTableModel::rowCount(const QModelIndex &parent) const
{
return m_columns.size();
}
int ColumnTableModel::columnCount(const QModelIndex &parent) const
{
return colCount;
}
Oid ColumnTableModel::getType(int column) const
{
Oid oid = Pgsql::VARCHAROID;
// switch (column) {
// case TypeCol:
// case NameCol:
// case NullCol:
// case DefaultCol:
// case CollationCol:
// oid = VARCHAROID;
// break;
// c = tr("Collation");
// break;
// }
return oid;
}
QVariant ColumnTableModel::getData(const QModelIndex &index) const
{
QVariant v;
const auto &t = m_columns[index.row()];
QString s;
switch (index.column()) {
case NameCol:
s = t.name;
break;
case TypeCol:
s = getTypeDisplayString(*m_catalog, t.typid);
break;
case NullCol:
s = t.notnull ? "NOT NULL" : "";
break;
case DefaultCol:
s = "";
break;
case CollationCol:
s = ""; //t.collation;
break;
}
v = s;
return v;
}
QVariant ColumnTableModel::data(const QModelIndex &index, int role) const
{
if (role == Qt::ForegroundRole && index.column() == TypeCol) {
QVariant v;
const auto &t = m_columns[index.row()];
auto c = m_catalog->types()->getByKey(t.typid);
switch (c.category) {
case TypCategory::Boolean:
v = QBrush(Qt::darkGreen);
break;
case TypCategory::Numeric:
v = QBrush(Qt::darkBlue);
break;
case TypCategory::DateTime:
case TypCategory::Timespan:
v = QBrush(Qt::darkMagenta);
break;
case TypCategory::String:
v = QBrush(Qt::darkYellow);
break;
case TypCategory::Array:
case TypCategory::Composite:
case TypCategory::Enum:
case TypCategory::Geometric:
case TypCategory::NetworkAddress:
case TypCategory::Pseudo:
case TypCategory::Range:
case TypCategory::UserDefined:
case TypCategory::BitString:
case TypCategory::Unknown:
default:
v = QBrush(Qt::black);
}
return v;
}
return BaseTableModel::data(index, role);
}

44
pglab/ColumnTableModel.h Normal file
View file

@ -0,0 +1,44 @@
#ifndef COLUMNTABLEMODEL_H
#define COLUMNTABLEMODEL_H
#include "BaseTableModel.h"
#include <memory>
class PgDatabaseCatalog;
class PgAttribute;
class ColumnTableModel: public BaseTableModel {
public:
enum e_Columns : int {
NameCol, ///
TypeCol,
NullCol,
DefaultCol,
CollationCol,
colCount };
using BaseTableModel::BaseTableModel;
void setData(std::shared_ptr<const PgDatabaseCatalog> cat, Oid table_oid);
// Header:
QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
// Basic functionality:
int rowCount(const QModelIndex &parent) const override;
int columnCount(const QModelIndex &parent) const override;
QVariant data(const QModelIndex &index, int role) const override;
protected:
virtual Oid getType(int column) const override;
virtual QVariant getData(const QModelIndex &index) const override;
using t_Columns = std::vector<PgAttribute>;
std::shared_ptr<const PgDatabaseCatalog> m_catalog;
t_Columns m_columns;
};
#endif // COLUMNTABLEMODEL_H

View file

@ -40,12 +40,6 @@ QueryTab* MainWindow::newSqlPage()
ui->tabWidget->addTab(qt, "Tab");
ui->tabWidget->setCurrentWidget(qt);
qt->newdoc();
auto tt = new TablesPage(this);
tt->setCatalog(m_database->catalogue());
ui->tabWidget->addTab(tt, "Tables");
ui->tabWidget->setCurrentWidget(tt);
return qt;
}
@ -68,6 +62,12 @@ void MainWindow::setConfig(const ConnectionConfig &config)
QString title = "pglab - ";
title += m_config.name().c_str();
setWindowTitle(title);
auto tt = new TablesPage(this);
tt->setCatalog(m_database->catalogue());
ui->tabWidget->addTab(tt, "Tables");
ui->tabWidget->setCurrentWidget(tt);
newSqlPage();
}

2
pglab/PgAttribute.cpp Normal file
View file

@ -0,0 +1,2 @@
#include "PgAttribute.h"

35
pglab/PgAttribute.h Normal file
View file

@ -0,0 +1,35 @@
#ifndef PGATTRIBUTE_H
#define PGATTRIBUTE_H
#include "Pgsql_declare.h"
#include <QString>
#include <libpq-fe.h>
#include <tuple>
class PgAttribute {
public:
using Key = std::tuple<Oid, int16_t>;
// Oid oid = InvalidOid;
Oid relid = InvalidOid;
QString name;
Oid typid = InvalidOid;
int32_t stattarget = 0;
int16_t num = 0;
int32_t ndims = 0; // array dimensions
int32_t typmod = -1;
bool notnull = false;
bool hasdef = false;
Oid collation = InvalidOid;
QString acl;
QString options;
bool operator==(Key _k) const { return relid == std::get<0>(_k) && num == std::get<1>(_k); }
bool operator==(const QString &n) const { return name == n; }
bool operator<(Key _k) const { return relid < std::get<0>(_k) || (relid == std::get<0>(_k) && num < std::get<1>(_k)); }
bool operator<(const PgAttribute &rhs) const { return relid < rhs.relid || (relid == rhs.relid && num < rhs.num); }
};
#endif // PGATTRIBUTE_H

View file

@ -0,0 +1,30 @@
#include "PgAttributeContainer.h"
#include "Pgsql_Col.h"
std::string PgAttributeContainer::getLoadQuery() const
{
return
"SELECT attrelid, attname, atttypid, attstattarget, \n"
" attnum, attndims, atttypmod, attnotnull, atthasdef, \n"
" attcollation, attacl, attoptions \n"
" FROM pg_catalog.pg_attribute";
}
PgAttribute PgAttributeContainer::loadElem(const Pgsql::Row &row)
{
Pgsql::Col col(row);
PgAttribute v;
col >> v.relid >> v.name >> v.typid >> v.stattarget
>> v.num >> v.ndims >> v.typmod >> v.notnull >> v.hasdef
>> v.collation >> v.acl >> v.options;
return v;
}
std::vector<PgAttribute> PgAttributeContainer::getColumnsForRelation(Oid oid) const
{
std::vector<PgAttribute> result;
for (const auto &e : m_container)
if (e.relid == oid)
result.push_back(e);
return result;
}

View file

@ -0,0 +1,20 @@
#ifndef PGATTRIBUTECONTAINER_H
#define PGATTRIBUTECONTAINER_H
#include "PgContainer.h"
#include "PgAttribute.h"
#include "Pgsql_declare.h"
#include <vector>
class PgAttributeContainer : public PgContainer<PgAttribute, PgAttribute::Key> {
public:
using PgContainer<PgAttribute, PgAttribute::Key>::PgContainer;
virtual std::string getLoadQuery() const override;
std::vector<PgAttribute> getColumnsForRelation(Oid oid) const;
protected:
PgAttribute loadElem(const Pgsql::Row &row) override;
};
#endif // PGATTRIBUTECONTAINER_H

View file

@ -12,22 +12,14 @@ std::string PgClassContainer::getLoadQuery() const
"FROM pg_catalog.pg_class";
}
void PgClassContainer::load(const Pgsql::Result &res)
PgClass PgClassContainer::loadElem(const Pgsql::Row &row)
{
const int n_rows = res.rows();
m_container.clear();
m_container.reserve(n_rows);
for (auto row : res) {
Pgsql::Col col(row);
PgClass v;
col >> v.oid >> v.name >> v.relnamespace >> v.type >> v.oftype
>> v.owner >> v.am >> v.filenode >> v.tablespace >> v.pages_est
>> v.tuples_est >> v.toastrelid >> v.isshared >> v.persistence
>> v.kind >> v.hasoids >> v.ispopulated >> v.frozenxid >> v.minmxid
>> v.acl >> v.options;
m_container.push_back(v);
}
std::sort(m_container.begin(), m_container.end());
Pgsql::Col col(row);
PgClass v;
col >> v.oid >> v.name >> v.relnamespace >> v.type >> v.oftype
>> v.owner >> v.am >> v.filenode >> v.tablespace >> v.pages_est
>> v.tuples_est >> v.toastrelid >> v.isshared >> v.persistence
>> v.kind >> v.hasoids >> v.ispopulated >> v.frozenxid >> v.minmxid
>> v.acl >> v.options;
return v;
}

View file

@ -16,8 +16,8 @@ public:
using PgContainer<PgClass>::PgContainer;
virtual std::string getLoadQuery() const override;
virtual void load(const Pgsql::Result &res) override;
protected:
PgClass loadElem(const Pgsql::Row &row) override;
private:
};

2
pglab/PgContainer.cpp Normal file
View file

@ -0,0 +1,2 @@
#include "PgContainer.h"

View file

@ -2,6 +2,7 @@
#define PGCONTAINER_H
#include "Pgsql_declare.h"
#include "Pgsql_Result.h"
#include <QString>
#include <memory>
#include <vector>
@ -18,7 +19,7 @@ public:
virtual void load(const Pgsql::Result &res) = 0;
};
template<typename T>
template<typename T, typename K=Oid>
class PgContainer: public IPgContainter {
public:
using t_Container = std::vector<T>; ///< Do not assume it will stay a vector only expect bidirectional access
@ -48,10 +49,10 @@ public:
return (int)m_container.size();
}
const T& getByOid(Oid oid) const
const T& getByKey(const K &key) const
{
auto lb_result = std::lower_bound(m_container.begin(), m_container.end(), oid);
if (lb_result != m_container.end() && lb_result->oid == oid)
auto lb_result = std::lower_bound(m_container.begin(), m_container.end(), key);
if (lb_result != m_container.end() && *lb_result == key)
return *lb_result;
return m_invalidInstance;
@ -71,9 +72,30 @@ public:
{
return m_container.at(idx);
}
/** Override to implement complete loading logic.
*
* Do not override this function if you only want to implement
* the loading of a single element. Override loadElem instead.
*/
virtual void load(const Pgsql::Result &res) override
{
m_container.clear();
m_container.reserve(res.rows());
for (auto row : res)
m_container.push_back(loadElem(row));
std::sort(m_container.begin(), m_container.end());
}
protected:
std::weak_ptr<PgDatabaseCatalog> m_catalogue;
t_Container m_container;
/** Override the implementation for this function to implement loading of single row.
*
* When overriding this function there is no need to override load.
*/
virtual T loadElem(const Pgsql::Row &) { return T(); }
private:
T m_invalidInstance;

View file

@ -1,8 +1,11 @@
#include "PgDatabaseCatalog.h"
#include "PgTypeContainer.h"
#include "PgDatabaseContainer.h"
#include "PgAttributeContainer.h"
#include "PgAuthIdContainer.h"
#include "PgClassContainer.h"
#include "PgDatabaseContainer.h"
#include "PgNamespaceContainer.h"
#include "PgTypeContainer.h"
#include "Pgsql_Connection.h"
@ -11,7 +14,7 @@ QString getRoleNameFromOid(const PgDatabaseCatalog &cat, Oid oid)
QString name;
auto auth_ids = cat.authIds();
if (auth_ids) {
const PgAuthId& auth_id = auth_ids->getByOid(oid);
const PgAuthId& auth_id = auth_ids->getByKey(oid);
if (auth_id.valid()) {
name = auth_id.name;
}
@ -22,13 +25,15 @@ QString getRoleNameFromOid(const PgDatabaseCatalog &cat, Oid oid)
QString getRoleDisplayString(const PgDatabaseCatalog &cat, Oid oid)
{
QString name = getRoleNameFromOid(cat, oid);
return QString("%1 (%2)").arg(name).arg(oid);
return name;
// return QString("%1 (%2)").arg(name).arg(oid);
}
QString getNamespaceDisplayString(const PgDatabaseCatalog &cat, Oid oid)
{
//QString name;
// auto c = cat.();
auto nss = cat.namespaces();
auto ns = nss->getByKey(oid);
// if (auth_ids) {
// const PgAuthId& auth_id = auth_ids->getByOid(oid);
// if (auth_id.valid()) {
@ -37,7 +42,7 @@ QString getNamespaceDisplayString(const PgDatabaseCatalog &cat, Oid oid)
// }
//return name;
// TODO load list and lookup name
return QString("ns %1").arg(oid);
return ns.name; //QString("ns %1").arg(oid);
}
@ -47,6 +52,13 @@ QString getTablespaceDisplayString(const PgDatabaseCatalog &cat, Oid oid)
return QString("ts %1").arg(oid);
}
QString getTypeDisplayString(const PgDatabaseCatalog &cat, Oid oid)
{
auto tc = cat.types();
auto t = tc->getByKey(oid);
return t.name;
}
PgDatabaseCatalog::PgDatabaseCatalog()
{
@ -59,10 +71,13 @@ PgDatabaseCatalog::~PgDatabaseCatalog()
void PgDatabaseCatalog::loadAll(Pgsql::Connection &conn)
{
loadInfo(conn);
loadTypes(conn);
loadDatabases(conn);
loadAttributes(conn);
loadAuthIds(conn);
loadClasses(conn);
loadDatabases(conn);
loadNamespaces(conn);
loadTypes(conn);
}
void PgDatabaseCatalog::loadInfo(Pgsql::Connection &conn)
@ -89,20 +104,12 @@ void load(Pgsql::Connection &conn, IPgContainter &pg_cont)
}
void PgDatabaseCatalog::loadTypes(Pgsql::Connection &conn)
void PgDatabaseCatalog::loadAttributes(Pgsql::Connection &conn)
{
if (!m_types)
m_types = std::make_shared<PgTypeContainer>(shared_from_this());
if (!m_attributes)
m_attributes = std::make_shared<PgAttributeContainer>(shared_from_this());
load(conn, *m_types);
}
void PgDatabaseCatalog::loadDatabases(Pgsql::Connection &conn)
{
if (!m_databases)
m_databases = std::make_shared<PgDatabaseContainer>(shared_from_this());
load(conn, *m_databases);
load(conn, *m_attributes);
}
void PgDatabaseCatalog::loadAuthIds(Pgsql::Connection &conn)
@ -121,6 +128,31 @@ void PgDatabaseCatalog::loadClasses(Pgsql::Connection &conn)
load(conn, *m_classes);
}
void PgDatabaseCatalog::loadDatabases(Pgsql::Connection &conn)
{
if (!m_databases)
m_databases = std::make_shared<PgDatabaseContainer>(shared_from_this());
load(conn, *m_databases);
}
void PgDatabaseCatalog::loadNamespaces(Pgsql::Connection &conn)
{
if (!m_namespaces)
m_namespaces = std::make_shared<PgNamespaceContainer>(shared_from_this());
load(conn, *m_namespaces);
}
void PgDatabaseCatalog::loadTypes(Pgsql::Connection &conn)
{
if (!m_types)
m_types = std::make_shared<PgTypeContainer>(shared_from_this());
load(conn, *m_types);
}
const QString& PgDatabaseCatalog::serverVersionString() const
{
return m_serverVersionString;
@ -131,14 +163,9 @@ int PgDatabaseCatalog::serverVersion() const
return m_serverVersion;
}
std::shared_ptr<const PgTypeContainer> PgDatabaseCatalog::types() const
std::shared_ptr<const PgAttributeContainer> PgDatabaseCatalog::attributes() const
{
return m_types;
}
std::shared_ptr<const PgDatabaseContainer> PgDatabaseCatalog::databases() const
{
return m_databases;
return m_attributes;
}
std::shared_ptr<const PgAuthIdContainer> PgDatabaseCatalog::authIds() const
@ -150,3 +177,19 @@ std::shared_ptr<const PgClassContainer> PgDatabaseCatalog::classes() const
{
return m_classes;
}
std::shared_ptr<const PgDatabaseContainer> PgDatabaseCatalog::databases() const
{
return m_databases;
}
std::shared_ptr<const PgNamespaceContainer> PgDatabaseCatalog::namespaces() const
{
return m_namespaces;
}
std::shared_ptr<const PgTypeContainer> PgDatabaseCatalog::types() const
{
return m_types;
}

View file

@ -12,9 +12,11 @@ namespace Pgsql {
}
class PgAttributeContainer;
class PgAuthIdContainer;
class PgClassContainer;
class PgDatabaseContainer;
class PgNamespaceContainer;
class PgTypeContainer;
class PgDatabaseCatalog: public std::enable_shared_from_this<PgDatabaseCatalog> {
@ -27,32 +29,41 @@ public:
void loadAll(Pgsql::Connection &conn);
void loadInfo(Pgsql::Connection &conn);
void loadTypes(Pgsql::Connection &conn);
void loadDatabases(Pgsql::Connection &conn);
void loadAttributes(Pgsql::Connection &conn);
void loadAuthIds(Pgsql::Connection &conn);
void loadClasses(Pgsql::Connection &conn);
void loadDatabases(Pgsql::Connection &conn);
void loadInfo(Pgsql::Connection &conn);
void loadNamespaces(Pgsql::Connection &conn);
void loadTypes(Pgsql::Connection &conn);
const QString& serverVersionString() const;
int serverVersion() const;
std::shared_ptr<const PgTypeContainer> types() const;
std::shared_ptr<const PgDatabaseContainer> databases() const;
std::shared_ptr<const PgAttributeContainer> attributes() const;
std::shared_ptr<const PgAuthIdContainer> authIds() const;
std::shared_ptr<const PgClassContainer> classes() const;
std::shared_ptr<const PgDatabaseContainer> databases() const;
std::shared_ptr<const PgNamespaceContainer> namespaces() const;
std::shared_ptr<const PgTypeContainer> types() const;
private:
QString m_serverVersionString;
int m_serverVersion;
std::shared_ptr<PgTypeContainer> m_types;
std::shared_ptr<PgDatabaseContainer> m_databases;
std::shared_ptr<PgAttributeContainer> m_attributes;
std::shared_ptr<PgAuthIdContainer> m_authIds;
std::shared_ptr<PgClassContainer> m_classes;
std::shared_ptr<PgDatabaseContainer> m_databases;
std::shared_ptr<PgNamespaceContainer> m_namespaces;
std::shared_ptr<PgTypeContainer> m_types;
};
QString getRoleNameFromOid(const PgDatabaseCatalog &cat, Oid oid);
QString getRoleDisplayString(const PgDatabaseCatalog &cat, Oid oid);
QString getNamespaceDisplayString(const PgDatabaseCatalog &cat, Oid oid);
QString getTablespaceDisplayString(const PgDatabaseCatalog &cat, Oid oid);
QString getTypeDisplayString(const PgDatabaseCatalog &cat, Oid oid);
#endif // PGSQLDATABASECATALOGUE_H

View file

@ -2,3 +2,8 @@
PgNamespace::PgNamespace() = default;
bool PgNamespace::isSystemCatalog() const
{
return name == "pg_catalog"
|| name == "information_schema";
}

View file

@ -4,14 +4,21 @@
#include <QString>
#include <libpq-fe.h>
class PgNamespace
{
class PgNamespace {
public:
PgNamespace();
Oid oid = InvalidOid;
QString name;
Oid owner = InvalidOid;
QString acl;
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 PgNamespace &rhs) const { return oid < rhs.oid; }
bool isSystemCatalog() const;
};
#endif // PGNAMESPACE_H

View file

@ -0,0 +1,23 @@
#include "PgNamespaceContainer.h"
#include "Pgsql_Col.h"
#include "Pgsql_Result.h"
#include "Pgsql_Value.h"
std::string PgNamespaceContainer::getLoadQuery() const
{
return "SELECT oid, nspname, nspowner, nspacl FROM pg_catalog.pg_namespace";
}
void PgNamespaceContainer::load(const Pgsql::Result &res)
{
const int n_rows = res.rows();
m_container.clear();
m_container.reserve(n_rows);
for (auto row : res) {
Pgsql::Col col(row);
PgNamespace v;
col >> v.oid >> v.name >> v.owner >> v.acl;
m_container.push_back(v);
}
std::sort(m_container.begin(), m_container.end());
}

View file

@ -0,0 +1,24 @@
#ifndef PGNAMESPACECONTAINER_H
#define PGNAMESPACECONTAINER_H
#include "PgNamespace.h"
#include "PgContainer.h"
namespace Pgsql {
class Result;
}
class PgNamespaceContainer: public PgContainer<PgNamespace> {
public:
using PgContainer<PgNamespace>::PgContainer;
virtual std::string getLoadQuery() const override;
virtual void load(const Pgsql::Result &res) override;
private:
};
#endif // PGNAMESPACECONTAINER_H

View file

@ -1,5 +1,56 @@
#include "PgType.h"
#include "Pgsql_Connection.h"
void operator<<(TypCategory &s, const Pgsql::Value &v)
{
//s = static_cast<T>(v);
const char *c = v.c_str();
switch (*c) {
case 'A':
s = TypCategory::Array;
break;
case 'B':
s = TypCategory::Boolean;
break;
case 'D':
s = TypCategory::DateTime;
break;
case 'E':
s = TypCategory::Enum;
break;
case 'G':
s = TypCategory::Geometric;
break;
case 'I':
s = TypCategory::NetworkAddress;
break;
case 'N':
s = TypCategory::Numeric;
break;
case 'P':
s = TypCategory::Pseudo;
break;
case 'R':
s = TypCategory::Range;
break;
case 'S':
s = TypCategory::String;
break;
case 'T':
s = TypCategory::Timespan;
break;
case 'U':
s = TypCategory::UserDefined;
break;
case 'V':
s = TypCategory::BitString;
break;
case 'X':
s = TypCategory::Unknown;
break;
}
}
PgType::PgType() = default;

View file

@ -3,19 +3,41 @@
#include <QString>
#include <libpq-fe.h>
#include "Pgsql_Value.h"
enum class TypCategory {
Array,
Boolean,
Composite,
DateTime,
Enum,
Geometric,
NetworkAddress,
Numeric,
Pseudo,
Range,
String,
Timespan,
UserDefined,
BitString,
Unknown
};
void operator<<(TypCategory &s, const Pgsql::Value &v);
class PgType {
public:
PgType();
Oid oid = InvalidOid;
QString typname;//"name";"NO"
QString name;//"name";"NO"
Oid typnamespace = InvalidOid;//"oid";"NO"
Oid typowner = InvalidOid;//"oid";"NO"
short typlen = -1;//"smallint";"NO"
bool typbyval = false;//"boolean";"NO"
QString typtype;//""char"";"NO"
QString typcategory;//""char"";"NO"
Oid owner = InvalidOid;//"oid";"NO"
short len = -1;//"smallint";"NO"
bool byval = false;//"boolean";"NO"
QString type;//""char"";"NO"
TypCategory category;//""char"";"NO"
bool typispreferred = false;//"boolean";"NO"
bool typisdefined = false;//"boolean";"NO"
QString typdelim;//""char"";"NO"
@ -41,7 +63,7 @@ public:
QString typacl;//"ARRAY";"YES"
bool operator==(Oid _oid) const { return oid == _oid; }
bool operator==(const QString &n) const { return typname == n; }
bool operator==(const QString &n) const { return name == n; }
bool operator<(Oid _oid) const { return oid < _oid; }
bool operator<(const PgType &rhs) const { return oid < rhs.oid; }
};

View file

@ -44,13 +44,13 @@ void PgTypeContainer::load(const Pgsql::Result &res)
for (auto row : res) {
PgType v;
v.oid << row.get(0); // InvalidOid;
v.typname << row.get(1); //. operator QString(); // "name";"NO"
v.name << row.get(1); //. operator QString(); // "name";"NO"
v.typnamespace << row.get(2); // InvalidOid;//"oid";"NO"
v.typowner << row.get(3); // InvalidOid;//"oid";"NO"
v.typlen << row.get(4); // -1;//"smallint";"NO"
v.typbyval << row.get(5); // false;//"boolean";"NO"
v.typtype << row.get(6);//""char"";"NO"
v.typcategory << row.get(7);//""char"";"NO"
v.owner << row.get(3); // InvalidOid;//"oid";"NO"
v.len << row.get(4); // -1;//"smallint";"NO"
v.byval << row.get(5); // false;//"boolean";"NO"
v.type << row.get(6);//""char"";"NO"
v.category << row.get(7);//""char"";"NO"
v.typispreferred << row.get(8); //false;//"boolean";"NO"
v.typisdefined << row.get(9); //false;//"boolean";"NO"
v.typdelim << row.get(10); //""char"";"NO"

View file

@ -3,7 +3,6 @@
#include "PgType.h"
#include "PgContainer.h"
#include <vector>
namespace Pgsql {

View file

@ -1,4 +1,6 @@
#include "ResultTableModelUtil.h"
#include <QTableView>
#include <QHeaderView>
using namespace Pgsql;
@ -55,3 +57,36 @@ QString FormatBoolForDisplay(bool v)
return v ? "TRUE" : "FALSE";
}
//<widget class="QTableView" name="ResultView">
// <property name="font">
// <font>
// <family>Source Sans Pro</family>
// <pointsize>10</pointsize>
// </font>
// </property>
// <property name="editTriggers">
// <set>QAbstractItemView::NoEditTriggers</set>
// </property>
// <property name="verticalScrollMode">
// <enum>QAbstractItemView::ScrollPerPixel</enum>
// </property>
// <property name="horizontalScrollMode">
// <enum>QAbstractItemView::ScrollPerPixel</enum>
// </property>
// <property name="wordWrap">
// <bool>false</bool>
// </property>
// <attribute name="verticalHeaderDefaultSectionSize">
// <number>20</number>
// </attribute>
// <attribute name="verticalHeaderMinimumSectionSize">
// <number>16</number>
// </attribute>
//</widget>
void SetTableViewDefault(QTableView *tv)
{
tv->setAlternatingRowColors(true);
tv->verticalHeader()->setMinimumSectionSize(16);
tv->verticalHeader()->setDefaultSectionSize(20);
}

View file

@ -21,3 +21,5 @@ inline QColor GetDefaultNumericColor() { return Qt::darkGreen; }
QString FormatBoolForDisplay(bool v);
class QTableView;
void SetTableViewDefault(QTableView *tv);

View file

@ -130,7 +130,7 @@ void SqlSyntaxHighlighter::setTypes(const PgTypeContainer& types)
{
m_typeNames.clear();
for (auto &e : types) {
m_typeNames.insert(e.typname);
m_typeNames.insert(e.name);
}
}

View file

@ -1,7 +1,10 @@
#include "TablesPage.h"
#include "ui_TablesPage.h"
#include "PgAttribute.h"
#include "TablesTableModel.h"
#include "ResultTableModelUtil.h"
#include "ColumnTableModel.h"
TablesPage::TablesPage(QWidget *parent) :
QWidget(parent),
@ -9,9 +12,22 @@ TablesPage::TablesPage(QWidget *parent) :
{
ui->setupUi(this);
SetTableViewDefault(ui->tableListTable);
m_tablesModel = new TablesTableModel(this);
ui->tableListTable->setModel(m_tablesModel);
SetTableViewDefault(ui->columnsTable);
m_columnsModel = new ColumnTableModel(this);
ui->columnsTable->setModel(m_columnsModel);
connect(ui->tableListTable->selectionModel(), &QItemSelectionModel::currentRowChanged, this,
&TablesPage::on_tableListTable_currentRowChanged);
}
TablesPage::~TablesPage()
{
delete ui;
}
void TablesPage::setCatalog(std::shared_ptr<PgDatabaseCatalog> cat)
@ -20,7 +36,10 @@ void TablesPage::setCatalog(std::shared_ptr<PgDatabaseCatalog> cat)
m_tablesModel->setCatalog(cat);
}
TablesPage::~TablesPage()
void TablesPage::on_tableListTable_currentRowChanged(const QModelIndex &current, const QModelIndex &previous)
{
delete ui;
if (current.row() != previous.row()) {
Oid table_oid = m_tablesModel->getTableOid(current.row());
m_columnsModel->setData(m_catalog, table_oid);
}
}

View file

@ -9,6 +9,7 @@ class TablesPage;
}
class TablesTableModel;
class ColumnTableModel;
class PgDatabaseCatalog;
class TablesPage : public QWidget
@ -24,6 +25,11 @@ private:
Ui::TablesPage *ui;
std::shared_ptr<PgDatabaseCatalog> m_catalog;
TablesTableModel* m_tablesModel = nullptr;
ColumnTableModel* m_columnsModel = nullptr;
private slots:
void on_tableListTable_currentRowChanged(const QModelIndex &current, const QModelIndex &previous);
};
#endif // TABLESPAGE_H

View file

@ -2,7 +2,10 @@
#include "PgDatabaseCatalog.h"
#include "PgClass.h"
#include "PgClassContainer.h"
#include "PgNamespace.h"
#include "PgNamespaceContainer.h"
#include "Pgsql_declare.h"
#include <QBrush>
TablesTableModel::TablesTableModel(QObject *parent)
: BaseTableModel(parent)
@ -44,6 +47,9 @@ QVariant TablesTableModel::headerData(int section, Qt::Orientation orientation,
case NameCol:
v = tr("Name");
break;
case NamespaceCol:
v = tr("Schema");
break;
case OwnerCol:
v = tr("Owner");
break;
@ -80,6 +86,7 @@ Oid TablesTableModel::getType(int column) const
case TablespaceCol:
case OwnerCol:
case NameCol:
case NamespaceCol:
case OptionsCol:
case AclCol:
default:
@ -94,7 +101,10 @@ QVariant TablesTableModel::getData(const QModelIndex &index) const
const auto &t = m_tables[index.row()];
switch (index.column()) {
case NameCol:
v = formatTableName(t);
v = t.name; //formatTableName(t);
break;
case NamespaceCol:
v = getNamespaceDisplayString(*m_catalog, t.relnamespace);
break;
case OwnerCol:
v = getRoleDisplayString(*m_catalog, t.owner);
@ -113,9 +123,33 @@ QVariant TablesTableModel::getData(const QModelIndex &index) const
return v;
}
Oid TablesTableModel::getTableOid(int row) const
{
return m_tables[row].oid;
}
QString TablesTableModel::formatTableName(const PgClass &cls) const
{
const char * format = "%2 (%1)";
QString ns_name = getNamespaceDisplayString(*m_catalog, cls.relnamespace);
return QString(format).arg(ns_name).arg(cls.name);
}
QVariant TablesTableModel::data(const QModelIndex &index, int role) const
{
if (role == Qt::ForegroundRole) {
const auto &t = m_tables[index.row()];
auto ns = m_catalog->namespaces()->getByKey(t.relnamespace);
if (ns.isSystemCatalog()) {
switch (index.column()) {
case NameCol:
case NamespaceCol:
return QBrush(Qt::blue);
break;
}
}
}
return BaseTableModel::data(index, role);
}

View file

@ -13,6 +13,7 @@ class TablesTableModel: public BaseTableModel
public:
enum e_Columns : int {
NameCol, ///< either table, ns.table or table (ns) depending on settings/filters
NamespaceCol,
OwnerCol,
TablespaceCol,
OptionsCol,
@ -30,6 +31,8 @@ public:
int rowCount(const QModelIndex &parent) const override;
int columnCount(const QModelIndex &parent) const override;
virtual QVariant data(const QModelIndex &index, int role) const override;
Oid getTableOid(int row) const;
protected:
virtual Oid getType(int column) const override;
virtual QVariant getData(const QModelIndex &index) const override;

View file

@ -61,8 +61,8 @@ void TypeSelectionItemModel::setTypeList(std::shared_ptr<const PgTypeContainer>
beginResetModel();
m_types.clear();
for (const auto &e : *types) {
if (e.typcategory != "A" && e.typtype != "c") {
m_types.push_back(e.typname);
if (e.category != TypCategory::Array && e.type != "c") {
m_types.push_back(e.name);
}
}
std::sort(m_types.begin(), m_types.end());

View file

@ -71,7 +71,12 @@ SOURCES += main.cpp\
TablesPage.cpp \
PgClassContainer.cpp \
TablesTableModel.cpp \
PgDatabaseCatalog.cpp
PgDatabaseCatalog.cpp \
PgNamespaceContainer.cpp \
ColumnTableModel.cpp \
PgAttribute.cpp \
PgContainer.cpp \
PgAttributeContainer.cpp
HEADERS += \
QueryResultModel.h \
@ -117,7 +122,11 @@ HEADERS += \
TablesPage.h \
PgClassContainer.h \
TablesTableModel.h \
PgDatabaseCatalog.h
PgDatabaseCatalog.h \
PgNamespaceContainer.h \
ColumnTableModel.h \
PgAttribute.h \
PgAttributeContainer.h
FORMS += mainwindow.ui \
DatabaseWindow.ui \
@ -136,12 +145,27 @@ RESOURCES += \
QMAKE_LFLAGS_WINDOWS = /SUBSYSTEM:WINDOWS,5.01
win32:CONFIG(release, debug|release): LIBS += -L$$OUT_PWD/../core/release/ -lcore
else:win32:CONFIG(debug, debug|release): LIBS += -L$$OUT_PWD/../core/debug/ -L$$OUT_PWD/../pgsql/debug/ -lcore -lpgsql
else:win32:CONFIG(debug, debug|release): LIBS += -L$$OUT_PWD/../core/debug/ -lcore
INCLUDEPATH += $$PWD/../core $$PWD/../pgsql
DEPENDPATH += $$PWD/../core $$PWD/../pgsql
INCLUDEPATH += $$PWD/../core
DEPENDPATH += $$PWD/../core
win32-g++:CONFIG(release, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../core/release/libcore.a
else:win32-g++:CONFIG(debug, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../core/debug/libcore.a
else:win32:!win32-g++:CONFIG(release, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../core/release/core.lib
else:win32:!win32-g++:CONFIG(debug, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../core/debug/core.lib $$OUT_PWD/../pgsql/debug/pgsql.lib
else:win32:!win32-g++:CONFIG(debug, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../core/debug/core.lib
win32:CONFIG(release, debug|release): LIBS += -L$$OUT_PWD/../pgsql/release/ -lpgsql
else:win32:CONFIG(debug, debug|release): LIBS += -L$$OUT_PWD/../pgsql/debug/ -lpgsql
else:unix:!macx: LIBS += -L$$OUT_PWD/../pgsql/ -lpgsql
INCLUDEPATH += $$PWD/../pgsql
DEPENDPATH += $$PWD/../pgsql
win32-g++:CONFIG(release, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../pgsql/release/libpgsql.a
else:win32-g++:CONFIG(debug, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../pgsql/debug/libpgsql.a
else:win32:!win32-g++:CONFIG(release, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../pgsql/release/pgsql.lib
else:win32:!win32-g++:CONFIG(debug, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../pgsql/debug/pgsql.lib
else:unix:!macx: PRE_TARGETDEPS += $$OUT_PWD/../pgsql/libpgsql.a