Retrieve tables sizes asynchronously when opening the catalog.
This commit is contained in:
parent
8fe5e05f7d
commit
39195153cd
8 changed files with 163 additions and 52 deletions
|
|
@ -1,4 +1,5 @@
|
|||
#include "TablesTableModel.h"
|
||||
#include "OpenDatabase.h"
|
||||
#include "ScopeGuard.h"
|
||||
#include "catalog/PgDatabaseCatalog.h"
|
||||
#include "catalog/PgClass.h"
|
||||
|
|
@ -8,9 +9,12 @@
|
|||
#include "Pgsql_declare.h"
|
||||
#include "CustomDataRole.h"
|
||||
#include <QBrush>
|
||||
#include <QtConcurrent>
|
||||
#include "Pgsql_Connection.h"
|
||||
|
||||
TablesTableModel::TablesTableModel(QObject *parent)
|
||||
TablesTableModel::TablesTableModel(std::shared_ptr<OpenDatabase> opendatabase, QObject *parent)
|
||||
: QAbstractTableModel(parent)
|
||||
, openDatabase(opendatabase)
|
||||
{}
|
||||
|
||||
void TablesTableModel::setNamespaceFilter(NamespaceFilter nsf)
|
||||
|
|
@ -40,6 +44,7 @@ void TablesTableModel::refresh()
|
|||
// 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;
|
||||
|
|
@ -57,9 +62,12 @@ void TablesTableModel::refresh()
|
|||
break;
|
||||
}
|
||||
}
|
||||
if (add)
|
||||
m_tables.push_back(e);
|
||||
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
|
||||
|
|
@ -75,10 +83,10 @@ QVariant TablesTableModel::headerData(int section, Qt::Orientation orientation,
|
|||
case OptionsCol: return tr("Options");
|
||||
case AclCol: return tr("ACL");
|
||||
case CommentCol: return tr("Comment");
|
||||
case TotalSize: return tr("Total size");
|
||||
case TableSize: return tr("Table size");
|
||||
case IndexSize: return tr("Index size");
|
||||
case ToastSize: return tr("TOAST size");
|
||||
case TotalSizeCol: return tr("Total size");
|
||||
case TableSizeCol: return tr("Table size");
|
||||
case IndexSizeCol: return tr("Index size");
|
||||
case ToastSizeCol: return tr("TOAST size");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -99,10 +107,10 @@ Oid TablesTableModel::getType(int column) const
|
|||
{
|
||||
Oid oid;
|
||||
switch (column) {
|
||||
case TotalSize:
|
||||
case TableSize:
|
||||
case IndexSize:
|
||||
case ToastSize:
|
||||
case TotalSizeCol:
|
||||
case TableSizeCol:
|
||||
case IndexSizeCol:
|
||||
case ToastSizeCol:
|
||||
oid = Pgsql::int8_oid;
|
||||
break;
|
||||
case TablespaceCol:
|
||||
|
|
@ -121,20 +129,22 @@ Oid TablesTableModel::getType(int column) const
|
|||
|
||||
QVariant TablesTableModel::getData(const QModelIndex &index) const
|
||||
{
|
||||
const auto &t = m_tables[index.row()];
|
||||
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 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 TotalSize: return t.totalBytes;
|
||||
case TableSize: return t.totalBytes - t.indexBytes - t.toastBytes;
|
||||
case IndexSize: return t.indexBytes;
|
||||
case ToastSize: return t.toastBytes;
|
||||
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();
|
||||
|
|
@ -142,12 +152,12 @@ QVariant TablesTableModel::getData(const QModelIndex &index) const
|
|||
|
||||
PgClass TablesTableModel::getTable(int row) const
|
||||
{
|
||||
return m_tables[row];
|
||||
return m_tables[row]._class;
|
||||
}
|
||||
|
||||
Oid TablesTableModel::getTableOid(int row) const
|
||||
{
|
||||
return m_tables[row].oid();
|
||||
return m_tables[row]._class.oid();
|
||||
}
|
||||
|
||||
QVariant TablesTableModel::data(const QModelIndex &index, int role) const
|
||||
|
|
@ -158,10 +168,10 @@ QVariant TablesTableModel::data(const QModelIndex &index, int role) const
|
|||
return getType(index.column());
|
||||
else if (role == CustomDataMeaningRole) {
|
||||
switch (index.column()) {
|
||||
case TotalSize:
|
||||
case TableSize:
|
||||
case IndexSize:
|
||||
case ToastSize:
|
||||
case TotalSizeCol:
|
||||
case TableSizeCol:
|
||||
case IndexSizeCol:
|
||||
case ToastSizeCol:
|
||||
return static_cast<int>(DataMeaningBytes);
|
||||
default:
|
||||
return static_cast<int>(DataMeaningNormal);
|
||||
|
|
@ -170,3 +180,80 @@ QVariant TablesTableModel::data(const QModelIndex &index, int role) const
|
|||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
void TablesTableModel::StartLoadTableSizes(std::map<Oid, int> oidIndex)
|
||||
{
|
||||
QPointer p(this);
|
||||
QtConcurrent::run([this]
|
||||
{
|
||||
return QueryTableSizes();
|
||||
})
|
||||
.then(qApp, [p, oidIndex] (std::vector<TableSize> 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)
|
||||
);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue