Reorganization of pgLab project
This commit is contained in:
parent
7300865c77
commit
c71fdc4af7
78 changed files with 204 additions and 148 deletions
28
pglab/catalog/models/BaseTableModel.cpp
Normal file
28
pglab/catalog/models/BaseTableModel.cpp
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
#include "BaseTableModel.h"
|
||||
#include "CustomDataRole.h"
|
||||
#include "ResultTableModelUtil.h"
|
||||
#include <QBrush>
|
||||
#include "Pgsql_oids.h"
|
||||
|
||||
using namespace Pgsql;
|
||||
|
||||
QVariant BaseTableModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
QVariant v;
|
||||
Oid oid = getType(index.column());
|
||||
if (role == Qt::DisplayRole) {
|
||||
v = getData(index);
|
||||
}
|
||||
else if (role == CustomDataTypeRole) {
|
||||
v = oid;
|
||||
}
|
||||
else if (role == CustomDataMeaningRole) {
|
||||
v = getDataMeaning(index);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
QVariant BaseTableModel::getDataMeaning(const QModelIndex &) const
|
||||
{
|
||||
return static_cast<int>(DataMeaningNormal);
|
||||
}
|
||||
23
pglab/catalog/models/BaseTableModel.h
Normal file
23
pglab/catalog/models/BaseTableModel.h
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
#ifndef BASETABLEMODEL_H
|
||||
#define BASETABLEMODEL_H
|
||||
|
||||
#include <QAbstractTableModel>
|
||||
#include "Pgsql_declare.h"
|
||||
|
||||
class BaseTableModel : public QAbstractTableModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
using QAbstractTableModel::QAbstractTableModel;
|
||||
|
||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||
|
||||
protected:
|
||||
virtual Oid getType(int column) const = 0;
|
||||
virtual QVariant getData(const QModelIndex &index) const = 0;
|
||||
virtual QVariant getDataMeaning(const QModelIndex &index) const;
|
||||
};
|
||||
|
||||
|
||||
#endif // BASETABLEMODEL_H
|
||||
318
pglab/catalog/models/ColumnTableModel.cpp
Normal file
318
pglab/catalog/models/ColumnTableModel.cpp
Normal file
|
|
@ -0,0 +1,318 @@
|
|||
#include "catalog/models/ColumnTableModel.h"
|
||||
#include "catalog/PgDatabaseCatalog.h"
|
||||
#include "catalog/PgAttribute.h"
|
||||
#include "catalog/PgAttributeContainer.h"
|
||||
#include "catalog/PgClassContainer.h"
|
||||
#include "catalog/PgConstraintContainer.h"
|
||||
#include "catalog/PgCollation.h"
|
||||
#include "catalog/PgCollationContainer.h"
|
||||
#include "catalog/PgType.h"
|
||||
#include "catalog/PgTypeContainer.h"
|
||||
#include "catalog/PgIndexContainer.h"
|
||||
#include "ScopeGuard.h"
|
||||
#include "SqlFormattingUtils.h"
|
||||
#include <QBrush>
|
||||
|
||||
namespace {
|
||||
|
||||
// Filter dropped and system columns but keep the oid column
|
||||
bool ColumnFilterWithOidsPred(PgAttribute &e)
|
||||
{
|
||||
return e.isdropped || (e.num <= 0 && e.name != "oid");
|
||||
}
|
||||
|
||||
// Filter dropped and system columns
|
||||
bool ColumnFilterWithoutOidsPred(PgAttribute &e)
|
||||
{
|
||||
return e.isdropped || e.num <= 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void ColumnTableModel::setData(std::shared_ptr<const PgDatabaseCatalog> cat, const std::optional<PgClass> &table)
|
||||
{
|
||||
if (cat != m_catalog) {
|
||||
m_catalog = cat;
|
||||
refreshConnection = connect(m_catalog.get(), &PgDatabaseCatalog::refreshed, this, &ColumnTableModel::refresh);
|
||||
}
|
||||
m_table = table;
|
||||
refresh();
|
||||
}
|
||||
|
||||
QVariant ColumnTableModel::headerData(int section, Qt::Orientation orientation, int role) const
|
||||
{
|
||||
QVariant v;
|
||||
if (orientation == Qt::Horizontal) {
|
||||
if (role == Qt::DisplayRole) {
|
||||
QString c;
|
||||
if (section >= colCount) {
|
||||
const auto &tbl_idx = m_indexes[section - colCount];
|
||||
if (tbl_idx.isprimary)
|
||||
c = "PK";
|
||||
else if (tbl_idx.isunique)
|
||||
c = "UIdx";
|
||||
else
|
||||
c = "Idx";
|
||||
}
|
||||
else {
|
||||
switch (section) {
|
||||
case AttnumCol:
|
||||
c = tr("#");
|
||||
break;
|
||||
case NameCol:
|
||||
c = tr("Name");
|
||||
break;
|
||||
case TypeCol:
|
||||
c = tr("Type");
|
||||
break;
|
||||
case NullCol:
|
||||
c = tr("N");
|
||||
break;
|
||||
case DefaultCol:
|
||||
c = tr("Default");
|
||||
break;
|
||||
case ForeignKeyCol:
|
||||
c = tr("Refs");
|
||||
break;
|
||||
case CollationCol:
|
||||
c = tr("Collation");
|
||||
break;
|
||||
case CommentCol:
|
||||
c = tr("Comment");
|
||||
break;
|
||||
}
|
||||
}
|
||||
v = c;
|
||||
}
|
||||
else if (role == Qt::ToolTipRole) {
|
||||
if (section >= colCount) {
|
||||
const auto &tbl_idx = m_indexes[section - colCount];
|
||||
//auto idx_cls = m_catalog->classes()->getByKey(tbl_idx.indexrelid);
|
||||
auto idx_class_name = tbl_idx.objectName(); // getClassDisplayString(*m_catalog, tbl_idx.indexrelid);
|
||||
QString s;
|
||||
if (tbl_idx.isprimary)
|
||||
s = tr("Primary key");
|
||||
else if (tbl_idx.isunique)
|
||||
s = tr("Unique index");
|
||||
else
|
||||
s = tr("Index");
|
||||
s += "\n" + idx_class_name;
|
||||
v = s;
|
||||
}
|
||||
else {
|
||||
switch (section) {
|
||||
// case NameCol:
|
||||
// c = tr("Name");
|
||||
// break;
|
||||
// case TypeCol:
|
||||
// c = tr("Type");
|
||||
// break;
|
||||
case NullCol:
|
||||
v = tr("N = Column is nullable");
|
||||
break;
|
||||
case DefaultCol:
|
||||
v = tr("Default value for the columns");
|
||||
break;
|
||||
case ForeignKeyCol:
|
||||
v = tr("Foreign key constraint for this column");
|
||||
break;
|
||||
// case CollationCol:
|
||||
// c = tr("Collation");
|
||||
// break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
int ColumnTableModel::rowCount(const QModelIndex &/*parent*/) const
|
||||
{
|
||||
return static_cast<int>(m_columns.size());
|
||||
}
|
||||
|
||||
int ColumnTableModel::columnCount(const QModelIndex &/*parent*/) const
|
||||
{
|
||||
return colCount + m_indexes.size();
|
||||
}
|
||||
|
||||
Oid ColumnTableModel::getType(int /*column*/) const
|
||||
{
|
||||
Oid oid = Pgsql::varchar_oid;
|
||||
// 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 int row = index.row();
|
||||
const auto &t = m_columns[row];
|
||||
|
||||
const int col = index.column();
|
||||
if (col >= colCount) {
|
||||
const auto &tbl_idx = m_indexes[col - colCount];
|
||||
int i = 1;
|
||||
for (auto attr : tbl_idx.key) {
|
||||
if (attr == t.num) {
|
||||
v = i;
|
||||
break;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
}
|
||||
else {
|
||||
switch (col) {
|
||||
case AttnumCol:
|
||||
//s = QString::asprintf("%d", (int) t.num);
|
||||
//break;
|
||||
return static_cast<int>(t.num);
|
||||
case NameCol:
|
||||
v = t.name;
|
||||
break;
|
||||
case TypeCol:
|
||||
v = getTypeDisplayString(*m_catalog, t.typid, t.typmod);
|
||||
break;
|
||||
case NullCol:
|
||||
v = QString::fromStdU16String(t.notnull ? u"" : u"N");
|
||||
break;
|
||||
case DefaultCol:
|
||||
v = t.defaultValue;
|
||||
break;
|
||||
case ForeignKeyCol:
|
||||
v = getFKey(t);
|
||||
break;
|
||||
case CollationCol:
|
||||
if (t.collation != InvalidOid) {
|
||||
auto&& col = m_catalog->collations()->getByKey(t.collation);
|
||||
if (col)
|
||||
v = col->objectName();
|
||||
}
|
||||
break;
|
||||
case CommentCol:
|
||||
v = t.description;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
QString ColumnTableModel::getFKey(const PgAttribute &column) const
|
||||
{
|
||||
QString result;
|
||||
auto&& list = m_catalog->constraints()->getFKeyForTableColumn(column.relid, column.num);
|
||||
for (auto&& elem : list) {
|
||||
if (elem.key[0] == column.num) {
|
||||
//result = elem.name;
|
||||
result = getForeignKeyConstraintReferencesShort(*m_catalog, elem);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void ColumnTableModel::refresh()
|
||||
{
|
||||
beginResetModel();
|
||||
SCOPE_EXIT { endResetModel(); };
|
||||
|
||||
if (m_table) {
|
||||
m_columns = m_catalog->attributes()->getColumnsForRelation(m_table->oid());
|
||||
// hide system and dropped columns
|
||||
auto column_filter_pred = m_table->hasoids ? ColumnFilterWithOidsPred : ColumnFilterWithoutOidsPred;
|
||||
auto si = std::remove_if(m_columns.begin(), m_columns.end(), column_filter_pred);
|
||||
// move columns to end and remove them
|
||||
m_columns.erase(si, 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; });
|
||||
}
|
||||
else
|
||||
m_columns.clear();
|
||||
|
||||
|
||||
if (m_table) {
|
||||
m_indexes = m_catalog->indexes()->getIndexesForTable(m_table->oid());
|
||||
std::sort(m_indexes.begin(), m_indexes.end(),
|
||||
[] (const auto &l, const auto &r) -> bool
|
||||
{
|
||||
return l.isprimary > r.isprimary
|
||||
|| (l.isprimary == r.isprimary && l.oid() < r.oid());
|
||||
});
|
||||
}
|
||||
else
|
||||
m_indexes.clear();
|
||||
|
||||
emit
|
||||
}
|
||||
|
||||
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()];
|
||||
if (t.typid == InvalidOid)
|
||||
v = QBrush(Qt::black);
|
||||
else {
|
||||
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;
|
||||
}
|
||||
if (role == Qt::TextAlignmentRole) {
|
||||
QVariant v;
|
||||
int col = index.column();
|
||||
if (col == NullCol || col >= colCount)
|
||||
v = int(Qt::AlignCenter | Qt::AlignVCenter);
|
||||
else
|
||||
v = int(Qt::AlignLeft | Qt::AlignVCenter);
|
||||
return v;
|
||||
}
|
||||
return BaseTableModel::data(index, role);
|
||||
}
|
||||
|
||||
const PgAttribute& ColumnTableModel::column(int row) const
|
||||
{
|
||||
return m_columns.at(static_cast<size_t>(row));
|
||||
}
|
||||
66
pglab/catalog/models/ColumnTableModel.h
Normal file
66
pglab/catalog/models/ColumnTableModel.h
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
#ifndef COLUMNTABLEMODEL_H
|
||||
#define COLUMNTABLEMODEL_H
|
||||
|
||||
#include "catalog/models/BaseTableModel.h"
|
||||
#include "catalog/PgAttribute.h"
|
||||
#include "catalog/PgDatabaseCatalog.h"
|
||||
#include "catalog/PgClass.h"
|
||||
#include "catalog/PgIndex.h"
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <vector>
|
||||
|
||||
class PgDatabaseCatalog;
|
||||
class PgAttribute;
|
||||
|
||||
class ColumnTableModel: public BaseTableModel {
|
||||
Q_OBJECT
|
||||
public:
|
||||
enum e_Columns : int {
|
||||
AttnumCol,
|
||||
NameCol, ///
|
||||
TypeCol,
|
||||
NullCol,
|
||||
DefaultCol,
|
||||
ForeignKeyCol,
|
||||
CollationCol,
|
||||
CommentCol,
|
||||
|
||||
colCount };
|
||||
|
||||
|
||||
using BaseTableModel::BaseTableModel;
|
||||
void setData(std::shared_ptr<const PgDatabaseCatalog> cat, const std::optional<PgClass> &table);
|
||||
|
||||
// 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;
|
||||
const PgAttribute& column(int row) const;
|
||||
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;
|
||||
std::optional<PgClass> m_table;
|
||||
t_Columns m_columns;
|
||||
std::vector<PgIndex> m_indexes;
|
||||
|
||||
QMetaObject::Connection refreshConnection;
|
||||
|
||||
QString getFKey(const PgAttribute &column) const;
|
||||
|
||||
|
||||
|
||||
private slots:
|
||||
/// Retrieves required data from catalog, called everytime it might have changed
|
||||
void refresh();
|
||||
};
|
||||
|
||||
#endif // COLUMNTABLEMODEL_H
|
||||
157
pglab/catalog/models/ConstraintModel.cpp
Normal file
157
pglab/catalog/models/ConstraintModel.cpp
Normal file
|
|
@ -0,0 +1,157 @@
|
|||
#include "ConstraintModel.h"
|
||||
#include "ScopeGuard.h"
|
||||
#include "catalog/PgDatabaseCatalog.h"
|
||||
#include "catalog/PgConstraintContainer.h"
|
||||
#include "Pgsql_oids.h"
|
||||
|
||||
ConstraintModel::ConstraintModel(QObject *parent)
|
||||
: BaseTableModel(parent)
|
||||
{
|
||||
}
|
||||
|
||||
void ConstraintModel::setData(std::shared_ptr<const PgDatabaseCatalog> cat, const std::optional<PgClass> &table)
|
||||
{
|
||||
if (cat != m_catalog) {
|
||||
m_catalog = cat;
|
||||
refreshConnection = connect(m_catalog.get(), &PgDatabaseCatalog::refreshed, this, &ConstraintModel::refresh);
|
||||
}
|
||||
m_table = table;
|
||||
refresh();
|
||||
}
|
||||
|
||||
void ConstraintModel::refresh()
|
||||
{
|
||||
beginResetModel();
|
||||
SCOPE_EXIT { endResetModel(); };
|
||||
|
||||
if (m_table) {
|
||||
m_constraints = m_catalog->constraints()->getConstraintsForRelation(m_table->oid());
|
||||
std::sort(m_constraints.begin(), m_constraints.end(),
|
||||
[] (auto &l, auto &r) {
|
||||
return l.type < r.type ||
|
||||
(l.type == r.type && l.objectName() < r.objectName());
|
||||
});
|
||||
}
|
||||
else
|
||||
m_constraints.clear();
|
||||
}
|
||||
|
||||
QVariant ConstraintModel::headerData(int section, Qt::Orientation orientation, int role) const
|
||||
{
|
||||
QVariant v;
|
||||
if (orientation == Qt::Horizontal) {
|
||||
if (role == Qt::DisplayRole) {
|
||||
QString c;
|
||||
switch (section) {
|
||||
case TypeCol:
|
||||
c = tr("Type");
|
||||
break;
|
||||
case NameCol:
|
||||
c = tr("Name");
|
||||
break;
|
||||
case NsCol:
|
||||
c = tr("Schema");
|
||||
break;
|
||||
case SupportingIndexCol:
|
||||
c = tr("Supporting index");
|
||||
break;
|
||||
// case DefinitionCol:
|
||||
// c = tr("Definition");
|
||||
// break;
|
||||
}
|
||||
v = c;
|
||||
}
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
int ConstraintModel::rowCount(const QModelIndex &) const
|
||||
{
|
||||
return static_cast<int>(m_constraints.size());
|
||||
}
|
||||
|
||||
int ConstraintModel::columnCount(const QModelIndex &) const
|
||||
{
|
||||
return colCount;
|
||||
}
|
||||
|
||||
//QVariant ConstraintModel::data(const QModelIndex &index, int role) const
|
||||
//{
|
||||
// QVariant v;
|
||||
// if (!index.isValid())
|
||||
// return QVariant();
|
||||
|
||||
// // FIXME: Implement me!
|
||||
// return v;
|
||||
//}
|
||||
|
||||
Oid ConstraintModel::getType(int ) const
|
||||
{
|
||||
Oid oid = Pgsql::varchar_oid;
|
||||
|
||||
return oid;
|
||||
}
|
||||
|
||||
QString IconForConstraintType(ConstraintType ct)
|
||||
{
|
||||
QString s = ":/icons/constraints/";
|
||||
switch (ct) {
|
||||
case ConstraintType::Check:
|
||||
s += "check.png";
|
||||
break;
|
||||
case ConstraintType::ForeignKey:
|
||||
s += "foreignkey.png";
|
||||
break;
|
||||
case ConstraintType::PrimaryKey:
|
||||
s += "primarykey.png";
|
||||
break;
|
||||
case ConstraintType::Unique:
|
||||
s += "unique.png";
|
||||
break;
|
||||
case ConstraintType::ConstraintTrigger:
|
||||
s = "CT";
|
||||
break;
|
||||
case ConstraintType::ExclusionConstraint:
|
||||
s = "XC";
|
||||
break;
|
||||
default:
|
||||
s = "?";
|
||||
break;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
QVariant ConstraintModel::getData(const QModelIndex &index) const
|
||||
{
|
||||
QVariant v;
|
||||
const int row = index.row();
|
||||
const auto &t = m_constraints[row];
|
||||
|
||||
const int col = index.column();
|
||||
QString s;
|
||||
switch (col) {
|
||||
case TypeCol:
|
||||
s = IconForConstraintType(t.type);
|
||||
break;
|
||||
case NameCol:
|
||||
s = t.objectName();
|
||||
break;
|
||||
case NsCol:
|
||||
s = t.nsName();
|
||||
break;
|
||||
case SupportingIndexCol:
|
||||
s = getIndexDisplayString(*m_catalog, t.indid);
|
||||
break;
|
||||
// case DefinitionCol:
|
||||
// s = t.definition;
|
||||
// break;
|
||||
}
|
||||
v = s;
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
const PgConstraint& ConstraintModel::constraint(int row)
|
||||
{
|
||||
return m_constraints[row];
|
||||
}
|
||||
57
pglab/catalog/models/ConstraintModel.h
Normal file
57
pglab/catalog/models/ConstraintModel.h
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
#ifndef CONSTRAINTMODEL_H
|
||||
#define CONSTRAINTMODEL_H
|
||||
|
||||
#include "BaseTableModel.h"
|
||||
#include "catalog/PgClass.h"
|
||||
#include "catalog/PgConstraint.h"
|
||||
#include <QAbstractTableModel>
|
||||
#include <optional>
|
||||
#include <vector>
|
||||
|
||||
class PgDatabaseCatalog;
|
||||
|
||||
class ConstraintModel : public BaseTableModel {
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
||||
enum e_Columns : int {
|
||||
TypeCol,
|
||||
NameCol, ///
|
||||
NsCol, ///
|
||||
SupportingIndexCol,
|
||||
// DefinitionCol,
|
||||
colCount };
|
||||
|
||||
explicit ConstraintModel(QObject *parent = nullptr);
|
||||
|
||||
void setData(std::shared_ptr<const PgDatabaseCatalog> cat, const std::optional<PgClass> &table);
|
||||
|
||||
|
||||
// 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;
|
||||
|
||||
const PgConstraint& constraint(int row);
|
||||
protected:
|
||||
|
||||
virtual Oid getType(int column) const override;
|
||||
virtual QVariant getData(const QModelIndex &index) const override;
|
||||
|
||||
private:
|
||||
std::shared_ptr<const PgDatabaseCatalog> m_catalog;
|
||||
std::optional<PgClass> m_table;
|
||||
|
||||
using t_Constraints = std::vector<PgConstraint>;
|
||||
t_Constraints m_constraints;
|
||||
QMetaObject::Connection refreshConnection;
|
||||
|
||||
private slots:
|
||||
void refresh();
|
||||
};
|
||||
|
||||
#endif // CONSTRAINTMODEL_H
|
||||
245
pglab/catalog/models/DatabasesTableModel.cpp
Normal file
245
pglab/catalog/models/DatabasesTableModel.cpp
Normal file
|
|
@ -0,0 +1,245 @@
|
|||
#include "DatabasesTableModel.h"
|
||||
#include "CustomDataRole.h"
|
||||
#include "OpenDatabase.h"
|
||||
#include "ScopeGuard.h"
|
||||
#include "catalog/PgDatabaseCatalog.h"
|
||||
#include "catalog/PgDatabaseContainer.h"
|
||||
#include "catalog/PgAuthIdContainer.h"
|
||||
#include "ResultTableModelUtil.h"
|
||||
#include <QtConcurrent>
|
||||
#include "Pgsql_Connection.h"
|
||||
|
||||
using namespace Pgsql;
|
||||
|
||||
DatabasesTableModel::DatabasesTableModel(std::shared_ptr<OpenDatabase> opendatabase, QObject *parent)
|
||||
: BaseTableModel(parent)
|
||||
, openDatabase(opendatabase)
|
||||
{
|
||||
}
|
||||
|
||||
void DatabasesTableModel::setDatabaseList(std::shared_ptr<const PgDatabaseCatalog> cat)
|
||||
{
|
||||
beginResetModel();
|
||||
SCOPE_EXIT { endResetModel(); };
|
||||
|
||||
databases.clear();
|
||||
|
||||
std::map<Oid, int> oidIndex;
|
||||
m_catalog = cat;
|
||||
auto dats = cat->databases();
|
||||
databases.reserve(dats->count());
|
||||
for (const auto& d : *dats)
|
||||
{
|
||||
databases.emplace_back(d);
|
||||
oidIndex.emplace(d.oid(), databases.size() - 1);
|
||||
}
|
||||
StartLoadDatabaseSizes(std::move(oidIndex));
|
||||
}
|
||||
|
||||
QVariant DatabasesTableModel::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 DbaCol:
|
||||
v = tr("Owner");
|
||||
break;
|
||||
case EncodingCol:
|
||||
v = tr("Encoding");
|
||||
break;
|
||||
case CollateCol:
|
||||
v = tr("Collation");
|
||||
break;
|
||||
case CTypeCol:
|
||||
v = tr("CType");
|
||||
break;
|
||||
case IsTemplateCol:
|
||||
v = tr("Is template");
|
||||
break;
|
||||
case AllowConnCol:
|
||||
v = tr("Can connect");
|
||||
break;
|
||||
case ConnLimitCol:
|
||||
v = tr("Conn. limit");
|
||||
break;
|
||||
case TablespaceCol:
|
||||
v = tr("Tablespace");
|
||||
break;
|
||||
case CommentCol:
|
||||
v = tr("Comment");
|
||||
break;
|
||||
case SizeCol:
|
||||
v = tr("Size");
|
||||
break;
|
||||
case AclCol:
|
||||
v = tr("ACL");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
int DatabasesTableModel::rowCount(const QModelIndex &) const
|
||||
{
|
||||
int result = 0;
|
||||
result = databases.size();
|
||||
return result;
|
||||
}
|
||||
|
||||
int DatabasesTableModel::columnCount(const QModelIndex &) const
|
||||
{
|
||||
int result = COL_COUNT;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Oid DatabasesTableModel::getType(int column) const
|
||||
{
|
||||
Oid oid;
|
||||
switch (column)
|
||||
{
|
||||
case AllowConnCol:
|
||||
case IsTemplateCol:
|
||||
oid = Pgsql::bool_oid;
|
||||
break;
|
||||
case ConnLimitCol:
|
||||
oid = Pgsql::int4_oid;
|
||||
break;
|
||||
case SizeCol:
|
||||
oid = Pgsql::int8_oid;
|
||||
break;
|
||||
case AclCol:
|
||||
case CollateCol:
|
||||
case CTypeCol:
|
||||
case EncodingCol:
|
||||
case DbaCol:
|
||||
case NameCol:
|
||||
case TablespaceCol:
|
||||
case CommentCol:
|
||||
oid = Pgsql::varchar_oid;
|
||||
break;
|
||||
default:
|
||||
oid = InvalidOid;
|
||||
}
|
||||
return oid;
|
||||
}
|
||||
|
||||
QVariant DatabasesTableModel::getData(const QModelIndex &index) const
|
||||
{
|
||||
QVariant v;
|
||||
const Database &d = databases[index.row()];
|
||||
const PgDatabase &db = d.database;
|
||||
switch (index.column()) {
|
||||
case NameCol:
|
||||
v = db.objectName();
|
||||
break;
|
||||
case DbaCol:
|
||||
v = db.ownerName();
|
||||
break;
|
||||
case EncodingCol:
|
||||
v = db.encodingString;
|
||||
break;
|
||||
case CollateCol:
|
||||
v = db.collate;
|
||||
break;
|
||||
case CTypeCol:
|
||||
v = db.ctype;
|
||||
break;
|
||||
case IsTemplateCol:
|
||||
v = db.isTemplate;
|
||||
break;
|
||||
case AllowConnCol:
|
||||
v = db.allowConn;
|
||||
break;
|
||||
case ConnLimitCol:
|
||||
v = db.connLimit;
|
||||
break;
|
||||
case TablespaceCol:
|
||||
v = getTablespaceDisplayString(*m_catalog, db.tablespace);
|
||||
break;
|
||||
case CommentCol:
|
||||
v = db.description;
|
||||
break;
|
||||
case SizeCol:
|
||||
if (d.size.totalBytes >= 0)
|
||||
v = d.size.totalBytes;
|
||||
break;
|
||||
case AclCol:
|
||||
v = db.aclString();
|
||||
break;
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
QVariant DatabasesTableModel::getDataMeaning(const QModelIndex &index) const
|
||||
{
|
||||
if (index.column() == SizeCol)
|
||||
{
|
||||
return static_cast<int>(DataMeaningBytes);
|
||||
}
|
||||
return BaseTableModel::getDataMeaning(index);
|
||||
}
|
||||
|
||||
void DatabasesTableModel::StartLoadDatabaseSizes(std::map<Oid, int> oidIndex)
|
||||
{
|
||||
QPointer p(this);
|
||||
QtConcurrent::run([this]
|
||||
{
|
||||
return QueryDatabaseSizes();
|
||||
})
|
||||
.then(qApp, [p, oi = std::move(oidIndex)] (DatabaseSizes sizes)
|
||||
{
|
||||
if (p)
|
||||
{
|
||||
p.data()->PopulateSizes(std::move(oi), std::move(sizes));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
DatabasesTableModel::DatabaseSizes DatabasesTableModel::QueryDatabaseSizes()
|
||||
{
|
||||
std::string q =
|
||||
"SELECT pg_database.oid, "
|
||||
" case when has_database_privilege(current_role, pg_database.oid, \n"
|
||||
" 'connect') then pg_database_size(pg_database.oid) else -1 end \n"
|
||||
"FROM pg_database";
|
||||
|
||||
Pgsql::Connection connection;
|
||||
connection.connect(openDatabase->config().connectionString());
|
||||
Pgsql::Result sizesResult = connection.query(q.c_str());
|
||||
|
||||
DatabaseSizes result;
|
||||
result.reserve(sizesResult.rows());
|
||||
for (auto& row : sizesResult)
|
||||
{
|
||||
DatabaseSize ds;
|
||||
ds.oid = row.get(0);
|
||||
ds.totalBytes = row.get(1);
|
||||
result.push_back(ds);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void DatabasesTableModel::PopulateSizes(std::map<Oid, int> oidIndex, DatabaseSizes sizes)
|
||||
{
|
||||
for (auto & s : sizes)
|
||||
{
|
||||
auto findIter = oidIndex.find(s.oid);
|
||||
if (findIter != oidIndex.end())
|
||||
{
|
||||
databases[findIter->second].size = s;
|
||||
}
|
||||
}
|
||||
emit dataChanged(
|
||||
createIndex(0, SizeCol),
|
||||
createIndex(static_cast<int>(databases.size()), SizeCol)
|
||||
);
|
||||
}
|
||||
80
pglab/catalog/models/DatabasesTableModel.h
Normal file
80
pglab/catalog/models/DatabasesTableModel.h
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
#ifndef DATABASESTABLEMODEL_H
|
||||
#define DATABASESTABLEMODEL_H
|
||||
|
||||
#include "BaseTableModel.h"
|
||||
#include "catalog/PgDatabase.h"
|
||||
#include <memory>
|
||||
|
||||
class OpenDatabase;
|
||||
class PgDatabaseCatalog;
|
||||
|
||||
/** Class for displaying the list of databases of a server in a QTableView
|
||||
*
|
||||
*/
|
||||
class DatabasesTableModel : public BaseTableModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
using RowItem = PgDatabase;
|
||||
|
||||
enum e_Columns : int { NameCol, DbaCol, EncodingCol, CollateCol,
|
||||
CTypeCol, IsTemplateCol, AllowConnCol, ConnLimitCol,
|
||||
TablespaceCol, CommentCol, SizeCol, AclCol, COL_COUNT };
|
||||
|
||||
|
||||
|
||||
explicit DatabasesTableModel(std::shared_ptr<OpenDatabase> opendatabase, QObject *parent);
|
||||
|
||||
void setDatabaseList(std::shared_ptr<const PgDatabaseCatalog> cat);
|
||||
|
||||
// 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;
|
||||
|
||||
virtual Oid getType(int column) const override;
|
||||
virtual QVariant getData(const QModelIndex &index) const override;
|
||||
|
||||
RowItem rowItem(int row) const
|
||||
{
|
||||
return databases.at(row).database;
|
||||
}
|
||||
protected:
|
||||
virtual QVariant getDataMeaning(const QModelIndex &index) const override;
|
||||
private:
|
||||
class DatabaseSize {
|
||||
public:
|
||||
Oid oid;
|
||||
int64_t totalBytes;
|
||||
|
||||
DatabaseSize()
|
||||
: oid(InvalidOid)
|
||||
, totalBytes(-1)
|
||||
{}
|
||||
};
|
||||
using DatabaseSizes = std::vector<DatabaseSize>;
|
||||
|
||||
class Database {
|
||||
public:
|
||||
PgDatabase database;
|
||||
DatabaseSize size;
|
||||
|
||||
Database(const PgDatabase &db)
|
||||
: database(db)
|
||||
{}
|
||||
};
|
||||
using Databases = std::vector<Database>;
|
||||
|
||||
std::shared_ptr<OpenDatabase> openDatabase;
|
||||
std::shared_ptr<const PgDatabaseCatalog> m_catalog;
|
||||
Databases databases;
|
||||
|
||||
void StartLoadDatabaseSizes(std::map<Oid, int> oidIndex);
|
||||
DatabaseSizes QueryDatabaseSizes();
|
||||
void PopulateSizes(std::map<Oid, int> oidIndex, DatabaseSizes sizes);
|
||||
};
|
||||
|
||||
#endif // DATABASESTABLEMODEL_H
|
||||
94
pglab/catalog/models/DependantsTableModel.cpp
Normal file
94
pglab/catalog/models/DependantsTableModel.cpp
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
#include "DependantsTableModel.h"
|
||||
#include "catalog/PgDatabaseCatalog.h"
|
||||
#include "catalog/PgConstraintContainer.h"
|
||||
#include "catalog/PgClassContainer.h"
|
||||
|
||||
|
||||
DependantsTableModel::DependantsTableModel(QObject *parent)
|
||||
: QAbstractTableModel(parent)
|
||||
{
|
||||
}
|
||||
|
||||
void DependantsTableModel::setCatalog(std::shared_ptr<const PgDatabaseCatalog> cat)
|
||||
{
|
||||
if (cat != m_catalog) {
|
||||
m_catalog = cat;
|
||||
refreshConnection = connect(m_catalog.get(), &PgDatabaseCatalog::refreshed,
|
||||
this, &DependantsTableModel::refresh);
|
||||
}
|
||||
refresh();
|
||||
}
|
||||
|
||||
void DependantsTableModel::loadForTable(Oid table_id)
|
||||
{
|
||||
if (table_id != tableId) {
|
||||
tableId = table_id;
|
||||
refresh();
|
||||
}
|
||||
}
|
||||
|
||||
QVariant DependantsTableModel::headerData(int section, Qt::Orientation orientation, int role) const
|
||||
{
|
||||
if (orientation == Qt::Horizontal) {
|
||||
if (role == Qt::DisplayRole) {
|
||||
switch (section) {
|
||||
case NameCol: return tr("Table");
|
||||
case NamespaceCol: return tr("Namespace");
|
||||
}
|
||||
}
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
int DependantsTableModel::rowCount(const QModelIndex &) const
|
||||
{
|
||||
return dependants.size();
|
||||
}
|
||||
|
||||
int DependantsTableModel::columnCount(const QModelIndex &) const
|
||||
{
|
||||
return colCount;
|
||||
}
|
||||
|
||||
QVariant DependantsTableModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (role == Qt::DisplayRole) {
|
||||
auto&& data = dependants[index.row()];
|
||||
switch (index.column()) {
|
||||
case NameCol: return data.tableName;
|
||||
case NamespaceCol: return data.namespaceName;
|
||||
case ConstraintCol: return data.constraintName;
|
||||
}
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
void DependantsTableModel::refresh()
|
||||
{
|
||||
if (!m_catalog)
|
||||
return;
|
||||
|
||||
beginResetModel();
|
||||
dependants.clear();
|
||||
|
||||
if (tableId != InvalidOid) {
|
||||
auto&& constraints = m_catalog->constraints();
|
||||
auto fkeys = constraints->getReferencedForRelation(tableId);
|
||||
|
||||
dependants.reserve(static_cast<int>(fkeys.size()));
|
||||
auto&& tables = m_catalog->classes();
|
||||
for (auto&& fk : fkeys) {
|
||||
//dependants.append(
|
||||
auto t = tables->getByKey(fk.relid);
|
||||
if (t) {
|
||||
Item i;
|
||||
i.tableOid = t->oid();
|
||||
i.tableName = t->objectName();
|
||||
i.namespaceName = t->nsName();
|
||||
i.constraintName = fk.objectName();
|
||||
dependants.push_back(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
endResetModel();
|
||||
}
|
||||
55
pglab/catalog/models/DependantsTableModel.h
Normal file
55
pglab/catalog/models/DependantsTableModel.h
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
#ifndef DEPENDENTSTABLEMODEL_H
|
||||
#define DEPENDENTSTABLEMODEL_H
|
||||
|
||||
#include <QAbstractTableModel>
|
||||
#include <memory>
|
||||
#include "catalog/PgClass.h"
|
||||
#include "Pgsql_oids.h"
|
||||
|
||||
#include <QVector>
|
||||
|
||||
class PgDatabaseCatalog;
|
||||
|
||||
class DependantsTableModel: public QAbstractTableModel {
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
||||
enum e_Columns : int {
|
||||
NameCol, //
|
||||
NamespaceCol, // Schema
|
||||
ConstraintCol,
|
||||
|
||||
colCount
|
||||
};
|
||||
|
||||
DependantsTableModel(QObject *parent = nullptr);
|
||||
|
||||
void setCatalog(std::shared_ptr<const PgDatabaseCatalog> cat);
|
||||
void loadForTable(Oid table_id);
|
||||
|
||||
// Basic functionality:
|
||||
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
QVariant data(const QModelIndex &index, int role) const override;
|
||||
|
||||
private:
|
||||
std::shared_ptr<const PgDatabaseCatalog> m_catalog;
|
||||
QMetaObject::Connection refreshConnection;
|
||||
Oid tableId;
|
||||
|
||||
class Item {
|
||||
public:
|
||||
Oid tableOid;
|
||||
QString tableName;
|
||||
QString namespaceName;
|
||||
QString constraintName;
|
||||
};
|
||||
|
||||
QVector<Item> dependants;
|
||||
|
||||
private slots:
|
||||
void refresh();
|
||||
};
|
||||
|
||||
#endif // DEPENDENTSTABLEMODEL_H
|
||||
142
pglab/catalog/models/IndexModel.cpp
Normal file
142
pglab/catalog/models/IndexModel.cpp
Normal file
|
|
@ -0,0 +1,142 @@
|
|||
#include "IndexModel.h"
|
||||
#include "catalog/PgDatabaseCatalog.h"
|
||||
#include "catalog/PgIndexContainer.h"
|
||||
#include "Pgsql_oids.h"
|
||||
#include "ScopeGuard.h"
|
||||
#include "CustomDataRole.h"
|
||||
|
||||
void IndexModel::setData(std::shared_ptr<const PgDatabaseCatalog> cat, const std::optional<PgClass> &table)
|
||||
{
|
||||
if (cat != m_catalog) {
|
||||
m_catalog = cat;
|
||||
refreshConnection = connect(m_catalog.get(), &PgDatabaseCatalog::refreshed, this, &IndexModel::refresh);
|
||||
}
|
||||
m_table = table;
|
||||
refresh();
|
||||
}
|
||||
|
||||
void IndexModel::refresh()
|
||||
{
|
||||
beginResetModel();
|
||||
SCOPE_EXIT { endResetModel(); };
|
||||
|
||||
if (m_table)
|
||||
m_indexes = m_catalog->indexes()->getIndexesForTable(m_table->oid());
|
||||
else
|
||||
m_indexes.clear();
|
||||
}
|
||||
|
||||
int IndexModel::rowCount(const QModelIndex &/*parent*/) const
|
||||
{
|
||||
return (int)m_indexes.size();
|
||||
}
|
||||
|
||||
int IndexModel::columnCount(const QModelIndex &/*parent*/) const
|
||||
{
|
||||
return colCount;
|
||||
}
|
||||
|
||||
Oid IndexModel::getType(int column) const
|
||||
{
|
||||
switch (column) {
|
||||
case SizeCol:
|
||||
return Pgsql::int8_oid;
|
||||
case ExplicitIndexCol:
|
||||
return Pgsql::bool_oid;
|
||||
default:
|
||||
return Pgsql::varchar_oid;
|
||||
}
|
||||
}
|
||||
|
||||
QVariant IndexModel::headerData(int section, Qt::Orientation orientation, int role) const
|
||||
{
|
||||
QVariant v;
|
||||
if (orientation == Qt::Horizontal) {
|
||||
if (role == Qt::DisplayRole) {
|
||||
QString c;
|
||||
switch (section) {
|
||||
case TypeCol:
|
||||
c = tr("Type");
|
||||
break;
|
||||
case NameCol:
|
||||
c = tr("Name");
|
||||
break;
|
||||
case AmCol:
|
||||
c = tr("AM");
|
||||
break;
|
||||
case ColumnsCol:
|
||||
c = tr("On");
|
||||
break;
|
||||
case ConditionCol:
|
||||
c = tr("Condition");
|
||||
break;
|
||||
case SizeCol:
|
||||
c = tr("Size");
|
||||
break;
|
||||
case ExplicitIndexCol:
|
||||
c = tr("Explicit");
|
||||
break;
|
||||
// case DefinitionCol:
|
||||
// c = tr("Definition");
|
||||
// break;
|
||||
}
|
||||
v = c;
|
||||
}
|
||||
}
|
||||
return v;
|
||||
|
||||
}
|
||||
|
||||
QVariant IndexModel::getData(const QModelIndex &index) const
|
||||
{
|
||||
QVariant v;
|
||||
int rij = index.row();
|
||||
const auto &dat = m_indexes[rij];
|
||||
switch (index.column()) {
|
||||
case TypeCol:
|
||||
if (dat.isprimary) v = ":/icons/constraints/primarykey.png";
|
||||
else if (dat.isunique) v = ":/icons/constraints/unique.png";
|
||||
else v = ":/icons/constraints/index.png";
|
||||
break;
|
||||
|
||||
case NameCol:
|
||||
v = dat.objectName(); // getIndexDisplayString(*m_catalog, dat.indexrelid);
|
||||
break;
|
||||
|
||||
case AmCol:
|
||||
v = dat.getAm();
|
||||
break;
|
||||
|
||||
case ColumnsCol:
|
||||
break;
|
||||
|
||||
case ConditionCol:
|
||||
break;
|
||||
|
||||
case SizeCol:
|
||||
v = dat.sizeBytes;
|
||||
break;
|
||||
case ExplicitIndexCol:
|
||||
v = !dat.isSupportingIndex();
|
||||
break;
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
QVariant IndexModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
QVariant v;
|
||||
if (role == Qt::DisplayRole)
|
||||
v = getData(index);
|
||||
else if (role == CustomDataTypeRole)
|
||||
v = getType(index.column());
|
||||
else if (role == CustomDataMeaningRole) {
|
||||
switch (index.column()) {
|
||||
case SizeCol:
|
||||
return static_cast<int>(DataMeaningBytes);
|
||||
default:
|
||||
return static_cast<int>(DataMeaningNormal);
|
||||
}
|
||||
}
|
||||
return v;
|
||||
}
|
||||
68
pglab/catalog/models/IndexModel.h
Normal file
68
pglab/catalog/models/IndexModel.h
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
#ifndef INDEXMODEL_H
|
||||
#define INDEXMODEL_H
|
||||
|
||||
#include <QAbstractTableModel>
|
||||
#include "catalog/PgClass.h"
|
||||
#include "catalog/PgIndex.h"
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <vector>
|
||||
|
||||
|
||||
class PgDatabaseCatalog;
|
||||
|
||||
class IndexModel: public QAbstractTableModel {
|
||||
Q_OBJECT
|
||||
public:
|
||||
using QAbstractTableModel::QAbstractTableModel;
|
||||
|
||||
enum e_Columns : int {
|
||||
TypeCol, /// primary/unique/normal
|
||||
NameCol, ///
|
||||
AmCol, ///< Access Method
|
||||
ColumnsCol, ///
|
||||
ConditionCol,
|
||||
SizeCol,
|
||||
ExplicitIndexCol,
|
||||
colCount };
|
||||
|
||||
// oid
|
||||
// tablespace
|
||||
// operator class
|
||||
// unique
|
||||
// primary
|
||||
// clustered
|
||||
// valid
|
||||
// constraint
|
||||
// system index
|
||||
// fill factor
|
||||
// comment
|
||||
|
||||
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
|
||||
void setData(std::shared_ptr<const PgDatabaseCatalog> cat, const std::optional<PgClass> &table);
|
||||
|
||||
|
||||
// Basic functionality:
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
|
||||
virtual QVariant data(const QModelIndex &index, int role) const override;
|
||||
|
||||
PgIndex getIndex(int row) const { return m_indexes[row]; }
|
||||
protected:
|
||||
Oid getType(int column) const;
|
||||
QVariant getData(const QModelIndex &index) const;
|
||||
|
||||
private:
|
||||
std::shared_ptr<const PgDatabaseCatalog> m_catalog;
|
||||
std::optional<PgClass> m_table;
|
||||
|
||||
using t_Indexes = std::vector<PgIndex>;
|
||||
t_Indexes m_indexes;
|
||||
QMetaObject::Connection refreshConnection;
|
||||
|
||||
private slots:
|
||||
void refresh();
|
||||
};
|
||||
|
||||
#endif // INDEXMODEL_H
|
||||
131
pglab/catalog/models/ProcTableModel.cpp
Normal file
131
pglab/catalog/models/ProcTableModel.cpp
Normal file
|
|
@ -0,0 +1,131 @@
|
|||
#include "ProcTableModel.h"
|
||||
#include "catalog/PgDatabaseCatalog.h"
|
||||
#include "catalog/PgProcContainer.h"
|
||||
#include "catalog/PgLanguageContainer.h"
|
||||
#include "catalog/PgNamespace.h"
|
||||
#include "CustomDataRole.h"
|
||||
|
||||
ProcTableModel::ProcTableModel(QObject *parent)
|
||||
: QAbstractTableModel(parent)
|
||||
{
|
||||
}
|
||||
|
||||
QVariant ProcTableModel::headerData(int section, Qt::Orientation orientation, int role) const
|
||||
{
|
||||
if (orientation == Qt::Horizontal) {
|
||||
if (role == Qt::DisplayRole) {
|
||||
switch (section) {
|
||||
case NameCol: return tr("Name");
|
||||
case NamespaceCol: return tr("Schema");
|
||||
case OwnerCol: return tr("Owner");
|
||||
case LangCol: return tr("Language");
|
||||
case AclCol: return tr("ACL");
|
||||
}
|
||||
}
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
void ProcTableModel::setCatalog(std::shared_ptr<const PgDatabaseCatalog> cat)
|
||||
{
|
||||
if (cat != m_catalog) {
|
||||
m_catalog = cat;
|
||||
refreshConnection = connect(m_catalog.get(), &PgDatabaseCatalog::refreshed,
|
||||
this, &ProcTableModel::refresh);
|
||||
}
|
||||
refresh();
|
||||
}
|
||||
|
||||
void ProcTableModel::setNamespaceFilter(NamespaceFilter filter)
|
||||
{
|
||||
m_namespaceFilter = filter;
|
||||
refresh();
|
||||
}
|
||||
|
||||
void ProcTableModel::refresh()
|
||||
{
|
||||
if (!m_catalog)
|
||||
return;
|
||||
|
||||
beginResetModel();
|
||||
|
||||
auto && procs = m_catalog->procs();
|
||||
m_procs.clear();
|
||||
for (auto&& p : *procs) {
|
||||
bool add = false;
|
||||
switch (m_namespaceFilter) {
|
||||
case NamespaceFilter::User:
|
||||
add = !p.ns().isSystemCatalog();
|
||||
break;
|
||||
case NamespaceFilter::PgCatalog:
|
||||
add = p.ns().objectName() == "pg_catalog";
|
||||
break;
|
||||
case NamespaceFilter::InformationSchema:
|
||||
add = p.ns().objectName() == "information_schema";
|
||||
break;
|
||||
}
|
||||
if (add)
|
||||
m_procs.push_back(p);
|
||||
}
|
||||
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
int ProcTableModel::rowCount(const QModelIndex &) const
|
||||
{
|
||||
return static_cast<int>(m_procs.size());
|
||||
}
|
||||
|
||||
int ProcTableModel::columnCount(const QModelIndex &) const
|
||||
{
|
||||
return colCount;
|
||||
}
|
||||
|
||||
QVariant ProcTableModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (role == Qt::DisplayRole)
|
||||
return getData(index);
|
||||
else if (role == CustomDataTypeRole)
|
||||
return getType(index.column());
|
||||
// else if (role == FirstHiddenValue) {
|
||||
// auto&& t = m_triggers->getByIdx(index.row());
|
||||
// return t.relid; //
|
||||
// }
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
PgProc ProcTableModel::proc(int row) const
|
||||
{
|
||||
return m_procs.at(static_cast<size_t>(row));
|
||||
}
|
||||
|
||||
Oid ProcTableModel::getType(int ) const
|
||||
{
|
||||
// switch (column) {
|
||||
// case NameCol: return tr("Name");
|
||||
// case NamespaceCol: return tr("Schema");
|
||||
// case OwnerCol: return tr("Owner");
|
||||
// case LangCol: return tr("Language");
|
||||
// return Pgsql::bool_oid;
|
||||
// }
|
||||
return Pgsql::varchar_oid;
|
||||
}
|
||||
|
||||
QVariant ProcTableModel::getData(const QModelIndex &index) const
|
||||
{
|
||||
auto&& t = m_procs.at(static_cast<size_t>(index.row()));
|
||||
switch (index.column()) {
|
||||
case NameCol: return t.objectName();
|
||||
case NamespaceCol: return t.nsName();
|
||||
case OwnerCol: return t.ownerName();
|
||||
case LangCol: {
|
||||
auto lan = m_catalog->languages()->getByKey(t.lang);
|
||||
if (lan) return lan->objectName();
|
||||
return t.lang;
|
||||
}
|
||||
case AclCol: return t.aclString();
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
|
||||
60
pglab/catalog/models/ProcTableModel.h
Normal file
60
pglab/catalog/models/ProcTableModel.h
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
#ifndef PROCTABLEMODEL_H
|
||||
#define PROCTABLEMODEL_H
|
||||
|
||||
#include "catalog/PgClass.h"
|
||||
#include "catalog/PgProc.h"
|
||||
#include "NamespaceFilter.h"
|
||||
#include <QAbstractTableModel>
|
||||
#include <memory>
|
||||
|
||||
class PgDatabaseCatalog;
|
||||
class PgProcContainer;
|
||||
|
||||
/**
|
||||
* @brief The ProcTableModel class
|
||||
*
|
||||
* Hidden values:
|
||||
*
|
||||
*/
|
||||
class ProcTableModel: public QAbstractTableModel {
|
||||
Q_OBJECT
|
||||
public:
|
||||
//using QAbstractTableModel::QAbstractTableModel;
|
||||
|
||||
enum e_Columns : int {
|
||||
NameCol, //
|
||||
NamespaceCol, // Schema
|
||||
OwnerCol,
|
||||
LangCol,
|
||||
AclCol,
|
||||
|
||||
colCount
|
||||
};
|
||||
|
||||
ProcTableModel(QObject *parent = nullptr);
|
||||
|
||||
void setCatalog(std::shared_ptr<const PgDatabaseCatalog> cat);
|
||||
void setNamespaceFilter(NamespaceFilter filter);
|
||||
|
||||
// Basic functionality:
|
||||
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
QVariant data(const QModelIndex &index, int role) const override;
|
||||
|
||||
PgProc proc(int row) const;
|
||||
|
||||
private:
|
||||
std::shared_ptr<const PgDatabaseCatalog> m_catalog;
|
||||
NamespaceFilter m_namespaceFilter = NamespaceFilter::User;
|
||||
std::vector<PgProc> m_procs;
|
||||
QMetaObject::Connection refreshConnection;
|
||||
|
||||
Oid getType(int column) const;
|
||||
QVariant getData(const QModelIndex &index) const;
|
||||
private slots:
|
||||
void refresh();
|
||||
};
|
||||
|
||||
|
||||
#endif // PROCTABLEMODEL_H
|
||||
152
pglab/catalog/models/RolesTableModel.cpp
Normal file
152
pglab/catalog/models/RolesTableModel.cpp
Normal file
|
|
@ -0,0 +1,152 @@
|
|||
#include "RolesTableModel.h"
|
||||
#include "catalog/PgAuthIdContainer.h"
|
||||
|
||||
RolesTableModel::RolesTableModel(QObject *parent)
|
||||
: BaseTableModel(parent)
|
||||
{
|
||||
}
|
||||
|
||||
void RolesTableModel::setRoleList(std::shared_ptr<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;
|
||||
}
|
||||
|
||||
Oid RolesTableModel::getType(int column) const
|
||||
{
|
||||
using namespace Pgsql;
|
||||
|
||||
Oid oid;
|
||||
switch (column) {
|
||||
case NameCol:
|
||||
oid = varchar_oid;
|
||||
break;
|
||||
|
||||
case ReplicationCol:
|
||||
case BypassRlsCol:
|
||||
case CanLoginCol:
|
||||
case CreateDBCol:
|
||||
case CreateRoleCol:
|
||||
case InheritCol:
|
||||
case SuperCol:
|
||||
oid = bool_oid;
|
||||
break;
|
||||
|
||||
case ConnlimitCol:
|
||||
oid = int4_oid;
|
||||
break;
|
||||
|
||||
case ValidUntilCol:
|
||||
oid = timestamp_oid;
|
||||
break;
|
||||
default:
|
||||
oid = InvalidOid;
|
||||
}
|
||||
|
||||
return oid;
|
||||
}
|
||||
|
||||
QVariant RolesTableModel::getData(const QModelIndex &index) const
|
||||
{
|
||||
QVariant v;
|
||||
if (m_roles) {
|
||||
const PgAuthId &authid = m_roles->getByIdx(index.row());
|
||||
switch (index.column()) {
|
||||
case NameCol:
|
||||
v = authid.objectName();
|
||||
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:
|
||||
v = authid.connLimit;
|
||||
break;
|
||||
case ValidUntilCol:
|
||||
v = authid.validUntil;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return v;
|
||||
}
|
||||
45
pglab/catalog/models/RolesTableModel.h
Normal file
45
pglab/catalog/models/RolesTableModel.h
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
#ifndef ROLESTABLEMODEL_H
|
||||
#define ROLESTABLEMODEL_H
|
||||
|
||||
|
||||
#include "BaseTableModel.h"
|
||||
#include <memory>
|
||||
|
||||
class PgAuthId;
|
||||
class PgAuthIdContainer;
|
||||
|
||||
/** Class for displaying the list of roles of a server in a QTableView
|
||||
*
|
||||
*/
|
||||
class RolesTableModel : public BaseTableModel {
|
||||
Q_OBJECT
|
||||
public:
|
||||
using RowItem = PgAuthId;
|
||||
enum e_Columns : int { NameCol, SuperCol, InheritCol, CreateRoleCol,
|
||||
CreateDBCol, CanLoginCol, ReplicationCol,
|
||||
BypassRlsCol, ConnlimitCol, ValidUntilCol };
|
||||
|
||||
|
||||
|
||||
explicit RolesTableModel(QObject *parent);
|
||||
|
||||
void setRoleList(std::shared_ptr<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;
|
||||
|
||||
virtual Oid getType(int column) const override;
|
||||
virtual QVariant getData(const QModelIndex &index) const override;
|
||||
|
||||
// QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||
|
||||
private:
|
||||
std::shared_ptr<const PgAuthIdContainer> m_roles;
|
||||
};
|
||||
|
||||
|
||||
#endif // ROLESTABLEMODEL_H
|
||||
118
pglab/catalog/models/SequenceModel.cpp
Normal file
118
pglab/catalog/models/SequenceModel.cpp
Normal file
|
|
@ -0,0 +1,118 @@
|
|||
#include "SequenceModel.h"
|
||||
#include "catalog/PgDatabaseCatalog.h"
|
||||
#include "catalog/PgNamespace.h"
|
||||
#include "catalog/PgSequenceContainer.h"
|
||||
|
||||
SequenceModel::SequenceModel(QObject * parent)
|
||||
: QAbstractTableModel(parent)
|
||||
{}
|
||||
|
||||
QVariant SequenceModel::headerData(int section, Qt::Orientation orientation, int role) const
|
||||
{
|
||||
if (orientation == Qt::Horizontal) {
|
||||
if (role == Qt::DisplayRole) {
|
||||
switch (section) {
|
||||
case NameCol: return tr("Name");
|
||||
case SchemaCol: return tr("Schema");
|
||||
case OwnerCol: return tr("Owner");
|
||||
case LastCol: return tr("Last");
|
||||
case StartCol: return tr("Start");
|
||||
case MinCol: return tr("Min");
|
||||
case MaxCol: return tr("Max");
|
||||
case IncrementCol: return tr("Inc");
|
||||
case CacheCol: return tr("Cached");
|
||||
case CycledCol: return tr("Cycled");
|
||||
case CalledCol: return tr("Called");
|
||||
case AclCol: return tr("ACL");
|
||||
}
|
||||
}
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
void SequenceModel::setCatalog(std::shared_ptr<const PgDatabaseCatalog> cat)
|
||||
{
|
||||
if (cat != m_catalog) {
|
||||
m_catalog = cat;
|
||||
refreshConnection = connect(m_catalog.get(), &PgDatabaseCatalog::refreshed,
|
||||
this, &SequenceModel::refresh);
|
||||
}
|
||||
refresh();
|
||||
}
|
||||
|
||||
void SequenceModel::setNamespaceFilter(NamespaceFilter filter)
|
||||
{
|
||||
m_namespaceFilter = filter;
|
||||
refresh();
|
||||
}
|
||||
|
||||
void SequenceModel::refresh()
|
||||
{
|
||||
if (!m_catalog)
|
||||
return;
|
||||
|
||||
beginResetModel();
|
||||
|
||||
auto && seqs = m_catalog->sequences();
|
||||
m_sequences.clear();
|
||||
for (auto&& s : *seqs) {
|
||||
bool add = false;
|
||||
switch (m_namespaceFilter) {
|
||||
case NamespaceFilter::User:
|
||||
add = !s.ns().isSystemCatalog();
|
||||
break;
|
||||
case NamespaceFilter::PgCatalog:
|
||||
add = s.ns().objectName() == "pg_catalog";
|
||||
break;
|
||||
case NamespaceFilter::InformationSchema:
|
||||
add = s.ns().objectName() == "information_schema";
|
||||
break;
|
||||
}
|
||||
if (add)
|
||||
m_sequences.push_back(s);
|
||||
}
|
||||
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
PgSequence SequenceModel::sequence(int row) const
|
||||
{
|
||||
return m_sequences.at(static_cast<size_t>(row));
|
||||
}
|
||||
|
||||
int SequenceModel::rowCount(const QModelIndex &) const
|
||||
{
|
||||
return static_cast<int>(m_sequences.size());
|
||||
}
|
||||
|
||||
int SequenceModel::columnCount(const QModelIndex &) const
|
||||
{
|
||||
return colCount;
|
||||
}
|
||||
|
||||
QVariant SequenceModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (m_sequences.empty())
|
||||
return {};
|
||||
|
||||
int row = index.row();
|
||||
auto && seq = m_sequences.at(static_cast<size_t>(row));
|
||||
if (role == Qt::DisplayRole) {
|
||||
switch (index.column()) {
|
||||
case NameCol: return seq.objectName();
|
||||
case SchemaCol: return seq.nsName();
|
||||
case OwnerCol: return seq.ownerName();
|
||||
case LastCol: return seq.last;
|
||||
case StartCol: return seq.start;
|
||||
case MinCol: return seq.min;
|
||||
case MaxCol: return seq.max;
|
||||
case IncrementCol: return seq.increment;
|
||||
case CacheCol: return seq.cache;
|
||||
case CycledCol: return seq.cycled;
|
||||
case CalledCol: return seq.called;
|
||||
case AclCol: return seq.aclString();
|
||||
}
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
53
pglab/catalog/models/SequenceModel.h
Normal file
53
pglab/catalog/models/SequenceModel.h
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
#ifndef SEQUENCEMODEL_H
|
||||
#define SEQUENCEMODEL_H
|
||||
|
||||
#include "NamespaceFilter.h"
|
||||
#include <QAbstractTableModel>
|
||||
#include "catalog/PgSequence.h"
|
||||
#include <memory>
|
||||
|
||||
class PgDatabaseCatalog;
|
||||
class PgSequenceContainer;
|
||||
|
||||
class SequenceModel: public QAbstractTableModel {
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
||||
enum e_Columns : int {
|
||||
NameCol,
|
||||
SchemaCol,
|
||||
OwnerCol,
|
||||
LastCol,
|
||||
StartCol,
|
||||
MinCol,
|
||||
MaxCol,
|
||||
IncrementCol,
|
||||
CacheCol,
|
||||
CycledCol,
|
||||
CalledCol,
|
||||
AclCol,
|
||||
|
||||
colCount
|
||||
};
|
||||
|
||||
SequenceModel(QObject * parent = nullptr);
|
||||
|
||||
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
|
||||
void setCatalog(std::shared_ptr<const PgDatabaseCatalog> cat);
|
||||
void setNamespaceFilter(NamespaceFilter filter);
|
||||
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
QVariant data(const QModelIndex &index, int role) const override;
|
||||
|
||||
PgSequence sequence(int row) const;
|
||||
private:
|
||||
std::shared_ptr<const PgDatabaseCatalog> m_catalog;
|
||||
std::vector<PgSequence> m_sequences;
|
||||
NamespaceFilter m_namespaceFilter = NamespaceFilter::User;
|
||||
QMetaObject::Connection refreshConnection;
|
||||
|
||||
void refresh();
|
||||
};
|
||||
|
||||
#endif // SEQUENCEMODEL_H
|
||||
259
pglab/catalog/models/TablesTableModel.cpp
Normal file
259
pglab/catalog/models/TablesTableModel.cpp
Normal file
|
|
@ -0,0 +1,259 @@
|
|||
#include "TablesTableModel.h"
|
||||
#include "OpenDatabase.h"
|
||||
#include "ScopeGuard.h"
|
||||
#include "catalog/PgDatabaseCatalog.h"
|
||||
#include "catalog/PgClass.h"
|
||||
#include "catalog/PgClassContainer.h"
|
||||
#include "catalog/PgNamespace.h"
|
||||
#include "catalog/PgNamespaceContainer.h"
|
||||
#include "Pgsql_declare.h"
|
||||
#include "CustomDataRole.h"
|
||||
#include <QBrush>
|
||||
#include <QtConcurrent>
|
||||
#include "Pgsql_Connection.h"
|
||||
|
||||
TablesTableModel::TablesTableModel(std::shared_ptr<OpenDatabase> opendatabase, QObject *parent)
|
||||
: QAbstractTableModel(parent)
|
||||
, openDatabase(opendatabase)
|
||||
{}
|
||||
|
||||
void TablesTableModel::setNamespaceFilter(NamespaceFilter nsf)
|
||||
{
|
||||
m_namespaceFilter = nsf;
|
||||
refresh();
|
||||
}
|
||||
|
||||
void TablesTableModel::setCatalog(std::shared_ptr<const PgDatabaseCatalog> cat)
|
||||
{
|
||||
if (cat != m_catalog) {
|
||||
m_catalog = cat;
|
||||
refreshConnection = connect(m_catalog.get(), &PgDatabaseCatalog::refreshed,
|
||||
this, &TablesTableModel::refresh);
|
||||
}
|
||||
refresh();
|
||||
}
|
||||
|
||||
void TablesTableModel::refresh()
|
||||
{
|
||||
beginResetModel();
|
||||
SCOPE_EXIT { endResetModel(); };
|
||||
|
||||
if (!m_catalog)
|
||||
return;
|
||||
|
||||
// Later afscheiden naar filter functie
|
||||
auto classes = m_catalog->classes();
|
||||
|
||||
std::map<Oid, int> oidIndex;
|
||||
m_tables.clear();
|
||||
for (const auto &e : *classes) {
|
||||
bool add = false;
|
||||
if (e.kind == RelKind::Table || e.kind == RelKind::View
|
||||
|| e.kind == RelKind::MaterializedView || e.kind == RelKind::ForeignTable) {
|
||||
switch (m_namespaceFilter) {
|
||||
case NamespaceFilter::User:
|
||||
add = !e.ns().isSystemCatalog();
|
||||
break;
|
||||
case NamespaceFilter::PgCatalog:
|
||||
add = e.ns().objectName() == "pg_catalog";
|
||||
break;
|
||||
case NamespaceFilter::InformationSchema:
|
||||
add = e.ns().objectName() == "information_schema";
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (add) {
|
||||
m_tables.emplace_back(e);
|
||||
oidIndex.emplace(e.oid(), m_tables.size() - 1);
|
||||
}
|
||||
}
|
||||
StartLoadTableSizes(std::move(oidIndex));
|
||||
}
|
||||
|
||||
QVariant TablesTableModel::headerData(int section, Qt::Orientation orientation, int role) const
|
||||
{
|
||||
if (orientation == Qt::Horizontal) {
|
||||
if (role == Qt::DisplayRole) {
|
||||
switch (section) {
|
||||
case NameCol: return tr("Name");
|
||||
case NamespaceCol: return tr("Schema");
|
||||
case KindCol: return tr("Kind");
|
||||
case OwnerCol: return tr("Owner");
|
||||
case TablespaceCol: return tr("Tablespace");
|
||||
case OptionsCol: return tr("Options");
|
||||
case AclCol: return tr("ACL");
|
||||
case CommentCol: return tr("Comment");
|
||||
case TotalSizeCol: return tr("Total size");
|
||||
case TableSizeCol: return tr("Table size");
|
||||
case IndexSizeCol: return tr("Index size");
|
||||
case ToastSizeCol: return tr("TOAST size");
|
||||
}
|
||||
}
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
int TablesTableModel::rowCount(const QModelIndex &) const
|
||||
{
|
||||
return static_cast<int>(m_tables.size());
|
||||
}
|
||||
|
||||
int TablesTableModel::columnCount(const QModelIndex &) const
|
||||
{
|
||||
return colCount;
|
||||
}
|
||||
|
||||
Oid TablesTableModel::getType(int column) const
|
||||
{
|
||||
Oid oid;
|
||||
switch (column) {
|
||||
case TotalSizeCol:
|
||||
case TableSizeCol:
|
||||
case IndexSizeCol:
|
||||
case ToastSizeCol:
|
||||
oid = Pgsql::int8_oid;
|
||||
break;
|
||||
case TablespaceCol:
|
||||
case OwnerCol:
|
||||
case NameCol:
|
||||
case NamespaceCol:
|
||||
case KindCol:
|
||||
case OptionsCol:
|
||||
case AclCol:
|
||||
case CommentCol:
|
||||
default:
|
||||
oid = Pgsql::varchar_oid;
|
||||
}
|
||||
return oid;
|
||||
}
|
||||
|
||||
QVariant TablesTableModel::getData(const QModelIndex &index) const
|
||||
{
|
||||
const auto &table = m_tables[index.row()];
|
||||
const auto &t = table._class;
|
||||
const auto &s = table.sizes;
|
||||
switch (index.column()) {
|
||||
case NameCol: return t.objectName();
|
||||
case NamespaceCol: return t.nsName();
|
||||
case KindCol: return t.typeName();
|
||||
case OwnerCol: return t.ownerName();
|
||||
case TablespaceCol: return getTablespaceDisplayString(*m_catalog, t.tablespace);
|
||||
case OptionsCol: break;
|
||||
case AclCol: return t.aclString();
|
||||
case CommentCol: return t.description;
|
||||
case TotalSizeCol: return s.oid == 0 ? QVariant() : s.totalBytes;
|
||||
case TableSizeCol: return s.oid == 0 ? QVariant() : s.totalBytes - s.indexBytes - s.toastBytes;
|
||||
case IndexSizeCol: return s.oid == 0 ? QVariant() : s.indexBytes;
|
||||
case ToastSizeCol: return s.oid == 0 ? QVariant() : s.toastBytes;
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
PgClass TablesTableModel::getTable(int row) const
|
||||
{
|
||||
return m_tables[row]._class;
|
||||
}
|
||||
|
||||
Oid TablesTableModel::getTableOid(int row) const
|
||||
{
|
||||
return m_tables[row]._class.oid();
|
||||
}
|
||||
|
||||
QVariant TablesTableModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (role == Qt::DisplayRole)
|
||||
return getData(index);
|
||||
else if (role == CustomDataTypeRole)
|
||||
return getType(index.column());
|
||||
else if (role == CustomDataMeaningRole) {
|
||||
switch (index.column()) {
|
||||
case TotalSizeCol:
|
||||
case TableSizeCol:
|
||||
case IndexSizeCol:
|
||||
case ToastSizeCol:
|
||||
return static_cast<int>(DataMeaningBytes);
|
||||
default:
|
||||
return static_cast<int>(DataMeaningNormal);
|
||||
}
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
void TablesTableModel::StartLoadTableSizes(std::map<Oid, int> oidIndex)
|
||||
{
|
||||
QPointer p(this);
|
||||
QtConcurrent::run([this]
|
||||
{
|
||||
return QueryTableSizes();
|
||||
})
|
||||
.then(qApp, [p, oidIndex] (TableSizes sizes)
|
||||
{
|
||||
if (p)
|
||||
{
|
||||
p.data()->PopulateSizes(std::move(oidIndex), std::move(sizes));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
TablesTableModel::TableSizes TablesTableModel::QueryTableSizes() const
|
||||
{
|
||||
std::string nsfilter;
|
||||
switch (m_namespaceFilter)
|
||||
{
|
||||
case NamespaceFilter::User:
|
||||
nsfilter = "(NOT (nspname LIKE 'pg_%' OR nspname='information_schema'))";
|
||||
break;
|
||||
case NamespaceFilter::PgCatalog:
|
||||
nsfilter = "nspname = 'pg_catalog'";
|
||||
break;
|
||||
case NamespaceFilter::InformationSchema:
|
||||
nsfilter = "nspname = 'information_schema'";
|
||||
break;
|
||||
}
|
||||
|
||||
std::string q =
|
||||
"SELECT pg_class.oid, "
|
||||
" pg_total_relation_size(pg_class.oid) AS total_bytes, "
|
||||
" CASE WHEN relkind='r' THEN pg_indexes_size(pg_class.oid) ELSE 0 END AS index_bytes, "
|
||||
" CASE WHEN relkind='r' THEN pg_total_relation_size(reltoastrelid) ELSE 0 END AS toast_bytes "
|
||||
"\nFROM pg_catalog.pg_class \n"
|
||||
" JOIN pg_namespace ON (relnamespace = pg_namespace.oid)"
|
||||
" LEFT JOIN pg_catalog.pg_description AS d ON (objoid=pg_class.oid AND objsubid=0) \n"
|
||||
"WHERE relkind IN ('r', 'p', 'm') AND " + nsfilter;
|
||||
|
||||
;
|
||||
Pgsql::Connection connection;
|
||||
connection.connect(openDatabase->config().connectionString());
|
||||
Pgsql::Result sizesResult = connection.query(q.c_str());
|
||||
|
||||
TablesTableModel::TableSizes sizes;
|
||||
sizes.reserve(sizesResult.rows());
|
||||
for (const Pgsql::Row& row : sizesResult)
|
||||
{
|
||||
TableSize size;
|
||||
size.oid = row.get(0);
|
||||
size.totalBytes = row.get(1);
|
||||
size.indexBytes = row.get(2);
|
||||
size.toastBytes = row.get(3);
|
||||
sizes.push_back(size);
|
||||
}
|
||||
return sizes;
|
||||
}
|
||||
|
||||
void TablesTableModel::PopulateSizes(std::map<Oid, int> oidIndex, std::vector<TableSize> sizes)
|
||||
{
|
||||
for (auto s : sizes)
|
||||
{
|
||||
auto findIter = oidIndex.find(s.oid);
|
||||
if (findIter != oidIndex.end())
|
||||
{
|
||||
m_tables[findIter->second].sizes = s;
|
||||
}
|
||||
}
|
||||
emit dataChanged(
|
||||
createIndex(0, TotalSizeCol),
|
||||
createIndex(static_cast<int>(m_tables.size()), ToastSizeCol)
|
||||
);
|
||||
}
|
||||
95
pglab/catalog/models/TablesTableModel.h
Normal file
95
pglab/catalog/models/TablesTableModel.h
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
#ifndef TABLESTABLEMODEL_H
|
||||
#define TABLESTABLEMODEL_H
|
||||
|
||||
#include "BaseTableModel.h"
|
||||
#include "NamespaceFilter.h"
|
||||
#include "catalog/PgClass.h"
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
class OpenDatabase;
|
||||
class PgClass;
|
||||
class PgDatabaseCatalog;
|
||||
|
||||
class TablesTableModel: public QAbstractTableModel {
|
||||
public:
|
||||
using RowItem = PgClass;
|
||||
enum e_Columns : int {
|
||||
NameCol, ///< either table, ns.table or table (ns) depending on settings/filters
|
||||
NamespaceCol,
|
||||
KindCol,
|
||||
OwnerCol,
|
||||
TablespaceCol,
|
||||
OptionsCol,
|
||||
AclCol,
|
||||
CommentCol,
|
||||
TotalSizeCol,
|
||||
TableSizeCol,
|
||||
IndexSizeCol,
|
||||
ToastSizeCol,
|
||||
|
||||
colCount };
|
||||
|
||||
TablesTableModel(std::shared_ptr<OpenDatabase> opendatabase, QObject *parent);
|
||||
|
||||
void setNamespaceFilter(NamespaceFilter nsf);
|
||||
void setCatalog(std::shared_ptr<const PgDatabaseCatalog> cat);
|
||||
|
||||
QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
|
||||
|
||||
int rowCount(const QModelIndex &parent) const override;
|
||||
int columnCount(const QModelIndex &parent) const override;
|
||||
|
||||
virtual QVariant data(const QModelIndex &index, int role) const override;
|
||||
PgClass getTable(int row) const;
|
||||
RowItem rowItem(int row) const
|
||||
{
|
||||
return getTable(row);
|
||||
}
|
||||
Oid getTableOid(int row) const;
|
||||
|
||||
private:
|
||||
class TableSize {
|
||||
public:
|
||||
int oid;
|
||||
int64_t totalBytes = -1;
|
||||
int64_t indexBytes = -1;
|
||||
int64_t toastBytes = -1;
|
||||
|
||||
TableSize()
|
||||
: oid(0)
|
||||
{}
|
||||
};
|
||||
using TableSizes = std::vector<TableSize>;
|
||||
|
||||
class Table {
|
||||
public:
|
||||
PgClass _class;
|
||||
TableSize sizes;
|
||||
|
||||
Table(const PgClass &cls)
|
||||
: _class(cls)
|
||||
{}
|
||||
};
|
||||
using t_Tables = std::vector<Table>;
|
||||
|
||||
std::shared_ptr<const PgDatabaseCatalog> m_catalog;
|
||||
NamespaceFilter m_namespaceFilter = NamespaceFilter::User;
|
||||
t_Tables m_tables;
|
||||
QMetaObject::Connection refreshConnection;
|
||||
std::shared_ptr<OpenDatabase> openDatabase;
|
||||
|
||||
|
||||
Oid getType(int column) const;
|
||||
QVariant getData(const QModelIndex &index) const;
|
||||
|
||||
void StartLoadTableSizes(std::map<Oid, int> oidIndex);
|
||||
TableSizes QueryTableSizes() const;
|
||||
void PopulateSizes(std::map<Oid, int> oidIndex, std::vector<TableSize> sizes);
|
||||
|
||||
private slots:
|
||||
void refresh();
|
||||
|
||||
};
|
||||
|
||||
#endif // TABLESTABLEMODEL_H
|
||||
109
pglab/catalog/models/TriggerTableModel.cpp
Normal file
109
pglab/catalog/models/TriggerTableModel.cpp
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
#include "TriggerTableModel.h"
|
||||
#include "catalog/PgDatabaseCatalog.h"
|
||||
#include "catalog/PgTriggerContainer.h"
|
||||
#include "CustomDataRole.h"
|
||||
#include "ScopeGuard.h"
|
||||
|
||||
TriggerTableModel::TriggerTableModel(QObject *parent)
|
||||
: QAbstractTableModel(parent)
|
||||
{
|
||||
}
|
||||
|
||||
QVariant TriggerTableModel::headerData(int section, Qt::Orientation orientation, int role) const
|
||||
{
|
||||
if (orientation == Qt::Horizontal) {
|
||||
if (role == Qt::DisplayRole) {
|
||||
switch (section) {
|
||||
case NameCol: return tr("Name");
|
||||
case EventsCol: return tr("Events");
|
||||
case WhenCol: return tr("When");
|
||||
case DeferrableCol: return tr("Df");
|
||||
case InitiallyCol: return tr("ID");
|
||||
case ForCol: return tr("For");
|
||||
case CondCol: return tr("Cond.");
|
||||
// case ReferencingCol: return tr("Referencing");
|
||||
case ProcedureCol: return tr("Function");
|
||||
}
|
||||
}
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
void TriggerTableModel::setCatalog(std::shared_ptr<const PgDatabaseCatalog> cat)
|
||||
{
|
||||
if (cat != m_catalog) {
|
||||
m_catalog = cat;
|
||||
refreshConnection = connect(m_catalog.get(), &PgDatabaseCatalog::refreshed, this,
|
||||
&TriggerTableModel::refresh);
|
||||
}
|
||||
refresh();
|
||||
}
|
||||
|
||||
int TriggerTableModel::rowCount(const QModelIndex &) const
|
||||
{
|
||||
return m_triggers ? static_cast<int>(m_triggers->count()) : 0;
|
||||
}
|
||||
|
||||
|
||||
int TriggerTableModel::columnCount(const QModelIndex &) const
|
||||
{
|
||||
return colCount;
|
||||
}
|
||||
|
||||
|
||||
QVariant TriggerTableModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (role == Qt::DisplayRole)
|
||||
return getData(index);
|
||||
else if (role == CustomDataTypeRole)
|
||||
return getType(index.column());
|
||||
else if (role == FirstHiddenValue) {
|
||||
auto&& t = m_triggers->getByIdx(index.row());
|
||||
return t.relid; //
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
|
||||
PgTrigger TriggerTableModel::trigger(int row) const
|
||||
{
|
||||
return m_triggers->getByIdx(row);
|
||||
}
|
||||
|
||||
|
||||
Oid TriggerTableModel::getType(int column) const
|
||||
{
|
||||
switch (column) {
|
||||
case DeferrableCol:
|
||||
case InitiallyCol:
|
||||
return Pgsql::bool_oid;
|
||||
}
|
||||
return Pgsql::varchar_oid;
|
||||
}
|
||||
|
||||
|
||||
QVariant TriggerTableModel::getData(const QModelIndex &index) const
|
||||
{
|
||||
auto&& t = m_triggers->getByIdx(index.row());
|
||||
switch (index.column()) {
|
||||
case NameCol: return t.objectName();
|
||||
case EventsCol: return t.eventAbbr();
|
||||
case WhenCol: return t.typeFireWhen();
|
||||
case DeferrableCol: return t.deferrable;
|
||||
case InitiallyCol: return t.initdeferred;
|
||||
case ForCol: return t.forEach();
|
||||
case CondCol: return t.whenclause;
|
||||
// case ReferencingCol: return tr("Referencing");
|
||||
case ProcedureCol: return t.procedure();
|
||||
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
void TriggerTableModel::refresh()
|
||||
{
|
||||
beginResetModel();
|
||||
SCOPE_EXIT { endResetModel(); };
|
||||
|
||||
m_triggers = m_catalog->triggers();
|
||||
}
|
||||
79
pglab/catalog/models/TriggerTableModel.h
Normal file
79
pglab/catalog/models/TriggerTableModel.h
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
#ifndef TRIGGERTABLEMODEL_H
|
||||
#define TRIGGERTABLEMODEL_H
|
||||
|
||||
#include <QAbstractTableModel>
|
||||
#include "catalog/PgClass.h"
|
||||
#include "catalog/PgTrigger.h"
|
||||
#include <memory>
|
||||
|
||||
class PgDatabaseCatalog;
|
||||
class PgTriggerContainer;
|
||||
|
||||
/**
|
||||
* @brief The TriggerTableModel class
|
||||
*
|
||||
* Hidden values:
|
||||
* - FirstHiddenValue: oid of table the trigger belongs to
|
||||
*/
|
||||
class TriggerTableModel: public QAbstractTableModel {
|
||||
Q_OBJECT
|
||||
public:
|
||||
//using QAbstractTableModel::QAbstractTableModel;
|
||||
|
||||
enum e_Columns : int {
|
||||
NameCol, //
|
||||
EventsCol, // Insert, Update, Delete Truncate
|
||||
WhenCol, // before after instead of
|
||||
DeferrableCol,
|
||||
InitiallyCol,
|
||||
ForCol,
|
||||
CondCol,
|
||||
//ReferencingCol,
|
||||
ProcedureCol,
|
||||
colCount
|
||||
};
|
||||
|
||||
TriggerTableModel(QObject *parent = nullptr);
|
||||
|
||||
// CREATE [ CONSTRAINT ] TRIGGER name { BEFORE | AFTER | INSTEAD OF } { event [ OR ... ] }
|
||||
// ON table_name
|
||||
// [ FROM referenced_table_name ]
|
||||
// [ NOT DEFERRABLE | [ DEFERRABLE ] [ INITIALLY IMMEDIATE | INITIALLY DEFERRED ] ]
|
||||
// [ REFERENCING { { OLD | NEW } TABLE [ AS ] transition_relation_name } [ ... ] ]
|
||||
// [ FOR [ EACH ] { ROW | STATEMENT } ]
|
||||
// [ WHEN ( condition ) ]
|
||||
// EXECUTE PROCEDURE function_name ( arguments )
|
||||
|
||||
// where event can be one of:
|
||||
|
||||
// INSERT
|
||||
// UPDATE [ OF column_name [, ... ] ]
|
||||
// DELETE
|
||||
// TRUNCATE
|
||||
|
||||
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
|
||||
void setCatalog(std::shared_ptr<const PgDatabaseCatalog> cat);
|
||||
|
||||
|
||||
// Basic functionality:
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
|
||||
virtual QVariant data(const QModelIndex &index, int role) const override;
|
||||
|
||||
PgTrigger trigger(int row) const;
|
||||
|
||||
private:
|
||||
std::shared_ptr<const PgDatabaseCatalog> m_catalog;
|
||||
std::shared_ptr<const PgTriggerContainer> m_triggers;
|
||||
QMetaObject::Connection refreshConnection;
|
||||
|
||||
Oid getType(int column) const;
|
||||
QVariant getData(const QModelIndex &index) const;
|
||||
|
||||
private slots:
|
||||
void refresh();
|
||||
};
|
||||
|
||||
|
||||
#endif // TRIGGERTABLEMODEL_H
|
||||
Loading…
Add table
Add a link
Reference in a new issue