2017-08-23 13:27:23 +02:00
|
|
|
|
#include "QueryExplainModel.h"
|
2016-12-29 13:48:35 +01:00
|
|
|
|
#include <QColor>
|
|
|
|
|
|
#include <QSize>
|
2017-08-23 13:27:23 +02:00
|
|
|
|
#include <cmath>
|
2016-12-29 13:48:35 +01:00
|
|
|
|
|
|
|
|
|
|
const int c_ColumnNode = 0;
|
|
|
|
|
|
const int c_ColumnExclusive = 1;
|
|
|
|
|
|
const int c_ColumnInclusive = 2;
|
|
|
|
|
|
const int c_ColumnEstErr = 3;
|
|
|
|
|
|
const int c_ColumnRowCount = 4;
|
|
|
|
|
|
const int c_ColumnLoops = 5;
|
|
|
|
|
|
const int c_ColumnDetails = 6;
|
2017-12-09 10:45:13 +01:00
|
|
|
|
const int c_ColumnShared = 7;
|
|
|
|
|
|
const int c_NumberOfColumns = 8;
|
2016-12-29 13:48:35 +01:00
|
|
|
|
|
2016-12-30 10:38:46 +01:00
|
|
|
|
QueryExplainModel::QueryExplainModel(QObject *parent, ExplainRoot::SPtr exp)
|
2016-12-29 13:48:35 +01:00
|
|
|
|
: QAbstractItemModel(parent)
|
|
|
|
|
|
, explain(std::move(exp))
|
|
|
|
|
|
{}
|
|
|
|
|
|
|
|
|
|
|
|
QVariant QueryExplainModel::data(const QModelIndex &index, int role) const
|
|
|
|
|
|
{
|
|
|
|
|
|
QVariant result;
|
|
|
|
|
|
if (index.isValid()) {
|
|
|
|
|
|
int col = index.column();
|
|
|
|
|
|
ExplainTreeModelItem *item = static_cast<ExplainTreeModelItem*>(index.internalPointer());
|
|
|
|
|
|
if (role == Qt::DisplayRole) {
|
|
|
|
|
|
switch (col) {
|
|
|
|
|
|
case c_ColumnNode:
|
2017-12-09 10:45:13 +01:00
|
|
|
|
result = item->nodeType;
|
2016-12-29 13:48:35 +01:00
|
|
|
|
break;
|
|
|
|
|
|
case c_ColumnExclusive:
|
|
|
|
|
|
result = item->exclusiveTime();
|
|
|
|
|
|
break;
|
|
|
|
|
|
case c_ColumnInclusive:
|
|
|
|
|
|
result = item->inclusiveTime();
|
|
|
|
|
|
break;
|
|
|
|
|
|
case c_ColumnEstErr:
|
|
|
|
|
|
result = item->estimateError();
|
|
|
|
|
|
break;
|
|
|
|
|
|
case c_ColumnRowCount:
|
2017-12-09 10:45:13 +01:00
|
|
|
|
result = item->actualRows;
|
2016-12-29 13:48:35 +01:00
|
|
|
|
break;
|
|
|
|
|
|
case c_ColumnLoops:
|
2017-12-09 10:45:13 +01:00
|
|
|
|
result = item->actualLoops;
|
2016-12-29 13:48:35 +01:00
|
|
|
|
break;
|
|
|
|
|
|
case c_ColumnDetails:
|
|
|
|
|
|
result = item->detailString();
|
|
|
|
|
|
break;
|
2017-12-09 10:45:13 +01:00
|
|
|
|
case c_ColumnShared:
|
|
|
|
|
|
result = item->sharedBlocks.asString();
|
|
|
|
|
|
break;
|
2016-12-29 13:48:35 +01:00
|
|
|
|
} // end switch column
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (role == Qt::TextAlignmentRole) {
|
|
|
|
|
|
if (col == c_ColumnNode || col == c_ColumnDetails) {
|
|
|
|
|
|
result = Qt::AlignLeft + Qt::AlignVCenter;
|
|
|
|
|
|
}
|
|
|
|
|
|
else {
|
|
|
|
|
|
result = Qt::AlignRight + Qt::AlignVCenter;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (role == Qt::BackgroundColorRole) {
|
|
|
|
|
|
if (col == c_ColumnExclusive || col == c_ColumnInclusive) {
|
|
|
|
|
|
float t = col == 1 ? item->exclusiveTime() : item->inclusiveTime();
|
|
|
|
|
|
float tt = explain->plan->inclusiveTime();
|
|
|
|
|
|
if (tt > 0.000000001) {
|
|
|
|
|
|
float f = t / tt;
|
|
|
|
|
|
if (f > 0.9) {
|
|
|
|
|
|
result = QColor(255, 192, 192);
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (f > 0.63) {
|
|
|
|
|
|
result = QColor(255, 224, 192);
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (f > 0.36f) {
|
|
|
|
|
|
result = QColor(255, 255, 192);
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (f > 0.09f) {
|
|
|
|
|
|
result = QColor(255, 255, 224);
|
|
|
|
|
|
}
|
|
|
|
|
|
else {
|
|
|
|
|
|
result = QColor(Qt::white);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
if (col == c_ColumnEstErr) {
|
2017-08-23 13:27:23 +02:00
|
|
|
|
float e = std::fabs(item->estimateError());
|
2016-12-29 13:48:35 +01:00
|
|
|
|
if (e > 1000.0f) {
|
|
|
|
|
|
result = QColor(255, 192, 192);
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (e > 100.0f) {
|
|
|
|
|
|
result = QColor(255, 224, 192);
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (e > 10.0f) {
|
|
|
|
|
|
result = QColor(255, 255, 192);
|
|
|
|
|
|
}
|
|
|
|
|
|
else {
|
|
|
|
|
|
result = QColor(Qt::white);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return result;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//Qt::ItemFlags QueryExplainModel::flags(const QModelIndex &index) const
|
|
|
|
|
|
//{
|
|
|
|
|
|
|
|
|
|
|
|
//}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
QVariant QueryExplainModel::headerData(int section, Qt::Orientation orientation,
|
|
|
|
|
|
int role) const
|
|
|
|
|
|
{
|
|
|
|
|
|
QVariant v;
|
|
|
|
|
|
if (orientation == Qt::Horizontal) {
|
|
|
|
|
|
if (role == Qt::DisplayRole ) {
|
|
|
|
|
|
switch (section) {
|
|
|
|
|
|
case c_ColumnNode:
|
|
|
|
|
|
v = "Node";
|
|
|
|
|
|
break;
|
|
|
|
|
|
case c_ColumnExclusive:
|
|
|
|
|
|
v = "Exclusive";
|
|
|
|
|
|
break;
|
|
|
|
|
|
case c_ColumnInclusive:
|
|
|
|
|
|
v = "Inclusive";
|
|
|
|
|
|
break;
|
|
|
|
|
|
case c_ColumnEstErr:
|
|
|
|
|
|
v = "Est. Err";
|
|
|
|
|
|
break;
|
|
|
|
|
|
case c_ColumnRowCount:
|
|
|
|
|
|
v = "Rows";
|
|
|
|
|
|
break;
|
|
|
|
|
|
case c_ColumnLoops:
|
|
|
|
|
|
v = "Loops";
|
|
|
|
|
|
break;
|
|
|
|
|
|
case c_ColumnDetails:
|
|
|
|
|
|
v = "Details";
|
|
|
|
|
|
break;
|
2017-12-09 10:45:13 +01:00
|
|
|
|
case c_ColumnShared:
|
|
|
|
|
|
v = "Shared";
|
|
|
|
|
|
break;
|
2016-12-29 13:48:35 +01:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
// else if (role == Qt::SizeHintRole) {
|
|
|
|
|
|
// switch (section) {
|
|
|
|
|
|
// case 0:
|
|
|
|
|
|
// v = QSize();
|
|
|
|
|
|
// break;
|
|
|
|
|
|
// case 1:
|
|
|
|
|
|
// v = "Exclusive";
|
|
|
|
|
|
// break;
|
|
|
|
|
|
// case 2:
|
|
|
|
|
|
// v = "Inclusive";
|
|
|
|
|
|
// break;
|
|
|
|
|
|
// case 3:
|
|
|
|
|
|
// v = "Est. Err";
|
|
|
|
|
|
// break;
|
|
|
|
|
|
// }
|
|
|
|
|
|
// }
|
|
|
|
|
|
}
|
|
|
|
|
|
return v;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
QModelIndex QueryExplainModel::index(int row, int column,
|
|
|
|
|
|
const QModelIndex &parent) const
|
|
|
|
|
|
{
|
|
|
|
|
|
QModelIndex result;
|
|
|
|
|
|
if (hasIndex(row, column, parent)) {
|
|
|
|
|
|
if (parent.isValid()) {
|
|
|
|
|
|
ExplainTreeModelItem *parentItem =
|
|
|
|
|
|
static_cast<ExplainTreeModelItem*>(parent.internalPointer());
|
|
|
|
|
|
if (parentItem) {
|
|
|
|
|
|
ExplainTreeModelItemPtr childItem = parentItem->child(row);
|
|
|
|
|
|
if (childItem) {
|
|
|
|
|
|
result = createIndex(row, column, childItem.get());
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
else {
|
|
|
|
|
|
result = createIndex(row, column, explain->plan.get());
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return result;
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
QModelIndex QueryExplainModel::parent(const QModelIndex &index) const
|
|
|
|
|
|
{
|
|
|
|
|
|
QModelIndex result;
|
|
|
|
|
|
if (index.isValid()) {
|
|
|
|
|
|
ExplainTreeModelItem *childItem = static_cast<ExplainTreeModelItem*>(index.internalPointer());
|
|
|
|
|
|
auto parentItem = childItem->parent();
|
|
|
|
|
|
|
|
|
|
|
|
if (parentItem != nullptr) {
|
|
|
|
|
|
result = createIndex( parentItem->row(), 0, parentItem.get());
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return result;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int QueryExplainModel::rowCount(const QModelIndex &parent) const
|
|
|
|
|
|
{
|
|
|
|
|
|
int result = 0;
|
|
|
|
|
|
if (parent.column() <= 0) {
|
|
|
|
|
|
if (parent.isValid()) {
|
|
|
|
|
|
auto item = static_cast<ExplainTreeModelItem*>(parent.internalPointer());
|
|
|
|
|
|
result = item->childCount();
|
|
|
|
|
|
}
|
|
|
|
|
|
else {
|
|
|
|
|
|
result = 1;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return result;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2017-02-02 07:22:54 +01:00
|
|
|
|
int QueryExplainModel::columnCount(const QModelIndex &) const
|
2016-12-29 13:48:35 +01:00
|
|
|
|
{
|
|
|
|
|
|
// if (parent.isValid()) {
|
|
|
|
|
|
// return 6;//static_cast<ExplainTreeModelItem*>(parent.internalPointer())->columnCount();
|
|
|
|
|
|
// }
|
|
|
|
|
|
// else {
|
|
|
|
|
|
// return 1;
|
|
|
|
|
|
// }
|
|
|
|
|
|
return c_NumberOfColumns;
|
|
|
|
|
|
}
|