diff --git a/pglab/DependantsPage.cpp b/pglab/DependantsPage.cpp new file mode 100644 index 0000000..103d9d4 --- /dev/null +++ b/pglab/DependantsPage.cpp @@ -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 +#include + +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 &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); +//} diff --git a/pglab/DependantsPage.h b/pglab/DependantsPage.h new file mode 100644 index 0000000..d2a2056 --- /dev/null +++ b/pglab/DependantsPage.h @@ -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 &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 diff --git a/pglab/DependantsTableModel.cpp b/pglab/DependantsTableModel.cpp new file mode 100644 index 0000000..69bb975 --- /dev/null +++ b/pglab/DependantsTableModel.cpp @@ -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 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(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(); +} diff --git a/pglab/DependantsTableModel.h b/pglab/DependantsTableModel.h new file mode 100644 index 0000000..2c6684b --- /dev/null +++ b/pglab/DependantsTableModel.h @@ -0,0 +1,55 @@ +#ifndef DEPENDENTSTABLEMODEL_H +#define DEPENDENTSTABLEMODEL_H + +#include +#include +#include "catalog/PgClass.h" +#include "Pgsql_oids.h" + +#include + +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 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 m_catalog; + QMetaObject::Connection refreshConnection; + Oid tableId; + + class Item { + public: + Oid tableOid; + QString tableName; + QString namespaceName; + QString constraintName; + }; + + QVector dependants; + +private slots: + void refresh(); +}; + +#endif // DEPENDENTSTABLEMODEL_H diff --git a/pglab/ProcTableModel.h b/pglab/ProcTableModel.h index c467803..4afb73b 100644 --- a/pglab/ProcTableModel.h +++ b/pglab/ProcTableModel.h @@ -33,11 +33,11 @@ public: ProcTableModel(QObject *parent = nullptr); - QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; void setCatalog(std::shared_ptr 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; diff --git a/pglab/pglab.pro b/pglab/pglab.pro index 751505d..f46a89e 100644 --- a/pglab/pglab.pro +++ b/pglab/pglab.pro @@ -23,6 +23,8 @@ win32:RC_ICONS += pglab.ico SOURCES += main.cpp\ ConnectionConfigurationWidget.cpp \ ConnectionController.cpp \ + DependantsPage.cpp \ + DependantsTableModel.cpp \ NotificationListWidget.cpp \ NotificationModel.cpp \ NotificationService.cpp \ @@ -88,6 +90,8 @@ PropertyProxyModel.cpp \ HEADERS += \ ConnectionConfigurationWidget.h \ ConnectionController.h \ + DependantsPage.h \ + DependantsTableModel.h \ IDatabaseWindow.h \ NotificationListWidget.h \ NotificationModel.h \ diff --git a/pglab/widgets/CatalogTablesPage.cpp b/pglab/widgets/CatalogTablesPage.cpp index 07aebda..b3c196c 100644 --- a/pglab/widgets/CatalogTablesPage.cpp +++ b/pglab/widgets/CatalogTablesPage.cpp @@ -3,6 +3,7 @@ #include "ColumnPage.h" #include "ColumnTableModel.h" #include "ConstraintModel.h" +#include "DependantsPage.h" #include "PgLabTableView.h" #include "PropertiesPage.h" #include "ResultTableModelUtil.h" @@ -62,6 +63,9 @@ CatalogTablesPage::CatalogTablesPage(QWidget *parent) m_triggerPage = new TriggerPage(this); m_detailsTabs->addTab(m_triggerPage, ""); + m_dependentsPage = new DependantsPage(this); + m_detailsTabs->addTab(m_dependentsPage, ""); + // SQL tab m_tableSql = new SqlCodePreview(this); 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_propertiesPage, QApplication::translate("TablesPage", "Properties", 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)); } @@ -109,6 +114,7 @@ void CatalogTablesPage::setCatalog(std::shared_ptr cat) m_constraintPage->setCatalog(cat); m_indexPage->setCatalog(cat); m_triggerPage->setCatalog(cat); + m_dependentsPage->setCatalog(cat); } void CatalogTablesPage::setNamespaceFilter(NamespaceFilter filter) @@ -159,6 +165,7 @@ void CatalogTablesPage::selectedTableChanged(const std::optional &table m_constraintPage->setFilter(table); m_indexPage->setFilter(table); m_triggerPage->setFilter(table); + m_dependentsPage->setFilter(table); updateSqlTab(table); } diff --git a/pglab/widgets/CatalogTablesPage.h b/pglab/widgets/CatalogTablesPage.h index b1a82de..102c325 100644 --- a/pglab/widgets/CatalogTablesPage.h +++ b/pglab/widgets/CatalogTablesPage.h @@ -13,6 +13,7 @@ class CatalogIndexPage; class ColumnPage; class ColumnTableModel; class ConstraintModel; +class DependantsPage; class PgClass; class PgDatabaseCatalog; class PgLabTableView; @@ -48,6 +49,7 @@ private: CatalogIndexPage *m_indexPage = nullptr; PropertiesPage *m_propertiesPage = nullptr; TriggerPage *m_triggerPage = nullptr; + DependantsPage *m_dependentsPage = nullptr; SqlCodePreview *m_tableSql = nullptr; std::shared_ptr m_catalog; diff --git a/pglablib/catalog/PgConstraintContainer.cpp b/pglablib/catalog/PgConstraintContainer.cpp index cde45d4..59d69d7 100644 --- a/pglablib/catalog/PgConstraintContainer.cpp +++ b/pglablib/catalog/PgConstraintContainer.cpp @@ -1,6 +1,7 @@ #include "PgConstraintContainer.h" #include "Pgsql_Col.h" #include +#include std::string PgConstraintContainer::getLoadQuery() const { @@ -56,9 +57,11 @@ std::vector PgConstraintContainer::getFKeyForTableColumn(Oid relid std::vector PgConstraintContainer::getConstraintsForRelation(Oid relid) const { std::vector result; - for (const auto &e : m_container) - if (e.relid == relid) - result.push_back(e); +// for (const auto &e : m_container) +// if (e.relid == relid) +// 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; } @@ -73,3 +76,14 @@ std::optional PgConstraintContainer::getPrimaryForRelation(Oid rel } return result; } + +std::vector PgConstraintContainer::getReferencedForRelation(Oid relid) const +{ + std::vector 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; +} diff --git a/pglablib/catalog/PgConstraintContainer.h b/pglablib/catalog/PgConstraintContainer.h index ca8f752..256fcbe 100644 --- a/pglablib/catalog/PgConstraintContainer.h +++ b/pglablib/catalog/PgConstraintContainer.h @@ -17,6 +17,7 @@ public: std::vector getConstraintsForRelation(Oid relid) const; std::optional getPrimaryForRelation(Oid relid) const; + std::vector getReferencedForRelation(Oid relid) const; protected: virtual PgConstraint loadElem(const Pgsql::Row &row) override; };