2017-12-09 10:45:13 +01:00
|
|
|
|
#include "DatabasesTableModel.h"
|
2021-03-31 16:06:45 +02:00
|
|
|
|
#include "CustomDataRole.h"
|
2022-01-19 19:10:05 +01:00
|
|
|
|
#include "OpenDatabase.h"
|
2021-03-31 16:06:45 +02:00
|
|
|
|
#include "ScopeGuard.h"
|
2018-12-16 10:17:59 +01:00
|
|
|
|
#include "catalog/PgDatabaseCatalog.h"
|
|
|
|
|
|
#include "catalog/PgDatabaseContainer.h"
|
|
|
|
|
|
#include "catalog/PgAuthIdContainer.h"
|
2022-01-19 19:10:05 +01:00
|
|
|
|
#include <QtConcurrent>
|
|
|
|
|
|
#include "Pgsql_Connection.h"
|
2017-12-09 10:45:13 +01:00
|
|
|
|
|
|
|
|
|
|
using namespace Pgsql;
|
2017-02-12 14:03:42 +01:00
|
|
|
|
|
2022-01-19 19:10:05 +01:00
|
|
|
|
DatabasesTableModel::DatabasesTableModel(std::shared_ptr<OpenDatabase> opendatabase, QObject *parent)
|
2017-12-09 10:45:13 +01:00
|
|
|
|
: BaseTableModel(parent)
|
2022-01-19 19:10:05 +01:00
|
|
|
|
, openDatabase(opendatabase)
|
2017-02-12 14:03:42 +01:00
|
|
|
|
{
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2017-12-10 10:35:46 +01:00
|
|
|
|
void DatabasesTableModel::setDatabaseList(std::shared_ptr<const PgDatabaseCatalog> cat)
|
2017-02-13 19:51:19 +01:00
|
|
|
|
{
|
|
|
|
|
|
beginResetModel();
|
2021-03-31 16:06:45 +02:00
|
|
|
|
SCOPE_EXIT { endResetModel(); };
|
|
|
|
|
|
|
2022-01-19 19:10:05 +01:00
|
|
|
|
databases.clear();
|
|
|
|
|
|
|
|
|
|
|
|
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);
|
2025-02-23 16:52:39 +01:00
|
|
|
|
oidIndex.emplace(d.oid(), static_cast<int>(databases.size() - 1));
|
2022-01-19 19:10:05 +01:00
|
|
|
|
}
|
|
|
|
|
|
StartLoadDatabaseSizes(std::move(oidIndex));
|
2017-02-13 19:51:19 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
2017-02-12 14:03:42 +01:00
|
|
|
|
QVariant DatabasesTableModel::headerData(int section, Qt::Orientation orientation, int role) const
|
|
|
|
|
|
{
|
|
|
|
|
|
QVariant v;
|
2022-01-19 19:10:05 +01:00
|
|
|
|
if (orientation == Qt::Horizontal)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (role == Qt::DisplayRole)
|
|
|
|
|
|
{
|
2017-02-12 14:03:42 +01:00
|
|
|
|
switch (section) {
|
|
|
|
|
|
case NameCol:
|
|
|
|
|
|
v = tr("Name");
|
|
|
|
|
|
break;
|
|
|
|
|
|
case DbaCol:
|
|
|
|
|
|
v = tr("Owner");
|
|
|
|
|
|
break;
|
|
|
|
|
|
case EncodingCol:
|
|
|
|
|
|
v = tr("Encoding");
|
|
|
|
|
|
break;
|
|
|
|
|
|
case CollateCol:
|
|
|
|
|
|
v = tr("Collation");
|
|
|
|
|
|
break;
|
|
|
|
|
|
case CTypeCol:
|
|
|
|
|
|
v = tr("CType");
|
|
|
|
|
|
break;
|
|
|
|
|
|
case IsTemplateCol:
|
|
|
|
|
|
v = tr("Is template");
|
|
|
|
|
|
break;
|
|
|
|
|
|
case AllowConnCol:
|
|
|
|
|
|
v = tr("Can connect");
|
|
|
|
|
|
break;
|
|
|
|
|
|
case ConnLimitCol:
|
|
|
|
|
|
v = tr("Conn. limit");
|
|
|
|
|
|
break;
|
|
|
|
|
|
case TablespaceCol:
|
|
|
|
|
|
v = tr("Tablespace");
|
|
|
|
|
|
break;
|
2021-03-11 06:59:31 +01:00
|
|
|
|
case CommentCol:
|
|
|
|
|
|
v = tr("Comment");
|
|
|
|
|
|
break;
|
2021-03-10 20:49:03 +01:00
|
|
|
|
case SizeCol:
|
|
|
|
|
|
v = tr("Size");
|
|
|
|
|
|
break;
|
2017-02-12 14:03:42 +01:00
|
|
|
|
case AclCol:
|
|
|
|
|
|
v = tr("ACL");
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return v;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2017-12-09 10:45:13 +01:00
|
|
|
|
int DatabasesTableModel::rowCount(const QModelIndex &) const
|
2017-02-12 14:03:42 +01:00
|
|
|
|
{
|
|
|
|
|
|
int result = 0;
|
2025-02-23 16:52:39 +01:00
|
|
|
|
result = static_cast<int>(databases.size());
|
2017-02-12 14:03:42 +01:00
|
|
|
|
return result;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2017-12-09 10:45:13 +01:00
|
|
|
|
int DatabasesTableModel::columnCount(const QModelIndex &) const
|
2017-02-12 14:03:42 +01:00
|
|
|
|
{
|
2017-12-09 10:45:13 +01:00
|
|
|
|
int result = COL_COUNT;
|
2017-02-12 14:03:42 +01:00
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2017-12-09 10:45:13 +01:00
|
|
|
|
Oid DatabasesTableModel::getType(int column) const
|
|
|
|
|
|
{
|
|
|
|
|
|
Oid oid;
|
2022-01-19 19:10:05 +01:00
|
|
|
|
switch (column)
|
|
|
|
|
|
{
|
2017-12-09 10:45:13 +01:00
|
|
|
|
case AllowConnCol:
|
|
|
|
|
|
case IsTemplateCol:
|
2021-03-31 16:06:45 +02:00
|
|
|
|
oid = Pgsql::bool_oid;
|
2017-12-09 10:45:13 +01:00
|
|
|
|
break;
|
|
|
|
|
|
case ConnLimitCol:
|
2021-03-31 16:06:45 +02:00
|
|
|
|
oid = Pgsql::int4_oid;
|
2017-12-09 10:45:13 +01:00
|
|
|
|
break;
|
2021-03-10 20:49:03 +01:00
|
|
|
|
case SizeCol:
|
2021-03-31 16:06:45 +02:00
|
|
|
|
oid = Pgsql::int8_oid;
|
2021-03-10 20:49:03 +01:00
|
|
|
|
break;
|
|
|
|
|
|
case AclCol:
|
2017-12-09 10:45:13 +01:00
|
|
|
|
case CollateCol:
|
|
|
|
|
|
case CTypeCol:
|
|
|
|
|
|
case EncodingCol:
|
|
|
|
|
|
case DbaCol:
|
|
|
|
|
|
case NameCol:
|
|
|
|
|
|
case TablespaceCol:
|
2021-03-11 06:59:31 +01:00
|
|
|
|
case CommentCol:
|
2021-03-31 16:06:45 +02:00
|
|
|
|
oid = Pgsql::varchar_oid;
|
2017-12-09 10:45:13 +01:00
|
|
|
|
break;
|
|
|
|
|
|
default:
|
2021-03-31 16:06:45 +02:00
|
|
|
|
oid = InvalidOid;
|
2017-12-09 10:45:13 +01:00
|
|
|
|
}
|
|
|
|
|
|
return oid;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
QVariant DatabasesTableModel::getData(const QModelIndex &index) const
|
2017-02-12 14:03:42 +01:00
|
|
|
|
{
|
|
|
|
|
|
QVariant v;
|
2022-01-19 19:10:05 +01:00
|
|
|
|
const Database &d = databases[index.row()];
|
|
|
|
|
|
const PgDatabase &db = d.database;
|
|
|
|
|
|
switch (index.column()) {
|
|
|
|
|
|
case NameCol:
|
|
|
|
|
|
v = db.objectName();
|
|
|
|
|
|
break;
|
|
|
|
|
|
case DbaCol:
|
2022-01-20 20:13:56 +01:00
|
|
|
|
v = db.ownerName();
|
2022-01-19 19:10:05 +01:00
|
|
|
|
break;
|
|
|
|
|
|
case EncodingCol:
|
|
|
|
|
|
v = db.encodingString;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case CollateCol:
|
|
|
|
|
|
v = db.collate;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case CTypeCol:
|
|
|
|
|
|
v = db.ctype;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case IsTemplateCol:
|
|
|
|
|
|
v = db.isTemplate;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case AllowConnCol:
|
|
|
|
|
|
v = db.allowConn;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case ConnLimitCol:
|
|
|
|
|
|
v = db.connLimit;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case TablespaceCol:
|
|
|
|
|
|
v = getTablespaceDisplayString(*m_catalog, db.tablespace);
|
|
|
|
|
|
break;
|
|
|
|
|
|
case CommentCol:
|
|
|
|
|
|
v = db.description;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case SizeCol:
|
|
|
|
|
|
if (d.size.totalBytes >= 0)
|
|
|
|
|
|
v = d.size.totalBytes;
|
|
|
|
|
|
break;
|
|
|
|
|
|
case AclCol:
|
|
|
|
|
|
v = db.aclString();
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
2017-02-12 14:03:42 +01:00
|
|
|
|
return v;
|
|
|
|
|
|
}
|
2021-03-31 16:06:45 +02:00
|
|
|
|
|
|
|
|
|
|
QVariant DatabasesTableModel::getDataMeaning(const QModelIndex &index) const
|
|
|
|
|
|
{
|
|
|
|
|
|
if (index.column() == SizeCol)
|
2022-01-19 19:10:05 +01:00
|
|
|
|
{
|
2024-04-12 06:29:57 +02:00
|
|
|
|
return static_cast<int>(DataMeaning::Bytes);
|
2022-01-19 19:10:05 +01:00
|
|
|
|
}
|
2021-03-31 16:06:45 +02:00
|
|
|
|
return BaseTableModel::getDataMeaning(index);
|
|
|
|
|
|
}
|
2022-01-19 19:10:05 +01:00
|
|
|
|
|
|
|
|
|
|
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)
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|