The list of indexes on a table now also shows the access method (ie btree)
This commit is contained in:
parent
7c4f1a4752
commit
50cb21b6f9
17 changed files with 198 additions and 26 deletions
|
|
@ -84,6 +84,31 @@ private:
|
|||
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 RowDataPtr = std::unique_ptr<RowData>;
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ void IndexModel::setData(std::shared_ptr<const PgDatabaseCatalog> cat, const PgC
|
|||
|
||||
int IndexModel::rowCount(const QModelIndex &/*parent*/) const
|
||||
{
|
||||
return m_indexes.size();
|
||||
return (int)m_indexes.size();
|
||||
}
|
||||
|
||||
int IndexModel::columnCount(const QModelIndex &/*parent*/) const
|
||||
|
|
@ -43,6 +43,9 @@ QVariant IndexModel::headerData(int section, Qt::Orientation orientation, int ro
|
|||
case NameCol:
|
||||
c = tr("Name");
|
||||
break;
|
||||
case AmCol:
|
||||
c = tr("AM");
|
||||
break;
|
||||
case ColumnsCol:
|
||||
c = tr("On");
|
||||
break;
|
||||
|
|
@ -75,6 +78,10 @@ QVariant IndexModel::getData(const QModelIndex &index) const
|
|||
v = getIndexDisplayString(*m_catalog, dat.indexrelid);
|
||||
break;
|
||||
|
||||
case AmCol:
|
||||
v = dat.getAm();
|
||||
break;
|
||||
|
||||
case ColumnsCol:
|
||||
break;
|
||||
|
||||
|
|
|
|||
|
|
@ -18,10 +18,23 @@ public:
|
|||
enum e_Columns : int {
|
||||
TypeCol, /// primary/unique/normal
|
||||
NameCol, ///
|
||||
AmCol, ///< Access Method
|
||||
ColumnsCol, ///
|
||||
ConditionCol,
|
||||
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;
|
||||
void setData(std::shared_ptr<const PgDatabaseCatalog> cat, const PgClass &table);
|
||||
|
||||
|
|
|
|||
|
|
@ -542,18 +542,18 @@ void QueryTab::markError(const Pgsql::ErrorDetails &details)
|
|||
if (details.state == "42703") {
|
||||
std::size_t pos = details.messagePrimary.find('"');
|
||||
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) {
|
||||
length = pos2 - pos;
|
||||
length = static_cast<int>(pos2 - pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (details.state == "42P01") {
|
||||
std::size_t pos = details.messagePrimary.find('"');
|
||||
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) {
|
||||
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));
|
||||
connect(action, &QAction::triggered, this, &QueryTab::save);
|
||||
actions.push_back(action);
|
||||
// Save as
|
||||
action = new QAction(QIcon(":/icons/script_go.png"), tr("Save SQL as"), this);
|
||||
//action->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_S));
|
||||
connect(action, &QAction::triggered, this, &QueryTab::saveAs);
|
||||
actions.push_back(action);
|
||||
// Save as (menu only)
|
||||
// action = new QAction(QIcon(":/icons/script_save.png"), tr("Save SQL as"), this);
|
||||
// //action->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_S));
|
||||
// connect(action, &QAction::triggered, this, &QueryTab::saveAs);
|
||||
// actions.push_back(action);
|
||||
// Save copy as
|
||||
// Copy
|
||||
// Copy as C-string
|
||||
|
|
|
|||
6
pglablib/PgAm.cpp
Normal file
6
pglablib/PgAm.cpp
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
#include "PgAm.h"
|
||||
|
||||
PgAm::PgAm()
|
||||
{
|
||||
|
||||
}
|
||||
19
pglablib/PgAm.h
Normal file
19
pglablib/PgAm.h
Normal 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
|
||||
17
pglablib/PgAmContainer.cpp
Normal file
17
pglablib/PgAmContainer.cpp
Normal 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
18
pglablib/PgAmContainer.h
Normal 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
|
||||
|
|
@ -95,7 +95,7 @@ protected:
|
|||
*
|
||||
* 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:
|
||||
T m_invalidInstance;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#include "PgDatabaseCatalog.h"
|
||||
|
||||
#include "ASyncDBConnection.h"
|
||||
#include "PgAmContainer.h"
|
||||
#include "PgAttributeContainer.h"
|
||||
#include "PgAuthIdContainer.h"
|
||||
#include "PgClassContainer.h"
|
||||
|
|
@ -128,32 +129,36 @@ void PgDatabaseCatalog::loadAll(Pgsql::Connection &conn,
|
|||
std::function<bool(int, int)> progress_callback)
|
||||
{
|
||||
loadInfo(conn);
|
||||
const int count = 10;
|
||||
int n = 0;
|
||||
if (progress_callback && !progress_callback(++n, 9))
|
||||
if (progress_callback && !progress_callback(++n, count))
|
||||
return;
|
||||
load2(m_namespaces, conn);
|
||||
if (progress_callback && !progress_callback(++n, 9))
|
||||
if (progress_callback && !progress_callback(++n, count))
|
||||
return;
|
||||
load2(m_classes, conn); // needs namespaces
|
||||
if (progress_callback && !progress_callback(++n, 9))
|
||||
if (progress_callback && !progress_callback(++n, count))
|
||||
return;
|
||||
load2(m_attributes, conn);
|
||||
if (progress_callback && !progress_callback(++n, 9))
|
||||
if (progress_callback && !progress_callback(++n, count))
|
||||
return;
|
||||
load2(m_authIds, conn);
|
||||
if (progress_callback && !progress_callback(++n, 9))
|
||||
if (progress_callback && !progress_callback(++n, count))
|
||||
return;
|
||||
load2(m_constraints, conn);
|
||||
if (progress_callback && !progress_callback(++n, 9))
|
||||
if (progress_callback && !progress_callback(++n, count))
|
||||
return;
|
||||
load2(m_databases, conn);
|
||||
if (progress_callback && !progress_callback(++n, 9))
|
||||
if (progress_callback && !progress_callback(++n, count))
|
||||
return;
|
||||
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;
|
||||
load2(m_types, conn);
|
||||
progress_callback && progress_callback(++n, 9);
|
||||
progress_callback && progress_callback(++n, count);
|
||||
}
|
||||
|
||||
void PgDatabaseCatalog::loadInfo(Pgsql::Connection &conn)
|
||||
|
|
@ -230,6 +235,11 @@ std::shared_ptr<const PgIndexContainer> PgDatabaseCatalog::indexes() const
|
|||
return m_indexes;
|
||||
}
|
||||
|
||||
std::shared_ptr<const PgAmContainer> PgDatabaseCatalog::ams() const
|
||||
{
|
||||
return m_ams;
|
||||
}
|
||||
|
||||
std::shared_ptr<const PgNamespaceContainer> PgDatabaseCatalog::namespaces() const
|
||||
{
|
||||
return m_namespaces;
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ class PgConstraintContainer;
|
|||
class PgDatabaseContainer;
|
||||
class PgIndexContainer;
|
||||
class PgNamespaceContainer;
|
||||
class PgAmContainer;
|
||||
class PgTypeContainer;
|
||||
|
||||
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 PgDatabaseContainer> databases() 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 PgTypeContainer> types() const;
|
||||
private:
|
||||
|
|
@ -55,6 +57,7 @@ private:
|
|||
std::shared_ptr<PgConstraintContainer> m_constraints;
|
||||
std::shared_ptr<PgDatabaseContainer> m_databases;
|
||||
std::shared_ptr<PgIndexContainer> m_indexes;
|
||||
std::shared_ptr<PgAmContainer> m_ams;
|
||||
std::shared_ptr<PgNamespaceContainer> m_namespaces;
|
||||
std::shared_ptr<PgTypeContainer> m_types;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,22 @@
|
|||
#include "PgIndex.h"
|
||||
#include "PgDatabaseCatalog.h"
|
||||
#include "PgClassContainer.h"
|
||||
#include "PgAmContainer.h"
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,15 +1,16 @@
|
|||
#ifndef PGINDEX_H
|
||||
#define PGINDEX_H
|
||||
|
||||
#include "PgObject.h"
|
||||
#include "Pgsql_declare.h"
|
||||
#include <QString>
|
||||
#include <vector>
|
||||
|
||||
class PgIndex {
|
||||
class PgIndex : public PgObject {
|
||||
public:
|
||||
|
||||
Oid indexrelid = InvalidOid;
|
||||
Oid relid = InvalidOid;
|
||||
Oid indexrelid = InvalidOid; // oid of pg_class for this index
|
||||
Oid relid = InvalidOid; // oid of table (pg_class) where this is an index on
|
||||
int16_t natts = 0;
|
||||
bool isunique = false;
|
||||
bool isprimary = false;
|
||||
|
|
@ -30,6 +31,9 @@ public:
|
|||
QString definition;
|
||||
|
||||
PgIndex();
|
||||
explicit PgIndex(std::weak_ptr<PgDatabaseCatalog> cat);
|
||||
|
||||
QString getAm() const;
|
||||
|
||||
bool operator==(Oid _oid) const { return indexrelid == _oid; }
|
||||
//bool operator==(const QString &n) const { return name == n; }
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ SELECT indexrelid, indrelid, indnatts, indisunique, indisprimary,
|
|||
PgIndex PgIndexContainer::loadElem(const Pgsql::Row &row)
|
||||
{
|
||||
Pgsql::Col col(row);
|
||||
PgIndex v;
|
||||
PgIndex v(m_catalogue);
|
||||
col >> v.indexrelid >> v.relid >> v.natts >> v.isunique
|
||||
>> v.isprimary >> v.isexclusion >> v.immediate >> v.isclustered
|
||||
>> v.isvalid >> v.checkxmin >> v.isready >> v.islive;
|
||||
|
|
|
|||
6
pglablib/PgObject.cpp
Normal file
6
pglablib/PgObject.cpp
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
#include "PgObject.h"
|
||||
|
||||
PgObject::PgObject()
|
||||
{
|
||||
|
||||
}
|
||||
19
pglablib/PgObject.h
Normal file
19
pglablib/PgObject.h
Normal 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
|
||||
|
|
@ -52,7 +52,10 @@ SOURCES += \
|
|||
util.cpp \
|
||||
SqlFormattingUtils.cpp \
|
||||
PgKeywordList.cpp \
|
||||
QueryGenerator.cpp
|
||||
QueryGenerator.cpp \
|
||||
PgAm.cpp \
|
||||
PgAmContainer.cpp \
|
||||
PgObject.cpp
|
||||
|
||||
HEADERS += \
|
||||
Pglablib.h \
|
||||
|
|
@ -82,7 +85,10 @@ HEADERS += \
|
|||
SqlFormattingUtils.h \
|
||||
PgCatalogTypes.h \
|
||||
PgKeywordList.h \
|
||||
QueryGenerator.h
|
||||
QueryGenerator.h \
|
||||
PgAm.h \
|
||||
PgAmContainer.h \
|
||||
PgObject.h
|
||||
|
||||
unix {
|
||||
target.path = /usr/lib
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue