Added dependants tab to table page

Retrieves all foreignkeys pointing to the current table
and shows the tables they are foreignkeys of.
This commit is contained in:
eelke 2019-11-17 10:27:11 +01:00
parent b90df1cd77
commit 8dd13d103e
10 changed files with 268 additions and 4 deletions

57
pglab/DependantsPage.cpp Normal file
View file

@ -0,0 +1,57 @@
#include "DependantsPage.h"
#include "ResultTableModelUtil.h"
#include "UserConfiguration.h"
#include "catalog/PgClass.h"
//#include "SqlCodePreview.h"
#include "DependantsTableModel.h"
#include "CustomFilterSortModel.h"
#include "CustomDataRole.h"
#include "PgLabTableView.h"
//#include "catalog/PgProcContainer.h"
#include <QStringBuilder>
#include <unordered_set>
DependantsPage::DependantsPage(QWidget *parent)
: CatalogPageBase(parent)
{
m_model = new DependantsTableModel(this);
m_sortFilterProxy->setSourceModel(m_model);
// connect(m_tableView->selectionModel(), &QItemSelectionModel::selectionChanged,
// this, &DependentsPage::tableView_selectionChanged);
// connect(m_model, &DependentsTableModel::modelReset, m_definitionView, &SqlCodePreview::clear);
}
void DependantsPage::catalogSet()
{
m_model->setCatalog(m_catalog);
}
void DependantsPage::setFilter(const std::optional<PgClass> &cls)
{
m_model->loadForTable(cls ? cls->oid() : InvalidOid);
m_tableView->resizeColumnsToContents();
}
//void DependentsPage::tableView_selectionChanged(const QItemSelection &/*selected*/, const QItemSelection &/*deselected*/)
//{
// auto rijen = selectedRows();
// QString drops;
// QString creates;
// for (auto rij : rijen) {
// auto&& t = m_model->trigger(rij);
// drops += t.dropSql() % "\n";
// creates += t.createSql() % "\n";
// const PgProc *proc = m_catalog->procs()->getByKey(t.foid);
// if (proc) {
// creates += "\n" % proc->createSql() % "\n";
// }
// }
// m_definitionView->setPlainText(drops % "\n" % creates);
//}

30
pglab/DependantsPage.h Normal file
View file

@ -0,0 +1,30 @@
#ifndef DEPENDENTSPAGE_H
#define DEPENDENTSPAGE_H
#include "widgets/CatalogPageBase.h"
class PgClass;
class DependantsTableModel;
class QItemSelection;
class DependantsPage : public CatalogPageBase {
Q_OBJECT
public:
explicit DependantsPage(QWidget *parent = nullptr);
void setFilter(const std::optional<PgClass> &cls);
signals:
public slots:
protected:
void catalogSet() override;
private:
DependantsTableModel *m_model = nullptr;
private slots:
// void tableView_selectionChanged(const QItemSelection &selected, const QItemSelection &deselected);
};
#endif // DEPENDENTSPAGE_H

View 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();
}

View 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

View file

@ -33,11 +33,11 @@ public:
ProcTableModel(QObject *parent = nullptr); ProcTableModel(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 setCatalog(std::shared_ptr<const PgDatabaseCatalog> cat);
void setNamespaceFilter(NamespaceFilter filter); void setNamespaceFilter(NamespaceFilter filter);
// Basic functionality: // Basic functionality:
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
int rowCount(const QModelIndex &parent = QModelIndex()) const override; int rowCount(const QModelIndex &parent = QModelIndex()) const override;
int columnCount(const QModelIndex &parent = QModelIndex()) const override; int columnCount(const QModelIndex &parent = QModelIndex()) const override;
QVariant data(const QModelIndex &index, int role) const override; QVariant data(const QModelIndex &index, int role) const override;

View file

@ -23,6 +23,8 @@ win32:RC_ICONS += pglab.ico
SOURCES += main.cpp\ SOURCES += main.cpp\
ConnectionConfigurationWidget.cpp \ ConnectionConfigurationWidget.cpp \
ConnectionController.cpp \ ConnectionController.cpp \
DependantsPage.cpp \
DependantsTableModel.cpp \
NotificationListWidget.cpp \ NotificationListWidget.cpp \
NotificationModel.cpp \ NotificationModel.cpp \
NotificationService.cpp \ NotificationService.cpp \
@ -88,6 +90,8 @@ PropertyProxyModel.cpp \
HEADERS += \ HEADERS += \
ConnectionConfigurationWidget.h \ ConnectionConfigurationWidget.h \
ConnectionController.h \ ConnectionController.h \
DependantsPage.h \
DependantsTableModel.h \
IDatabaseWindow.h \ IDatabaseWindow.h \
NotificationListWidget.h \ NotificationListWidget.h \
NotificationModel.h \ NotificationModel.h \

View file

@ -3,6 +3,7 @@
#include "ColumnPage.h" #include "ColumnPage.h"
#include "ColumnTableModel.h" #include "ColumnTableModel.h"
#include "ConstraintModel.h" #include "ConstraintModel.h"
#include "DependantsPage.h"
#include "PgLabTableView.h" #include "PgLabTableView.h"
#include "PropertiesPage.h" #include "PropertiesPage.h"
#include "ResultTableModelUtil.h" #include "ResultTableModelUtil.h"
@ -62,6 +63,9 @@ CatalogTablesPage::CatalogTablesPage(QWidget *parent)
m_triggerPage = new TriggerPage(this); m_triggerPage = new TriggerPage(this);
m_detailsTabs->addTab(m_triggerPage, ""); m_detailsTabs->addTab(m_triggerPage, "");
m_dependentsPage = new DependantsPage(this);
m_detailsTabs->addTab(m_dependentsPage, "");
// SQL tab // SQL tab
m_tableSql = new SqlCodePreview(this); m_tableSql = new SqlCodePreview(this);
m_detailsTabs->addTab(m_tableSql, ""); m_detailsTabs->addTab(m_tableSql, "");
@ -97,6 +101,7 @@ void CatalogTablesPage::retranslateUi(bool /*all*/)
set_tabtext(m_indexPage, QApplication::translate("TablesPage", "Indexes", nullptr)); set_tabtext(m_indexPage, QApplication::translate("TablesPage", "Indexes", nullptr));
set_tabtext(m_propertiesPage, QApplication::translate("TablesPage", "Properties", nullptr)); set_tabtext(m_propertiesPage, QApplication::translate("TablesPage", "Properties", nullptr));
set_tabtext(m_triggerPage, QApplication::translate("TablesPage", "Triggers", nullptr)); set_tabtext(m_triggerPage, QApplication::translate("TablesPage", "Triggers", nullptr));
set_tabtext(m_dependentsPage, QApplication::translate("TablesPage", "Dependants", nullptr));
set_tabtext(m_tableSql, QApplication::translate("TablesPage", "SQL", nullptr)); set_tabtext(m_tableSql, QApplication::translate("TablesPage", "SQL", nullptr));
} }
@ -109,6 +114,7 @@ void CatalogTablesPage::setCatalog(std::shared_ptr<PgDatabaseCatalog> cat)
m_constraintPage->setCatalog(cat); m_constraintPage->setCatalog(cat);
m_indexPage->setCatalog(cat); m_indexPage->setCatalog(cat);
m_triggerPage->setCatalog(cat); m_triggerPage->setCatalog(cat);
m_dependentsPage->setCatalog(cat);
} }
void CatalogTablesPage::setNamespaceFilter(NamespaceFilter filter) void CatalogTablesPage::setNamespaceFilter(NamespaceFilter filter)
@ -159,6 +165,7 @@ void CatalogTablesPage::selectedTableChanged(const std::optional<PgClass> &table
m_constraintPage->setFilter(table); m_constraintPage->setFilter(table);
m_indexPage->setFilter(table); m_indexPage->setFilter(table);
m_triggerPage->setFilter(table); m_triggerPage->setFilter(table);
m_dependentsPage->setFilter(table);
updateSqlTab(table); updateSqlTab(table);
} }

