The list of indexes on a table now also shows the access method (ie btree)

This commit is contained in:
eelke 2018-08-25 18:11:12 +02:00
parent 7c4f1a4752
commit 50cb21b6f9
17 changed files with 198 additions and 26 deletions

View file

@ -84,6 +84,31 @@ private:
using PKeyValues = std::vector<std::string>; using PKeyValues = std::vector<std::string>;
class ColumnSort {
public:
enum Direction { Ascending, Descending };
enum NullSorting {
Default, ///< Behaves like NULL values are larger then non NULL values ASC NULLS LAST or DESC NULLS FIRST
First,
Last };
std::string columnName;
Direction direction = Direction::Ascending;
NullSorting nulls = NullSorting::Default;
std::string toSql() const
{
std::string res = columnName;
if (direction == Direction::Descending)
res += " DESC";
if (nulls == NullSorting::First)
res += " NULLS FIRST";
else if (nulls == NullSorting::Last)
res += " NULLS LAST";
}
};
// using RowData = std::vector<std::string>; // using RowData = std::vector<std::string>;
// using RowDataPtr = std::unique_ptr<RowData>; // using RowDataPtr = std::unique_ptr<RowData>;

View file

@ -17,7 +17,7 @@ void IndexModel::setData(std::shared_ptr<const PgDatabaseCatalog> cat, const PgC
int IndexModel::rowCount(const QModelIndex &/*parent*/) const int IndexModel::rowCount(const QModelIndex &/*parent*/) const
{ {
return m_indexes.size(); return (int)m_indexes.size();
} }
int IndexModel::columnCount(const QModelIndex &/*parent*/) const int IndexModel::columnCount(const QModelIndex &/*parent*/) const
@ -43,6 +43,9 @@ QVariant IndexModel::headerData(int section, Qt::Orientation orientation, int ro
case NameCol: case NameCol:
c = tr("Name"); c = tr("Name");
break; break;
case AmCol:
c = tr("AM");
break;
case ColumnsCol: case ColumnsCol:
c = tr("On"); c = tr("On");
break; break;
@ -75,6 +78,10 @@ QVariant IndexModel::getData(const QModelIndex &index) const
v = getIndexDisplayString(*m_catalog, dat.indexrelid); v = getIndexDisplayString(*m_catalog, dat.indexrelid);
break; break;
case AmCol:
v = dat.getAm();
break;
case ColumnsCol: case ColumnsCol:
break; break;

View file

@ -18,10 +18,23 @@ public:
enum e_Columns : int { enum e_Columns : int {
TypeCol, /// primary/unique/normal TypeCol, /// primary/unique/normal
NameCol, /// NameCol, ///
AmCol, ///< Access Method
ColumnsCol, /// ColumnsCol, ///
ConditionCol, ConditionCol,
colCount }; colCount };
// oid
// tablespace
// operator class
// unique
// primary
// clustered
// valid
// constraint
// system index
// fill factor
// comment
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
void setData(std::shared_ptr<const PgDatabaseCatalog> cat, const PgClass &table); void setData(std::shared_ptr<const PgDatabaseCatalog> cat, const PgClass &table);

View file

@ -542,18 +542,18 @@ void QueryTab::markError(const Pgsql::ErrorDetails &details)
if (details.state == "42703") { if (details.state == "42703") {
std::size_t pos = details.messagePrimary.find('"'); std::size_t pos = details.messagePrimary.find('"');
if (pos != std::string::npos) { if (pos != std::string::npos) {
int pos2 = details.messagePrimary.find('"', pos+1); std::size_t pos2 = details.messagePrimary.find('"', pos+1);
if (pos2 != std::string::npos) { if (pos2 != std::string::npos) {
length = pos2 - pos; length = static_cast<int>(pos2 - pos);
} }
} }
} }
else if (details.state == "42P01") { else if (details.state == "42P01") {
std::size_t pos = details.messagePrimary.find('"'); std::size_t pos = details.messagePrimary.find('"');
if (pos != std::string::npos) { if (pos != std::string::npos) {
int pos2 = details.messagePrimary.find('"', pos+1); std::size_t pos2 = details.messagePrimary.find('"', pos+1);
if (pos2 != std::string::npos) { if (pos2 != std::string::npos) {
length = pos2 - pos; length = static_cast<int>(pos2 - pos);
} }
} }
} }
@ -623,11 +623,11 @@ std::vector<QAction*> QueryTab::getToolbarActions()
action->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_S)); action->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_S));
connect(action, &QAction::triggered, this, &QueryTab::save); connect(action, &QAction::triggered, this, &QueryTab::save);
actions.push_back(action); actions.push_back(action);
// Save as // Save as (menu only)
action = new QAction(QIcon(":/icons/script_go.png"), tr("Save SQL as"), this); // action = new QAction(QIcon(":/icons/script_save.png"), tr("Save SQL as"), this);
//action->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_S)); // //action->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_S));
connect(action, &QAction::triggered, this, &QueryTab::saveAs); // connect(action, &QAction::triggered, this, &QueryTab::saveAs);
actions.push_back(action); // actions.push_back(action);
// Save copy as // Save copy as
// Copy // Copy
// Copy as C-string // Copy as C-string

