Show sizes

table, index, toast and total size per Table
size of each index
This commit is contained in:
eelke 2021-03-10 19:06:40 +01:00
parent d6aeef492d
commit 11459e1e12
17 changed files with 138 additions and 28 deletions

View file

@ -131,7 +131,7 @@ QVariant ColumnTableModel::headerData(int section, Qt::Orientation orientation,
int ColumnTableModel::rowCount(const QModelIndex &/*parent*/) const int ColumnTableModel::rowCount(const QModelIndex &/*parent*/) const
{ {
return m_columns.size(); return static_cast<int>(m_columns.size());
} }
int ColumnTableModel::columnCount(const QModelIndex &/*parent*/) const int ColumnTableModel::columnCount(const QModelIndex &/*parent*/) const

View file

@ -67,7 +67,7 @@ QVariant ConstraintModel::headerData(int section, Qt::Orientation orientation, i
int ConstraintModel::rowCount(const QModelIndex &) const int ConstraintModel::rowCount(const QModelIndex &) const
{ {
return m_constraints.size(); return static_cast<int>(m_constraints.size());
} }
int ConstraintModel::columnCount(const QModelIndex &) const int ConstraintModel::columnCount(const QModelIndex &) const

View file

@ -13,10 +13,17 @@ enum class ReferencedType {
PgRole PgRole
}; };
///
enum DataMeaning {
DataMeaningNormal,
DataMeaningBytes ///< the value represents bytes pretty print in KiB, MiB, GiB, TiB, PiB, EiB
};
enum CustomDataRole { enum CustomDataRole {
CustomDataTypeRole = Qt::UserRole, ///< Requist the basic type of the value CustomDataTypeRole = Qt::UserRole, ///< Requist the basic type of the value
CustomReferencedTypeRole, ///< CustomReferencedTypeRole, ///<
// Add other enum before this one is we might want to have multiple hidden values CustomDataMeaningRole,
// Add other enum before this one as we might want to have multiple hidden values
FirstHiddenValue, ///< Used to request value from a model which is not handed to the view FirstHiddenValue, ///< Used to request value from a model which is not handed to the view
}; };

View file

@ -63,6 +63,9 @@ QVariant IndexModel::headerData(int section, Qt::Orientation orientation, int ro
case ConditionCol: case ConditionCol:
c = tr("Condition"); c = tr("Condition");
break; break;
case SizeCol:
c = tr("Size");
break;
// case DefinitionCol: // case DefinitionCol:
// c = tr("Definition"); // c = tr("Definition");
// break; // break;
@ -99,6 +102,10 @@ QVariant IndexModel::getData(const QModelIndex &index) const
case ConditionCol: case ConditionCol:
break; break;
case SizeCol:
v = dat.sizeBytes;
break;
} }
return v; return v;
} }
@ -110,5 +117,13 @@ QVariant IndexModel::data(const QModelIndex &index, int role) const
v = getData(index); v = getData(index);
else if (role == CustomDataTypeRole) else if (role == CustomDataTypeRole)
v = getType(index.column()); v = getType(index.column());
else if (role == CustomDataMeaningRole) {
switch (index.column()) {
case SizeCol:
return static_cast<int>(DataMeaningBytes);
default:
return static_cast<int>(DataMeaningNormal);
}
}
return v; return v;
} }

View file

@ -22,6 +22,7 @@ public:
AmCol, ///< Access Method AmCol, ///< Access Method
ColumnsCol, /// ColumnsCol, ///
ConditionCol, ConditionCol,
SizeCol,
colCount }; colCount };
// oid // oid

View file

@ -87,6 +87,11 @@ void PgLabItemDelegate::initStyleOption(QStyleOptionViewItem *option,
if (value.isValid()) if (value.isValid())
oid = value.toUInt(); //getType(index.column()); oid = value.toUInt(); //getType(index.column());
value = index.data(CustomDataMeaningRole);
DataMeaning meaning = value.isValid()
? static_cast<DataMeaning>(value.toInt())
: DataMeaningNormal;
value = index.data(Qt::DisplayRole); value = index.data(Qt::DisplayRole);
option->displayAlignment = GetDefaultAlignmentForType(oid); option->displayAlignment = GetDefaultAlignmentForType(oid);
@ -96,18 +101,47 @@ void PgLabItemDelegate::initStyleOption(QStyleOptionViewItem *option,
QColor forground_color = oid == Pgsql::bool_oid QColor forground_color = oid == Pgsql::bool_oid
? GetDefaultBoolColor(value.toBool()) ? GetDefaultBoolColor(value.toBool())
: GetDefaultColorForType(oid); : GetDefaultColorForType(oid);
option->palette.setBrush(QPalette::Text, QBrush(forground_color));
option->features |= QStyleOptionViewItem::HasDisplay; option->features |= QStyleOptionViewItem::HasDisplay;
if (oid == Pgsql::bool_oid) if (oid == Pgsql::bool_oid)
option->text = FormatBoolForDisplay(value.toBool()); option->text = FormatBoolForDisplay(value.toBool());
else { else {
if (meaning == DataMeaningBytes) {
QString suffix;
auto s = value.toLongLong();
double val;
if (s > 1024 * 1024 * 1000) {
val = s / (1024 * 1024 * 1024);
suffix = "GiB";
forground_color = QColorConstants::Svg::darkorange;
option->font.setBold(true);
}
else if (s > 1024 * 1000) {
val = s / (1024 * 1024);
suffix = "MiB";
forground_color = QColorConstants::Svg::darkgoldenrod;
}
else if (s > 1000) {
val = s / 1024;
suffix = "KiB";
forground_color = QColorConstants::Svg::darkgreen;
}
else {
val = s;
suffix = "B";
forground_color = QColorConstants::Svg::darkblue;
}
option->text = QString{ "%1 %2" }.arg(val, 3, 'g', -1 ).arg(suffix) ;
}
else {
auto str = value.toString(); auto str = value.toString();
auto s = str.left(100); auto s = str.left(100);
// auto f = s.indexOf('\n'); // auto f = s.indexOf('\n');
// option->text = ((f > 0) ? s.left(f) : s).toString(); // option->text = ((f > 0) ? s.left(f) : s).toString();
option->text = s; option->text = s;
} }
option->palette.setBrush(QPalette::Text, QBrush(forground_color));
}
} }
else { else {
option->palette.setBrush(QPalette::Text, QBrush(GetDefaultNullColor())); option->palette.setBrush(QPalette::Text, QBrush(GetDefaultNullColor()));

View file

@ -100,7 +100,8 @@ QVariant PropertyProxyModel::data(const QModelIndex &proxyIndex, int role) const
void PropertyProxyModel::setActiveRow(const QModelIndex &row) void PropertyProxyModel::setActiveRow(const QModelIndex &row)
{ {
activeRow = row.isValid() ? row.row() : -1; activeRow = row.isValid() ? row.row() : -1;
emit dataChanged(index(0, valueColumn), index(rowCount(QModelIndex()), valueColumn), QVector<int>() << Qt::DisplayRole); emit dataChanged(index(0, valueColumn), index(rowCount(QModelIndex()), valueColumn),
QVector<int>() << Qt::DisplayRole);
} }
Qt::ItemFlags PropertyProxyModel::flags(const QModelIndex &index) const Qt::ItemFlags PropertyProxyModel::flags(const QModelIndex &index) const

View file

@ -20,7 +20,7 @@ public:
public Q_SLOTS: public Q_SLOTS:
/** Updates the model (and view) to show the values for row /** Updates the model (and view) to show the values for row
* *
* The column part of the index is not used QModelIndex is used to make is eacy to connect to * The column part of the index is not used QModelIndex is used to make it easy to connect to
* QItemSelectionModel::currentRowChanged * QItemSelectionModel::currentRowChanged
*/ */
void setActiveRow(const QModelIndex &row); void setActiveRow(const QModelIndex &row);

View file

@ -132,6 +132,10 @@ QVariant TablesTableModel::headerData(int section, Qt::Orientation orientation,
case OptionsCol: return tr("Options"); case OptionsCol: return tr("Options");
case AclCol: return tr("ACL"); case AclCol: return tr("ACL");
case CommentCol: return tr("Comment"); 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");
} }
} }
} }
@ -153,6 +157,12 @@ Oid TablesTableModel::getType(int column) const
{ {
Oid oid; Oid oid;
switch (column) { switch (column) {
case TotalSize:
case TableSize:
case IndexSize:
case ToastSize:
oid = Pgsql::int8_oid;
break;
case TablespaceCol: case TablespaceCol:
case OwnerCol: case OwnerCol:
case NameCol: case NameCol:
@ -179,6 +189,10 @@ QVariant TablesTableModel::getData(const QModelIndex &index) const
case OptionsCol: break; case OptionsCol: break;
case AclCol: return t.aclString(); case AclCol: return t.aclString();
case CommentCol: return t.description; 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;
} }
return QVariant(); return QVariant();
@ -207,5 +221,17 @@ QVariant TablesTableModel::data(const QModelIndex &index, int role) const
return getData(index); return getData(index);
else if (role == CustomDataTypeRole) else if (role == CustomDataTypeRole)
return getType(index.column()); return getType(index.column());
else if (role == CustomDataMeaningRole) {
switch (index.column()) {
case TotalSize:
case TableSize:
case IndexSize:
case ToastSize:
return static_cast<int>(DataMeaningBytes);
default:
return static_cast<int>(DataMeaningNormal);
}
}
return QVariant(); return QVariant();
} }

