The table inheritance works mostly

This commit is contained in:
Eelke Klein 2023-01-24 17:47:52 +00:00
parent ccd88d0578
commit 2ff9577d41
22 changed files with 473 additions and 145 deletions

View file

@ -38,9 +38,9 @@ public:
virtual Oid getType(int column) const override;
virtual QVariant getData(const QModelIndex &index) const override;
RowItem rowItem(int row) const
RowItem rowItem(const QModelIndex &index) const
{
return databases.at(row).database;
return databases.at(index.row()).database;
}
protected:
virtual QVariant getDataMeaning(const QModelIndex &index) const override;

View file

@ -5,15 +5,16 @@
#include "catalog/PgClass.h"
#include "catalog/PgClassContainer.h"
#include "catalog/PgNamespace.h"
#include "catalog/PgNamespaceContainer.h"
#include "Pgsql_declare.h"
#include "catalog/PgInheritsContainer.h"
//#include "Pgsql_declare.h"
#include "ui/catalog/tables/TableTreeBuilder.h"
#include "CustomDataRole.h"
#include <QBrush>
#include <QtConcurrent>
#include "Pgsql_Connection.h"
TablesTableModel::TablesTableModel(std::shared_ptr<OpenDatabase> opendatabase, QObject *parent)
: QAbstractTableModel(parent)
: QAbstractItemModel(parent)
, openDatabase(opendatabase)
{}
@ -36,17 +37,18 @@ void TablesTableModel::setCatalog(std::shared_ptr<const PgDatabaseCatalog> cat)
bool TableLike(RelKind relkind)
{
switch (relkind) {
case RelKind::Table:
case RelKind::View:
case RelKind::MaterializedView:
case RelKind::ForeignTable:
case RelKind::PartitionedTable:
return true;
default:
return false;
case RelKind::Table:
case RelKind::View:
case RelKind::MaterializedView:
case RelKind::ForeignTable:
case RelKind::PartitionedTable:
return true;
default:
return false;
}
}
void TablesTableModel::refresh()
{
beginResetModel();
@ -55,31 +57,19 @@ void TablesTableModel::refresh()
if (!m_catalog)
return;
// Later afscheiden naar filter functie
auto classes = m_catalog->classes();
rootNode.reset();
auto nsfilter = GetNamespaceFilterLambda();
std::map<Oid, PgClass> temp;
for (const auto &e : *classes)
if (TableLike(e.kind) && nsfilter(e))
temp.emplace(e.oid(), e);
TableTreeBuilder treeBuilder(temp, *m_catalog->inherits());
auto [rn, oidIndex] = treeBuilder.Build();
rootNode = rn;
std::map<Oid, int> oidIndex;
m_tables.clear();
for (const auto &e : *classes) {
bool add = false;
if (TableLike(e.kind)) {
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));
}
@ -106,14 +96,46 @@ QVariant TablesTableModel::headerData(int section, Qt::Orientation orientation,
return QVariant();
}
int TablesTableModel::rowCount(const QModelIndex &) const
int TablesTableModel::rowCount(const QModelIndex &parent) const
{
return static_cast<int>(m_tables.size());
if (parent.isValid())
{
const TableNode *parentItem = static_cast<const TableNode*>(parent.internalPointer());
return static_cast<int>(parentItem->children.size());
}
if (rootNode != nullptr)
return static_cast<int>(rootNode->children.size());
return 0;
}
int TablesTableModel::columnCount(const QModelIndex &) const
{
return colCount;
return colCount;
}
QModelIndex TablesTableModel::index(int row, int column, const QModelIndex &parent) const
{
if (parent.isValid())
{
const TableNode *parentItem = static_cast<const TableNode*>(parent.internalPointer());
return createIndex(row, column, parentItem->getChildPtr(row));
}
return createIndex(row, column, rootNode->getChildPtr(row));
}
QModelIndex TablesTableModel::parent(const QModelIndex &index) const
{
if (index.isValid())
{
const TableNode *item = static_cast<const TableNode*>(index.internalPointer());
auto parent = item->parent.lock();
if (parent && parent != rootNode)
{
return createIndex(parent->myIndex, 0, parent.get());
}
}
return {};
}
Oid TablesTableModel::getType(int column) const
@ -142,37 +164,29 @@ Oid TablesTableModel::getType(int column) const
QVariant TablesTableModel::getData(const QModelIndex &index) const
{
const auto &table = m_tables[index.row()];
const auto &t = table._class;
const auto &s = table.sizes;
// const auto &table = rootNode->children[index.row()];
const TableNode* table = nodeFromIndex(index);
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;
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)
@ -195,7 +209,7 @@ QVariant TablesTableModel::data(const QModelIndex &index, int role) const
return QVariant();
}
void TablesTableModel::StartLoadTableSizes(std::map<Oid, int> oidIndex)
void TablesTableModel::StartLoadTableSizes(OidClassIndex oidIndex)
{
QPointer p(this);
QtConcurrent::run([this]
@ -205,7 +219,7 @@ void TablesTableModel::StartLoadTableSizes(std::map<Oid, int> oidIndex)
.then(qApp, [p, oidIndex] (TableSizes sizes)
{
if (p)
p.data()->PopulateSizes(std::move(oidIndex), std::move(sizes));
p.data()->PopulateSizes(oidIndex, sizes);
});
}
@ -254,18 +268,41 @@ TablesTableModel::TableSizes TablesTableModel::QueryTableSizes() const
return sizes;
}
void TablesTableModel::PopulateSizes(std::map<Oid, int> oidIndex, std::vector<TableSize> sizes)
void TablesTableModel::PopulateSizes(
const OidClassIndex &oidIndex,
const std::vector<TableSize> &sizes
)
{
for (auto s : sizes)
{
auto findIter = oidIndex.find(s.oid);
if (findIter != oidIndex.end())
{
m_tables[findIter->second].sizes = s;
findIter->second->sizes = s;
}
}
emit dataChanged(
createIndex(0, TotalSizeCol),
createIndex(static_cast<int>(m_tables.size()), ToastSizeCol)
);
index(0, TotalSizeCol),
index(static_cast<int>(rootNode->children.size()), ToastSizeCol)
);
}
const TableNode* TablesTableModel::nodeFromIndex(const QModelIndex &index)
{
return static_cast<const TableNode*>(index.internalPointer());
}
std::function<bool (const PgClass &)> TablesTableModel::GetNamespaceFilterLambda()
{
switch (m_namespaceFilter) {
case NamespaceFilter::User:
return [] (const PgClass &c) { return !c.ns().isSystemCatalog(); };
case NamespaceFilter::PgCatalog:
return [] (const PgClass &c) { return c.ns().objectName() == "pg_catalog"; };
case NamespaceFilter::InformationSchema:
return [] (const PgClass &c) { return c.ns().objectName() == "information_schema"; };
}
}