6
pglablib/PgAm.cpp Normal file
View file

@ -0,0 +1,6 @@
#include "PgAm.h"
PgAm::PgAm()
{
}

19
pglablib/PgAm.h Normal file
View file

@ -0,0 +1,19 @@
#ifndef PGAM_H
#define PGAM_H
#include "Pgsql_declare.h"
#include <QString>
class PgAm {
public:
Oid oid;
QString name;
PgAm();
bool operator==(Oid rhs) const { return oid == rhs; }
bool operator<(Oid rhs) const { return oid < rhs; }
bool operator<(const PgAm &rhs) const { return oid < rhs.oid; }
};
#endif // PGAM_H

View file

@ -0,0 +1,17 @@
#include "PgAmContainer.h"
#include "Pgsql_Col.h"
std::string PgAmContainer::getLoadQuery() const
{
std::string q = "SELECT oid, amname FROM pg_am";
return q;
}
PgAm PgAmContainer::loadElem(const Pgsql::Row &row)
{
Pgsql::Col col(row);
PgAm v;
col >> v.oid >> v.name;
return v;
}

18
pglablib/PgAmContainer.h Normal file
View file

@ -0,0 +1,18 @@
#ifndef PGAMCONTAINER_H
#define PGAMCONTAINER_H
#include "PgContainer.h"
#include "PgAm.h"
#include "Pgsql_declare.h"
#include <vector>
class PgAmContainer : public PgContainer<PgAm> {
public:
using PgContainer<PgAm>::PgContainer;
virtual std::string getLoadQuery() const override;
protected:
virtual PgAm loadElem(const Pgsql::Row &row) override;
};
#endif // PGAMCONTAINER_H

View file

@ -95,7 +95,7 @@ protected:
* *
* When overriding this function there is no need to override load. * When overriding this function there is no need to override load.
*/ */
virtual T loadElem(const Pgsql::Row &) { return T(); } virtual T loadElem(const Pgsql::Row &) { return m_invalidInstance; }
private: private:
T m_invalidInstance; T m_invalidInstance;

View file

@ -1,6 +1,7 @@
#include "PgDatabaseCatalog.h" #include "PgDatabaseCatalog.h"
#include "ASyncDBConnection.h" #include "ASyncDBConnection.h"
#include "PgAmContainer.h"
#include "PgAttributeContainer.h" #include "PgAttributeContainer.h"
#include "PgAuthIdContainer.h" #include "PgAuthIdContainer.h"
#include "PgClassContainer.h" #include "PgClassContainer.h"
@ -128,32 +129,36 @@ void PgDatabaseCatalog::loadAll(Pgsql::Connection &conn,
std::function<bool(int, int)> progress_callback) std::function<bool(int, int)> progress_callback)
{ {
loadInfo(conn); loadInfo(conn);
const int count = 10;
int n = 0; int n = 0;
if (progress_callback && !progress_callback(++n, 9)) if (progress_callback && !progress_callback(++n, count))
return; return;
load2(m_namespaces, conn); load2(m_namespaces, conn);
if (progress_callback && !progress_callback(++n, 9)) if (progress_callback && !progress_callback(++n, count))
return; return;
load2(m_classes, conn); // needs namespaces load2(m_classes, conn); // needs namespaces
if (progress_callback && !progress_callback(++n, 9)) if (progress_callback && !progress_callback(++n, count))
return; return;
load2(m_attributes, conn); load2(m_attributes, conn);
if (progress_callback && !progress_callback(++n, 9)) if (progress_callback && !progress_callback(++n, count))
return; return;
load2(m_authIds, conn); load2(m_authIds, conn);
if (progress_callback && !progress_callback(++n, 9)) if (progress_callback && !progress_callback(++n, count))
return; return;
load2(m_constraints, conn); load2(m_constraints, conn);
if (progress_callback && !progress_callback(++n, 9)) if (progress_callback && !progress_callback(++n, count))
return; return;
load2(m_databases, conn); load2(m_databases, conn);
if (progress_callback && !progress_callback(++n, 9)) if (progress_callback && !progress_callback(++n, count))
return; return;
load2(m_indexes, conn); load2(m_indexes, conn);
if (progress_callback && !progress_callback(++n, 9)) if (progress_callback && !progress_callback(++n, count))
return;
load2(m_ams, conn);
if (progress_callback && !progress_callback(++n, count))
return; return;
load2(m_types, conn); load2(m_types, conn);
progress_callback && progress_callback(++n, 9); progress_callback && progress_callback(++n, count);
} }
void PgDatabaseCatalog::loadInfo(Pgsql::Connection &conn) void PgDatabaseCatalog::loadInfo(Pgsql::Connection &conn)
@ -230,6 +235,11 @@ std::shared_ptr<const PgIndexContainer> PgDatabaseCatalog::indexes() const
return m_indexes; return m_indexes;
} }
std::shared_ptr<const PgAmContainer> PgDatabaseCatalog::ams() const
{
return m_ams;
}
std::shared_ptr<const PgNamespaceContainer> PgDatabaseCatalog::namespaces() const std::shared_ptr<const PgNamespaceContainer> PgDatabaseCatalog::namespaces() const
{ {
return m_namespaces; return m_namespaces;

View file

@ -20,6 +20,7 @@ class PgConstraintContainer;
class PgDatabaseContainer; class PgDatabaseContainer;
class PgIndexContainer; class PgIndexContainer;
class PgNamespaceContainer; class PgNamespaceContainer;
class PgAmContainer;
class PgTypeContainer; class PgTypeContainer;
class PgDatabaseCatalog: public std::enable_shared_from_this<PgDatabaseCatalog> { class PgDatabaseCatalog: public std::enable_shared_from_this<PgDatabaseCatalog> {
@ -43,6 +44,7 @@ public:
std::shared_ptr<const PgConstraintContainer> constraints() const; std::shared_ptr<const PgConstraintContainer> constraints() const;
std::shared_ptr<const PgDatabaseContainer> databases() const; std::shared_ptr<const PgDatabaseContainer> databases() const;
std::shared_ptr<const PgIndexContainer> indexes() const; std::shared_ptr<const PgIndexContainer> indexes() const;
std::shared_ptr<const PgAmContainer> ams() const;
std::shared_ptr<const PgNamespaceContainer> namespaces() const; std::shared_ptr<const PgNamespaceContainer> namespaces() const;
std::shared_ptr<const PgTypeContainer> types() const; std::shared_ptr<const PgTypeContainer> types() const;
private: private:
@ -55,6 +57,7 @@ private:
std::shared_ptr<PgConstraintContainer> m_constraints; std::shared_ptr<PgConstraintContainer> m_constraints;
std::shared_ptr<PgDatabaseContainer> m_databases; std::shared_ptr<PgDatabaseContainer> m_databases;
std::shared_ptr<PgIndexContainer> m_indexes; std::shared_ptr<PgIndexContainer> m_indexes;
std::shared_ptr<PgAmContainer> m_ams;
std::shared_ptr<PgNamespaceContainer> m_namespaces; std::shared_ptr<PgNamespaceContainer> m_namespaces;
std::shared_ptr<PgTypeContainer> m_types; std::shared_ptr<PgTypeContainer> m_types;

View file

@ -1,3 +1,22 @@
#include "PgIndex.h" #include "PgIndex.h"
#include "PgDatabaseCatalog.h"
#include "PgClassContainer.h"
#include "PgAmContainer.h"
PgIndex::PgIndex() = default; PgIndex::PgIndex() = default;
PgIndex::PgIndex(std::weak_ptr<PgDatabaseCatalog> cat)
: PgObject(cat)
{}
QString PgIndex::getAm() const
{
auto cat = catalog.lock();
QString result;
if (cat) {
auto idxcls = cat->classes()->getByKey(indexrelid);
auto am = cat->ams()->getByKey(idxcls.am);
result = am.name;
}
return result;
}

View file

@ -1,15 +1,16 @@
#ifndef PGINDEX_H #ifndef PGINDEX_H
#define PGINDEX_H #define PGINDEX_H
#include "PgObject.h"
#include "Pgsql_declare.h" #include "Pgsql_declare.h"
#include <QString> #include <QString>
#include <vector> #include <vector>
class PgIndex { class PgIndex : public PgObject {
public: public:
Oid indexrelid = InvalidOid; Oid indexrelid = InvalidOid; // oid of pg_class for this index
Oid relid = InvalidOid; Oid relid = InvalidOid; // oid of table (pg_class) where this is an index on
int16_t natts = 0; int16_t natts = 0;
bool isunique = false; bool isunique = false;
bool isprimary = false; bool isprimary = false;
@ -30,6 +31,9 @@ public:
QString definition; QString definition;
PgIndex(); PgIndex();
explicit PgIndex(std::weak_ptr<PgDatabaseCatalog> cat);
QString getAm() const;
bool operator==(Oid _oid) const { return indexrelid == _oid; } bool operator==(Oid _oid) const { return indexrelid == _oid; }
//bool operator==(const QString &n) const { return name == n; } //bool operator==(const QString &n) const { return name == n; }

View file

@ -22,7 +22,7 @@ SELECT indexrelid, indrelid, indnatts, indisunique, indisprimary,
PgIndex PgIndexContainer::loadElem(const Pgsql::Row &row) PgIndex PgIndexContainer::loadElem(const Pgsql::Row &row)
{ {
Pgsql::Col col(row); Pgsql::Col col(row);
PgIndex v; PgIndex v(m_catalogue);
col >> v.indexrelid >> v.relid >> v.natts >> v.isunique col >> v.indexrelid >> v.relid >> v.natts >> v.isunique
>> v.isprimary >> v.isexclusion >> v.immediate >> v.isclustered >> v.isprimary >> v.isexclusion >> v.immediate >> v.isclustered
>> v.isvalid >> v.checkxmin >> v.isready >> v.islive; >> v.isvalid >> v.checkxmin >> v.isready >> v.islive;

6
pglablib/PgObject.cpp Normal file
View file

@ -0,0 +1,6 @@
#include "PgObject.h"
PgObject::PgObject()
{
}

19
pglablib/PgObject.h Normal file
View file

@ -0,0 +1,19 @@
#ifndef PGOBJECT_H
#define PGOBJECT_H
#include <memory>
class PgDatabaseCatalog;
class PgObject
{
public:
PgObject();
explicit PgObject(std::weak_ptr<PgDatabaseCatalog> cat)
: catalog(cat)
{}
protected:
std::weak_ptr<PgDatabaseCatalog> catalog;
};
#endif // PGOBJECT_H

View file

@ -52,7 +52,10 @@ SOURCES += \
util.cpp \ util.cpp \
SqlFormattingUtils.cpp \ SqlFormattingUtils.cpp \
PgKeywordList.cpp \ PgKeywordList.cpp \
QueryGenerator.cpp QueryGenerator.cpp \
PgAm.cpp \
PgAmContainer.cpp \
PgObject.cpp
HEADERS += \ HEADERS += \
Pglablib.h \ Pglablib.h \
@ -82,7 +85,10 @@ HEADERS += \
SqlFormattingUtils.h \ SqlFormattingUtils.h \
PgCatalogTypes.h \ PgCatalogTypes.h \
PgKeywordList.h \ PgKeywordList.h \
QueryGenerator.h QueryGenerator.h \
PgAm.h \
PgAmContainer.h \
PgObject.h
unix { unix {
target.path = /usr/lib target.path = /usr/lib