View file

@ -23,6 +23,11 @@ public:
OptionsCol, OptionsCol,
AclCol, AclCol,
CommentCol, CommentCol,
TotalSize,
TableSize,
IndexSize,
ToastSize,
colCount }; colCount };
TablesTableModel(QObject *parent); TablesTableModel(QObject *parent);

View file

@ -58,9 +58,6 @@ CatalogTablesPage::CatalogTablesPage(QWidget *parent)
m_propertiesPage->setSourceModel(m_tablesModel); m_propertiesPage->setSourceModel(m_tablesModel);
m_detailsTabs->addTab(m_propertiesPage, ""); m_detailsTabs->addTab(m_propertiesPage, "");
connect(m_tableView->selectionModel(), &QItemSelectionModel::currentRowChanged,
m_propertiesPage, &PropertiesPage::setActiveRow);
// - Trigger page // - Trigger page
m_triggerPage = new TriggerPage(this); m_triggerPage = new TriggerPage(this);
m_detailsTabs->addTab(m_triggerPage, ""); m_detailsTabs->addTab(m_triggerPage, "");
@ -129,12 +126,16 @@ void CatalogTablesPage::tableListTable_currentRowChanged(const QModelIndex &curr
{ {
if (current.row() != previous.row()) { if (current.row() != previous.row()) {
if (current.isValid()) { if (current.isValid()) {
auto row = m_tablesSortFilter->mapToSource(current).row(); auto sourceIndex = m_tablesSortFilter->mapToSource(current);
auto row = sourceIndex.row();
PgClass table = m_tablesModel->getTable(row); PgClass table = m_tablesModel->getTable(row);
selectedTableChanged(table); selectedTableChanged(table);
m_propertiesPage->setActiveRow(sourceIndex);
} }
else else {
selectedTableChanged({}); selectedTableChanged({});
m_propertiesPage->setActiveRow({});
}
} }
} }

View file

@ -50,6 +50,10 @@ public:
QString viewdef; QString viewdef;
QString description; // from pg_description QString description; // from pg_description
int64_t totalBytes;
int64_t indexBytes;
int64_t toastBytes;
using PgNamespaceObject::PgNamespaceObject; using PgNamespaceObject::PgNamespaceObject;

View file

@ -11,7 +11,11 @@ std::string PgClassContainer::getLoadQuery() const
" relowner, relam, relfilenode, reltablespace, relpages, " " relowner, relam, relfilenode, reltablespace, relpages, "
" reltuples, reltoastrelid, relisshared, relpersistence, " " reltuples, reltoastrelid, relisshared, relpersistence, "
" relkind, relispopulated, relfrozenxid, relminmxid, " " relkind, relispopulated, relfrozenxid, relminmxid, "
" reloptions, d.description, relacl, pg_get_viewdef(oid)"; " reloptions, d.description, "
" pg_total_relation_size(oid) AS total_bytes, "
" CASE WHEN relkind='r' THEN pg_indexes_size(oid) ELSE 0 END AS index_bytes, "
" CASE WHEN relkind='r' THEN pg_total_relation_size(reltoastrelid) ELSE 0 END AS toast_bytes, "
" relacl, pg_get_viewdef(oid)";
if (lessThenVersion(120000)) if (lessThenVersion(120000))
q += ", relhasoids "; q += ", relhasoids ";
@ -37,7 +41,7 @@ PgClass PgClassContainer::loadElem(const Pgsql::Row &row)
>> owner >> v.am >> v.filenode >> v.tablespace >> v.pages_est >> owner >> v.am >> v.filenode >> v.tablespace >> v.pages_est
>> v.tuples_est >> v.toastrelid >> v.isshared >> v.persistence >> v.tuples_est >> v.toastrelid >> v.isshared >> v.persistence
>> v.kind >> v.ispopulated >> v.frozenxid >> v.minmxid >> v.kind >> v.ispopulated >> v.frozenxid >> v.minmxid
>> v.options >> v.description; >> v.options >> v.description >> v.totalBytes >> v.indexBytes >> v.toastBytes;
v.setOwnerOid(owner); v.setOwnerOid(owner);

View file

@ -29,6 +29,7 @@ public:
QString exprs; QString exprs;
QString pred; QString pred;
QString definition; QString definition;
int64_t sizeBytes;
using PgNamespaceObject::PgNamespaceObject; using PgNamespaceObject::PgNamespaceObject;
QString getAm() const; QString getAm() const;

View file

@ -11,7 +11,7 @@ SELECT indexrelid, indrelid, indnatts, indisunique, indisprimary,
indisexclusion, indimmediate, indisclustered, indisvalid, indisexclusion, indimmediate, indisclustered, indisvalid,
indcheckxmin, indisready, indislive, indkey, indcheckxmin, indisready, indislive, indkey,
indcollation, indclass, indoption, indexprs, indpred, indcollation, indclass, indoption, indexprs, indpred,
pg_get_indexdef(indexrelid))__"; pg_get_indexdef(indexrelid), pg_total_relation_size(indexrelid))__";
if (minimumVersion(90400)) if (minimumVersion(90400))
q += ", indisreplident "; q += ", indisreplident ";
@ -35,7 +35,7 @@ PgIndex PgIndexContainer::loadElem(const Pgsql::Row &row)
col.getAsVector<Oid>(std::back_inserter(v.collation)); col.getAsVector<Oid>(std::back_inserter(v.collation));
col.getAsVector<Oid>(std::back_inserter(v.indclass)); col.getAsVector<Oid>(std::back_inserter(v.indclass));
col.getAsVector<int16_t>(std::back_inserter(v.option)); col.getAsVector<int16_t>(std::back_inserter(v.option));
col >> v.exprs >> v.pred >> v.definition; col >> v.exprs >> v.pred >> v.definition >> v.sizeBytes;
if (minimumVersion(90400)) if (minimumVersion(90400))
col >> v.isreplident; col >> v.isreplident;