View file

@ -1,9 +1,12 @@
#ifndef TABLESTABLEMODEL_H
#ifndef TABLESTABLEMODEL_H
#define TABLESTABLEMODEL_H
#include "BaseTableModel.h"
//#include "catalog/models/BaseTableModel.h"
#include "ui/catalog/tables/TableNode.h"
#include "ui/catalog/tables/TableSize.h"
#include "NamespaceFilter.h"
#include "catalog/PgClass.h"
#include <QAbstractItemModel>
#include <memory>
#include <vector>
@ -11,7 +14,7 @@ class OpenDatabase;
class PgClass;
class PgDatabaseCatalog;
class TablesTableModel: public QAbstractTableModel {
class TablesTableModel: public QAbstractItemModel {
public:
using RowItem = PgClass;
enum e_Columns : int {
@ -40,42 +43,31 @@ public:
int rowCount(const QModelIndex &parent) const override;
int columnCount(const QModelIndex &parent) const override;
virtual QVariant data(const QModelIndex &index, int role) const override;
PgClass getTable(int row) const;
RowItem rowItem(int row) const
QModelIndex index(int row, int column,
const QModelIndex &parent = QModelIndex()) const override;
QModelIndex parent(const QModelIndex &index) const override;
QVariant data(const QModelIndex &index, int role) const override;
RowItem rowItem(const QModelIndex &index) const
{
return getTable(row);
return nodeFromIndex(index)->_class;
}
Oid getTableOid(int row) const;
static const TableNode* nodeFromIndex(const QModelIndex &index);
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>;
// this is a readonly model so when the vectors have been filled
// they will not change anymore and it is safe to assume the indexes
// of elements do not change
std::shared_ptr<const PgDatabaseCatalog> m_catalog;
NamespaceFilter m_namespaceFilter = NamespaceFilter::User;
t_Tables m_tables;
std::shared_ptr<TableNode> rootNode;
QMetaObject::Connection refreshConnection;
std::shared_ptr<OpenDatabase> openDatabase;
@ -83,10 +75,17 @@ private:
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);
using OidClassIndex = std::map<Oid, std::shared_ptr<TableNode>>;
void StartLoadTableSizes(OidClassIndex oidIndex);
TableSizes QueryTableSizes() const;
void PopulateSizes(
const OidClassIndex &oidIndex,
const std::vector<TableSize> &sizes
);
std::function<bool(const PgClass&)> GetNamespaceFilterLambda();
private slots:
void refresh();

View file

@ -8,7 +8,7 @@
#include "catalog/widgets/TriggerPage.h"
#include "catalog/models/ColumnTableModel.h"
#include "catalog/models/ConstraintModel.h"
#include "catalog/models/TablesTableModel.h"
#include "catalog/tables/TablesTableModel.h"
#include "util/PgLabTableView.h"
#include "ResultTableModelUtil.h"
#include "widgets/SqlCodePreview.h"
@ -27,7 +27,7 @@ CatalogTablesPage::CatalogTablesPage(std::shared_ptr<OpenDatabase> opendatabase,
: QSplitter(Qt::Horizontal, parent)
, m_tablesTableView(this, new TablesTableModel(opendatabase, this))
{
auto tv = m_tablesTableView.tableView();
auto tv = m_tablesTableView.itemView();
tv->setSelectionMode(QAbstractItemView::SingleSelection);
m_detailsTabs = new QTabWidget(this);
@ -106,7 +106,7 @@ void CatalogTablesPage::setCatalog(std::shared_ptr<PgDatabaseCatalog> cat)
void CatalogTablesPage::setNamespaceFilter(NamespaceFilter filter)
{
m_tablesTableView.dataModel()->setNamespaceFilter(filter);
m_tablesTableView.tableView()->resizeColumnsToContents();
//m_tablesTableView.tableView()->resizeColumnsToContents();
}
void CatalogTablesPage::tableListTable_currentRowChanged(const QModelIndex &current, const QModelIndex &previous)
@ -114,8 +114,8 @@ void CatalogTablesPage::tableListTable_currentRowChanged(const QModelIndex &curr
if (current.row() == previous.row())
return;
auto table = m_tablesTableView.rowItemForProxyIndex(current);
selectedTableChanged(table);
auto tableNode = TablesTableModel::nodeFromIndex(m_tablesTableView.sortFilter()->mapToSource(current)); // m_tablesTableView.rowItemForProxyIndex(current);
selectedTableChanged(tableNode->_class);
}
@ -127,11 +127,15 @@ void CatalogTablesPage::tableListTable_layoutChanged(const QList<QPersistentMode
void CatalogTablesPage::on_tableListTable_doubleClicked(const QModelIndex &index)
{
auto row = m_tablesTableView.sortFilter()->mapToSource(index).row();
PgClass table = m_tablesTableView.dataModel()->getTable(row);
if (table.oid() != InvalidOid) {
tableSelected(table.oid());
}
auto sourceIndex = m_tablesTableView.sortFilter()->mapToSource(index);
auto tableNode = TablesTableModel::nodeFromIndex(sourceIndex);
if (tableNode)
{
Oid oid = tableNode->_class.oid();
if (oid != InvalidOid) {
tableSelected(oid);
}
}
}
void CatalogTablesPage::selectedTableChanged(const std::optional<PgClass> &table)

View file

@ -2,13 +2,13 @@
#define CATALOGTABLESPAGE_H
#include "NamespaceFilter.h"
#include "catalog/models/TablesTableModel.h"
#include "catalog/tables/TablesTableModel.h"
#include "util/PgLabTableViewHelper.h"
#include <QSplitter>
#include <memory>
#include <optional>
#include <QAbstractItemModel>
#include "Pgsql_oids.h"
class CatalogConstraintPage;
class CatalogIndexPage;
@ -39,7 +39,7 @@ public:
signals:
void tableSelected(Oid tableoid);
private:
PgLabTableViewHelper<TablesTableModel> m_tablesTableView;
PgLabTableViewHelper<TablesTableModel, QTreeView> m_tablesTableView;
// Details
QTabWidget *m_detailsTabs = nullptr;