View file

@ -13,6 +13,7 @@ class CatalogIndexPage;
class ColumnPage; class ColumnPage;
class ColumnTableModel; class ColumnTableModel;
class ConstraintModel; class ConstraintModel;
class DependantsPage;
class PgClass; class PgClass;
class PgDatabaseCatalog; class PgDatabaseCatalog;
class PgLabTableView; class PgLabTableView;
@ -48,6 +49,7 @@ private:
CatalogIndexPage *m_indexPage = nullptr; CatalogIndexPage *m_indexPage = nullptr;
PropertiesPage *m_propertiesPage = nullptr; PropertiesPage *m_propertiesPage = nullptr;
TriggerPage *m_triggerPage = nullptr; TriggerPage *m_triggerPage = nullptr;
DependantsPage *m_dependentsPage = nullptr;
SqlCodePreview *m_tableSql = nullptr; SqlCodePreview *m_tableSql = nullptr;
std::shared_ptr<PgDatabaseCatalog> m_catalog; std::shared_ptr<PgDatabaseCatalog> m_catalog;

View file

@ -1,6 +1,7 @@
#include "PgConstraintContainer.h" #include "PgConstraintContainer.h"
#include "Pgsql_Col.h" #include "Pgsql_Col.h"
#include <algorithm> #include <algorithm>
#include <iterator>
std::string PgConstraintContainer::getLoadQuery() const std::string PgConstraintContainer::getLoadQuery() const
{ {
@ -56,9 +57,11 @@ std::vector<PgConstraint> PgConstraintContainer::getFKeyForTableColumn(Oid relid
std::vector<PgConstraint> PgConstraintContainer::getConstraintsForRelation(Oid relid) const std::vector<PgConstraint> PgConstraintContainer::getConstraintsForRelation(Oid relid) const
{ {
std::vector<PgConstraint> result; std::vector<PgConstraint> result;
for (const auto &e : m_container) // for (const auto &e : m_container)
if (e.relid == relid) // if (e.relid == relid)
result.push_back(e); // result.push_back(e);
std::copy_if(m_container.begin(), m_container.end(), std::back_inserter(result),
[relid] (auto && item) { return item.relid == relid; });
return result; return result;
} }
@ -73,3 +76,14 @@ std::optional<PgConstraint> PgConstraintContainer::getPrimaryForRelation(Oid rel
} }
return result; return result;
} }
std::vector<PgConstraint> PgConstraintContainer::getReferencedForRelation(Oid relid) const
{
std::vector<PgConstraint> result;
// for (const auto &e : m_container)
// if (e.frelid == relid)
// result.push_back(e);
std::copy_if(m_container.begin(), m_container.end(), std::back_inserter(result),
[relid] (auto && item) { return item.frelid == relid; });
return result;
}

View file

@ -17,6 +17,7 @@ public:
std::vector<PgConstraint> getConstraintsForRelation(Oid relid) const; std::vector<PgConstraint> getConstraintsForRelation(Oid relid) const;
std::optional<PgConstraint> getPrimaryForRelation(Oid relid) const; std::optional<PgConstraint> getPrimaryForRelation(Oid relid) const;
std::vector<PgConstraint> getReferencedForRelation(Oid relid) const;
protected: protected:
virtual PgConstraint loadElem(const Pgsql::Row &row) override; virtual PgConstraint loadElem(const Pgsql::Row &row) override;
}; };