View file

@ -47,6 +47,9 @@ Value::operator std::string() const
Value::operator int16_t() const Value::operator int16_t() const
{ {
if (m_val == nullptr)
return 0;
int32_t r = operator int32_t(); int32_t r = operator int32_t();
if (r <= std::numeric_limits<int16_t>::max() if (r <= std::numeric_limits<int16_t>::max()
&& r >= std::numeric_limits<int16_t>::min()) && r >= std::numeric_limits<int16_t>::min())
@ -57,6 +60,9 @@ Value::operator int16_t() const
Value::operator int32_t() const Value::operator int32_t() const
{ {
if (m_val == nullptr)
return 0;
const size_t len = std::strlen(m_val); const size_t len = std::strlen(m_val);
if (len > 0) { if (len > 0) {
char *endptr = nullptr; char *endptr = nullptr;
@ -74,6 +80,9 @@ Value::operator Oid() const
Value::operator int64_t() const Value::operator int64_t() const
{ {
if (m_val == nullptr)
return 0LL;
const int len = std::strlen(m_val); const int len = std::strlen(m_val);
if (len > 0) { if (len > 0) {
char *endptr = nullptr; char *endptr = nullptr;

View file

@ -44,6 +44,8 @@ namespace Pgsql {
bool isString() const; bool isString() const;
/// Retrieves an array type value and passes them to an insert iterator. /// Retrieves an array type value and passes them to an insert iterator.
/// ///
/// When the array it self is NULL this function behaves the same as for an empty array. No /// When the array it self is NULL this function behaves the same as for an empty array. No