lazy load the database sizes only when needed by the server inspector.
This commit is contained in:
parent
39195153cd
commit
b5a706a2a2
10 changed files with 165 additions and 70 deletions
|
|
@ -1,15 +1,19 @@
|
||||||
#include "DatabasesTableModel.h"
|
#include "DatabasesTableModel.h"
|
||||||
#include "CustomDataRole.h"
|
#include "CustomDataRole.h"
|
||||||
|
#include "OpenDatabase.h"
|
||||||
#include "ScopeGuard.h"
|
#include "ScopeGuard.h"
|
||||||
#include "catalog/PgDatabaseCatalog.h"
|
#include "catalog/PgDatabaseCatalog.h"
|
||||||
#include "catalog/PgDatabaseContainer.h"
|
#include "catalog/PgDatabaseContainer.h"
|
||||||
#include "catalog/PgAuthIdContainer.h"
|
#include "catalog/PgAuthIdContainer.h"
|
||||||
#include "ResultTableModelUtil.h"
|
#include "ResultTableModelUtil.h"
|
||||||
|
#include <QtConcurrent>
|
||||||
|
#include "Pgsql_Connection.h"
|
||||||
|
|
||||||
using namespace Pgsql;
|
using namespace Pgsql;
|
||||||
|
|
||||||
DatabasesTableModel::DatabasesTableModel(QObject *parent)
|
DatabasesTableModel::DatabasesTableModel(std::shared_ptr<OpenDatabase> opendatabase, QObject *parent)
|
||||||
: BaseTableModel(parent)
|
: BaseTableModel(parent)
|
||||||
|
, openDatabase(opendatabase)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -18,15 +22,27 @@ void DatabasesTableModel::setDatabaseList(std::shared_ptr<const PgDatabaseCatalo
|
||||||
beginResetModel();
|
beginResetModel();
|
||||||
SCOPE_EXIT { endResetModel(); };
|
SCOPE_EXIT { endResetModel(); };
|
||||||
|
|
||||||
m_catalog = cat;
|
databases.clear();
|
||||||
m_databases = cat->databases();
|
|
||||||
|
std::map<Oid, int> oidIndex;
|
||||||
|
m_catalog = cat;
|
||||||
|
auto dats = cat->databases();
|
||||||
|
databases.reserve(dats->count());
|
||||||
|
for (const auto& d : *dats)
|
||||||
|
{
|
||||||
|
databases.emplace_back(d);
|
||||||
|
oidIndex.emplace(d.oid(), databases.size() - 1);
|
||||||
|
}
|
||||||
|
StartLoadDatabaseSizes(std::move(oidIndex));
|
||||||
}
|
}
|
||||||
|
|
||||||
QVariant DatabasesTableModel::headerData(int section, Qt::Orientation orientation, int role) const
|
QVariant DatabasesTableModel::headerData(int section, Qt::Orientation orientation, int role) const
|
||||||
{
|
{
|
||||||
QVariant v;
|
QVariant v;
|
||||||
if (orientation == Qt::Horizontal) {
|
if (orientation == Qt::Horizontal)
|
||||||
if (role == Qt::DisplayRole) {
|
{
|
||||||
|
if (role == Qt::DisplayRole)
|
||||||
|
{
|
||||||
switch (section) {
|
switch (section) {
|
||||||
case NameCol:
|
case NameCol:
|
||||||
v = tr("Name");
|
v = tr("Name");
|
||||||
|
|
@ -74,9 +90,7 @@ QVariant DatabasesTableModel::headerData(int section, Qt::Orientation orientatio
|
||||||
int DatabasesTableModel::rowCount(const QModelIndex &) const
|
int DatabasesTableModel::rowCount(const QModelIndex &) const
|
||||||
{
|
{
|
||||||
int result = 0;
|
int result = 0;
|
||||||
if (m_databases) {
|
result = databases.size();
|
||||||
result = m_databases->count();
|
|
||||||
}
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -90,7 +104,8 @@ int DatabasesTableModel::columnCount(const QModelIndex &) const
|
||||||
Oid DatabasesTableModel::getType(int column) const
|
Oid DatabasesTableModel::getType(int column) const
|
||||||
{
|
{
|
||||||
Oid oid;
|
Oid oid;
|
||||||
switch (column) {
|
switch (column)
|
||||||
|
{
|
||||||
case AllowConnCol:
|
case AllowConnCol:
|
||||||
case IsTemplateCol:
|
case IsTemplateCol:
|
||||||
oid = Pgsql::bool_oid;
|
oid = Pgsql::bool_oid;
|
||||||
|
|
@ -120,58 +135,113 @@ Oid DatabasesTableModel::getType(int column) const
|
||||||
QVariant DatabasesTableModel::getData(const QModelIndex &index) const
|
QVariant DatabasesTableModel::getData(const QModelIndex &index) const
|
||||||
{
|
{
|
||||||
QVariant v;
|
QVariant v;
|
||||||
//if (!index.isValid())
|
const Database &d = databases[index.row()];
|
||||||
if (m_databases) {
|
const PgDatabase &db = d.database;
|
||||||
const PgDatabase &db = m_databases->getByIdx(index.row());
|
switch (index.column()) {
|
||||||
switch (index.column()) {
|
case NameCol:
|
||||||
case NameCol:
|
v = db.objectName();
|
||||||
v = db.objectName();
|
break;
|
||||||
break;
|
case DbaCol:
|
||||||
case DbaCol:
|
v = getRoleDisplayString(*m_catalog, db.dba);
|
||||||
v = getRoleDisplayString(*m_catalog, db.dba);
|
break;
|
||||||
break;
|
case EncodingCol:
|
||||||
case EncodingCol:
|
// todo lookup encoding name
|
||||||
// todo lookup encoding name
|
v = db.encodingString;
|
||||||
v = db.encodingString;
|
break;
|
||||||
break;
|
case CollateCol:
|
||||||
case CollateCol:
|
v = db.collate;
|
||||||
v = db.collate;
|
break;
|
||||||
break;
|
case CTypeCol:
|
||||||
case CTypeCol:
|
v = db.ctype;
|
||||||
v = db.ctype;
|
break;
|
||||||
break;
|
case IsTemplateCol:
|
||||||
case IsTemplateCol:
|
v = db.isTemplate;
|
||||||
v = db.isTemplate;
|
break;
|
||||||
break;
|
case AllowConnCol:
|
||||||
case AllowConnCol:
|
v = db.allowConn;
|
||||||
v = db.allowConn;
|
break;
|
||||||
break;
|
case ConnLimitCol:
|
||||||
case ConnLimitCol:
|
v = db.connLimit;
|
||||||
v = db.connLimit;
|
break;
|
||||||
break;
|
case TablespaceCol:
|
||||||
case TablespaceCol:
|
// todo lookup tablespace name
|
||||||
// todo lookup tablespace name
|
v = getTablespaceDisplayString(*m_catalog, db.tablespace);
|
||||||
v = getTablespaceDisplayString(*m_catalog, db.tablespace);
|
break;
|
||||||
break;
|
case CommentCol:
|
||||||
case CommentCol:
|
v = db.description;
|
||||||
v = db.description;
|
break;
|
||||||
break;
|
case SizeCol:
|
||||||
case SizeCol:
|
if (d.size.totalBytes >= 0)
|
||||||
if (db.sizeBytes >= 0)
|
v = d.size.totalBytes;
|
||||||
v = db.sizeBytes;
|
break;
|
||||||
break;
|
case AclCol:
|
||||||
case AclCol:
|
v = db.aclString();
|
||||||
v = db.aclString();
|
break;
|
||||||
break;
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
QVariant DatabasesTableModel::getDataMeaning(const QModelIndex &index) const
|
QVariant DatabasesTableModel::getDataMeaning(const QModelIndex &index) const
|
||||||
{
|
{
|
||||||
if (index.column() == SizeCol)
|
if (index.column() == SizeCol)
|
||||||
|
{
|
||||||
return static_cast<int>(DataMeaningBytes);
|
return static_cast<int>(DataMeaningBytes);
|
||||||
|
}
|
||||||
return BaseTableModel::getDataMeaning(index);
|
return BaseTableModel::getDataMeaning(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DatabasesTableModel::StartLoadDatabaseSizes(std::map<Oid, int> oidIndex)
|
||||||
|
{
|
||||||
|
QPointer p(this);
|
||||||
|
QtConcurrent::run([this]
|
||||||
|
{
|
||||||
|
return QueryDatabaseSizes();
|
||||||
|
})
|
||||||
|
.then(qApp, [p, oi = std::move(oidIndex)] (DatabaseSizes sizes)
|
||||||
|
{
|
||||||
|
if (p)
|
||||||
|
{
|
||||||
|
p.data()->PopulateSizes(std::move(oi), std::move(sizes));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
DatabasesTableModel::DatabaseSizes DatabasesTableModel::QueryDatabaseSizes()
|
||||||
|
{
|
||||||
|
std::string q =
|
||||||
|
"SELECT pg_database.oid, "
|
||||||
|
" case when has_database_privilege(current_role, pg_database.oid, \n"
|
||||||
|
" 'connect') then pg_database_size(pg_database.oid) else -1 end \n"
|
||||||
|
"FROM pg_database";
|
||||||
|
|
||||||
|
Pgsql::Connection connection;
|
||||||
|
connection.connect(openDatabase->config().connectionString());
|
||||||
|
Pgsql::Result sizesResult = connection.query(q.c_str());
|
||||||
|
|
||||||
|
DatabaseSizes result;
|
||||||
|
result.reserve(sizesResult.rows());
|
||||||
|
for (auto& row : sizesResult)
|
||||||
|
{
|
||||||
|
DatabaseSize ds;
|
||||||
|
ds.oid = row.get(0);
|
||||||
|
ds.totalBytes = row.get(1);
|
||||||
|
result.push_back(ds);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DatabasesTableModel::PopulateSizes(std::map<Oid, int> oidIndex, DatabaseSizes sizes)
|
||||||
|
{
|
||||||
|
for (auto & s : sizes)
|
||||||
|
{
|
||||||
|
auto findIter = oidIndex.find(s.oid);
|
||||||
|
if (findIter != oidIndex.end())
|
||||||
|
{
|
||||||
|
databases[findIter->second].size = s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
emit dataChanged(
|
||||||
|
createIndex(0, SizeCol),
|
||||||
|
createIndex(static_cast<int>(databases.size()), SizeCol)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,11 @@
|
||||||
#define DATABASESTABLEMODEL_H
|
#define DATABASESTABLEMODEL_H
|
||||||
|
|
||||||
#include "BaseTableModel.h"
|
#include "BaseTableModel.h"
|
||||||
|
#include "catalog/PgDatabase.h"
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
class PgDatabaseContainer;
|
class OpenDatabase;
|
||||||
class PgDatabaseCatalog;
|
class PgDatabaseCatalog;
|
||||||
class PgDatabase;
|
|
||||||
|
|
||||||
/** Class for displaying the list of databases of a server in a QTableView
|
/** Class for displaying the list of databases of a server in a QTableView
|
||||||
*
|
*
|
||||||
|
|
@ -24,7 +24,7 @@ public:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
explicit DatabasesTableModel(QObject *parent);
|
explicit DatabasesTableModel(std::shared_ptr<OpenDatabase> opendatabase, QObject *parent);
|
||||||
|
|
||||||
void setDatabaseList(std::shared_ptr<const PgDatabaseCatalog> cat);
|
void setDatabaseList(std::shared_ptr<const PgDatabaseCatalog> cat);
|
||||||
|
|
||||||
|
|
@ -41,8 +41,36 @@ public:
|
||||||
protected:
|
protected:
|
||||||
virtual QVariant getDataMeaning(const QModelIndex &index) const override;
|
virtual QVariant getDataMeaning(const QModelIndex &index) const override;
|
||||||
private:
|
private:
|
||||||
|
class DatabaseSize {
|
||||||
|
public:
|
||||||
|
Oid oid;
|
||||||
|
int64_t totalBytes;
|
||||||
|
|
||||||
|
DatabaseSize()
|
||||||
|
: oid(InvalidOid)
|
||||||
|
, totalBytes(-1)
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
using DatabaseSizes = std::vector<DatabaseSize>;
|
||||||
|
|
||||||
|
class Database {
|
||||||
|
public:
|
||||||
|
PgDatabase database;
|
||||||
|
DatabaseSize size;
|
||||||
|
|
||||||
|
Database(const PgDatabase &db)
|
||||||
|
: database(db)
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
using Databases = std::vector<Database>;
|
||||||
|
|
||||||
|
std::shared_ptr<OpenDatabase> openDatabase;
|
||||||
std::shared_ptr<const PgDatabaseCatalog> m_catalog;
|
std::shared_ptr<const PgDatabaseCatalog> m_catalog;
|
||||||
std::shared_ptr<const PgDatabaseContainer> m_databases;
|
Databases databases;
|
||||||
|
|
||||||
|
void StartLoadDatabaseSizes(std::map<Oid, int> oidIndex);
|
||||||
|
DatabaseSizes QueryDatabaseSizes();
|
||||||
|
void PopulateSizes(std::map<Oid, int> oidIndex, DatabaseSizes sizes);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // DATABASESTABLEMODEL_H
|
#endif // DATABASESTABLEMODEL_H
|
||||||
|
|
|
||||||
|
|
@ -188,7 +188,7 @@ void TablesTableModel::StartLoadTableSizes(std::map<Oid, int> oidIndex)
|
||||||
{
|
{
|
||||||
return QueryTableSizes();
|
return QueryTableSizes();
|
||||||
})
|
})
|
||||||
.then(qApp, [p, oidIndex] (std::vector<TableSize> sizes)
|
.then(qApp, [p, oidIndex] (TableSizes sizes)
|
||||||
{
|
{
|
||||||
if (p)
|
if (p)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -60,12 +60,12 @@ private:
|
||||||
: oid(0)
|
: oid(0)
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
using TableSizes = std::vector<class TableSize>;
|
using TableSizes = std::vector<TableSize>;
|
||||||
|
|
||||||
class Table {
|
class Table {
|
||||||
public:
|
public:
|
||||||
PgClass _class;
|
PgClass _class;
|
||||||
class TableSize sizes;
|
TableSize sizes;
|
||||||
|
|
||||||
Table(const PgClass &cls)
|
Table(const PgClass &cls)
|
||||||
: _class(cls)
|
: _class(cls)
|
||||||
|
|
|
||||||
|
|
@ -5,9 +5,9 @@
|
||||||
#include "PgLabTableView.h"
|
#include "PgLabTableView.h"
|
||||||
|
|
||||||
|
|
||||||
DatabasesPage::DatabasesPage(QWidget * parent)
|
DatabasesPage::DatabasesPage(std::shared_ptr<OpenDatabase> opendatabase, QWidget * parent)
|
||||||
: QSplitter(Qt::Horizontal, parent)
|
: QSplitter(Qt::Horizontal, parent)
|
||||||
, m_databasesTableView(this)
|
, m_databasesTableView(this, new DatabasesTableModel(opendatabase, this))
|
||||||
{
|
{
|
||||||
auto tv = m_databasesTableView.tableView();
|
auto tv = m_databasesTableView.tableView();
|
||||||
tv->setSelectionMode(QAbstractItemView::SingleSelection);
|
tv->setSelectionMode(QAbstractItemView::SingleSelection);
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ class QSortFilterProxyModel;
|
||||||
|
|
||||||
class DatabasesPage: public QSplitter {
|
class DatabasesPage: public QSplitter {
|
||||||
public:
|
public:
|
||||||
explicit DatabasesPage(QWidget * parent = nullptr);
|
explicit DatabasesPage(std::shared_ptr<OpenDatabase> opendatabase, QWidget * parent = nullptr);
|
||||||
|
|
||||||
void setCatalog(std::shared_ptr<PgDatabaseCatalog> cat);
|
void setCatalog(std::shared_ptr<PgDatabaseCatalog> cat);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@
|
||||||
ServerInspector::ServerInspector(std::shared_ptr<OpenDatabase> open_database, QWidget *parent)
|
ServerInspector::ServerInspector(std::shared_ptr<OpenDatabase> open_database, QWidget *parent)
|
||||||
: QWidget(parent)
|
: QWidget(parent)
|
||||||
{
|
{
|
||||||
m_databasesPage = new DatabasesPage(this);
|
m_databasesPage = new DatabasesPage(open_database, this);
|
||||||
m_rolesPage = new RolesPage(this);
|
m_rolesPage = new RolesPage(this);
|
||||||
|
|
||||||
m_tabWidget = new QTabWidget(this);
|
m_tabWidget = new QTabWidget(this);
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,6 @@ public:
|
||||||
bool allowConn;
|
bool allowConn;
|
||||||
int connLimit;
|
int connLimit;
|
||||||
Oid tablespace;
|
Oid tablespace;
|
||||||
int64_t sizeBytes;
|
|
||||||
QString description;
|
QString description;
|
||||||
|
|
||||||
using PgServerObject::PgServerObject;
|
using PgServerObject::PgServerObject;
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,6 @@ std::string PgDatabaseContainer::getLoadQuery() const
|
||||||
return
|
return
|
||||||
"SELECT pg_database.oid, datname, datdba, encoding, pg_encoding_to_char(encoding), datcollate,\n"
|
"SELECT pg_database.oid, datname, datdba, encoding, pg_encoding_to_char(encoding), datcollate,\n"
|
||||||
" datctype, datistemplate, datallowconn, datconnlimit, dattablespace, \n"
|
" datctype, datistemplate, datallowconn, datconnlimit, dattablespace, \n"
|
||||||
" case when has_database_privilege(current_role, pg_database.oid, 'connect') then pg_database_size(pg_database.oid) else -1 end,\n"
|
|
||||||
" d.description, datacl\n"
|
" d.description, datacl\n"
|
||||||
"FROM pg_database\n"
|
"FROM pg_database\n"
|
||||||
" LEFT JOIN pg_catalog.pg_shdescription AS d ON (objoid=pg_database.oid)";
|
" LEFT JOIN pg_catalog.pg_shdescription AS d ON (objoid=pg_database.oid)";
|
||||||
|
|
@ -20,7 +19,7 @@ PgDatabase PgDatabaseContainer::loadElem(const Pgsql::Row &row)
|
||||||
QString name = col.nextValue();
|
QString name = col.nextValue();
|
||||||
PgDatabase v(m_catalog, oid, name);
|
PgDatabase v(m_catalog, oid, name);
|
||||||
col >> v.dba >> v.encoding >> v.encodingString >> v.collate >> v.ctype >> v.isTemplate
|
col >> v.dba >> v.encoding >> v.encodingString >> v.collate >> v.ctype >> v.isTemplate
|
||||||
>> v.allowConn >> v.connLimit >> v.tablespace >> v.sizeBytes >> v.description;
|
>> v.allowConn >> v.connLimit >> v.tablespace >> v.description;
|
||||||
|
|
||||||
AclList acl_list;
|
AclList acl_list;
|
||||||
col >> acl_list;
|
col >> acl_list;
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,6 @@ namespace Pgsql {
|
||||||
|
|
||||||
class PgDatabaseContainer: public PgContainer<PgDatabase> {
|
class PgDatabaseContainer: public PgContainer<PgDatabase> {
|
||||||
public:
|
public:
|
||||||
//explicit PgDatabaseContainer(PgDatabaseCatalog *cat);
|
|
||||||
using PgContainer<PgDatabase>::PgContainer;
|
using PgContainer<PgDatabase>::PgContainer;
|
||||||
|
|
||||||
virtual std::string getLoadQuery() const override;
|
virtual std::string getLoadQuery() const override;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue