diff --git a/pglab/ColumnTableModel.cpp b/pglab/ColumnTableModel.cpp index a58acab..be1d67e 100644 --- a/pglab/ColumnTableModel.cpp +++ b/pglab/ColumnTableModel.cpp @@ -11,35 +11,56 @@ #include "SqlFormattingUtils.h" #include -void ColumnTableModel::setData(std::shared_ptr cat, const PgClass &table) +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 cat, const std::optional &table) { beginResetModel(); SCOPE_EXIT { endResetModel(); }; m_table = table; m_catalog = cat; - m_columns = cat->attributes()->getColumnsForRelation(table.oid); + if (m_table) { + m_columns = cat->attributes()->getColumnsForRelation(table->oid); + // hide system and dropped columns + auto column_filter_pred = 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()); - // hide system columns - auto si = table.hasoids - ? std::remove_if(m_columns.begin(), m_columns.end(), - [](PgAttribute &e) { return e.num <= 0 && e.name != "oid"; }) - : std::remove_if(m_columns.begin(), m_columns.end(), - [](PgAttribute &e) { return e.num <= 0; }); - // 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(); - // 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; }); - m_indexes = m_catalog->indexes()->getIndexesForTable(table.oid); - std::sort(m_indexes.begin(), m_indexes.end(), + if (m_table) { + m_indexes = m_catalog->indexes()->getIndexesForTable(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.indexrelid < r.indexrelid); }); + } + else + m_indexes.clear(); } QVariant ColumnTableModel::headerData(int section, Qt::Orientation orientation, int role) const @@ -224,33 +245,37 @@ QVariant ColumnTableModel::data(const QModelIndex &index, int role) const if (role == Qt::ForegroundRole && index.column() == TypeCol) { QVariant v; const auto &t = m_columns[index.row()]; - auto c = m_catalog->types()->getByKey(t.typid); - switch (c->category) { - case TypCategory::Boolean: - v = QBrush(Qt::darkGreen); - break; - case TypCategory::Numeric: - v = QBrush(Qt::darkBlue); - break; - case TypCategory::DateTime: - case TypCategory::Timespan: - v = QBrush(Qt::darkMagenta); - break; - case TypCategory::String: - v = QBrush(Qt::darkYellow); - break; - case TypCategory::Array: - case TypCategory::Composite: - case TypCategory::Enum: - case TypCategory::Geometric: - case TypCategory::NetworkAddress: - case TypCategory::Pseudo: - case TypCategory::Range: - case TypCategory::UserDefined: - case TypCategory::BitString: - case TypCategory::Unknown: - default: + 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; } diff --git a/pglab/ColumnTableModel.h b/pglab/ColumnTableModel.h index 61c7b20..e14bd4b 100644 --- a/pglab/ColumnTableModel.h +++ b/pglab/ColumnTableModel.h @@ -5,6 +5,7 @@ #include "PgClass.h" #include "PgIndex.h" #include +#include #include class PgDatabaseCatalog; @@ -25,7 +26,7 @@ public: using BaseTableModel::BaseTableModel; - void setData(std::shared_ptr cat, const PgClass &table); + void setData(std::shared_ptr cat, const std::optional &table); // Header: QVariant headerData(int section, Qt::Orientation orientation, int role) const override; @@ -42,7 +43,7 @@ protected: using t_Columns = std::vector; std::shared_ptr m_catalog; - PgClass m_table; + std::optional m_table; t_Columns m_columns; std::vector m_indexes; diff --git a/pglab/ConstraintModel.cpp b/pglab/ConstraintModel.cpp index acf682d..e0a5698 100644 --- a/pglab/ConstraintModel.cpp +++ b/pglab/ConstraintModel.cpp @@ -12,42 +12,23 @@ ConstraintModel::ConstraintModel(QObject *parent) -void ConstraintModel::setData(std::shared_ptr cat, const PgClass &table) +void ConstraintModel::setData(std::shared_ptr cat, const std::optional &table) { beginResetModel(); SCOPE_EXIT { endResetModel(); }; m_table = table; m_catalog = cat; - m_constraints = cat->constraints()->getConstraintsForRelation(table.oid); - - std::sort(m_constraints.begin(), m_constraints.end(), - [] (auto &l, auto &r) { - return l.type < r.type || - (l.type == r.type && l.name < r.name); - }); - -// // hide system columns -// auto si = table.hasoids -// ? std::remove_if(m_columns.begin(), m_columns.end(), -// [](PgAttribute &e) { return e.num <= 0 && e.name != "oid"; }) -// : std::remove_if(m_columns.begin(), m_columns.end(), -// [](PgAttribute &e) { return e.num <= 0; }); -// // 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; }); - -// m_indexes = m_catalog->indexes()->getIndexesForTable(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.indexrelid < r.indexrelid); -// }); - + if (table) { + m_constraints = cat->constraints()->getConstraintsForRelation(table->oid); + std::sort(m_constraints.begin(), m_constraints.end(), + [] (auto &l, auto &r) { + return l.type < r.type || + (l.type == r.type && l.name < r.name); + }); + } + else + m_constraints.clear(); } QVariant ConstraintModel::headerData(int section, Qt::Orientation orientation, int role) const diff --git a/pglab/ConstraintModel.h b/pglab/ConstraintModel.h index ae4fa16..e467fca 100644 --- a/pglab/ConstraintModel.h +++ b/pglab/ConstraintModel.h @@ -5,6 +5,7 @@ #include "PgClass.h" #include "PgConstraint.h" #include +#include #include class PgDatabaseCatalog; @@ -23,7 +24,7 @@ public: explicit ConstraintModel(QObject *parent = nullptr); - void setData(std::shared_ptr cat, const PgClass &table); + void setData(std::shared_ptr cat, const std::optional &table); // Header: @@ -43,7 +44,7 @@ protected: private: std::shared_ptr m_catalog; - PgClass m_table; + std::optional m_table; using t_Constraints = std::vector; t_Constraints m_constraints; diff --git a/pglab/IndexModel.cpp b/pglab/IndexModel.cpp index 4e41fa3..4a5c422 100644 --- a/pglab/IndexModel.cpp +++ b/pglab/IndexModel.cpp @@ -5,15 +5,17 @@ #include "ScopeGuard.h" #include "CustomDataRole.h" -void IndexModel::setData(std::shared_ptr cat, const PgClass &table) +void IndexModel::setData(std::shared_ptr cat, const std::optional &table) { beginResetModel(); SCOPE_EXIT { endResetModel(); }; m_catalog = cat; m_table = table; - - m_indexes = cat->indexes()->getIndexesForTable(table.oid); + if (table) + m_indexes = cat->indexes()->getIndexesForTable(table->oid); + else + m_indexes.clear(); } int IndexModel::rowCount(const QModelIndex &/*parent*/) const diff --git a/pglab/IndexModel.h b/pglab/IndexModel.h index 64cbe2c..f931ea7 100644 --- a/pglab/IndexModel.h +++ b/pglab/IndexModel.h @@ -5,6 +5,7 @@ #include "PgClass.h" #include "PgIndex.h" #include +#include #include @@ -36,7 +37,7 @@ public: // comment QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; - void setData(std::shared_ptr cat, const PgClass &table); + void setData(std::shared_ptr cat, const std::optional &table); // Basic functionality: @@ -52,7 +53,7 @@ protected: private: std::shared_ptr m_catalog; - PgClass m_table; + std::optional m_table; using t_Indexes = std::vector; t_Indexes m_indexes; diff --git a/pglab/TablesPage.cpp b/pglab/TablesPage.cpp index a622e07..be3a2b2 100644 --- a/pglab/TablesPage.cpp +++ b/pglab/TablesPage.cpp @@ -139,8 +139,12 @@ void TablesPage::setCatalog(std::shared_ptr cat) void TablesPage::tableListTable_currentRowChanged(const QModelIndex ¤t, const QModelIndex &previous) { if (current.row() != previous.row()) { - PgClass table = m_tablesModel->getTable(current.row()); - selectedTableChanged(table); + if (current.isValid()) { + PgClass table = m_tablesModel->getTable(current.row()); + selectedTableChanged(table); + } + else + selectedTableChanged({}); } } @@ -148,12 +152,16 @@ void TablesPage::tableListTable_currentRowChanged(const QModelIndex ¤t, co void TablesPage::tableListTable_layoutChanged(const QList &, QAbstractItemModel::LayoutChangeHint ) { auto&& index = ui->tableListTable->selectionModel()->currentIndex(); - PgClass table = m_tablesModel->getTable(index.row()); - selectedTableChanged(table); + if (index.isValid()) { + PgClass table = m_tablesModel->getTable(index.row()); + selectedTableChanged(table); + } + else + selectedTableChanged({}); } -void TablesPage::selectedTableChanged(const PgClass & table) +void TablesPage::selectedTableChanged(const std::optional &table) { m_columnsModel->setData(m_catalog, table); ui->columnsTable->resizeColumnsToContents(); diff --git a/pglab/TablesPage.h b/pglab/TablesPage.h index 08284be..ec35106 100644 --- a/pglab/TablesPage.h +++ b/pglab/TablesPage.h @@ -3,6 +3,7 @@ #include #include +#include #include namespace Ui { @@ -25,7 +26,7 @@ class TablesPage : public QWidget Q_OBJECT public: - explicit TablesPage(MainWindow *parent = 0); + explicit TablesPage(MainWindow *parent = nullptr); ~TablesPage(); void setCatalog(std::shared_ptr cat); @@ -46,7 +47,7 @@ private: void retranslateUi(bool all = true); QWidget* addDetailTab(QWidget *contents); - void selectedTableChanged(const PgClass & table); + void selectedTableChanged(const std::optional &table); private slots: void tableListTable_currentRowChanged(const QModelIndex ¤t, const QModelIndex &previous); diff --git a/pglab/TriggerPage.cpp b/pglab/TriggerPage.cpp index e89c23a..e1d993c 100644 --- a/pglab/TriggerPage.cpp +++ b/pglab/TriggerPage.cpp @@ -45,9 +45,9 @@ void TriggerPage::setCatalog(std::shared_ptr cat) } -void TriggerPage::setFilter(const PgClass &cls) +void TriggerPage::setFilter(const std::optional &cls) { - m_sortFilterProxy->setOidFilterTable(cls.oid, FirstHiddenValue); + m_sortFilterProxy->setOidFilterTable(cls ? cls->oid : InvalidOid, FirstHiddenValue); } diff --git a/pglab/TriggerPage.h b/pglab/TriggerPage.h index 00bb9ee..40b3918 100644 --- a/pglab/TriggerPage.h +++ b/pglab/TriggerPage.h @@ -3,6 +3,7 @@ #include #include +#include class QTableView; class SqlCodePreview; @@ -20,7 +21,7 @@ public: // TriggerPage(QWidget *parent = nullptr); void setCatalog(std::shared_ptr cat); - void setFilter(const PgClass &cls); + void setFilter(const std::optional &cls); signals: public slots: diff --git a/pglablib/PgAttribute.h b/pglablib/PgAttribute.h index 818e8e7..d03b81d 100644 --- a/pglablib/PgAttribute.h +++ b/pglablib/PgAttribute.h @@ -20,6 +20,7 @@ public: int32_t typmod = -1; bool notnull = false; bool hasdef = false; + bool isdropped = false; Oid collation = InvalidOid; QString acl; QString options; diff --git a/pglablib/PgAttributeContainer.cpp b/pglablib/PgAttributeContainer.cpp index 89eda0f..42e173c 100644 --- a/pglablib/PgAttributeContainer.cpp +++ b/pglablib/PgAttributeContainer.cpp @@ -10,7 +10,7 @@ std::string PgAttributeContainer::getLoadQuery() const { return R"__( SELECT attrelid, attname, atttypid, attstattarget, - attnum, attndims, atttypmod, attnotnull, atthasdef, + attnum, attndims, atttypmod, attnotnull, atthasdef, attisdropped, attcollation, attacl, attoptions, pg_get_expr(adbin, adrelid) AS def_value FROM pg_catalog.pg_attribute LEFT JOIN pg_attrdef ON attrelid=adrelid AND attnum=adnum)__"; @@ -21,7 +21,7 @@ PgAttribute PgAttributeContainer::loadElem(const Pgsql::Row &row) Pgsql::Col col(row); PgAttribute v; col >> v.relid >> v.name >> v.typid >> v.stattarget - >> v.num >> v.ndims >> v.typmod >> v.notnull >> v.hasdef + >> v.num >> v.ndims >> v.typmod >> v.notnull >> v.hasdef >> v.isdropped >> v.collation >> v.acl >> v.options >> v.defaultValue; return v; }